Merge "Changes on the ContentCaptureContext APIs."
diff --git a/Android.bp b/Android.bp
index 1ee7405..6288940 100644
--- a/Android.bp
+++ b/Android.bp
@@ -69,7 +69,6 @@
"core/java/android/app/ITaskStackListener.aidl",
"core/java/android/app/IBackupAgent.aidl",
"core/java/android/app/IEphemeralResolver.aidl",
- "core/java/android/app/IInputForwarder.aidl",
"core/java/android/app/IInstantAppResolver.aidl",
"core/java/android/app/IInstrumentationWatcher.aidl",
"core/java/android/app/INotificationManager.aidl",
diff --git a/apct-tests/perftests/autofill/Android.bp b/apct-tests/perftests/autofill/Android.bp
new file mode 100644
index 0000000..65c28fb
--- /dev/null
+++ b/apct-tests/perftests/autofill/Android.bp
@@ -0,0 +1,26 @@
+// Copyright (C) 2018 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+android_test {
+ name: "AutofillPerfTests",
+ srcs: ["src/**/*.java"],
+ resource_dirs: ["res"],
+ static_libs: [
+ "androidx.test.rules",
+ "androidx.annotation_annotation",
+ "apct-perftests-utils",
+ ],
+ platform_apis: true,
+ test_suites: ["device-tests"],
+}
diff --git a/apct-tests/perftests/autofill/Android.mk b/apct-tests/perftests/autofill/Android.mk
deleted file mode 100644
index f4da40b..0000000
--- a/apct-tests/perftests/autofill/Android.mk
+++ /dev/null
@@ -1,34 +0,0 @@
-# Copyright (C) 2018 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-LOCAL_PATH := $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_TAGS := tests
-
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-
-LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res
-
-LOCAL_STATIC_JAVA_LIBRARIES := \
- androidx.test.rules \
- androidx.annotation_annotation \
- apct-perftests-utils
-
-LOCAL_PACKAGE_NAME := AutofillPerfTests
-LOCAL_PRIVATE_PLATFORM_APIS := true
-
-LOCAL_COMPATIBILITY_SUITE += device-tests
-
-include $(BUILD_PACKAGE)
diff --git a/apct-tests/perftests/multiuser/Android.bp b/apct-tests/perftests/multiuser/Android.bp
new file mode 100644
index 0000000..508bf60
--- /dev/null
+++ b/apct-tests/perftests/multiuser/Android.bp
@@ -0,0 +1,25 @@
+// Copyright (C) 2016 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+android_test {
+ name: "MultiUserPerfTests",
+ srcs: ["src/**/*.java"],
+ static_libs: [
+ "androidx.test.rules",
+ "apct-perftests-utils",
+ ],
+ platform_apis: true,
+ test_suites: ["device-tests"],
+ certificate: "platform",
+}
diff --git a/apct-tests/perftests/multiuser/Android.mk b/apct-tests/perftests/multiuser/Android.mk
deleted file mode 100644
index 5852044..0000000
--- a/apct-tests/perftests/multiuser/Android.mk
+++ /dev/null
@@ -1,34 +0,0 @@
-# Copyright (C) 2016 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-LOCAL_PATH := $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_TAGS := tests
-
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-
-LOCAL_STATIC_JAVA_LIBRARIES := \
- androidx.test.rules \
- apct-perftests-utils
-
-LOCAL_PACKAGE_NAME := MultiUserPerfTests
-LOCAL_PRIVATE_PLATFORM_APIS := true
-
-LOCAL_COMPATIBILITY_SUITE += device-tests
-
-LOCAL_CERTIFICATE := platform
-
-include $(BUILD_PACKAGE)
-
diff --git a/apct-tests/perftests/utils/Android.bp b/apct-tests/perftests/utils/Android.bp
new file mode 100644
index 0000000..be85816
--- /dev/null
+++ b/apct-tests/perftests/utils/Android.bp
@@ -0,0 +1,9 @@
+java_library {
+ name: "apct-perftests-utils",
+ static_libs: [
+ "androidx.test.rules",
+ "androidx.annotation_annotation",
+ ],
+ // Build all java files in the java subdirectory
+ srcs: ["**/*.java"],
+}
diff --git a/apct-tests/perftests/utils/Android.mk b/apct-tests/perftests/utils/Android.mk
deleted file mode 100644
index 19f83c8..0000000
--- a/apct-tests/perftests/utils/Android.mk
+++ /dev/null
@@ -1,15 +0,0 @@
-LOCAL_PATH := $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_STATIC_JAVA_LIBRARIES := \
- androidx.test.rules \
- androidx.annotation_annotation
-
-# Build all java files in the java subdirectory
-LOCAL_SRC_FILES := $(call all-subdir-java-files)
-
-# The name of the jar file to create
-LOCAL_MODULE := apct-perftests-utils
-
-# Build a static jar file.
-include $(BUILD_STATIC_JAVA_LIBRARY)
\ No newline at end of file
diff --git a/api/TEST_MAPPING b/api/TEST_MAPPING
index 8a676e9..2cdf54b 100644
--- a/api/TEST_MAPPING
+++ b/api/TEST_MAPPING
@@ -2,6 +2,9 @@
"presubmit": [
{
"name": "CtsCurrentApiSignatureTestCases"
+ },
+ {
+ "name": "GtsUnofficialApisUsageTestCases"
}
]
}
diff --git a/api/current.txt b/api/current.txt
index f6fe771..833b87b 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -9348,25 +9348,7 @@
field public static final android.os.Parcelable.Creator<android.content.ComponentName> CREATOR;
}
- public interface ContentInterface {
- method @NonNull public android.content.ContentProviderResult[] applyBatch(@NonNull String, @NonNull java.util.ArrayList<android.content.ContentProviderOperation>) throws android.content.OperationApplicationException, android.os.RemoteException;
- method public int bulkInsert(@NonNull android.net.Uri, @NonNull android.content.ContentValues[]) throws android.os.RemoteException;
- method @Nullable public android.os.Bundle call(@NonNull String, @NonNull String, @Nullable String, @Nullable android.os.Bundle) throws android.os.RemoteException;
- method @Nullable public android.net.Uri canonicalize(@NonNull android.net.Uri) throws android.os.RemoteException;
- method public int delete(@NonNull android.net.Uri, @Nullable String, @Nullable String[]) throws android.os.RemoteException;
- method @Nullable public String[] getStreamTypes(@NonNull android.net.Uri, @NonNull String) throws android.os.RemoteException;
- method @Nullable public String getType(@NonNull android.net.Uri) throws android.os.RemoteException;
- method @Nullable public android.net.Uri insert(@NonNull android.net.Uri, @Nullable android.content.ContentValues) throws android.os.RemoteException;
- method @Nullable public android.content.res.AssetFileDescriptor openAssetFile(@NonNull android.net.Uri, @NonNull String, @Nullable android.os.CancellationSignal) throws java.io.FileNotFoundException, android.os.RemoteException;
- method @Nullable public android.os.ParcelFileDescriptor openFile(@NonNull android.net.Uri, @NonNull String, @Nullable android.os.CancellationSignal) throws java.io.FileNotFoundException, android.os.RemoteException;
- method @Nullable public android.content.res.AssetFileDescriptor openTypedAssetFile(@NonNull android.net.Uri, @NonNull String, @Nullable android.os.Bundle, @Nullable android.os.CancellationSignal) throws java.io.FileNotFoundException, android.os.RemoteException;
- method @Nullable public android.database.Cursor query(@NonNull android.net.Uri, @Nullable String[], @Nullable android.os.Bundle, @Nullable android.os.CancellationSignal) throws android.os.RemoteException;
- method public boolean refresh(@NonNull android.net.Uri, @Nullable android.os.Bundle, @Nullable android.os.CancellationSignal) throws android.os.RemoteException;
- method @Nullable public android.net.Uri uncanonicalize(@NonNull android.net.Uri) throws android.os.RemoteException;
- method public int update(@NonNull android.net.Uri, @Nullable android.content.ContentValues, @Nullable String, @Nullable String[]) throws android.os.RemoteException;
- }
-
- public abstract class ContentProvider implements android.content.ComponentCallbacks2 android.content.ContentInterface {
+ public abstract class ContentProvider implements android.content.ComponentCallbacks2 {
ctor public ContentProvider();
method @NonNull public android.content.ContentProviderResult[] applyBatch(@NonNull String, @NonNull java.util.ArrayList<android.content.ContentProviderOperation>) throws android.content.OperationApplicationException;
method @NonNull public android.content.ContentProviderResult[] applyBatch(@NonNull java.util.ArrayList<android.content.ContentProviderOperation>) throws android.content.OperationApplicationException;
@@ -9419,7 +9401,7 @@
method public void writeDataToPipe(@NonNull android.os.ParcelFileDescriptor, @NonNull android.net.Uri, @NonNull String, @Nullable android.os.Bundle, @Nullable T);
}
- public class ContentProviderClient implements java.lang.AutoCloseable android.content.ContentInterface {
+ public class ContentProviderClient implements java.lang.AutoCloseable {
method @NonNull public android.content.ContentProviderResult[] applyBatch(@NonNull java.util.ArrayList<android.content.ContentProviderOperation>) throws android.content.OperationApplicationException, android.os.RemoteException;
method @NonNull public android.content.ContentProviderResult[] applyBatch(@NonNull String, @NonNull java.util.ArrayList<android.content.ContentProviderOperation>) throws android.content.OperationApplicationException, android.os.RemoteException;
method public int bulkInsert(@NonNull android.net.Uri, @NonNull android.content.ContentValues[]) throws android.os.RemoteException;
@@ -9427,7 +9409,6 @@
method @Nullable public android.os.Bundle call(@NonNull String, @NonNull String, @Nullable String, @Nullable android.os.Bundle) throws android.os.RemoteException;
method @Nullable public final android.net.Uri canonicalize(@NonNull android.net.Uri) throws android.os.RemoteException;
method public void close();
- method public static void closeQuietly(android.content.ContentProviderClient);
method public int delete(@NonNull android.net.Uri, @Nullable String, @Nullable String[]) throws android.os.RemoteException;
method @Nullable public android.content.ContentProvider getLocalContentProvider();
method @Nullable public String[] getStreamTypes(@NonNull android.net.Uri, @NonNull String) throws android.os.RemoteException;
@@ -9502,8 +9483,8 @@
method public void setKeepUpdated(boolean);
}
- public abstract class ContentResolver implements android.content.ContentInterface {
- ctor public ContentResolver(android.content.Context);
+ public abstract class ContentResolver {
+ ctor public ContentResolver(@Nullable android.content.Context);
method @Nullable public final android.content.ContentProviderClient acquireContentProviderClient(@NonNull android.net.Uri);
method @Nullable public final android.content.ContentProviderClient acquireContentProviderClient(@NonNull String);
method @Nullable public final android.content.ContentProviderClient acquireUnstableContentProviderClient(@NonNull android.net.Uri);
@@ -9568,6 +9549,8 @@
method public final void unregisterContentObserver(@NonNull android.database.ContentObserver);
method public final int update(@RequiresPermission.Write @NonNull android.net.Uri, @Nullable android.content.ContentValues, @Nullable String, @Nullable String[]);
method public static void validateSyncExtrasBundle(android.os.Bundle);
+ method public static android.content.ContentResolver wrap(@NonNull android.content.ContentProvider);
+ method public static android.content.ContentResolver wrap(@NonNull android.content.ContentProviderClient);
field public static final String ANY_CURSOR_ITEM_TYPE = "vnd.android.cursor.item/*";
field public static final String CURSOR_DIR_BASE_TYPE = "vnd.android.cursor.dir";
field public static final String CURSOR_ITEM_BASE_TYPE = "vnd.android.cursor.item";
@@ -9609,10 +9592,10 @@
public class ContentUris {
ctor public ContentUris();
- method public static android.net.Uri.Builder appendId(android.net.Uri.Builder, long);
- method public static long parseId(android.net.Uri);
- method public static android.net.Uri removeId(android.net.Uri);
- method public static android.net.Uri withAppendedId(android.net.Uri, long);
+ method @NonNull public static android.net.Uri.Builder appendId(@NonNull android.net.Uri.Builder, long);
+ method public static long parseId(@NonNull android.net.Uri);
+ method @NonNull public static android.net.Uri removeId(@NonNull android.net.Uri);
+ method @NonNull public static android.net.Uri withAppendedId(@NonNull android.net.Uri, long);
}
public final class ContentValues implements android.os.Parcelable {
@@ -10239,8 +10222,7 @@
field public static final String ACTION_MEDIA_NOFS = "android.intent.action.MEDIA_NOFS";
field public static final String ACTION_MEDIA_REMOVED = "android.intent.action.MEDIA_REMOVED";
field public static final String ACTION_MEDIA_SCANNER_FINISHED = "android.intent.action.MEDIA_SCANNER_FINISHED";
- field public static final String ACTION_MEDIA_SCANNER_SCAN_FILE = "android.intent.action.MEDIA_SCANNER_SCAN_FILE";
- field public static final String ACTION_MEDIA_SCANNER_SCAN_VOLUME = "android.intent.action.MEDIA_SCANNER_SCAN_VOLUME";
+ field @Deprecated public static final String ACTION_MEDIA_SCANNER_SCAN_FILE = "android.intent.action.MEDIA_SCANNER_SCAN_FILE";
field public static final String ACTION_MEDIA_SCANNER_STARTED = "android.intent.action.MEDIA_SCANNER_STARTED";
field public static final String ACTION_MEDIA_SHARED = "android.intent.action.MEDIA_SHARED";
field public static final String ACTION_MEDIA_UNMOUNTABLE = "android.intent.action.MEDIA_UNMOUNTABLE";
@@ -26018,6 +26000,7 @@
method public void broadcastSessionCommand(@NonNull android.media.Session2Command, @Nullable android.os.Bundle);
method public void cancelSessionCommand(@NonNull android.media.MediaSession2.ControllerInfo, @NonNull Object);
method public void close();
+ method @NonNull public java.util.List<android.media.MediaSession2.ControllerInfo> getConnectedControllers();
method @NonNull public String getSessionId();
method @NonNull public android.media.Session2Token getSessionToken();
method public boolean isPlaybackActive();
@@ -26044,6 +26027,7 @@
method public void onCommandResult(@NonNull android.media.MediaSession2, @NonNull android.media.MediaSession2.ControllerInfo, @NonNull Object, @NonNull android.media.Session2Command, @NonNull android.media.Session2Command.Result);
method @Nullable public android.media.Session2CommandGroup onConnect(@NonNull android.media.MediaSession2, @NonNull android.media.MediaSession2.ControllerInfo);
method public void onDisconnected(@NonNull android.media.MediaSession2, @NonNull android.media.MediaSession2.ControllerInfo);
+ method public void onPostConnect(@NonNull android.media.MediaSession2, @NonNull android.media.MediaSession2.ControllerInfo);
method @Nullable public android.media.Session2Command.Result onSessionCommand(@NonNull android.media.MediaSession2, @NonNull android.media.MediaSession2.ControllerInfo, @NonNull android.media.Session2Command, @Nullable android.os.Bundle);
}
@@ -29964,7 +29948,7 @@
method public java.util.List<android.net.wifi.ScanResult> getScanResults();
method public int getWifiState();
method public boolean is5GHzBandSupported();
- method public boolean isDeviceToApRttSupported();
+ method @Deprecated public boolean isDeviceToApRttSupported();
method public boolean isEasyConnectSupported();
method public boolean isEnhancedPowerReportingSupported();
method public boolean isOweSupported();
@@ -34632,11 +34616,9 @@
ctor public FileUriExposedException(String);
}
- public class FileUtils {
+ public final class FileUtils {
method public static void closeQuietly(@Nullable AutoCloseable);
method public static void closeQuietly(@Nullable java.io.FileDescriptor);
- method public static long copy(@NonNull java.io.File, @NonNull java.io.File) throws java.io.IOException;
- method public static long copy(@NonNull java.io.File, @NonNull java.io.File, @Nullable android.os.CancellationSignal, @Nullable java.util.concurrent.Executor, @Nullable android.os.FileUtils.ProgressListener) throws java.io.IOException;
method public static long copy(@NonNull java.io.InputStream, @NonNull java.io.OutputStream) throws java.io.IOException;
method public static long copy(@NonNull java.io.InputStream, @NonNull java.io.OutputStream, @Nullable android.os.CancellationSignal, @Nullable java.util.concurrent.Executor, @Nullable android.os.FileUtils.ProgressListener) throws java.io.IOException;
method public static long copy(@NonNull java.io.FileDescriptor, @NonNull java.io.FileDescriptor) throws java.io.IOException;
@@ -35708,6 +35690,7 @@
method public String getMountedObbPath(String);
method @NonNull public android.os.storage.StorageVolume getPrimaryStorageVolume();
method @Nullable public android.os.storage.StorageVolume getStorageVolume(java.io.File);
+ method @NonNull public android.os.storage.StorageVolume getStorageVolume(@NonNull android.net.Uri);
method @NonNull public java.util.List<android.os.storage.StorageVolume> getStorageVolumes();
method @NonNull public java.util.UUID getUuidForPath(@NonNull java.io.File) throws java.io.IOException;
method public boolean isAllocationSupported(@NonNull java.io.FileDescriptor);
@@ -38180,38 +38163,26 @@
method public static android.net.Uri buildRootsUri(String);
method public static android.net.Uri buildSearchDocumentsUri(String, String, String);
method public static android.net.Uri buildTreeDocumentUri(String, String);
- method public static android.net.Uri copyDocument(android.content.ContentInterface, android.net.Uri, android.net.Uri) throws java.io.FileNotFoundException;
- method @Deprecated public static android.net.Uri copyDocument(android.content.ContentResolver, android.net.Uri, android.net.Uri) throws java.io.FileNotFoundException;
- method public static android.net.Uri createDocument(android.content.ContentInterface, android.net.Uri, String, String) throws java.io.FileNotFoundException;
- method @Deprecated public static android.net.Uri createDocument(android.content.ContentResolver, android.net.Uri, String, String) throws java.io.FileNotFoundException;
- method public static android.content.IntentSender createWebLinkIntent(android.content.ContentInterface, android.net.Uri, android.os.Bundle) throws java.io.FileNotFoundException;
- method @Deprecated public static android.content.IntentSender createWebLinkIntent(android.content.ContentResolver, android.net.Uri, android.os.Bundle) throws java.io.FileNotFoundException;
- method public static boolean deleteDocument(android.content.ContentInterface, android.net.Uri) throws java.io.FileNotFoundException;
- method @Deprecated public static boolean deleteDocument(android.content.ContentResolver, android.net.Uri) throws java.io.FileNotFoundException;
- method public static void ejectRoot(android.content.ContentInterface, android.net.Uri);
- method @Deprecated public static void ejectRoot(android.content.ContentResolver, android.net.Uri);
- method public static android.provider.DocumentsContract.Path findDocumentPath(android.content.ContentInterface, android.net.Uri) throws java.io.FileNotFoundException;
- method @Deprecated public static android.provider.DocumentsContract.Path findDocumentPath(android.content.ContentResolver, android.net.Uri) throws java.io.FileNotFoundException;
+ method @Nullable public static android.net.Uri copyDocument(@NonNull android.content.ContentResolver, @NonNull android.net.Uri, @NonNull android.net.Uri) throws java.io.FileNotFoundException;
+ method @Nullable public static android.net.Uri createDocument(@NonNull android.content.ContentResolver, @NonNull android.net.Uri, @NonNull String, @NonNull String) throws java.io.FileNotFoundException;
+ method @Nullable public static android.content.IntentSender createWebLinkIntent(@NonNull android.content.ContentResolver, @NonNull android.net.Uri, @Nullable android.os.Bundle) throws java.io.FileNotFoundException;
+ method public static boolean deleteDocument(@NonNull android.content.ContentResolver, @NonNull android.net.Uri) throws java.io.FileNotFoundException;
+ method public static void ejectRoot(@NonNull android.content.ContentResolver, @NonNull android.net.Uri);
+ method @Nullable public static android.provider.DocumentsContract.Path findDocumentPath(@NonNull android.content.ContentResolver, @NonNull android.net.Uri) throws java.io.FileNotFoundException;
method public static String getDocumentId(android.net.Uri);
- method @Nullable public static android.os.Bundle getDocumentMetadata(@NonNull android.content.ContentInterface, @NonNull android.net.Uri) throws java.io.FileNotFoundException;
- method @Deprecated public static android.os.Bundle getDocumentMetadata(android.content.ContentResolver, android.net.Uri) throws java.io.FileNotFoundException;
- method public static android.graphics.Bitmap getDocumentThumbnail(android.content.ContentInterface, android.net.Uri, android.graphics.Point, android.os.CancellationSignal) throws java.io.FileNotFoundException;
- method @Deprecated public static android.graphics.Bitmap getDocumentThumbnail(android.content.ContentResolver, android.net.Uri, android.graphics.Point, android.os.CancellationSignal) throws java.io.FileNotFoundException;
+ method @Nullable public static android.os.Bundle getDocumentMetadata(@NonNull android.content.ContentResolver, @NonNull android.net.Uri) throws java.io.FileNotFoundException;
+ method @Nullable public static android.graphics.Bitmap getDocumentThumbnail(@NonNull android.content.ContentResolver, @NonNull android.net.Uri, @NonNull android.graphics.Point, @Nullable android.os.CancellationSignal) throws java.io.FileNotFoundException;
method public static String getRootId(android.net.Uri);
method public static String getSearchDocumentsQuery(android.net.Uri);
method public static String getTreeDocumentId(android.net.Uri);
- method public static boolean isChildDocument(@NonNull android.content.ContentInterface, @NonNull android.net.Uri, @NonNull android.net.Uri) throws java.io.FileNotFoundException;
- method @Deprecated public static boolean isChildDocument(android.content.ContentResolver, android.net.Uri, android.net.Uri) throws java.io.FileNotFoundException;
+ method public static boolean isChildDocument(@NonNull android.content.ContentResolver, @NonNull android.net.Uri, @NonNull android.net.Uri) throws java.io.FileNotFoundException;
method public static boolean isDocumentUri(android.content.Context, @Nullable android.net.Uri);
method public static boolean isRootUri(@NonNull android.content.Context, @Nullable android.net.Uri);
method public static boolean isRootsUri(@NonNull android.content.Context, @Nullable android.net.Uri);
method public static boolean isTreeUri(android.net.Uri);
- method public static android.net.Uri moveDocument(android.content.ContentInterface, android.net.Uri, android.net.Uri, android.net.Uri) throws java.io.FileNotFoundException;
- method @Deprecated public static android.net.Uri moveDocument(android.content.ContentResolver, android.net.Uri, android.net.Uri, android.net.Uri) throws java.io.FileNotFoundException;
- method public static boolean removeDocument(android.content.ContentInterface, android.net.Uri, android.net.Uri) throws java.io.FileNotFoundException;
- method @Deprecated public static boolean removeDocument(android.content.ContentResolver, android.net.Uri, android.net.Uri) throws java.io.FileNotFoundException;
- method public static android.net.Uri renameDocument(android.content.ContentInterface, android.net.Uri, String) throws java.io.FileNotFoundException;
- method @Deprecated public static android.net.Uri renameDocument(android.content.ContentResolver, android.net.Uri, String) throws java.io.FileNotFoundException;
+ method @Nullable public static android.net.Uri moveDocument(@NonNull android.content.ContentResolver, @NonNull android.net.Uri, @NonNull android.net.Uri, @NonNull android.net.Uri) throws java.io.FileNotFoundException;
+ method public static boolean removeDocument(@NonNull android.content.ContentResolver, @NonNull android.net.Uri, @NonNull android.net.Uri) throws java.io.FileNotFoundException;
+ method @Nullable public static android.net.Uri renameDocument(@NonNull android.content.ContentResolver, @NonNull android.net.Uri, @NonNull String) throws java.io.FileNotFoundException;
field public static final String ACTION_DOCUMENT_SETTINGS = "android.provider.action.DOCUMENT_SETTINGS";
field public static final String EXTRA_ERROR = "error";
field public static final String EXTRA_EXCLUDE_SELF = "android.provider.extra.EXCLUDE_SELF";
@@ -38646,13 +38617,13 @@
public static final class MediaStore.Images.Media implements android.provider.MediaStore.Images.ImageColumns {
ctor public MediaStore.Images.Media();
- method public static android.graphics.Bitmap getBitmap(android.content.ContentResolver, android.net.Uri) throws java.io.FileNotFoundException, java.io.IOException;
+ method @Deprecated public static android.graphics.Bitmap getBitmap(android.content.ContentResolver, android.net.Uri) throws java.io.FileNotFoundException, java.io.IOException;
method public static android.net.Uri getContentUri(String);
- method public static String insertImage(android.content.ContentResolver, String, String, String) throws java.io.FileNotFoundException;
- method public static String insertImage(android.content.ContentResolver, android.graphics.Bitmap, String, String);
- method public static android.database.Cursor query(android.content.ContentResolver, android.net.Uri, String[]);
- method public static android.database.Cursor query(android.content.ContentResolver, android.net.Uri, String[], String, String);
- method public static android.database.Cursor query(android.content.ContentResolver, android.net.Uri, String[], String, String[], String);
+ method @Deprecated public static String insertImage(android.content.ContentResolver, String, String, String) throws java.io.FileNotFoundException;
+ method @Deprecated public static String insertImage(android.content.ContentResolver, android.graphics.Bitmap, String, String);
+ method @Deprecated public static android.database.Cursor query(android.content.ContentResolver, android.net.Uri, String[]);
+ method @Deprecated public static android.database.Cursor query(android.content.ContentResolver, android.net.Uri, String[], String, String);
+ method @Deprecated public static android.database.Cursor query(android.content.ContentResolver, android.net.Uri, String[], String, String[], String);
field public static final String CONTENT_TYPE = "vnd.android.cursor.dir/image";
field public static final String DEFAULT_SORT_ORDER = "bucket_display_name";
field public static final android.net.Uri EXTERNAL_CONTENT_URI;
@@ -38721,7 +38692,7 @@
public static final class MediaStore.Video {
ctor public MediaStore.Video();
- method public static android.database.Cursor query(android.content.ContentResolver, android.net.Uri, String[]);
+ method @Deprecated public static android.database.Cursor query(android.content.ContentResolver, android.net.Uri, String[]);
field public static final String DEFAULT_SORT_ORDER = "_display_name";
}
@@ -41604,13 +41575,13 @@
package android.service.notification {
public final class Adjustment implements android.os.Parcelable {
- ctor public Adjustment(String, String, android.os.Bundle, CharSequence, int);
+ ctor public Adjustment(String, String, android.os.Bundle, CharSequence, android.os.UserHandle);
method public int describeContents();
method public CharSequence getExplanation();
method public String getKey();
method public String getPackage();
method public android.os.Bundle getSignals();
- method public int getUser();
+ method public android.os.UserHandle getUserHandle();
method public void writeToParcel(android.os.Parcel, int);
field public static final android.os.Parcelable.Creator<android.service.notification.Adjustment> CREATOR;
field public static final String KEY_CONTEXTUAL_ACTIONS = "key_contextual_actions";
@@ -42173,7 +42144,7 @@
method protected void dump(String, java.io.FileDescriptor, java.io.PrintWriter, String[]);
method public int getDesiredMinimumHeight();
method public int getDesiredMinimumWidth();
- method public android.content.Context getDisplayContext();
+ method @Nullable public android.content.Context getDisplayContext();
method public android.view.SurfaceHolder getSurfaceHolder();
method public boolean isPreview();
method public boolean isVisible();
@@ -54060,6 +54031,10 @@
ctor public PropertyReader.PropertyTypeMismatchException(int, @NonNull String, @NonNull String);
}
+ public final class WindowInspector {
+ method @NonNull public static java.util.List<android.view.View> getGlobalWindowViews();
+ }
+
}
package android.view.textclassifier {
diff --git a/api/system-current.txt b/api/system-current.txt
index 6e3050f..5c89b05 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -304,11 +304,12 @@
}
public class AppOpsManager {
- method @RequiresPermission(android.Manifest.permission.GET_APP_OPS_STATS) public void getHistoricalOps(int, @Nullable String, @Nullable String[], long, long, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<android.app.AppOpsManager.HistoricalOps>);
+ method @RequiresPermission(android.Manifest.permission.GET_APP_OPS_STATS) public void getHistoricalOps(@NonNull android.app.AppOpsManager.HistoricalOpsRequest, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<android.app.AppOpsManager.HistoricalOps>);
method public static String[] getOpStrs();
method @Deprecated @RequiresPermission(android.Manifest.permission.GET_APP_OPS_STATS) public java.util.List<android.app.AppOpsManager.PackageOps> getOpsForPackage(int, String, int[]);
method @NonNull @RequiresPermission(android.Manifest.permission.GET_APP_OPS_STATS) public java.util.List<android.app.AppOpsManager.PackageOps> getOpsForPackage(int, @NonNull String, @Nullable java.lang.String...);
method @NonNull @RequiresPermission(android.Manifest.permission.GET_APP_OPS_STATS) public java.util.List<android.app.AppOpsManager.PackageOps> getPackagesForOps(@Nullable String[]);
+ method public int noteProxyOpNoThrow(@NonNull String, @Nullable String, int);
method public static int opToDefaultMode(@NonNull String);
method @Nullable public static String opToPermission(@NonNull String);
method @RequiresPermission("android.permission.MANAGE_APP_OPS_MODES") public void setMode(String, int, String, int);
@@ -393,6 +394,17 @@
field public static final android.os.Parcelable.Creator<android.app.AppOpsManager.HistoricalOps> CREATOR;
}
+ public static final class AppOpsManager.HistoricalOpsRequest {
+ }
+
+ public static final class AppOpsManager.HistoricalOpsRequest.Builder {
+ ctor public AppOpsManager.HistoricalOpsRequest.Builder(long, long);
+ method @NonNull public android.app.AppOpsManager.HistoricalOpsRequest build();
+ method @NonNull public android.app.AppOpsManager.HistoricalOpsRequest.Builder setOpNames(@Nullable java.util.List<java.lang.String>);
+ method @NonNull public android.app.AppOpsManager.HistoricalOpsRequest.Builder setPackageName(@Nullable String);
+ method @NonNull public android.app.AppOpsManager.HistoricalOpsRequest.Builder setUid(int);
+ }
+
public static final class AppOpsManager.HistoricalPackageOps implements android.os.Parcelable {
method public int describeContents();
method @Nullable public android.app.AppOpsManager.HistoricalOp getOp(@NonNull String);
@@ -442,6 +454,7 @@
public class BroadcastOptions {
method public static android.app.BroadcastOptions makeBasic();
+ method @RequiresPermission("android.permission.START_ACTIVITIES_FROM_BACKGROUND") public void setAllowBackgroundActivityStarts(boolean);
method public void setDontSendToRestrictedApps(boolean);
method @RequiresPermission(android.Manifest.permission.CHANGE_DEVICE_IDLE_TEMP_WHITELIST) public void setTemporaryAppWhitelistDuration(long);
method public android.os.Bundle toBundle();
@@ -1283,14 +1296,14 @@
package android.content {
- public class ContentProviderClient implements java.lang.AutoCloseable android.content.ContentInterface {
+ public class ContentProviderClient implements java.lang.AutoCloseable {
method @RequiresPermission(android.Manifest.permission.REMOVE_TASKS) public void setDetectNotResponding(long);
}
- public abstract class ContentResolver implements android.content.ContentInterface {
- method public android.os.Bundle getCache(android.net.Uri);
+ public abstract class ContentResolver {
+ method @Nullable public android.os.Bundle getCache(@NonNull android.net.Uri);
method public android.graphics.drawable.Drawable getTypeDrawable(String);
- method public void putCache(android.net.Uri, android.os.Bundle);
+ method public void putCache(@NonNull android.net.Uri, @Nullable android.os.Bundle);
}
public abstract class Context {
@@ -3484,6 +3497,18 @@
method public android.media.AudioRecord.Builder setSessionId(int) throws java.lang.IllegalArgumentException;
}
+ public class HwAudioSource {
+ method public void start();
+ method public void stop();
+ }
+
+ public static class HwAudioSource.Builder {
+ ctor public HwAudioSource.Builder();
+ method @NonNull public android.media.HwAudioSource build();
+ method @NonNull public android.media.HwAudioSource.Builder setAudioAttributes(@NonNull android.media.AudioAttributes);
+ method @NonNull public android.media.HwAudioSource.Builder setAudioDeviceInfo(@NonNull android.media.AudioDeviceInfo);
+ }
+
public final class MediaRecorder.AudioSource {
field @RequiresPermission(android.Manifest.permission.CAPTURE_AUDIO_OUTPUT) public static final int ECHO_REFERENCE = 1997; // 0x7cd
field @RequiresPermission(android.Manifest.permission.CAPTURE_AUDIO_HOTWORD) public static final int HOTWORD = 1999; // 0x7cf
@@ -3604,6 +3629,28 @@
method public android.media.audiopolicy.AudioPolicy.Builder setLooper(@NonNull android.os.Looper) throws java.lang.IllegalArgumentException;
}
+ public final class AudioProductStrategies implements java.lang.Iterable<android.media.audiopolicy.AudioProductStrategy> android.os.Parcelable {
+ ctor public AudioProductStrategies();
+ method public int describeContents();
+ method @NonNull public android.media.AudioAttributes getAudioAttributesForLegacyStreamType(int);
+ method @NonNull public android.media.AudioAttributes getAudioAttributesForProductStrategy(@NonNull android.media.audiopolicy.AudioProductStrategy);
+ method @Nullable public android.media.audiopolicy.AudioProductStrategy getById(int);
+ method public int getLegacyStreamTypeForAudioAttributes(@NonNull android.media.AudioAttributes);
+ method public java.util.Iterator<android.media.audiopolicy.AudioProductStrategy> iterator();
+ method public int size();
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator<android.media.audiopolicy.AudioProductStrategies> CREATOR;
+ }
+
+ public final class AudioProductStrategy implements android.os.Parcelable {
+ method public int describeContents();
+ method @NonNull public android.media.AudioAttributes getAudioAttributes();
+ method public int getId();
+ method @NonNull public String name();
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator<android.media.audiopolicy.AudioProductStrategy> CREATOR;
+ }
+
}
package android.media.session {
@@ -4630,7 +4677,7 @@
method @RequiresPermission(allOf={android.Manifest.permission.ACCESS_FINE_LOCATION, android.Manifest.permission.ACCESS_WIFI_STATE, android.Manifest.permission.READ_WIFI_CREDENTIAL}) public java.util.List<android.net.wifi.WifiConfiguration> getPrivilegedConfiguredNetworks();
method @RequiresPermission(android.Manifest.permission.ACCESS_WIFI_STATE) public android.net.wifi.WifiConfiguration getWifiApConfiguration();
method @RequiresPermission(android.Manifest.permission.ACCESS_WIFI_STATE) public int getWifiApState();
- method public boolean isDeviceToDeviceRttSupported();
+ method @Deprecated public boolean isDeviceToDeviceRttSupported();
method public boolean isPortableHotspotSupported();
method @RequiresPermission(android.Manifest.permission.ACCESS_WIFI_STATE) public boolean isWifiApEnabled();
method public boolean isWifiScannerSupported();
@@ -5327,6 +5374,7 @@
public final class PowerManager {
method @RequiresPermission(allOf={android.Manifest.permission.READ_DREAM_STATE, android.Manifest.permission.WRITE_DREAM_STATE}) public void dream(long);
+ method @RequiresPermission(android.Manifest.permission.DEVICE_POWER) public boolean forceSuspend();
method @RequiresPermission(android.Manifest.permission.POWER_SAVER) public int getPowerSaveMode();
method @RequiresPermission(anyOf={android.Manifest.permission.DEVICE_POWER, android.Manifest.permission.POWER_SAVER}) public boolean setAdaptivePowerSaveEnabled(boolean);
method @RequiresPermission(anyOf={android.Manifest.permission.DEVICE_POWER, android.Manifest.permission.POWER_SAVER}) public boolean setAdaptivePowerSavePolicy(@NonNull android.os.BatterySaverPolicyConfig);
@@ -6275,6 +6323,8 @@
ctor public AugmentedAutofillService();
method protected final void dump(java.io.FileDescriptor, java.io.PrintWriter, String[]);
method protected void dump(@NonNull java.io.PrintWriter, @NonNull String[]);
+ method public void onConnected();
+ method public void onDisconnected();
method public void onFillRequest(@NonNull android.service.autofill.augmented.FillRequest, @NonNull android.os.CancellationSignal, @NonNull android.service.autofill.augmented.FillController, @NonNull android.service.autofill.augmented.FillCallback);
field public static final String SERVICE_INTERFACE = "android.service.autofill.augmented.AugmentedAutofillService";
}
@@ -6342,6 +6392,7 @@
public abstract class ContentCaptureService extends android.app.Service {
ctor public ContentCaptureService();
+ method public final void disableContentCaptureServices();
method public void onActivitySnapshot(@NonNull android.view.contentcapture.ContentCaptureSessionId, @NonNull android.service.contentcapture.SnapshotData);
method public void onConnected();
method public void onContentCaptureEvent(@NonNull android.view.contentcapture.ContentCaptureSessionId, @NonNull android.view.contentcapture.ContentCaptureEvent);
@@ -6523,7 +6574,9 @@
package android.service.notification {
public final class Adjustment implements android.os.Parcelable {
+ ctor public Adjustment(String, String, android.os.Bundle, CharSequence, int);
ctor protected Adjustment(android.os.Parcel);
+ method public int getUser();
field public static final String KEY_PEOPLE = "key_people";
}
@@ -9356,7 +9409,6 @@
public final class ContentCaptureManager {
method public boolean isContentCaptureFeatureEnabled();
- method public void setContentCaptureFeatureEnabled(boolean);
}
public final class ViewNode extends android.app.assist.AssistStructure.ViewNode {
diff --git a/api/test-current.txt b/api/test-current.txt
index 6cf6cd85..963584c 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -101,8 +101,8 @@
public class AppOpsManager {
method @RequiresPermission("android.permission.MANAGE_APPOPS") public void addHistoricalOps(@NonNull android.app.AppOpsManager.HistoricalOps);
method @RequiresPermission("android.permission.MANAGE_APPOPS") public void clearHistory();
- method @RequiresPermission("android.permission.GET_APP_OPS_STATS") public void getHistoricalOps(int, @Nullable String, @Nullable String[], long, long, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<android.app.AppOpsManager.HistoricalOps>);
- method @RequiresPermission("android.permission.GET_APP_OPS_STATS") public void getHistoricalOpsFromDiskRaw(int, @Nullable String, @Nullable String[], long, long, @Nullable java.util.concurrent.Executor, @NonNull java.util.function.Consumer<android.app.AppOpsManager.HistoricalOps>);
+ method @RequiresPermission("android.permission.GET_APP_OPS_STATS") public void getHistoricalOps(@NonNull android.app.AppOpsManager.HistoricalOpsRequest, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<android.app.AppOpsManager.HistoricalOps>);
+ method @RequiresPermission("android.permission.GET_APP_OPS_STATS") public void getHistoricalOpsFromDiskRaw(@NonNull android.app.AppOpsManager.HistoricalOpsRequest, @Nullable java.util.concurrent.Executor, @NonNull java.util.function.Consumer<android.app.AppOpsManager.HistoricalOps>);
method public static int getNumOps();
method public static String[] getOpStrs();
method public boolean isOperationActive(int, int, String);
@@ -206,6 +206,17 @@
field public static final android.os.Parcelable.Creator<android.app.AppOpsManager.HistoricalOps> CREATOR;
}
+ public static final class AppOpsManager.HistoricalOpsRequest {
+ }
+
+ public static final class AppOpsManager.HistoricalOpsRequest.Builder {
+ ctor public AppOpsManager.HistoricalOpsRequest.Builder(long, long);
+ method @NonNull public android.app.AppOpsManager.HistoricalOpsRequest build();
+ method @NonNull public android.app.AppOpsManager.HistoricalOpsRequest.Builder setOpNames(@Nullable java.util.List<java.lang.String>);
+ method @NonNull public android.app.AppOpsManager.HistoricalOpsRequest.Builder setPackageName(@Nullable String);
+ method @NonNull public android.app.AppOpsManager.HistoricalOpsRequest.Builder setUid(int);
+ }
+
public static final class AppOpsManager.HistoricalPackageOps implements android.os.Parcelable {
method public int describeContents();
method @Nullable public android.app.AppOpsManager.HistoricalOp getOp(@NonNull String);
@@ -472,11 +483,11 @@
package android.content {
- public class ContentProviderClient implements java.lang.AutoCloseable android.content.ContentInterface {
+ public class ContentProviderClient implements java.lang.AutoCloseable {
method @RequiresPermission(android.Manifest.permission.REMOVE_TASKS) public void setDetectNotResponding(long);
}
- public abstract class ContentResolver implements android.content.ContentInterface {
+ public abstract class ContentResolver {
method public static String[] getSyncAdapterPackagesForAuthorityAsUser(String, int);
}
@@ -1290,7 +1301,7 @@
method public static java.io.File getStorageDirectory();
}
- public class FileUtils {
+ public final class FileUtils {
method public static boolean contains(java.io.File, java.io.File);
}
@@ -2046,6 +2057,8 @@
ctor public AugmentedAutofillService();
method protected final void dump(java.io.FileDescriptor, java.io.PrintWriter, String[]);
method protected void dump(@NonNull java.io.PrintWriter, @NonNull String[]);
+ method public void onConnected();
+ method public void onDisconnected();
method public void onFillRequest(@NonNull android.service.autofill.augmented.FillRequest, @NonNull android.os.CancellationSignal, @NonNull android.service.autofill.augmented.FillController, @NonNull android.service.autofill.augmented.FillCallback);
field public static final String SERVICE_INTERFACE = "android.service.autofill.augmented.AugmentedAutofillService";
}
@@ -2103,6 +2116,7 @@
public abstract class ContentCaptureService extends android.app.Service {
ctor public ContentCaptureService();
+ method public final void disableContentCaptureServices();
method public void onActivitySnapshot(@NonNull android.view.contentcapture.ContentCaptureSessionId, @NonNull android.service.contentcapture.SnapshotData);
method public void onConnected();
method public void onContentCaptureEvent(@NonNull android.view.contentcapture.ContentCaptureSessionId, @NonNull android.view.contentcapture.ContentCaptureEvent);
@@ -2744,7 +2758,6 @@
public final class ContentCaptureManager {
method public boolean isContentCaptureFeatureEnabled();
- method public void setContentCaptureFeatureEnabled(boolean);
field public static final String DEVICE_CONFIG_PROPERTY_IDLE_FLUSH_FREQUENCY = "idle_flush_frequency";
field public static final String DEVICE_CONFIG_PROPERTY_LOGGING_LEVEL = "logging_level";
field public static final String DEVICE_CONFIG_PROPERTY_LOG_HISTORY_SIZE = "log_history_size";
diff --git a/cmds/idmap2/idmap2d/aidl/android/os/IIdmap2.aidl b/cmds/idmap2/idmap2d/aidl/android/os/IIdmap2.aidl
index ea7274f..4a66715 100644
--- a/cmds/idmap2/idmap2d/aidl/android/os/IIdmap2.aidl
+++ b/cmds/idmap2/idmap2d/aidl/android/os/IIdmap2.aidl
@@ -24,6 +24,7 @@
const int POLICY_SYSTEM_PARTITION = 0x00000002;
const int POLICY_VENDOR_PARTITION = 0x00000004;
const int POLICY_PRODUCT_PARTITION = 0x00000008;
+ const int POLICY_SIGNATURE = 0x00000010;
@utf8InCpp String getIdmapPath(@utf8InCpp String overlayApkPath, int userId);
boolean removeIdmap(@utf8InCpp String overlayApkPath, int userId);
diff --git a/cmds/idmap2/libidmap2/Idmap.cpp b/cmds/idmap2/libidmap2/Idmap.cpp
index 99b5f0f..ec498ff 100644
--- a/cmds/idmap2/libidmap2/Idmap.cpp
+++ b/cmds/idmap2/libidmap2/Idmap.cpp
@@ -284,7 +284,7 @@
bool CheckOverlayable(const LoadedPackage& target_package,
const utils::OverlayManifestInfo& overlay_info,
- const PolicyBitmask& fulfilled_polices, const ResourceId& resid) {
+ const PolicyBitmask& fulfilled_policies, const ResourceId& resid) {
const OverlayableInfo* overlayable_info = target_package.GetOverlayableInfo(resid);
if (overlayable_info == nullptr) {
// If the resource does not have an overlayable definition, allow the resource to be overlaid.
@@ -299,7 +299,7 @@
}
// Enforce policy restrictions if the resource is declared as overlayable.
- return (overlayable_info->policy_flags & fulfilled_polices) != 0;
+ return (overlayable_info->policy_flags & fulfilled_policies) != 0;
}
std::unique_ptr<const Idmap> Idmap::FromApkAssets(
diff --git a/cmds/idmap2/libidmap2/Policies.cpp b/cmds/idmap2/libidmap2/Policies.cpp
index 0f87ef0..6649288 100644
--- a/cmds/idmap2/libidmap2/Policies.cpp
+++ b/cmds/idmap2/libidmap2/Policies.cpp
@@ -35,6 +35,7 @@
{"product", PolicyFlags::POLICY_PRODUCT_PARTITION},
{"system", PolicyFlags::POLICY_SYSTEM_PARTITION},
{"vendor", PolicyFlags::POLICY_VENDOR_PARTITION},
+ {"signature", PolicyFlags::POLICY_SIGNATURE},
};
} // namespace
diff --git a/cmds/idmap2/tests/BinaryStreamVisitorTests.cpp b/cmds/idmap2/tests/BinaryStreamVisitorTests.cpp
index 0e0e25f..9a0412e 100644
--- a/cmds/idmap2/tests/BinaryStreamVisitorTests.cpp
+++ b/cmds/idmap2/tests/BinaryStreamVisitorTests.cpp
@@ -129,28 +129,31 @@
success = LoadedIdmap::Lookup(header, 0x0008, &entry); // string/policy_system_vendor
ASSERT_FALSE(success);
- success = LoadedIdmap::Lookup(header, 0x0009, &entry); // string/str1
+ success = LoadedIdmap::Lookup(header, 0x0009, &entry); // string/policy_signature
+ ASSERT_FALSE(success);
+
+ success = LoadedIdmap::Lookup(header, 0x000a, &entry); // string/str1
ASSERT_TRUE(success);
ASSERT_EQ(entry, 0x0000);
- success = LoadedIdmap::Lookup(header, 0x000a, &entry); // string/str2
+ success = LoadedIdmap::Lookup(header, 0x000b, &entry); // string/str2
ASSERT_FALSE(success);
- success = LoadedIdmap::Lookup(header, 0x000b, &entry); // string/str3
+ success = LoadedIdmap::Lookup(header, 0x000c, &entry); // string/str3
ASSERT_TRUE(success);
ASSERT_EQ(entry, 0x0001);
- success = LoadedIdmap::Lookup(header, 0x000c, &entry); // string/str4
+ success = LoadedIdmap::Lookup(header, 0x000d, &entry); // string/str4
ASSERT_TRUE(success);
ASSERT_EQ(entry, 0x0002);
- success = LoadedIdmap::Lookup(header, 0x000d, &entry); // string/x
+ success = LoadedIdmap::Lookup(header, 0x000e, &entry); // string/x
ASSERT_FALSE(success);
- success = LoadedIdmap::Lookup(header, 0x000e, &entry); // string/y
+ success = LoadedIdmap::Lookup(header, 0x000f, &entry); // string/y
ASSERT_FALSE(success);
- success = LoadedIdmap::Lookup(header, 0x000f, &entry); // string/z
+ success = LoadedIdmap::Lookup(header, 0x0010, &entry); // string/z
ASSERT_FALSE(success);
}
diff --git a/cmds/idmap2/tests/FileUtilsTests.cpp b/cmds/idmap2/tests/FileUtilsTests.cpp
index 8514e12..2e85eb6 100644
--- a/cmds/idmap2/tests/FileUtilsTests.cpp
+++ b/cmds/idmap2/tests/FileUtilsTests.cpp
@@ -39,12 +39,13 @@
[](unsigned char type ATTRIBUTE_UNUSED,
const std::string& path ATTRIBUTE_UNUSED) -> bool { return true; });
ASSERT_THAT(v, NotNull());
- ASSERT_EQ(v->size(), 6U);
+ ASSERT_EQ(v->size(), 7U);
ASSERT_EQ(std::set<std::string>(v->begin(), v->end()), std::set<std::string>({
root + "/.",
root + "/..",
root + "/overlay",
root + "/target",
+ root + "/signature-overlay",
root + "/system-overlay",
root + "/system-overlay-invalid",
}));
@@ -56,15 +57,22 @@
return type == DT_REG && path.size() > 4 && path.compare(path.size() - 4, 4, ".apk") == 0;
});
ASSERT_THAT(v, NotNull());
- ASSERT_EQ(v->size(), 9U);
+ ASSERT_EQ(v->size(), 10U);
ASSERT_EQ(
std::set<std::string>(v->begin(), v->end()),
std::set<std::string>(
- {root + "/target/target.apk", root + "/target/target-no-overlayable.apk",
- root + "/overlay/overlay.apk", root + "/overlay/overlay-no-name.apk",
- root + "/overlay/overlay-no-name-static.apk", root + "/overlay/overlay-static-1.apk",
- root + "/overlay/overlay-static-2.apk", root + "/system-overlay/system-overlay.apk",
- root + "/system-overlay-invalid/system-overlay-invalid.apk"}));
+ {
+ root + "/target/target.apk",
+ root + "/target/target-no-overlayable.apk",
+ root + "/overlay/overlay.apk",
+ root + "/overlay/overlay-no-name.apk",
+ root + "/overlay/overlay-no-name-static.apk",
+ root + "/overlay/overlay-static-1.apk",
+ root + "/overlay/overlay-static-2.apk",
+ root + "/signature-overlay/signature-overlay.apk",
+ root + "/system-overlay/system-overlay.apk",
+ root + "/system-overlay-invalid/system-overlay-invalid.apk"
+ }));
}
TEST(FileUtilsTests, ReadFile) {
diff --git a/cmds/idmap2/tests/Idmap2BinaryTests.cpp b/cmds/idmap2/tests/Idmap2BinaryTests.cpp
index 1216f9ec..a6a2ada 100644
--- a/cmds/idmap2/tests/Idmap2BinaryTests.cpp
+++ b/cmds/idmap2/tests/Idmap2BinaryTests.cpp
@@ -132,9 +132,9 @@
ASSERT_THAT(result, NotNull());
ASSERT_EQ(result->status, EXIT_SUCCESS) << result->stderr;
ASSERT_NE(result->stdout.find("0x7f010000 -> 0x7f010000 integer/int1"), std::string::npos);
- ASSERT_NE(result->stdout.find("0x7f020009 -> 0x7f020000 string/str1"), std::string::npos);
- ASSERT_NE(result->stdout.find("0x7f02000b -> 0x7f020001 string/str3"), std::string::npos);
- ASSERT_NE(result->stdout.find("0x7f02000c -> 0x7f020002 string/str4"), std::string::npos);
+ ASSERT_NE(result->stdout.find("0x7f02000a -> 0x7f020000 string/str1"), std::string::npos);
+ ASSERT_NE(result->stdout.find("0x7f02000c -> 0x7f020001 string/str3"), std::string::npos);
+ ASSERT_NE(result->stdout.find("0x7f02000d -> 0x7f020002 string/str4"), std::string::npos);
ASSERT_EQ(result->stdout.find("00000210: 007f target package id"), std::string::npos);
// clang-format off
@@ -286,7 +286,7 @@
"lookup",
"--idmap-path", GetIdmapPath(),
"--config", "",
- "--resid", "0x7f020009"}); // string/str1
+ "--resid", "0x7f02000a"}); // string/str1
// clang-format on
ASSERT_THAT(result, NotNull());
ASSERT_EQ(result->status, EXIT_SUCCESS) << result->stderr;
diff --git a/cmds/idmap2/tests/IdmapTests.cpp b/cmds/idmap2/tests/IdmapTests.cpp
index b40521f..53ec03b 100644
--- a/cmds/idmap2/tests/IdmapTests.cpp
+++ b/cmds/idmap2/tests/IdmapTests.cpp
@@ -191,8 +191,8 @@
ASSERT_THAT(idmap->GetHeader(), NotNull());
ASSERT_EQ(idmap->GetHeader()->GetMagic(), 0x504d4449U);
ASSERT_EQ(idmap->GetHeader()->GetVersion(), 0x01U);
- ASSERT_EQ(idmap->GetHeader()->GetTargetCrc(), 0xdd53ca29);
- ASSERT_EQ(idmap->GetHeader()->GetOverlayCrc(), 0xa71ccd77);
+ ASSERT_EQ(idmap->GetHeader()->GetTargetCrc(), 0xd513ca1b);
+ ASSERT_EQ(idmap->GetHeader()->GetOverlayCrc(), 0x8635c2ed);
ASSERT_EQ(idmap->GetHeader()->GetTargetPath().to_string(), target_apk_path);
ASSERT_EQ(idmap->GetHeader()->GetOverlayPath(), overlay_apk_path);
ASSERT_EQ(idmap->GetHeader()->GetOverlayPath(), overlay_apk_path);
@@ -217,7 +217,7 @@
ASSERT_EQ(types[1]->GetTargetTypeId(), 0x02U);
ASSERT_EQ(types[1]->GetOverlayTypeId(), 0x02U);
ASSERT_EQ(types[1]->GetEntryCount(), 4U);
- ASSERT_EQ(types[1]->GetEntryOffset(), 9U);
+ ASSERT_EQ(types[1]->GetEntryOffset(), 10U);
ASSERT_EQ(types[1]->GetEntry(0), 0x0000U);
ASSERT_EQ(types[1]->GetEntry(1), kNoEntry);
ASSERT_EQ(types[1]->GetEntry(2), 0x0001U);
@@ -254,11 +254,76 @@
ASSERT_EQ(types[0]->GetTargetTypeId(), 0x02U);
ASSERT_EQ(types[0]->GetOverlayTypeId(), 0x01U);
- ASSERT_EQ(types[0]->GetEntryCount(), 3U);
+ ASSERT_EQ(types[0]->GetEntryCount(), 4U);
ASSERT_EQ(types[0]->GetEntryOffset(), 6U);
ASSERT_EQ(types[0]->GetEntry(0), 0x0000U); // string/policy_public
- ASSERT_EQ(types[0]->GetEntry(1), 0x0001U); // string/policy_system
- ASSERT_EQ(types[0]->GetEntry(2), 0x0002U); // string/policy_system_vendor
+ ASSERT_EQ(types[0]->GetEntry(1), kNoEntry); // string/policy_signature
+ ASSERT_EQ(types[0]->GetEntry(2), 0x0001U); // string/policy_system
+ ASSERT_EQ(types[0]->GetEntry(3), 0x0002U); // string/policy_system_vendor
+}
+
+TEST(IdmapOverlayableTests, CreateIdmapFromApkAssetsPolicySignature) {
+ const std::string target_apk_path(GetTestDataPath() + "/target/target.apk");
+ std::unique_ptr<const ApkAssets> target_apk = ApkAssets::Load(target_apk_path);
+ ASSERT_THAT(target_apk, NotNull());
+
+ const std::string overlay_apk_path(GetTestDataPath() + "/signature-overlay/signature-overlay.apk");
+ std::unique_ptr<const ApkAssets> overlay_apk = ApkAssets::Load(overlay_apk_path);
+ ASSERT_THAT(overlay_apk, NotNull());
+
+ uint32_t policy_flags = PolicyFlags::POLICY_PUBLIC | PolicyFlags::POLICY_SIGNATURE;
+
+ std::stringstream error;
+ std::unique_ptr<const Idmap> idmap =
+ Idmap::FromApkAssets(target_apk_path, *target_apk, overlay_apk_path, *overlay_apk,
+ policy_flags, /* enforce_overlayable */ true, error);
+ ASSERT_THAT(idmap, NotNull());
+
+ const std::vector<std::unique_ptr<const IdmapData>>& dataBlocks = idmap->GetData();
+ ASSERT_EQ(dataBlocks.size(), 1U);
+
+ const std::unique_ptr<const IdmapData>& data = dataBlocks[0];
+
+ ASSERT_EQ(data->GetHeader()->GetTargetPackageId(), 0x7fU);
+ ASSERT_EQ(data->GetHeader()->GetTypeCount(), 1U);
+
+ const std::vector<std::unique_ptr<const IdmapData::TypeEntry>>& types = data->GetTypeEntries();
+ ASSERT_EQ(types.size(), 1U);
+
+ ASSERT_EQ(types[0]->GetTargetTypeId(), 0x02U);
+ ASSERT_EQ(types[0]->GetOverlayTypeId(), 0x01U);
+ ASSERT_EQ(types[0]->GetEntryCount(), 1U);
+ ASSERT_EQ(types[0]->GetEntryOffset(), 7U);
+ ASSERT_EQ(types[0]->GetEntry(0), 0x0000U); // string/policy_signature
+}
+
+TEST(IdmapOverlayableTests, CreateIdmapFromApkAssetsPolicySignatureNotFulfilled) {
+ const std::string target_apk_path(GetTestDataPath() + "/target/target.apk");
+ std::unique_ptr<const ApkAssets> target_apk = ApkAssets::Load(target_apk_path);
+ ASSERT_THAT(target_apk, NotNull());
+
+ const std::string overlay_apk_path(GetTestDataPath() + "/signature-overlay/signature-overlay.apk");
+ std::unique_ptr<const ApkAssets> overlay_apk = ApkAssets::Load(overlay_apk_path);
+ ASSERT_THAT(overlay_apk, NotNull());
+
+ uint32_t policy_flags = PolicyFlags::POLICY_PUBLIC;
+
+ std::stringstream error;
+ std::unique_ptr<const Idmap> idmap =
+ Idmap::FromApkAssets(target_apk_path, *target_apk, overlay_apk_path, *overlay_apk,
+ policy_flags, /* enforce_overlayable */ true, error);
+ ASSERT_THAT(idmap, NotNull());
+
+ const std::vector<std::unique_ptr<const IdmapData>>& dataBlocks = idmap->GetData();
+ ASSERT_EQ(dataBlocks.size(), 1U);
+
+ const std::unique_ptr<const IdmapData>& data = dataBlocks[0];
+
+ ASSERT_EQ(data->GetHeader()->GetTargetPackageId(), 0x7fU);
+ ASSERT_EQ(data->GetHeader()->GetTypeCount(), 0U);
+
+ const std::vector<std::unique_ptr<const IdmapData::TypeEntry>>& types = data->GetTypeEntries();
+ ASSERT_EQ(types.size(), 0U); // can't overlay, so contains nothing
}
// Overlays should abide by all overlayable restrictions if enforcement of overlayable is enabled.
@@ -292,11 +357,12 @@
ASSERT_EQ(types[0]->GetTargetTypeId(), 0x02U);
ASSERT_EQ(types[0]->GetOverlayTypeId(), 0x01U);
- ASSERT_EQ(types[0]->GetEntryCount(), 3U);
+ ASSERT_EQ(types[0]->GetEntryCount(), 4U);
ASSERT_EQ(types[0]->GetEntryOffset(), 6U);
ASSERT_EQ(types[0]->GetEntry(0), 0x0003U); // string/policy_public
- ASSERT_EQ(types[0]->GetEntry(1), 0x0004U); // string/policy_system
- ASSERT_EQ(types[0]->GetEntry(2), 0x0005U); // string/policy_system_vendor
+ ASSERT_EQ(types[0]->GetEntry(1), kNoEntry); // string/policy_signature
+ ASSERT_EQ(types[0]->GetEntry(2), 0x0005U); // string/policy_system
+ ASSERT_EQ(types[0]->GetEntry(3), 0x0006U); // string/policy_system_vendor
}
// Overlays should ignore all overlayable restrictions if enforcement of overlayable is disabled.
@@ -330,14 +396,15 @@
ASSERT_EQ(types[0]->GetTargetTypeId(), 0x02U);
ASSERT_EQ(types[0]->GetOverlayTypeId(), 0x01U);
- ASSERT_EQ(types[0]->GetEntryCount(), 6U);
+ ASSERT_EQ(types[0]->GetEntryCount(), 7U);
ASSERT_EQ(types[0]->GetEntryOffset(), 3U);
ASSERT_EQ(types[0]->GetEntry(0), 0x0000U); // string/not_overlayable
ASSERT_EQ(types[0]->GetEntry(1), 0x0001U); // string/other
ASSERT_EQ(types[0]->GetEntry(2), 0x0002U); // string/policy_product
- ASSERT_EQ(types[0]->GetEntry(3), 0x0003U); // string/policy_public
- ASSERT_EQ(types[0]->GetEntry(4), 0x0004U); // string/policy_system
- ASSERT_EQ(types[0]->GetEntry(5), 0x0005U); // string/policy_system_vendor
+ ASSERT_EQ(types[0]->GetEntry(3), 0x0003U); // string/policy_signature
+ ASSERT_EQ(types[0]->GetEntry(4), 0x0004U); // string/policy_public
+ ASSERT_EQ(types[0]->GetEntry(5), 0x0005U); // string/policy_system
+ ASSERT_EQ(types[0]->GetEntry(6), 0x0006U); // string/policy_system_vendor
}
// The resources of APKs that do not include an overlayable declaration should not restrict what
@@ -371,14 +438,15 @@
ASSERT_EQ(types[0]->GetTargetTypeId(), 0x02U);
ASSERT_EQ(types[0]->GetOverlayTypeId(), 0x01U);
- ASSERT_EQ(types[0]->GetEntryCount(), 6U);
+ ASSERT_EQ(types[0]->GetEntryCount(), 7U);
ASSERT_EQ(types[0]->GetEntryOffset(), 3U);
ASSERT_EQ(types[0]->GetEntry(0), 0x0000U); // string/not_overlayable
ASSERT_EQ(types[0]->GetEntry(1), 0x0001U); // string/other
ASSERT_EQ(types[0]->GetEntry(2), 0x0002U); // string/policy_product
ASSERT_EQ(types[0]->GetEntry(3), 0x0003U); // string/policy_public
- ASSERT_EQ(types[0]->GetEntry(4), 0x0004U); // string/policy_system
- ASSERT_EQ(types[0]->GetEntry(5), 0x0005U); // string/policy_system_vendor
+ ASSERT_EQ(types[0]->GetEntry(4), 0x0004U); // string/string/policy_signature
+ ASSERT_EQ(types[0]->GetEntry(5), 0x0005U); // string/policy_system
+ ASSERT_EQ(types[0]->GetEntry(6), 0x0006U); // string/policy_system_vendor
}
// The resources of APKs that do not include an overlayable declaration should not restrict what
@@ -418,7 +486,7 @@
ASSERT_EQ(types[1]->GetTargetTypeId(), 0x02U);
ASSERT_EQ(types[1]->GetOverlayTypeId(), 0x02U);
ASSERT_EQ(types[1]->GetEntryCount(), 4U);
- ASSERT_EQ(types[1]->GetEntryOffset(), 9U);
+ ASSERT_EQ(types[1]->GetEntryOffset(), 10U);
ASSERT_EQ(types[1]->GetEntry(0), 0x0000U);
ASSERT_EQ(types[1]->GetEntry(1), kNoEntry);
ASSERT_EQ(types[1]->GetEntry(2), 0x0001U);
diff --git a/cmds/idmap2/tests/RawPrintVisitorTests.cpp b/cmds/idmap2/tests/RawPrintVisitorTests.cpp
index a5588c3..7ec13ed 100644
--- a/cmds/idmap2/tests/RawPrintVisitorTests.cpp
+++ b/cmds/idmap2/tests/RawPrintVisitorTests.cpp
@@ -52,8 +52,8 @@
ASSERT_NE(stream.str().find("00000000: 504d4449 magic\n"), std::string::npos);
ASSERT_NE(stream.str().find("00000004: 00000001 version\n"), std::string::npos);
- ASSERT_NE(stream.str().find("00000008: dd53ca29 target crc\n"), std::string::npos);
- ASSERT_NE(stream.str().find("0000000c: a71ccd77 overlay crc\n"), std::string::npos);
+ ASSERT_NE(stream.str().find("00000008: d513ca1b target crc\n"), std::string::npos);
+ ASSERT_NE(stream.str().find("0000000c: 8635c2ed overlay crc\n"), std::string::npos);
ASSERT_NE(stream.str().find("0000021c: 00000000 0x7f010000 -> 0x7f010000 integer/int1\n"),
std::string::npos);
}
diff --git a/cmds/idmap2/tests/data/overlay/build b/cmds/idmap2/tests/data/overlay/build
old mode 100644
new mode 100755
index e60da80..e879f44
--- a/cmds/idmap2/tests/data/overlay/build
+++ b/cmds/idmap2/tests/data/overlay/build
@@ -12,7 +12,7 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-FRAMEWORK_RES_APK="$(gettop)/out/target/common/obj/APPS/framework-res_intermediates/package-export.apk"
+FRAMEWORK_RES_APK="${ANDROID_BUILD_TOP}/out/target/common/obj/APPS/framework-res_intermediates/package-export.apk"
aapt2 compile --dir res -o compiled.flata
diff --git a/cmds/idmap2/tests/data/signature-overlay/AndroidManifest.xml b/cmds/idmap2/tests/data/signature-overlay/AndroidManifest.xml
new file mode 100644
index 0000000..5dacebd
--- /dev/null
+++ b/cmds/idmap2/tests/data/signature-overlay/AndroidManifest.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+<manifest
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ package="test.overlay.system">
+ <overlay
+ android:targetPackage="test.target"
+ android:targetName="TestResources"/>
+</manifest>
diff --git a/tools/aapt2/integration-tests/AutoVersionTest/Android.mk b/cmds/idmap2/tests/data/signature-overlay/build
old mode 100644
new mode 100755
similarity index 60%
rename from tools/aapt2/integration-tests/AutoVersionTest/Android.mk
rename to cmds/idmap2/tests/data/signature-overlay/build
index 03cce35..fdd8301
--- a/tools/aapt2/integration-tests/AutoVersionTest/Android.mk
+++ b/cmds/idmap2/tests/data/signature-overlay/build
@@ -1,5 +1,4 @@
-#
-# Copyright (C) 2017 The Android Open Source Project
+# 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.
@@ -12,13 +11,16 @@
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
-#
-LOCAL_PATH := $(call my-dir)
+FRAMEWORK_RES_APK=${ANDROID_BUILD_TOP}/prebuilts/sdk/current/public/android.jar
-include $(CLEAR_VARS)
-LOCAL_USE_AAPT2 := true
-LOCAL_PACKAGE_NAME := AaptAutoVersionTest
-LOCAL_SDK_VERSION := current
-LOCAL_MODULE_TAGS := tests
-include $(BUILD_PACKAGE)
+aapt2 compile --dir res -o compiled.flata
+
+aapt2 link \
+ --no-resource-removal \
+ -I "$FRAMEWORK_RES_APK" \
+ --manifest AndroidManifest.xml \
+ -o signature-overlay.apk \
+ compiled.flata
+
+rm compiled.flata
diff --git a/cmds/idmap2/tests/data/signature-overlay/res/values/values.xml b/cmds/idmap2/tests/data/signature-overlay/res/values/values.xml
new file mode 100644
index 0000000..59e7d8e
--- /dev/null
+++ b/cmds/idmap2/tests/data/signature-overlay/res/values/values.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+<resources>
+ <!-- This overlay will fulfill the policy "signature". This allows it overlay the
+ following resources. -->
+ <string name="policy_signature">policy_signature</string>
+</resources>
diff --git a/cmds/idmap2/tests/data/signature-overlay/signature-overlay.apk b/cmds/idmap2/tests/data/signature-overlay/signature-overlay.apk
new file mode 100644
index 0000000..b2c490d
--- /dev/null
+++ b/cmds/idmap2/tests/data/signature-overlay/signature-overlay.apk
Binary files differ
diff --git a/cmds/idmap2/tests/data/system-overlay-invalid/build b/cmds/idmap2/tests/data/system-overlay-invalid/build
old mode 100644
new mode 100755
diff --git a/cmds/idmap2/tests/data/system-overlay-invalid/res/values/values.xml b/cmds/idmap2/tests/data/system-overlay-invalid/res/values/values.xml
index af1bea1..0270400 100644
--- a/cmds/idmap2/tests/data/system-overlay-invalid/res/values/values.xml
+++ b/cmds/idmap2/tests/data/system-overlay-invalid/res/values/values.xml
@@ -22,6 +22,7 @@
<!-- Requests to overlay a resource that belongs to a policy the overlay does not fulfill. -->
<string name="policy_product">policy_product</string>
+ <string name="policy_signature">policy_signature</string>
<!-- Requests to overlay a resource that is not declared as overlayable. -->
<string name="not_overlayable">not_overlayable</string>
diff --git a/cmds/idmap2/tests/data/system-overlay-invalid/system-overlay-invalid.apk b/cmds/idmap2/tests/data/system-overlay-invalid/system-overlay-invalid.apk
index 710ed90..9448939 100644
--- a/cmds/idmap2/tests/data/system-overlay-invalid/system-overlay-invalid.apk
+++ b/cmds/idmap2/tests/data/system-overlay-invalid/system-overlay-invalid.apk
Binary files differ
diff --git a/cmds/idmap2/tests/data/system-overlay/build b/cmds/idmap2/tests/data/system-overlay/build
old mode 100644
new mode 100755
diff --git a/cmds/idmap2/tests/data/target/build b/cmds/idmap2/tests/data/target/build
old mode 100644
new mode 100755
index 137ddb5..e6df742
--- a/cmds/idmap2/tests/data/target/build
+++ b/cmds/idmap2/tests/data/target/build
@@ -17,5 +17,5 @@
rm compiled.flata
aapt2 compile res/values/values.xml -o .
-aapt2 link --manifest AndroidManifest.xml -A assets -o target_no_overlayable.apk values_values.arsc.flat
+aapt2 link --manifest AndroidManifest.xml -A assets -o target-no-overlayable.apk values_values.arsc.flat
rm values_values.arsc.flat
\ No newline at end of file
diff --git a/cmds/idmap2/tests/data/target/res/values/overlayable.xml b/cmds/idmap2/tests/data/target/res/values/overlayable.xml
index 02d2563..0bf83fa 100644
--- a/cmds/idmap2/tests/data/target/res/values/overlayable.xml
+++ b/cmds/idmap2/tests/data/target/res/values/overlayable.xml
@@ -15,20 +15,12 @@
-->
<resources>
<overlayable name="TestResources">
- <!-- Publicly overlayable resources -->
- <item type="string" name="a" />
- <item type="string" name="b" />
- <item type="string" name="c" />
- <item type="string" name="str1" />
- <item type="string" name="str2" />
- <item type="string" name="str3" />
- <item type="string" name="str4" />
- <item type="string" name="x" />
- <item type="string" name="y" />
- <item type="string" name="z" />
- <item type="integer" name="int1" />
+ <!-- Resources with signature restrictions -->
+ <policy type="signature">
+ <item type="string" name="policy_signature" />
+ </policy>
- <!-- Resources with partition restrictins -->
+ <!-- Resources with partition restrictions -->
<policy type="system">
<item type="string" name="policy_system" />
</policy>
@@ -41,12 +33,26 @@
<item type="string" name="policy_product" />
</policy>
+ <!-- Resources publicly overlayable -->
<policy type="public">
<item type="string" name="policy_public" />
+ <item type="string" name="a" />
+ <item type="string" name="b" />
+ <item type="string" name="c" />
+ <item type="string" name="str1" />
+ <item type="string" name="str2" />
+ <item type="string" name="str3" />
+ <item type="string" name="str4" />
+ <item type="string" name="x" />
+ <item type="string" name="y" />
+ <item type="string" name="z" />
+ <item type="integer" name="int1" />
</policy>
</overlayable>
<overlayable name="OtherResources">
- <item type="string" name="other" />
+ <policy type="public">
+ <item type="string" name="other" />
+ </policy>
</overlayable>
</resources>
\ No newline at end of file
diff --git a/cmds/idmap2/tests/data/target/res/values/values.xml b/cmds/idmap2/tests/data/target/res/values/values.xml
index 0d337f3..edd53f4 100644
--- a/cmds/idmap2/tests/data/target/res/values/values.xml
+++ b/cmds/idmap2/tests/data/target/res/values/values.xml
@@ -33,6 +33,7 @@
<string name="policy_system_vendor">policy_system_vendor</string>
<string name="policy_product">policy_product</string>
<string name="policy_public">policy_public</string>
+ <string name="policy_signature">policy_signature</string>
<item type="string" name="other" />
</resources>
diff --git a/cmds/idmap2/tests/data/target/target-no-overlayable.apk b/cmds/idmap2/tests/data/target/target-no-overlayable.apk
index 8676cbb..908b54a 100644
--- a/cmds/idmap2/tests/data/target/target-no-overlayable.apk
+++ b/cmds/idmap2/tests/data/target/target-no-overlayable.apk
Binary files differ
diff --git a/cmds/idmap2/tests/data/target/target.apk b/cmds/idmap2/tests/data/target/target.apk
index ecbe875..da3c1ae 100644
--- a/cmds/idmap2/tests/data/target/target.apk
+++ b/cmds/idmap2/tests/data/target/target.apk
Binary files differ
diff --git a/cmds/statsd/src/atoms.proto b/cmds/statsd/src/atoms.proto
index 2632294d..d78647e 100644
--- a/cmds/statsd/src/atoms.proto
+++ b/cmds/statsd/src/atoms.proto
@@ -245,6 +245,8 @@
AssistGestureStageReported assist_gesture_stage_reported = 174;
AssistGestureFeedbackReported assist_gesture_feedback_reported = 175;
AssistGestureProgressReported assist_gesture_progress_reported = 176;
+ TouchGestureClassified touch_gesture_classified = 177;
+ HiddenApiUsed hidden_api_used = 178 [(allow_from_any_uid) = true];
}
// Pulled events will start at field 10000.
@@ -2409,6 +2411,37 @@
}
/**
+ * Logs gesture classification and timing information for touch events.
+ *
+ * Logged from:
+ * frameworks/base/core/java/android/view/GestureDetector.java
+ * frameworks/base/core/java/android/view/View.java
+ */
+message TouchGestureClassified {
+ // The source of the classification (e.g. Java class name).
+ optional string source = 1;
+
+ enum Classification {
+ UNKNOWN_CLASSIFICATION = 0;
+ SINGLE_TAP = 1;
+ DOUBLE_TAP = 2;
+ LONG_PRESS = 3;
+ DEEP_PRESS = 4;
+ SCROLL = 5;
+ }
+ // The classification of the gesture.
+ optional Classification classification = 2;
+
+ // The interval from the start of a touch event stream until the
+ // classification was made.
+ optional int32 latency_millis = 3;
+
+ // The distance from the location of the first touch event to the
+ // location of the touch event when the classification was made.
+ optional float displacement_px = 4;
+}
+
+/**
* Logs that a setting was updated.
* Logged from:
* frameworks/base/packages/SettingsProvider/src/com/android/providers/settings/SettingsState.java
@@ -3306,6 +3339,33 @@
optional string service_name = 3;
}
+/**
+ * Logs when a hidden API is used.
+ *
+ * Logged from:
+ * libcore/libart/src/main/java/dalvik/system/VMRuntime.java
+ */
+message HiddenApiUsed {
+ // The uid of the app making the hidden access.
+ optional int32 uid = 1 [(is_uid) = true];
+
+ // Signature of the method or field accessed.
+ optional string signature = 2;
+
+ enum AccessMethod {
+ NONE = 0;
+ REFLECTION = 1;
+ JNI = 2;
+ LINKING = 3;
+ }
+
+ // Type of access.
+ optional AccessMethod access_method = 3;
+
+ // Whether the access was prevented or not.
+ optional bool access_denied = 4;
+}
+
//////////////////////////////////////////////////////////////////////
// Pulled atoms below this line //
//////////////////////////////////////////////////////////////////////
@@ -4789,6 +4849,12 @@
// The process state at the time of compaction.
optional android.app.ProcessStateEnum process_state = 16 [default = PROCESS_STATE_UNKNOWN];
+
+ // Free ZRAM in kilobytes before compaction.
+ optional int64 before_zram_free_kilobytes = 17;
+
+ // Free ZRAM in kilobytes after compaction.
+ optional int64 after_zram_free_kilobytes = 18;
}
/**
diff --git a/cmds/svc/src/com/android/commands/svc/PowerCommand.java b/cmds/svc/src/com/android/commands/svc/PowerCommand.java
index d29e68e..3180b77 100644
--- a/cmds/svc/src/com/android/commands/svc/PowerCommand.java
+++ b/cmds/svc/src/com/android/commands/svc/PowerCommand.java
@@ -26,6 +26,8 @@
import android.os.SystemProperties;
public class PowerCommand extends Svc.Command {
+ private static final int FORCE_SUSPEND_DELAY_DEFAULT_MILLIS = 0;
+
public PowerCommand() {
super("power");
}
@@ -42,7 +44,17 @@
+ " svc power reboot [reason]\n"
+ " Perform a runtime shutdown and reboot device with specified reason.\n"
+ " svc power shutdown\n"
- + " Perform a runtime shutdown and power off the device.\n";
+ + " Perform a runtime shutdown and power off the device.\n"
+ + " svc power forcesuspend [t]\n"
+ + " Force the system into suspend, ignoring all wakelocks.\n"
+ + " t - Number of milliseconds to wait before issuing force-suspend.\n"
+ + " Helps with devices that can't suspend while plugged in.\n"
+ + " Defaults to " + FORCE_SUSPEND_DELAY_DEFAULT_MILLIS + ".\n"
+ + " When using a delay, you must use the nohup shell modifier:\n"
+ + " 'adb shell nohup svc power forcesuspend [time]'\n"
+ + " Use caution; this is dangerous. It puts the device to sleep\n"
+ + " immediately without giving apps or the system an opportunity to\n"
+ + " save their state.\n";
}
public void run(String[] args) {
@@ -101,6 +113,20 @@
maybeLogRemoteException("Failed to shutdown.");
}
return;
+ } else if ("forcesuspend".equals(args[1])) {
+ int delayMillis = args.length > 2
+ ? Integer.parseInt(args[2]) : FORCE_SUSPEND_DELAY_DEFAULT_MILLIS;
+ try {
+ Thread.sleep(delayMillis);
+ if (!pm.forceSuspend()) {
+ System.err.println("Failed to force suspend.");
+ }
+ } catch (InterruptedException e) {
+ System.err.println("Failed to force suspend: " + e);
+ } catch (RemoteException e) {
+ maybeLogRemoteException("Failed to force-suspend with exception: " + e);
+ }
+ return;
}
}
}
diff --git a/config/hiddenapi-force-blacklist.txt b/config/hiddenapi-force-blacklist.txt
index dca3b52..b328f2a 100644
--- a/config/hiddenapi-force-blacklist.txt
+++ b/config/hiddenapi-force-blacklist.txt
@@ -1,4 +1,6 @@
Ldalvik/system/VMRuntime;->setHiddenApiExemptions([Ljava/lang/String;)V
+Ldalvik/system/VMRuntime;->setTargetSdkVersion(I)V
+Ldalvik/system/VMRuntime;->setTargetSdkVersionNative(I)V
Ljava/lang/invoke/MethodHandles$Lookup;->IMPL_LOOKUP:Ljava/lang/invoke/MethodHandles$Lookup;
Ljava/lang/invoke/VarHandle;->acquireFence()V
Ljava/lang/invoke/VarHandle;->compareAndExchange([Ljava/lang/Object;)Ljava/lang/Object;
diff --git a/config/hiddenapi-greylist-max-o.txt b/config/hiddenapi-greylist-max-o.txt
index 4b6cc0e..d9c1cd0 100644
--- a/config/hiddenapi-greylist-max-o.txt
+++ b/config/hiddenapi-greylist-max-o.txt
@@ -109777,7 +109777,6 @@
Ldalvik/system/VMRuntime;->setNonSdkApiUsageConsumer(Ljava/util/function/Consumer;)V
Ldalvik/system/VMRuntime;->setProcessPackageName(Ljava/lang/String;)V
Ldalvik/system/VMRuntime;->setSystemDaemonThreadPriority()V
-Ldalvik/system/VMRuntime;->setTargetSdkVersionNative(I)V
Ldalvik/system/VMRuntime;->startHeapTaskProcessor()V
Ldalvik/system/VMRuntime;->startJitCompilation()V
Ldalvik/system/VMRuntime;->stopHeapTaskProcessor()V
diff --git a/config/hiddenapi-greylist.txt b/config/hiddenapi-greylist.txt
index dc2ed4c..a836e8e 100644
--- a/config/hiddenapi-greylist.txt
+++ b/config/hiddenapi-greylist.txt
@@ -170,7 +170,6 @@
Landroid/app/IAssistDataReceiver$Stub;-><init>()V
Landroid/app/IAssistDataReceiver;->onHandleAssistData(Landroid/os/Bundle;)V
Landroid/app/IAssistDataReceiver;->onHandleAssistScreenshot(Landroid/graphics/Bitmap;)V
-Landroid/app/IInputForwarder;->forwardEvent(Landroid/view/InputEvent;)Z
Landroid/app/IInstrumentationWatcher$Stub;-><init>()V
Landroid/app/IInstrumentationWatcher;->instrumentationStatus(Landroid/content/ComponentName;ILandroid/os/Bundle;)V
Landroid/app/INotificationManager$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
diff --git a/core/java/android/annotation/CurrentTimeMillisLong.java b/core/java/android/annotation/CurrentTimeMillisLong.java
index 9846cce..355bb5a 100644
--- a/core/java/android/annotation/CurrentTimeMillisLong.java
+++ b/core/java/android/annotation/CurrentTimeMillisLong.java
@@ -25,12 +25,12 @@
import java.lang.annotation.Target;
/**
- * @memberDoc Value is a non-negative timestamp in the
- * {@link System#currentTimeMillis()} time base.
- * @paramDoc Value is a non-negative timestamp in the
- * {@link System#currentTimeMillis()} time base.
- * @returnDoc Value is a non-negative timestamp in the
- * {@link System#currentTimeMillis()} time base.
+ * @memberDoc Value is a non-negative timestamp measured as the number of
+ * milliseconds since 1970-01-01T00:00:00Z.
+ * @paramDoc Value is a non-negative timestamp measured as the number of
+ * milliseconds since 1970-01-01T00:00:00Z.
+ * @returnDoc Value is a non-negative timestamp measured as the number of
+ * milliseconds since 1970-01-01T00:00:00Z.
* @hide
*/
@Retention(SOURCE)
diff --git a/core/java/android/annotation/CurrentTimeSecondsLong.java b/core/java/android/annotation/CurrentTimeSecondsLong.java
new file mode 100644
index 0000000..2b4ffd7
--- /dev/null
+++ b/core/java/android/annotation/CurrentTimeSecondsLong.java
@@ -0,0 +1,39 @@
+/*
+ * 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.annotation;
+
+import static java.lang.annotation.ElementType.FIELD;
+import static java.lang.annotation.ElementType.METHOD;
+import static java.lang.annotation.ElementType.PARAMETER;
+import static java.lang.annotation.RetentionPolicy.SOURCE;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+/**
+ * @memberDoc Value is a non-negative timestamp measured as the number of
+ * seconds since 1970-01-01T00:00:00Z.
+ * @paramDoc Value is a non-negative timestamp measured as the number of
+ * seconds since 1970-01-01T00:00:00Z.
+ * @returnDoc Value is a non-negative timestamp measured as the number of
+ * seconds since 1970-01-01T00:00:00Z.
+ * @hide
+ */
+@Retention(SOURCE)
+@Target({METHOD, PARAMETER, FIELD})
+public @interface CurrentTimeSecondsLong {
+}
diff --git a/core/java/android/annotation/Px.java b/core/java/android/annotation/Px.java
index ad99fdb..cec7f80 100644
--- a/core/java/android/annotation/Px.java
+++ b/core/java/android/annotation/Px.java
@@ -29,6 +29,7 @@
* Denotes that a numeric parameter, field or method return value is expected
* to represent a pixel dimension.
*
+ * @memberDoc This units of this value are pixels.
* @paramDoc This units of this value are pixels.
* @returnDoc This units of this value are pixels.
* {@hide}
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index e55c964..d29fedd 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -3783,14 +3783,14 @@
/**
- * Moves the activity from {@link WindowConfiguration#WINDOWING_MODE_FREEFORM} windowing mode to
- * {@link WindowConfiguration#WINDOWING_MODE_FULLSCREEN}.
+ * Moves the activity between {@link WindowConfiguration#WINDOWING_MODE_FREEFORM} windowing mode
+ * and {@link WindowConfiguration#WINDOWING_MODE_FULLSCREEN}.
*
* @hide
*/
@Override
- public void exitFreeformMode() throws RemoteException {
- ActivityTaskManager.getService().exitFreeformMode(mToken);
+ public void toggleFreeformWindowingMode() throws RemoteException {
+ ActivityTaskManager.getService().toggleFreeformWindowingMode(mToken);
}
/**
diff --git a/core/java/android/app/ActivityManagerInternal.java b/core/java/android/app/ActivityManagerInternal.java
index 69c450c..7d828d8 100644
--- a/core/java/android/app/ActivityManagerInternal.java
+++ b/core/java/android/app/ActivityManagerInternal.java
@@ -259,10 +259,11 @@
public abstract void tempWhitelistForPendingIntent(int callerPid, int callerUid, int targetUid,
long duration, String tag);
- public abstract int broadcastIntentInPackage(String packageName, int uid, Intent intent,
- String resolvedType, IIntentReceiver resultTo, int resultCode, String resultData,
- Bundle resultExtras, String requiredPermission, Bundle bOptions, boolean serialized,
- boolean sticky, int userId, boolean allowBackgroundActivityStarts);
+ public abstract int broadcastIntentInPackage(String packageName, int uid, int realCallingUid,
+ int realCallingPid, Intent intent, String resolvedType, IIntentReceiver resultTo,
+ int resultCode, String resultData, Bundle resultExtras, String requiredPermission,
+ Bundle bOptions, boolean serialized, boolean sticky, int userId,
+ boolean allowBackgroundActivityStarts);
public abstract ComponentName startServiceInPackage(int uid, Intent service,
String resolvedType, boolean fgRequired, String callingPackage, int userId,
boolean allowBackgroundActivityStarts) throws TransactionTooLargeException;
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index cc419b8..7908637 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -3229,8 +3229,9 @@
TAG, "Handling launch of " + r);
// Initialize before creating the activity
- if (!ThreadedRenderer.sRendererDisabled) {
- GraphicsEnvironment.earlyInitEGL();
+ if (!ThreadedRenderer.sRendererDisabled
+ && (r.activityInfo.flags & ActivityInfo.FLAG_HARDWARE_ACCELERATED) != 0) {
+ HardwareRenderer.preload();
}
WindowManagerGlobal.initialize();
diff --git a/core/java/android/app/ActivityView.java b/core/java/android/app/ActivityView.java
index ce71998..e0ae4e3 100644
--- a/core/java/android/app/ActivityView.java
+++ b/core/java/android/app/ActivityView.java
@@ -29,12 +29,17 @@
import android.graphics.Insets;
import android.hardware.display.DisplayManager;
import android.hardware.display.VirtualDisplay;
+import android.hardware.input.InputManager;
import android.os.RemoteException;
+import android.os.SystemClock;
import android.os.UserHandle;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.IWindowManager;
+import android.view.InputDevice;
+import android.view.KeyCharacterMap;
+import android.view.KeyEvent;
import android.view.SurfaceControl;
import android.view.SurfaceHolder;
import android.view.SurfaceSession;
@@ -291,6 +296,9 @@
/** Send current location and size to the WM to set tap exclude region for this view. */
private void updateLocation() {
+ if (!isAttachedToWindow()) {
+ return;
+ }
try {
getLocationInWindow(mLocationInWindow);
WindowManagerGlobal.getWindowSession().updateTapExcludeRegion(getWindow(), hashCode(),
@@ -343,6 +351,32 @@
mSurfaceView.setVisibility(visibility);
}
+ /**
+ * Injects a pair of down/up key events with keycode {@link KeyEvent#KEYCODE_BACK} to the
+ * virtual display.
+ */
+ public void performBackPress() {
+ if (mVirtualDisplay == null) {
+ return;
+ }
+ final int displayId = mVirtualDisplay.getDisplay().getDisplayId();
+ final InputManager im = InputManager.getInstance();
+ im.injectInputEvent(createKeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_BACK, displayId),
+ InputManager.INJECT_INPUT_EVENT_MODE_ASYNC);
+ im.injectInputEvent(createKeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_BACK, displayId),
+ InputManager.INJECT_INPUT_EVENT_MODE_ASYNC);
+ }
+
+ private static KeyEvent createKeyEvent(int action, int code, int displayId) {
+ long when = SystemClock.uptimeMillis();
+ final KeyEvent ev = new KeyEvent(when, when, action, code, 0 /* repeat */,
+ 0 /* metaState */, KeyCharacterMap.VIRTUAL_KEYBOARD, 0 /* scancode */,
+ KeyEvent.FLAG_FROM_SYSTEM | KeyEvent.FLAG_VIRTUAL_HARD_KEY,
+ InputDevice.SOURCE_KEYBOARD);
+ ev.setDisplayId(displayId);
+ return ev;
+ }
+
private void initVirtualDisplay(SurfaceSession surfaceSession) {
if (mVirtualDisplay != null) {
throw new IllegalStateException("Trying to initialize for the second time.");
@@ -429,6 +463,9 @@
/** Report to server that tap exclude region on hosting display should be cleared. */
private void cleanTapExcludeRegion() {
+ if (!isAttachedToWindow()) {
+ return;
+ }
// Update tap exclude region with an empty rect to clean the state on server.
try {
WindowManagerGlobal.getWindowSession().updateTapExcludeRegion(getWindow(), hashCode(),
diff --git a/core/java/android/app/AppOpsManager.java b/core/java/android/app/AppOpsManager.java
index f76f7b9..040ad06 100644
--- a/core/java/android/app/AppOpsManager.java
+++ b/core/java/android/app/AppOpsManager.java
@@ -46,6 +46,8 @@
import android.util.SparseArray;
import com.android.internal.annotations.GuardedBy;
+
+import com.android.internal.annotations.Immutable;
import com.android.internal.app.IAppOpsActiveCallback;
import com.android.internal.app.IAppOpsCallback;
import com.android.internal.app.IAppOpsNotedCallback;
@@ -2210,6 +2212,115 @@
}
/**
+ * Request for getting historical app op usage. The request acts
+ * as a filtering criteria when querying historical op usage.
+ *
+ * @hide
+ */
+ @Immutable
+ @TestApi
+ @SystemApi
+ public static final class HistoricalOpsRequest {
+ private final int mUid;
+ private final @Nullable String mPackageName;
+ private final @Nullable List<String> mOpNames;
+ private final long mBeginTimeMillis;
+ private final long mEndTimeMillis;
+
+ private HistoricalOpsRequest(int uid, @Nullable String packageName,
+ @Nullable List<String> opNames, long beginTimeMillis, long endTimeMillis) {
+ mUid = uid;
+ mPackageName = packageName;
+ mOpNames = opNames;
+ mBeginTimeMillis = beginTimeMillis;
+ mEndTimeMillis = endTimeMillis;
+ }
+
+ /**
+ * Builder for creating a {@link HistoricalOpsRequest}.
+ *
+ * @hide
+ */
+ @TestApi
+ @SystemApi
+ public static final class Builder {
+ private int mUid = Process.INVALID_UID;
+ private @Nullable String mPackageName;
+ private @Nullable List<String> mOpNames;
+ private final long mBeginTimeMillis;
+ private final long mEndTimeMillis;
+
+ /**
+ * Creates a new builder.
+ *
+ * @param beginTimeMillis The beginning of the interval in milliseconds since
+ * epoch start (January 1, 1970 00:00:00.000 GMT - Gregorian). Must be non
+ * negative.
+ * @param endTimeMillis The end of the interval in milliseconds since
+ * epoch start (January 1, 1970 00:00:00.000 GMT - Gregorian). Must be after
+ * {@code beginTimeMillis}. Pass {@link Long#MAX_VALUE} to get the most recent
+ * history including ops that happen while this call is in flight.
+ */
+ public Builder(long beginTimeMillis, long endTimeMillis) {
+ Preconditions.checkArgument(beginTimeMillis >= 0 && beginTimeMillis < endTimeMillis,
+ "beginTimeMillis must be non negative and lesser than endTimeMillis");
+ mBeginTimeMillis = beginTimeMillis;
+ mEndTimeMillis = endTimeMillis;
+ }
+
+ /**
+ * Sets the UID to query for.
+ *
+ * @param uid The uid. Pass {@link android.os.Process#INVALID_UID} for any uid.
+ * @return This builder.
+ */
+ public @NonNull Builder setUid(int uid) {
+ Preconditions.checkArgument(uid == Process.INVALID_UID || uid >= 0,
+ "uid must be " + Process.INVALID_UID + " or non negative");
+ mUid = uid;
+ return this;
+ }
+
+ /**
+ * Sets the package to query for.
+ *
+ * @param packageName The package name. <code>Null</code> for any package.
+ * @return This builder.
+ */
+ public @NonNull Builder setPackageName(@Nullable String packageName) {
+ mPackageName = packageName;
+ return this;
+ }
+
+ /**
+ * Sets the op names to query for.
+ *
+ * @param opNames The op names. <code>Null</code> for any op.
+ * @return This builder.
+ */
+ public @NonNull Builder setOpNames(@Nullable List<String> opNames) {
+ if (opNames != null) {
+ final int opCount = opNames.size();
+ for (int i = 0; i < opCount; i++) {
+ Preconditions.checkArgument(AppOpsManager.strOpToOp(
+ opNames.get(i)) != AppOpsManager.OP_NONE);
+ }
+ }
+ mOpNames = opNames;
+ return this;
+ }
+
+ /**
+ * @return a new {@link HistoricalOpsRequest}.
+ */
+ public @NonNull HistoricalOpsRequest build() {
+ return new HistoricalOpsRequest(mUid, mPackageName, mOpNames,
+ mBeginTimeMillis, mEndTimeMillis);
+ }
+ }
+ }
+
+ /**
* This class represents historical app op state of all UIDs for a given time interval.
*
* @hide
@@ -3671,26 +3782,7 @@
/**
* Retrieve historical app op stats for a period.
*
- * <p>Historical data can be obtained
- * for a specific package by specifying the <code>packageName</code> argument,
- * for a specific UID if specifying the <code>uid</code> argument, for a
- * specific package in a UID by specifying the <code>packageName</code>
- * and the <code>uid</code> arguments, for all packages by passing
- * {@link android.os.Process#INVALID_UID} and <code>null</code> for the
- * <code>uid</code> and <code>packageName</code> arguments, respectively.
- * Similarly, you can specify the <code>opNames</code> argument to get
- * data only for these ops or <code>null</code> for all ops.
- *
- * @param uid The UID to query for.
- * @param packageName The package to query for.
- * @param beginTimeMillis The beginning of the interval in milliseconds since
- * epoch start (January 1, 1970 00:00:00.000 GMT - Gregorian). Must be non
- * negative.
- * @param endTimeMillis The end of the interval in milliseconds since
- * epoch start (January 1, 1970 00:00:00.000 GMT - Gregorian). Must be after
- * {@code beginTimeMillis}. Pass {@link Long#MAX_VALUE} to get the most recent
- * history including ops that happen while this call is in flight.
- * @param opNames The ops to query for. Pass {@code null} for all ops.
+ * @param request A request object describing the data being queried for.
* @param executor Executor on which to run the callback. If <code>null</code>
* the callback is executed on the default executor running on the main thread.
* @param callback Callback on which to deliver the result.
@@ -3702,13 +3794,13 @@
@TestApi
@SystemApi
@RequiresPermission(android.Manifest.permission.GET_APP_OPS_STATS)
- public void getHistoricalOps(int uid, @Nullable String packageName,
- @Nullable String[] opNames, long beginTimeMillis, long endTimeMillis,
+ public void getHistoricalOps(@NonNull HistoricalOpsRequest request,
@NonNull Executor executor, @NonNull Consumer<HistoricalOps> callback) {
Preconditions.checkNotNull(executor, "executor cannot be null");
Preconditions.checkNotNull(callback, "callback cannot be null");
try {
- mService.getHistoricalOps(uid, packageName, opNames, beginTimeMillis, endTimeMillis,
+ mService.getHistoricalOps(request.mUid, request.mPackageName, request.mOpNames,
+ request.mBeginTimeMillis, request.mEndTimeMillis,
new RemoteCallback((result) -> {
final HistoricalOps ops = result.getParcelable(KEY_HISTORICAL_OPS);
final long identity = Binder.clearCallingIdentity();
@@ -3725,29 +3817,12 @@
/**
* Retrieve historical app op stats for a period.
- *
- * <p>Historical data can be obtained
- * for a specific package by specifying the <code>packageName</code> argument,
- * for a specific UID if specifying the <code>uid</code> argument, for a
- * specific package in a UID by specifying the <code>packageName</code>
- * and the <code>uid</code> arguments, for all packages by passing
- * {@link android.os.Process#INVALID_UID} and <code>null</code> for the
- * <code>uid</code> and <code>packageName</code> arguments, respectively.
- * Similarly, you can specify the <code>opNames</code> argument to get
- * data only for these ops or <code>null</code> for all ops.
* <p>
* This method queries only the on disk state and the returned ops are raw,
* which is their times are relative to the history start as opposed to the
* epoch start.
*
- * @param uid The UID to query for.
- * @param packageName The package to query for.
- * @param beginTimeMillis The beginning of the interval in milliseconds since
- * history start. History time grows as one goes into the past.
- * @param endTimeMillis The end of the interval in milliseconds since
- * history start. History time grows as one goes into the past. Must be after
- * {@code beginTimeMillis}.
- * @param opNames The ops to query for. Pass {@code null} for all ops.
+ * @param request A request object describing the data being queried for.
* @param executor Executor on which to run the callback. If <code>null</code>
* the callback is executed on the default executor running on the main thread.
* @param callback Callback on which to deliver the result.
@@ -3758,15 +3833,15 @@
*/
@TestApi
@RequiresPermission(android.Manifest.permission.GET_APP_OPS_STATS)
- public void getHistoricalOpsFromDiskRaw(int uid, @Nullable String packageName,
- @Nullable String[] opNames, long beginTimeMillis, long endTimeMillis,
+ public void getHistoricalOpsFromDiskRaw(@NonNull HistoricalOpsRequest request,
@Nullable Executor executor, @NonNull Consumer<HistoricalOps> callback) {
Preconditions.checkNotNull(executor, "executor cannot be null");
Preconditions.checkNotNull(callback, "callback cannot be null");
try {
- mService.getHistoricalOpsFromDiskRaw(uid, packageName, opNames, beginTimeMillis,
- endTimeMillis, new RemoteCallback((result) -> {
- final HistoricalOps ops = result.getParcelable(KEY_HISTORICAL_OPS);
+ mService.getHistoricalOpsFromDiskRaw(request.mUid, request.mPackageName,
+ request.mOpNames, request.mBeginTimeMillis, request.mEndTimeMillis,
+ new RemoteCallback((result) -> {
+ final HistoricalOps ops = result.getParcelable(KEY_HISTORICAL_OPS);
final long identity = Binder.clearCallingIdentity();
try {
executor.execute(() -> callback.accept(ops));
@@ -4291,12 +4366,35 @@
/**
* Like {@link #noteProxyOp(String, String)} but instead
* of throwing a {@link SecurityException} it returns {@link #MODE_ERRORED}.
+ *
+ * <p>This API requires the package with the {@code proxiedPackageName} to belongs to
+ * {@link Binder#getCallingUid()}.
*/
public int noteProxyOpNoThrow(String op, String proxiedPackageName) {
return noteProxyOpNoThrow(strOpToOp(op), proxiedPackageName);
}
/**
+ * Like {@link #noteProxyOp(String, String)} but instead
+ * of throwing a {@link SecurityException} it returns {@link #MODE_ERRORED}.
+ *
+ * <p>This API requires package with the {@code proxiedPackageName} to belong to
+ * {@code proxiedUid}.
+ *
+ * @param op The op to note
+ * @param proxiedPackageName The package to note the op for or {@code null} if the op should be
+ * noted for the "android" package
+ * @param proxiedUid The uid the package belongs to
+ *
+ * @hide
+ */
+ @SystemApi
+ public int noteProxyOpNoThrow(@NonNull String op, @Nullable String proxiedPackageName,
+ int proxiedUid) {
+ return noteProxyOpNoThrow(strOpToOp(op), proxiedPackageName, proxiedUid);
+ }
+
+ /**
* Report that an application has started executing a long-running operation. Note that you
* must pass in both the uid and name of the application to be checked; this function will
* verify that these two match, and if not, return {@link #MODE_IGNORED}. If this call
@@ -4495,17 +4593,30 @@
* of throwing a {@link SecurityException} it returns {@link #MODE_ERRORED}.
* @hide
*/
- public int noteProxyOpNoThrow(int op, String proxiedPackageName) {
+ public int noteProxyOpNoThrow(int op, String proxiedPackageName, int proxiedUid) {
logOperationIfNeeded(op, mContext.getOpPackageName(), proxiedPackageName);
try {
return mService.noteProxyOperation(op, Process.myUid(), mContext.getOpPackageName(),
- Binder.getCallingUid(), proxiedPackageName);
+ proxiedUid, proxiedPackageName);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
/**
+ * Like {@link #noteProxyOp(int, String)} but instead
+ * of throwing a {@link SecurityException} it returns {@link #MODE_ERRORED}.
+ *
+ * <p>This API requires the package with {@code proxiedPackageName} to belongs to
+ * {@link Binder#getCallingUid()}.
+ *
+ * @hide
+ */
+ public int noteProxyOpNoThrow(int op, String proxiedPackageName) {
+ return noteProxyOpNoThrow(op, proxiedPackageName, Binder.getCallingUid());
+ }
+
+ /**
* Like {@link #noteOp} but instead of throwing a {@link SecurityException} it
* returns {@link #MODE_ERRORED}.
* @hide
diff --git a/core/java/android/app/BroadcastOptions.java b/core/java/android/app/BroadcastOptions.java
index 69c3632..062a462 100644
--- a/core/java/android/app/BroadcastOptions.java
+++ b/core/java/android/app/BroadcastOptions.java
@@ -33,6 +33,7 @@
private int mMinManifestReceiverApiLevel = 0;
private int mMaxManifestReceiverApiLevel = Build.VERSION_CODES.CUR_DEVELOPMENT;
private boolean mDontSendToRestrictedApps = false;
+ private boolean mAllowBackgroundActivityStarts;
/**
* How long to temporarily put an app on the power whitelist when executing this broadcast
@@ -54,11 +55,17 @@
= "android:broadcast.maxManifestReceiverApiLevel";
/**
- * Corresponds to {@link #setMaxManifestReceiverApiLevel}.
+ * Corresponds to {@link #setDontSendToRestrictedApps}.
*/
static final String KEY_DONT_SEND_TO_RESTRICTED_APPS =
"android:broadcast.dontSendToRestrictedApps";
+ /**
+ * Corresponds to {@link #setAllowBackgroundActivityStarts}.
+ */
+ static final String KEY_ALLOW_BACKGROUND_ACTIVITY_STARTS =
+ "android:broadcast.allowBackgroundActivityStarts";
+
public static BroadcastOptions makeBasic() {
BroadcastOptions opts = new BroadcastOptions();
return opts;
@@ -74,6 +81,8 @@
mMaxManifestReceiverApiLevel = opts.getInt(KEY_MAX_MANIFEST_RECEIVER_API_LEVEL,
Build.VERSION_CODES.CUR_DEVELOPMENT);
mDontSendToRestrictedApps = opts.getBoolean(KEY_DONT_SEND_TO_RESTRICTED_APPS, false);
+ mAllowBackgroundActivityStarts = opts.getBoolean(KEY_ALLOW_BACKGROUND_ACTIVITY_STARTS,
+ false);
}
/**
@@ -148,6 +157,23 @@
}
/**
+ * Sets the process will be able to start activities from background for the duration of
+ * the broadcast dispatch. Default value is {@code false}
+ */
+ @RequiresPermission(android.Manifest.permission.START_ACTIVITIES_FROM_BACKGROUND)
+ public void setAllowBackgroundActivityStarts(boolean allowBackgroundActivityStarts) {
+ mAllowBackgroundActivityStarts = allowBackgroundActivityStarts;
+ }
+
+ /**
+ * @hide
+ * @return #setAllowBackgroundActivityStarts
+ */
+ public boolean allowsBackgroundActivityStarts() {
+ return mAllowBackgroundActivityStarts;
+ }
+
+ /**
* Returns the created options as a Bundle, which can be passed to
* {@link android.content.Context#sendBroadcast(android.content.Intent)
* Context.sendBroadcast(Intent)} and related methods.
@@ -169,6 +195,9 @@
if (mDontSendToRestrictedApps) {
b.putBoolean(KEY_DONT_SEND_TO_RESTRICTED_APPS, true);
}
+ if (mAllowBackgroundActivityStarts) {
+ b.putBoolean(KEY_ALLOW_BACKGROUND_ACTIVITY_STARTS, true);
+ }
return b.isEmpty() ? null : b;
}
}
diff --git a/core/java/android/app/IActivityTaskManager.aidl b/core/java/android/app/IActivityTaskManager.aidl
index 2b765b2..497d5ba 100644
--- a/core/java/android/app/IActivityTaskManager.aidl
+++ b/core/java/android/app/IActivityTaskManager.aidl
@@ -215,7 +215,7 @@
void registerTaskStackListener(in ITaskStackListener listener);
void unregisterTaskStackListener(in ITaskStackListener listener);
void setTaskResizeable(int taskId, int resizeableMode);
- void exitFreeformMode(in IBinder token);
+ void toggleFreeformWindowingMode(in IBinder token);
void resizeTask(int taskId, in Rect bounds, int resizeMode);
void moveStackToDisplay(int stackId, int displayId);
void removeStack(int stackId);
diff --git a/core/java/android/app/IInputForwarder.aidl b/core/java/android/app/IInputForwarder.aidl
deleted file mode 100644
index d6be63e..0000000
--- a/core/java/android/app/IInputForwarder.aidl
+++ /dev/null
@@ -1,29 +0,0 @@
-/**
- * Copyright (c) 2017, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.app;
-
-import android.view.InputEvent;
-
-/**
- * Forwards input events into owned activity container, used in {@link android.app.ActivityView}.
- * To forward input to other apps {@link android.Manifest.permission.INJECT_EVENTS} permission is
- * required.
- * @hide
- */
-interface IInputForwarder {
- boolean forwardEvent(in InputEvent event);
-}
\ No newline at end of file
diff --git a/core/java/android/app/WallpaperInfo.java b/core/java/android/app/WallpaperInfo.java
index f0f7d89..28c79aa 100644
--- a/core/java/android/app/WallpaperInfo.java
+++ b/core/java/android/app/WallpaperInfo.java
@@ -371,10 +371,17 @@
* Returns whether this wallpaper service can support multiple engines to render on each surface
* independently. An example use case is a multi-display set-up where the wallpaper service can
* render surfaces to each of the connected displays.
+ * <p>
+ * This corresponds to the value {@link android.R.styleable#Wallpaper_supportsMultipleDisplays}
+ * in the XML description of the wallpaper.
+ * <p>
+ * The default value is {@code false}.
*
* @see WallpaperService#onCreateEngine()
* @see WallpaperService.Engine#onCreate(SurfaceHolder)
* @return {@code true} if multiple engines can render independently on each surface.
+ *
+ * @attr ref android.R.styleable#Wallpaper_supportsMultipleDisplays
*/
public boolean supportsMultipleDisplays() {
return mSupportMultipleDisplays;
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index 806536b..3587c68 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -7036,9 +7036,9 @@
}
/**
- * Called by a profile or device owner to set the permitted input methods services. When set by
- * a device owner or profile owner the restriction applies to all profiles of the user the
- * device owner or profile owner is an admin for. By default, the user can use any input method.
+ * Called by a profile or device owner to set the permitted input methods services for this
+ * user. By default, the user can use any input method.
+ * <p>
* When zero or more packages have been added, input method that are not in the list and not
* part of the system can not be enabled by the user. This method will fail if it is called for
* a admin that is not for the foreground user or a profile of the foreground user. Any
@@ -7047,7 +7047,7 @@
* Calling with a null value for the list disables the restriction so that all input methods can
* be used, calling with an empty list disables all but the system's own input methods.
* <p>
- * System input methods are always available to the user this method can't modify this.
+ * System input methods are always available to the user - this method can't modify this.
*
* @param admin Which {@link DeviceAdminReceiver} this request is associated with.
* @param packageNames List of input method package names.
diff --git a/core/java/android/app/admin/TEST_MAPPING b/core/java/android/app/admin/TEST_MAPPING
new file mode 100644
index 0000000..8f88c22
--- /dev/null
+++ b/core/java/android/app/admin/TEST_MAPPING
@@ -0,0 +1,7 @@
+{
+ "imports": [
+ {
+ "path": "frameworks/base/services/devicepolicy"
+ }
+ ]
+}
diff --git a/core/java/android/content/ContentInterface.java b/core/java/android/content/ContentInterface.java
index 3d732eb..d41d8d9 100644
--- a/core/java/android/content/ContentInterface.java
+++ b/core/java/android/content/ContentInterface.java
@@ -36,6 +36,8 @@
* These methods have been extracted into a general interface so that APIs can
* be flexible in accepting either a {@link ContentProvider}, a
* {@link ContentResolver}, or a {@link ContentProviderClient}.
+ *
+ * @hide
*/
public interface ContentInterface {
public @Nullable Cursor query(@NonNull Uri uri, @Nullable String[] projection,
diff --git a/core/java/android/content/ContentProvider.java b/core/java/android/content/ContentProvider.java
index f138d39..e06322df 100644
--- a/core/java/android/content/ContentProvider.java
+++ b/core/java/android/content/ContentProvider.java
@@ -134,7 +134,7 @@
private boolean mNoPerms;
private boolean mSingleUser;
- private final ThreadLocal<String> mCallingPackage = new ThreadLocal<>();
+ private ThreadLocal<String> mCallingPackage;
private Transport mTransport = new Transport();
@@ -2034,6 +2034,7 @@
private void attachInfo(Context context, ProviderInfo info, boolean testing) {
mNoPerms = testing;
+ mCallingPackage = new ThreadLocal<>();
/*
* Only allow it to be set once, so after the content service gives
diff --git a/core/java/android/content/ContentProviderClient.java b/core/java/android/content/ContentProviderClient.java
index 0b5bdb5..93bf518 100644
--- a/core/java/android/content/ContentProviderClient.java
+++ b/core/java/android/content/ContentProviderClient.java
@@ -626,15 +626,14 @@
return ContentProvider.coerceToLocalContentProvider(mContentProvider);
}
- /**
- * Closes the given object quietly, ignoring any checked exceptions. Does
- * nothing if the given object is {@code null}.
- */
+ /** {@hide} */
+ @Deprecated
public static void closeQuietly(ContentProviderClient client) {
IoUtils.closeQuietly(client);
}
/** {@hide} */
+ @Deprecated
public static void releaseQuietly(ContentProviderClient client) {
IoUtils.closeQuietly(client);
}
diff --git a/core/java/android/content/ContentResolver.java b/core/java/android/content/ContentResolver.java
index 7672ccf..0e11d4e 100644
--- a/core/java/android/content/ContentResolver.java
+++ b/core/java/android/content/ContentResolver.java
@@ -609,10 +609,60 @@
private static final int SLOW_THRESHOLD_MILLIS = 500;
private final Random mRandom = new Random(); // guarded by itself
- public ContentResolver(Context context) {
+ public ContentResolver(@Nullable Context context) {
+ this(context, null);
+ }
+
+ /** {@hide} */
+ public ContentResolver(@Nullable Context context, @Nullable ContentInterface wrapped) {
mContext = context != null ? context : ActivityThread.currentApplication();
mPackageName = mContext.getOpPackageName();
mTargetSdkVersion = mContext.getApplicationInfo().targetSdkVersion;
+ mWrapped = wrapped;
+ }
+
+ /** {@hide} */
+ public static ContentResolver wrap(@NonNull ContentInterface wrapped) {
+ Preconditions.checkNotNull(wrapped);
+
+ return new ContentResolver(null, wrapped) {
+ @Override
+ public void unstableProviderDied(IContentProvider icp) {
+ throw new UnsupportedOperationException();
+ }
+ @Override
+ public boolean releaseUnstableProvider(IContentProvider icp) {
+ throw new UnsupportedOperationException();
+ }
+ @Override
+ public boolean releaseProvider(IContentProvider icp) {
+ throw new UnsupportedOperationException();
+ }
+ @Override
+ protected IContentProvider acquireUnstableProvider(Context c, String name) {
+ throw new UnsupportedOperationException();
+ }
+ @Override
+ protected IContentProvider acquireProvider(Context c, String name) {
+ throw new UnsupportedOperationException();
+ }
+ };
+ }
+
+ /**
+ * Create a {@link ContentResolver} instance that redirects all its methods
+ * to the given {@link ContentProvider}.
+ */
+ public static ContentResolver wrap(@NonNull ContentProvider wrapped) {
+ return wrap((ContentInterface) wrapped);
+ }
+
+ /**
+ * Create a {@link ContentResolver} instance that redirects all its methods
+ * to the given {@link ContentProviderClient}.
+ */
+ public static ContentResolver wrap(@NonNull ContentProviderClient wrapped) {
+ return wrap((ContentInterface) wrapped);
}
/** @hide */
@@ -660,6 +710,12 @@
public final @Nullable String getType(@NonNull Uri url) {
Preconditions.checkNotNull(url, "url");
+ try {
+ if (mWrapped != null) return mWrapped.getType(url);
+ } catch (RemoteException e) {
+ return null;
+ }
+
// XXX would like to have an acquireExistingUnstableProvider for this.
IContentProvider provider = acquireExistingProvider(url);
if (provider != null) {
@@ -715,6 +771,12 @@
Preconditions.checkNotNull(url, "url");
Preconditions.checkNotNull(mimeTypeFilter, "mimeTypeFilter");
+ try {
+ if (mWrapped != null) return mWrapped.getStreamTypes(url, mimeTypeFilter);
+ } catch (RemoteException e) {
+ return null;
+ }
+
IContentProvider provider = acquireProvider(url);
if (provider == null) {
return null;
@@ -843,6 +905,15 @@
@Nullable String[] projection, @Nullable Bundle queryArgs,
@Nullable CancellationSignal cancellationSignal) {
Preconditions.checkNotNull(uri, "uri");
+
+ try {
+ if (mWrapped != null) {
+ return mWrapped.query(uri, projection, queryArgs, cancellationSignal);
+ }
+ } catch (RemoteException e) {
+ return null;
+ }
+
IContentProvider unstableProvider = acquireUnstableProvider(uri);
if (unstableProvider == null) {
return null;
@@ -942,6 +1013,13 @@
@Override
public final @Nullable Uri canonicalize(@NonNull Uri url) {
Preconditions.checkNotNull(url, "url");
+
+ try {
+ if (mWrapped != null) return mWrapped.canonicalize(url);
+ } catch (RemoteException e) {
+ return null;
+ }
+
IContentProvider provider = acquireProvider(url);
if (provider == null) {
return null;
@@ -979,6 +1057,13 @@
@Override
public final @Nullable Uri uncanonicalize(@NonNull Uri url) {
Preconditions.checkNotNull(url, "url");
+
+ try {
+ if (mWrapped != null) return mWrapped.uncanonicalize(url);
+ } catch (RemoteException e) {
+ return null;
+ }
+
IContentProvider provider = acquireProvider(url);
if (provider == null) {
return null;
@@ -1015,6 +1100,13 @@
public final boolean refresh(@NonNull Uri url, @Nullable Bundle args,
@Nullable CancellationSignal cancellationSignal) {
Preconditions.checkNotNull(url, "url");
+
+ try {
+ if (mWrapped != null) return mWrapped.refresh(url, args, cancellationSignal);
+ } catch (RemoteException e) {
+ return false;
+ }
+
IContentProvider provider = acquireProvider(url);
if (provider == null) {
return false;
@@ -1126,6 +1218,12 @@
@Override
public final @Nullable ParcelFileDescriptor openFile(@NonNull Uri uri, @NonNull String mode,
@Nullable CancellationSignal signal) throws FileNotFoundException {
+ try {
+ if (mWrapped != null) return mWrapped.openFile(uri, mode, signal);
+ } catch (RemoteException e) {
+ return null;
+ }
+
return openFileDescriptor(uri, mode, signal);
}
@@ -1237,6 +1335,12 @@
@Override
public final @Nullable AssetFileDescriptor openAssetFile(@NonNull Uri uri, @NonNull String mode,
@Nullable CancellationSignal signal) throws FileNotFoundException {
+ try {
+ if (mWrapped != null) return mWrapped.openAssetFile(uri, mode, signal);
+ } catch (RemoteException e) {
+ return null;
+ }
+
return openAssetFileDescriptor(uri, mode, signal);
}
@@ -1448,6 +1552,14 @@
public final @Nullable AssetFileDescriptor openTypedAssetFile(@NonNull Uri uri,
@NonNull String mimeTypeFilter, @Nullable Bundle opts,
@Nullable CancellationSignal signal) throws FileNotFoundException {
+ try {
+ if (mWrapped != null) {
+ return mWrapped.openTypedAssetFile(uri, mimeTypeFilter, opts, signal);
+ }
+ } catch (RemoteException e) {
+ return null;
+ }
+
return openTypedAssetFileDescriptor(uri, mimeTypeFilter, opts, signal);
}
@@ -1664,6 +1776,13 @@
public final @Nullable Uri insert(@RequiresPermission.Write @NonNull Uri url,
@Nullable ContentValues values) {
Preconditions.checkNotNull(url, "url");
+
+ try {
+ if (mWrapped != null) return mWrapped.insert(url, values);
+ } catch (RemoteException e) {
+ return null;
+ }
+
IContentProvider provider = acquireProvider(url);
if (provider == null) {
throw new IllegalArgumentException("Unknown URL " + url);
@@ -1705,6 +1824,13 @@
throws RemoteException, OperationApplicationException {
Preconditions.checkNotNull(authority, "authority");
Preconditions.checkNotNull(operations, "operations");
+
+ try {
+ if (mWrapped != null) return mWrapped.applyBatch(authority, operations);
+ } catch (RemoteException e) {
+ return null;
+ }
+
ContentProviderClient provider = acquireContentProviderClient(authority);
if (provider == null) {
throw new IllegalArgumentException("Unknown authority " + authority);
@@ -1731,6 +1857,13 @@
@NonNull ContentValues[] values) {
Preconditions.checkNotNull(url, "url");
Preconditions.checkNotNull(values, "values");
+
+ try {
+ if (mWrapped != null) return mWrapped.bulkInsert(url, values);
+ } catch (RemoteException e) {
+ return 0;
+ }
+
IContentProvider provider = acquireProvider(url);
if (provider == null) {
throw new IllegalArgumentException("Unknown URL " + url);
@@ -1764,6 +1897,13 @@
public final int delete(@RequiresPermission.Write @NonNull Uri url, @Nullable String where,
@Nullable String[] selectionArgs) {
Preconditions.checkNotNull(url, "url");
+
+ try {
+ if (mWrapped != null) return mWrapped.delete(url, where, selectionArgs);
+ } catch (RemoteException e) {
+ return 0;
+ }
+
IContentProvider provider = acquireProvider(url);
if (provider == null) {
throw new IllegalArgumentException("Unknown URL " + url);
@@ -1801,6 +1941,13 @@
@Nullable ContentValues values, @Nullable String where,
@Nullable String[] selectionArgs) {
Preconditions.checkNotNull(uri, "uri");
+
+ try {
+ if (mWrapped != null) return mWrapped.update(uri, values, where, selectionArgs);
+ } catch (RemoteException e) {
+ return 0;
+ }
+
IContentProvider provider = acquireProvider(uri);
if (provider == null) {
throw new IllegalArgumentException("Unknown URI " + uri);
@@ -1844,6 +1991,13 @@
@Nullable String arg, @Nullable Bundle extras) {
Preconditions.checkNotNull(authority, "authority");
Preconditions.checkNotNull(method, "method");
+
+ try {
+ if (mWrapped != null) return mWrapped.call(authority, method, arg, extras);
+ } catch (RemoteException e) {
+ return null;
+ }
+
IContentProvider provider = acquireProvider(authority);
if (provider == null) {
throw new IllegalArgumentException("Unknown authority " + authority);
@@ -2994,14 +3148,17 @@
}
/**
- * Put the cache with the key.
+ * Store the given {@link Bundle} as a long-lived cached object within the
+ * system. This can be useful to avoid expensive re-parsing when apps are
+ * restarted multiple times on low-RAM devices.
+ * <p>
+ * The {@link Bundle} is automatically invalidated when a
+ * {@link #notifyChange(Uri, ContentObserver)} event applies to the key.
*
- * @param key the key to add
- * @param value the value to add
- * {@hide}
+ * @hide
*/
@SystemApi
- public void putCache(Uri key, Bundle value) {
+ public void putCache(@NonNull Uri key, @Nullable Bundle value) {
try {
getContentService().putCache(mContext.getPackageName(), key, value,
mContext.getUserId());
@@ -3011,15 +3168,16 @@
}
/**
- * Get the cache with the key.
+ * Retrieve the last {@link Bundle} stored as a long-lived cached object
+ * within the system.
*
- * @param key the key to get the value
- * @return the matched value. If the key doesn't exist, will return null.
- * @see #putCache(Uri, Bundle)
- * {@hide}
+ * @return {@code null} if no cached object has been stored, or if the
+ * stored object has been invalidated due to a
+ * {@link #notifyChange(Uri, ContentObserver)} event.
+ * @hide
*/
@SystemApi
- public Bundle getCache(Uri key) {
+ public @Nullable Bundle getCache(@NonNull Uri key) {
try {
final Bundle bundle = getContentService().getCache(mContext.getPackageName(), key,
mContext.getUserId());
@@ -3193,6 +3351,7 @@
@UnsupportedAppUsage
final String mPackageName;
final int mTargetSdkVersion;
+ final ContentInterface mWrapped;
private static final String TAG = "ContentResolver";
diff --git a/core/java/android/content/ContentUris.java b/core/java/android/content/ContentUris.java
index fd7b372..767d3f6 100644
--- a/core/java/android/content/ContentUris.java
+++ b/core/java/android/content/ContentUris.java
@@ -16,6 +16,7 @@
package android.content;
+import android.annotation.NonNull;
import android.net.Uri;
import java.util.List;
@@ -83,7 +84,7 @@
* @return the long conversion of the last segment or -1 if the path is
* empty
*/
- public static long parseId(Uri contentUri) {
+ public static long parseId(@NonNull Uri contentUri) {
String last = contentUri.getLastPathSegment();
return last == null ? -1 : Long.parseLong(last);
}
@@ -96,7 +97,7 @@
*
* @return the given builder
*/
- public static Uri.Builder appendId(Uri.Builder builder, long id) {
+ public static @NonNull Uri.Builder appendId(@NonNull Uri.Builder builder, long id) {
return builder.appendEncodedPath(String.valueOf(id));
}
@@ -108,7 +109,7 @@
*
* @return a new URI with the given ID appended to the end of the path
*/
- public static Uri withAppendedId(Uri contentUri, long id) {
+ public static @NonNull Uri withAppendedId(@NonNull Uri contentUri, long id) {
return appendId(contentUri.buildUpon(), id).build();
}
@@ -120,7 +121,7 @@
* @throws IllegalArgumentException when the given URI has no ID to remove
* from the end of the path
*/
- public static Uri removeId(Uri contentUri) {
+ public static @NonNull Uri removeId(@NonNull Uri contentUri) {
// Verify that we have a valid ID to actually remove
final String last = contentUri.getLastPathSegment();
if (last == null) {
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index fda9085..b67349f 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -37,6 +37,7 @@
import android.content.res.Resources;
import android.content.res.TypedArray;
import android.graphics.Rect;
+import android.media.MediaScannerConnection;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
@@ -3094,18 +3095,25 @@
@SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
public static final String ACTION_MEDIA_SCANNER_FINISHED = "android.intent.action.MEDIA_SCANNER_FINISHED";
- /**
- * Broadcast Action: Request the media scanner to scan a file and add it to the media database.
- * The path to the file is contained in the Intent.mData field.
+ /**
+ * Broadcast Action: Request the media scanner to scan a file and add it to
+ * the media database.
+ * <p>
+ * The path to the file is contained in {@link Intent#getData()}.
+ *
+ * @deprecated Starting in the {@link android.os.Build.VERSION_CODES#Q}
+ * release, shared storage paths are sandboxed per application,
+ * and this broadcast cannot correctly translate those sandboxed
+ * paths. Callers will need to instead migrate to using
+ * {@link MediaScannerConnection}.
*/
@SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+ @Deprecated
public static final String ACTION_MEDIA_SCANNER_SCAN_FILE = "android.intent.action.MEDIA_SCANNER_SCAN_FILE";
- /**
- * Broadcast Action: Request the media scanner to scan a storage volume and add it to the media database.
- * The path to the storage volume is contained in the Intent.mData field.
- */
+ /** @hide */
@SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+ @Deprecated
public static final String ACTION_MEDIA_SCANNER_SCAN_VOLUME = "android.intent.action.MEDIA_SCANNER_SCAN_VOLUME";
/**
diff --git a/core/java/android/content/PermissionChecker.java b/core/java/android/content/PermissionChecker.java
index 9f5c877..6fe6e99 100644
--- a/core/java/android/content/PermissionChecker.java
+++ b/core/java/android/content/PermissionChecker.java
@@ -108,8 +108,7 @@
packageName = packageNames[0];
}
- if (appOpsManager.noteProxyOpNoThrow(op, packageName)
- != AppOpsManager.MODE_ALLOWED) {
+ if (appOpsManager.noteProxyOpNoThrow(op, packageName, uid) != AppOpsManager.MODE_ALLOWED) {
return PERMISSION_DENIED_APP_OP;
}
@@ -120,6 +119,9 @@
* Checks whether your app has a given permission and whether the app op
* that corresponds to this permission is allowed.
*
+ * <p>This API assumes the the {@link Binder#getCallingUid()} is the same as
+ * {@link Process#myUid()}.
+ *
* @param context Context for accessing resources.
* @param permission The permission to check.
* @return The permission check result which is either {@link #PERMISSION_GRANTED}
diff --git a/core/java/android/database/sqlite/SQLiteOpenHelper.java b/core/java/android/database/sqlite/SQLiteOpenHelper.java
index ceeecbc..0e869c8 100644
--- a/core/java/android/database/sqlite/SQLiteOpenHelper.java
+++ b/core/java/android/database/sqlite/SQLiteOpenHelper.java
@@ -48,6 +48,9 @@
*
* <p class="note"><strong>Note:</strong> this class assumes
* monotonically increasing version numbers for upgrades.</p>
+ *
+ * <p class="note"><strong>Note:</strong> the {@link AutoCloseable} interface was
+ * first added in the {@link android.os.Build.VERSION_CODES#Q} release.</p>
*/
public abstract class SQLiteOpenHelper implements AutoCloseable {
private static final String TAG = SQLiteOpenHelper.class.getSimpleName();
diff --git a/core/java/android/database/sqlite/SQLiteQueryBuilder.java b/core/java/android/database/sqlite/SQLiteQueryBuilder.java
index ea489c4..03e8507 100644
--- a/core/java/android/database/sqlite/SQLiteQueryBuilder.java
+++ b/core/java/android/database/sqlite/SQLiteQueryBuilder.java
@@ -68,16 +68,16 @@
}
/**
- * Mark the query as DISTINCT.
+ * Mark the query as {@code DISTINCT}.
*
- * @param distinct if true the query is DISTINCT, otherwise it isn't
+ * @param distinct if true the query is {@code DISTINCT}, otherwise it isn't
*/
public void setDistinct(boolean distinct) {
mDistinct = distinct;
}
/**
- * Get if the query is marked as DISTINCT, as last configured by
+ * Get if the query is marked as {@code DISTINCT}, as last configured by
* {@link #setDistinct(boolean)}.
*/
public boolean getDistinct() {
@@ -106,13 +106,13 @@
}
/**
- * Append a chunk to the WHERE clause of the query. All chunks appended are surrounded
- * by parenthesis and ANDed with the selection passed to {@link #query}. The final
- * WHERE clause looks like:
- *
+ * Append a chunk to the {@code WHERE} clause of the query. All chunks appended are surrounded
+ * by parenthesis and {@code AND}ed with the selection passed to {@link #query}. The final
+ * {@code WHERE} clause looks like:
+ * <p>
* WHERE (<append chunk 1><append chunk2>) AND (<query() selection parameter>)
*
- * @param inWhere the chunk of text to append to the WHERE clause.
+ * @param inWhere the chunk of text to append to the {@code WHERE} clause.
*/
public void appendWhere(@NonNull CharSequence inWhere) {
if (mWhereClause == null) {
@@ -122,13 +122,13 @@
}
/**
- * Append a chunk to the WHERE clause of the query. All chunks appended are surrounded
+ * Append a chunk to the {@code WHERE} clause of the query. All chunks appended are surrounded
* by parenthesis and ANDed with the selection passed to {@link #query}. The final
- * WHERE clause looks like:
- *
+ * {@code WHERE} clause looks like:
+ * <p>
* WHERE (<append chunk 1><append chunk2>) AND (<query() selection parameter>)
*
- * @param inWhere the chunk of text to append to the WHERE clause. it will be escaped
+ * @param inWhere the chunk of text to append to the {@code WHERE} clause. it will be escaped
* to avoid SQL injection attacks
*/
public void appendWhereEscapeString(@NonNull String inWhere) {
@@ -264,21 +264,21 @@
* return all columns, which is discouraged to prevent reading
* data from storage that isn't going to be used.
* @param where A filter declaring which rows to return, formatted as an SQL
- * WHERE clause (excluding the WHERE itself). Passing null will
+ * {@code WHERE} clause (excluding the {@code WHERE} itself). Passing {@code null} will
* return all rows for the given URL.
* @param groupBy A filter declaring how to group rows, formatted as an SQL
- * GROUP BY clause (excluding the GROUP BY itself). Passing null
+ * {@code GROUP BY} clause (excluding the {@code GROUP BY} itself). Passing {@code null}
* will cause the rows to not be grouped.
* @param having A filter declare which row groups to include in the cursor,
- * if row grouping is being used, formatted as an SQL HAVING
- * clause (excluding the HAVING itself). Passing null will cause
+ * if row grouping is being used, formatted as an SQL {@code HAVING}
+ * clause (excluding the {@code HAVING} itself). Passing null will cause
* all row groups to be included, and is required when row
* grouping is not being used.
- * @param orderBy How to order the rows, formatted as an SQL ORDER BY clause
- * (excluding the ORDER BY itself). Passing null will use the
+ * @param orderBy How to order the rows, formatted as an SQL {@code ORDER BY} clause
+ * (excluding the {@code ORDER BY} itself). Passing null will use the
* default sort order, which may be unordered.
* @param limit Limits the number of rows returned by the query,
- * formatted as LIMIT clause. Passing null denotes no LIMIT clause.
+ * formatted as {@code LIMIT} clause. Passing null denotes no {@code LIMIT} clause.
* @return the SQL query string
*/
public static String buildQueryString(
@@ -350,22 +350,22 @@
* null will return all columns, which is discouraged to prevent
* reading data from storage that isn't going to be used.
* @param selection A filter declaring which rows to return,
- * formatted as an SQL WHERE clause (excluding the WHERE
+ * formatted as an SQL {@code WHERE} clause (excluding the {@code WHERE}
* itself). Passing null will return all rows for the given URL.
* @param selectionArgs You may include ?s in selection, which
* will be replaced by the values from selectionArgs, in order
* that they appear in the selection. The values will be bound
* as Strings.
* @param groupBy A filter declaring how to group rows, formatted
- * as an SQL GROUP BY clause (excluding the GROUP BY
+ * as an SQL {@code GROUP BY} clause (excluding the {@code GROUP BY}
* itself). Passing null will cause the rows to not be grouped.
* @param having A filter declare which row groups to include in
* the cursor, if row grouping is being used, formatted as an
- * SQL HAVING clause (excluding the HAVING itself). Passing
+ * SQL {@code HAVING} clause (excluding the {@code HAVING} itself). Passing
* null will cause all row groups to be included, and is
* required when row grouping is not being used.
* @param sortOrder How to order the rows, formatted as an SQL
- * ORDER BY clause (excluding the ORDER BY itself). Passing null
+ * {@code ORDER BY} clause (excluding the {@code ORDER BY} itself). Passing null
* will use the default sort order, which may be unordered.
* @return a cursor over the result set
* @see android.content.ContentResolver#query(android.net.Uri, String[],
@@ -387,25 +387,25 @@
* null will return all columns, which is discouraged to prevent
* reading data from storage that isn't going to be used.
* @param selection A filter declaring which rows to return,
- * formatted as an SQL WHERE clause (excluding the WHERE
+ * formatted as an SQL {@code WHERE} clause (excluding the {@code WHERE}
* itself). Passing null will return all rows for the given URL.
* @param selectionArgs You may include ?s in selection, which
* will be replaced by the values from selectionArgs, in order
* that they appear in the selection. The values will be bound
* as Strings.
* @param groupBy A filter declaring how to group rows, formatted
- * as an SQL GROUP BY clause (excluding the GROUP BY
+ * as an SQL {@code GROUP BY} clause (excluding the {@code GROUP BY}
* itself). Passing null will cause the rows to not be grouped.
* @param having A filter declare which row groups to include in
* the cursor, if row grouping is being used, formatted as an
- * SQL HAVING clause (excluding the HAVING itself). Passing
+ * SQL {@code HAVING} clause (excluding the {@code HAVING} itself). Passing
* null will cause all row groups to be included, and is
* required when row grouping is not being used.
* @param sortOrder How to order the rows, formatted as an SQL
- * ORDER BY clause (excluding the ORDER BY itself). Passing null
+ * {@code ORDER BY} clause (excluding the {@code ORDER BY} itself). Passing null
* will use the default sort order, which may be unordered.
* @param limit Limits the number of rows returned by the query,
- * formatted as LIMIT clause. Passing null denotes no LIMIT clause.
+ * formatted as {@code LIMIT} clause. Passing null denotes no {@code LIMIT} clause.
* @return a cursor over the result set
* @see android.content.ContentResolver#query(android.net.Uri, String[],
* String, String[], String)
@@ -426,25 +426,25 @@
* null will return all columns, which is discouraged to prevent
* reading data from storage that isn't going to be used.
* @param selection A filter declaring which rows to return,
- * formatted as an SQL WHERE clause (excluding the WHERE
+ * formatted as an SQL {@code WHERE} clause (excluding the {@code WHERE}
* itself). Passing null will return all rows for the given URL.
* @param selectionArgs You may include ?s in selection, which
* will be replaced by the values from selectionArgs, in order
* that they appear in the selection. The values will be bound
* as Strings.
* @param groupBy A filter declaring how to group rows, formatted
- * as an SQL GROUP BY clause (excluding the GROUP BY
+ * as an SQL {@code GROUP BY} clause (excluding the {@code GROUP BY}
* itself). Passing null will cause the rows to not be grouped.
* @param having A filter declare which row groups to include in
* the cursor, if row grouping is being used, formatted as an
- * SQL HAVING clause (excluding the HAVING itself). Passing
+ * SQL {@code HAVING} clause (excluding the {@code HAVING} itself). Passing
* null will cause all row groups to be included, and is
* required when row grouping is not being used.
* @param sortOrder How to order the rows, formatted as an SQL
- * ORDER BY clause (excluding the ORDER BY itself). Passing null
+ * {@code ORDER BY} clause (excluding the {@code ORDER BY} itself). Passing null
* will use the default sort order, which may be unordered.
* @param limit Limits the number of rows returned by the query,
- * formatted as LIMIT clause. Passing null denotes no LIMIT clause.
+ * formatted as {@code LIMIT} clause. Passing null denotes no {@code LIMIT} clause.
* @param cancellationSignal A signal to cancel the operation in progress, or null if none.
* If the operation is canceled, then {@link OperationCanceledException} will be thrown
* when the query is executed.
@@ -509,7 +509,7 @@
*
* @param db the database to update on
* @param selection A filter declaring which rows to return,
- * formatted as an SQL WHERE clause (excluding the WHERE
+ * formatted as an SQL {@code WHERE} clause (excluding the {@code WHERE}
* itself). Passing null will return all rows for the given URL.
* @param selectionArgs You may include ?s in selection, which
* will be replaced by the values from selectionArgs, in order
@@ -579,7 +579,7 @@
*
* @param db the database to delete on
* @param selection A filter declaring which rows to return,
- * formatted as an SQL WHERE clause (excluding the WHERE
+ * formatted as an SQL {@code WHERE} clause (excluding the {@code WHERE}
* itself). Passing null will return all rows for the given URL.
* @param selectionArgs You may include ?s in selection, which
* will be replaced by the values from selectionArgs, in order
@@ -631,8 +631,8 @@
}
/**
- * Construct a SELECT statement suitable for use in a group of
- * SELECT statements that will be joined through UNION operators
+ * Construct a {@code SELECT} statement suitable for use in a group of
+ * {@code SELECT} statements that will be joined through {@code UNION} operators
* in buildUnionQuery.
*
* @param projectionIn A list of which columns to return. Passing
@@ -640,23 +640,23 @@
* prevent reading data from storage that isn't going to be
* used.
* @param selection A filter declaring which rows to return,
- * formatted as an SQL WHERE clause (excluding the WHERE
+ * formatted as an SQL {@code WHERE} clause (excluding the {@code WHERE}
* itself). Passing null will return all rows for the given
* URL.
* @param groupBy A filter declaring how to group rows, formatted
- * as an SQL GROUP BY clause (excluding the GROUP BY itself).
+ * as an SQL {@code GROUP BY} clause (excluding the {@code GROUP BY} itself).
* Passing null will cause the rows to not be grouped.
* @param having A filter declare which row groups to include in
* the cursor, if row grouping is being used, formatted as an
- * SQL HAVING clause (excluding the HAVING itself). Passing
+ * SQL {@code HAVING} clause (excluding the {@code HAVING} itself). Passing
* null will cause all row groups to be included, and is
* required when row grouping is not being used.
* @param sortOrder How to order the rows, formatted as an SQL
- * ORDER BY clause (excluding the ORDER BY itself). Passing null
+ * {@code ORDER BY} clause (excluding the {@code ORDER BY} itself). Passing null
* will use the default sort order, which may be unordered.
* @param limit Limits the number of rows returned by the query,
- * formatted as LIMIT clause. Passing null denotes no LIMIT clause.
- * @return the resulting SQL SELECT statement
+ * formatted as {@code LIMIT} clause. Passing null denotes no {@code LIMIT} clause.
+ * @return the resulting SQL {@code SELECT} statement
*/
public String buildQuery(
String[] projectionIn, String selection, String groupBy,
@@ -719,8 +719,8 @@
}
/**
- * Construct a SELECT statement suitable for use in a group of
- * SELECT statements that will be joined through UNION operators
+ * Construct a {@code SELECT} statement suitable for use in a group of
+ * {@code SELECT} statements that will be joined through {@code UNION} operators
* in buildUnionQuery.
*
* @param typeDiscriminatorColumn the name of the result column
@@ -728,8 +728,8 @@
* each row was drawn.
* @param unionColumns the names of the columns to appear in the
* result. This may include columns that do not appear in the
- * table this SELECT is querying (i.e. mTables), but that do
- * appear in one of the other tables in the UNION query that we
+ * table this {@code SELECT} is querying (i.e. mTables), but that do
+ * appear in one of the other tables in the {@code UNION} query that we
* are constructing.
* @param columnsPresentInTable a Set of the names of the columns
* that appear in this table (i.e. in the table whose name is
@@ -744,18 +744,18 @@
* @param typeDiscriminatorValue the value used for the
* type-discriminator column in this subquery
* @param selection A filter declaring which rows to return,
- * formatted as an SQL WHERE clause (excluding the WHERE
+ * formatted as an SQL {@code WHERE} clause (excluding the {@code WHERE}
* itself). Passing null will return all rows for the given
* URL.
* @param groupBy A filter declaring how to group rows, formatted
- * as an SQL GROUP BY clause (excluding the GROUP BY itself).
+ * as an SQL {@code GROUP BY} clause (excluding the {@code GROUP BY} itself).
* Passing null will cause the rows to not be grouped.
* @param having A filter declare which row groups to include in
* the cursor, if row grouping is being used, formatted as an
- * SQL HAVING clause (excluding the HAVING itself). Passing
+ * SQL {@code HAVING} clause (excluding the {@code HAVING} itself). Passing
* null will cause all row groups to be included, and is
* required when row grouping is not being used.
- * @return the resulting SQL SELECT statement
+ * @return the resulting SQL {@code SELECT} statement
*/
public String buildUnionSubQuery(
String typeDiscriminatorColumn,
@@ -813,18 +813,18 @@
}
/**
- * Given a set of subqueries, all of which are SELECT statements,
+ * Given a set of subqueries, all of which are {@code SELECT} statements,
* construct a query that returns the union of what those
* subqueries return.
- * @param subQueries an array of SQL SELECT statements, all of
+ * @param subQueries an array of SQL {@code SELECT} statements, all of
* which must have the same columns as the same positions in
* their results
* @param sortOrder How to order the rows, formatted as an SQL
- * ORDER BY clause (excluding the ORDER BY itself). Passing
+ * {@code ORDER BY} clause (excluding the {@code ORDER BY} itself). Passing
* null will use the default sort order, which may be unordered.
* @param limit The limit clause, which applies to the entire union result set
*
- * @return the resulting SQL SELECT statement
+ * @return the resulting SQL {@code SELECT} statement
*/
public String buildUnionQuery(String[] subQueries, String sortOrder, String limit) {
StringBuilder query = new StringBuilder(128);
diff --git a/core/java/android/hardware/display/ColorDisplayManager.java b/core/java/android/hardware/display/ColorDisplayManager.java
index f413d7c..0c07a67 100644
--- a/core/java/android/hardware/display/ColorDisplayManager.java
+++ b/core/java/android/hardware/display/ColorDisplayManager.java
@@ -65,7 +65,8 @@
@SystemApi
public static final int CAPABILITY_NONE = 0x0;
/**
- * The device can properly apply transforms over protected content.
+ * The device can use GPU composition on protected content (layers whose buffers are protected
+ * in the trusted memory zone).
*
* @hide
*/
diff --git a/core/java/android/hardware/display/DisplayManager.java b/core/java/android/hardware/display/DisplayManager.java
index 44b653c..8a0a9c7 100644
--- a/core/java/android/hardware/display/DisplayManager.java
+++ b/core/java/android/hardware/display/DisplayManager.java
@@ -563,7 +563,8 @@
* 0 produces a grayscale image, 1 is normal.
*
* @hide
- * @deprecated use {@link ColorDisplayManager#setSaturationLevel(int)}.
+ * @deprecated use {@link ColorDisplayManager#setSaturationLevel(int)} instead. The level passed
+ * as a parameter here will be rounded to the nearest hundredth.
*/
@SystemApi
@RequiresPermission(Manifest.permission.CONTROL_DISPLAY_SATURATION)
diff --git a/core/java/android/hardware/input/IInputManager.aidl b/core/java/android/hardware/input/IInputManager.aidl
index 97868fa..64448fd9 100644
--- a/core/java/android/hardware/input/IInputManager.aidl
+++ b/core/java/android/hardware/input/IInputManager.aidl
@@ -16,7 +16,6 @@
package android.hardware.input;
-import android.app.IInputForwarder;
import android.hardware.input.InputDeviceIdentifier;
import android.hardware.input.KeyboardLayout;
import android.hardware.input.IInputDevicesChangedListener;
@@ -82,7 +81,4 @@
void setCustomPointerIcon(in PointerIcon icon);
void requestPointerCapture(IBinder windowToken, boolean enabled);
-
- /** Create input forwarder to deliver touch events to owned display. */
- IInputForwarder createInputForwarder(int displayId);
}
diff --git a/core/java/android/hardware/input/InputManager.java b/core/java/android/hardware/input/InputManager.java
index bfb7c58..fec5c34 100644
--- a/core/java/android/hardware/input/InputManager.java
+++ b/core/java/android/hardware/input/InputManager.java
@@ -21,7 +21,6 @@
import android.annotation.SdkConstant.SdkConstantType;
import android.annotation.SystemService;
import android.annotation.UnsupportedAppUsage;
-import android.app.IInputForwarder;
import android.content.Context;
import android.media.AudioAttributes;
import android.os.Binder;
@@ -934,26 +933,6 @@
}
}
-
- /**
- * Create an {@link IInputForwarder} targeted to provided display.
- * {@link android.Manifest.permission.INJECT_EVENTS} permission is required to call this method.
- *
- * @param displayId Id of the target display where input events should be forwarded.
- * Display must exist and must be owned by the caller.
- * @return The forwarder instance.
- *
- * @hide
- */
- @UnsupportedAppUsage
- public IInputForwarder createInputForwarder(int displayId) {
- try {
- return mIm.createInputForwarder(displayId);
- } catch (RemoteException ex) {
- throw ex.rethrowFromSystemServer();
- }
- }
-
private void populateInputDevicesLocked() {
if (mInputDevicesChangedListener == null) {
final InputDevicesChangedListener listener = new InputDevicesChangedListener();
diff --git a/core/java/android/os/Debug.java b/core/java/android/os/Debug.java
index aba81af..149ef54 100644
--- a/core/java/android/os/Debug.java
+++ b/core/java/android/os/Debug.java
@@ -2439,4 +2439,11 @@
VMDebug.attachAgent(library + "=" + options, classLoader);
}
}
+
+ /**
+ * Return the current free ZRAM usage in kilobytes.
+ *
+ * @hide
+ */
+ public static native long getZramFreeKb();
}
diff --git a/core/java/android/os/Environment.java b/core/java/android/os/Environment.java
index 3feccf5..0aed981 100644
--- a/core/java/android/os/Environment.java
+++ b/core/java/android/os/Environment.java
@@ -388,7 +388,7 @@
/** {@hide} */
public static File getDataStagingDirectory(String volumeUuid) {
- return new File(getDataDirectory(volumeUuid), "staging");
+ return new File(getDataDirectory(volumeUuid), "pkg_staging");
}
/** {@hide} */
diff --git a/core/java/android/os/FileUtils.java b/core/java/android/os/FileUtils.java
index 0384faa..316572c 100644
--- a/core/java/android/os/FileUtils.java
+++ b/core/java/android/os/FileUtils.java
@@ -85,7 +85,7 @@
/**
* Utility methods useful for working with files.
*/
-public class FileUtils {
+public final class FileUtils {
private static final String TAG = "FileUtils";
/** {@hide} */ public static final int S_IRWXU = 00700;
@@ -309,6 +309,7 @@
* kernel before falling back to a userspace copy as a last resort.
*
* @return number of bytes copied.
+ * @hide
*/
public static long copy(@NonNull File from, @NonNull File to) throws IOException {
return copy(from, to, null, null, null);
@@ -324,6 +325,7 @@
* @param executor that listener events should be delivered via.
* @param listener to be periodically notified as the copy progresses.
* @return number of bytes copied.
+ * @hide
*/
public static long copy(@NonNull File from, @NonNull File to,
@Nullable CancellationSignal signal, @Nullable Executor executor,
diff --git a/core/java/android/os/GraphicsEnvironment.java b/core/java/android/os/GraphicsEnvironment.java
index cc241b3..4a14ece 100644
--- a/core/java/android/os/GraphicsEnvironment.java
+++ b/core/java/android/os/GraphicsEnvironment.java
@@ -25,7 +25,6 @@
import android.content.pm.ResolveInfo;
import android.content.res.AssetFileDescriptor;
import android.content.res.AssetManager;
-import android.opengl.EGL14;
import android.provider.Settings;
import android.util.Log;
import android.widget.Toast;
@@ -61,6 +60,7 @@
private static final String SYSTEM_DRIVER_VERSION_NAME = "";
private static final long SYSTEM_DRIVER_VERSION_CODE = 0;
private static final String PROPERTY_GFX_DRIVER = "ro.gfx.driver.0";
+ private static final String PROPERTY_GFX_DRIVER_BUILD_DATE = "ro.gfx.driver.build_date";
private static final String ANGLE_RULES_FILE = "a4a_rules.json";
private static final String ANGLE_TEMP_RULES = "debug.angle.rules";
private static final String ACTION_ANGLE_FOR_ANDROID = "android.app.action.ANGLE_FOR_ANDROID";
@@ -79,8 +79,9 @@
setupGpuLayers(context, coreSettings, pm, packageName);
setupAngle(context, coreSettings, pm, packageName);
if (!chooseDriver(context, coreSettings, pm, packageName)) {
+ final String driverBuildDate = SystemProperties.get(PROPERTY_GFX_DRIVER_BUILD_DATE);
setGpuStats(SYSTEM_DRIVER_NAME, SYSTEM_DRIVER_VERSION_NAME, SYSTEM_DRIVER_VERSION_CODE,
- packageName);
+ driverBuildDate == null ? "" : driverBuildDate, packageName);
}
}
@@ -574,8 +575,8 @@
final PackageInfo driverPackageInfo;
try {
- driverPackageInfo =
- pm.getPackageInfo(driverPackageName, PackageManager.MATCH_SYSTEM_ONLY);
+ driverPackageInfo = pm.getPackageInfo(driverPackageName,
+ PackageManager.MATCH_SYSTEM_ONLY | PackageManager.GET_META_DATA);
} catch (PackageManager.NameNotFoundException e) {
Log.w(TAG, "driver package '" + driverPackageName + "' not installed");
return false;
@@ -655,9 +656,6 @@
return false;
}
- setGpuStats(driverPackageName, driverPackageInfo.versionName, driverAppInfo.longVersionCode,
- packageName);
-
final StringBuilder sb = new StringBuilder();
sb.append(driverAppInfo.nativeLibraryDir)
.append(File.pathSeparator);
@@ -669,26 +667,13 @@
if (DEBUG) Log.v(TAG, "gfx driver package libs: " + paths);
setDriverPath(paths);
- return true;
- }
+ final String driverBuildDate = driverAppInfo.metaData == null
+ ? ""
+ : driverAppInfo.metaData.getString("driver_build_date");
+ setGpuStats(driverPackageName, driverPackageInfo.versionName, driverAppInfo.longVersionCode,
+ driverBuildDate == null ? "" : driverBuildDate, packageName);
- /**
- * Start a background thread to initialize EGL.
- *
- * Initializing EGL involves loading and initializing the graphics driver. Some drivers take
- * several 10s of milliseconds to do this, so doing it on-demand when an app tries to render
- * its first frame adds directly to user-visible app launch latency. By starting it earlier
- * on a separate thread, it can usually be finished well before the UI is ready to be drawn.
- *
- * Should only be called after chooseDriver().
- */
- public static void earlyInitEGL() {
- final Thread eglInitThread = new Thread(
- () -> {
- EGL14.eglGetDisplay(EGL14.EGL_DEFAULT_DISPLAY);
- },
- "EGL Init");
- eglInitThread.start();
+ return true;
}
private static String chooseAbi(ApplicationInfo ai) {
@@ -710,7 +695,7 @@
private static native void setDebugLayersGLES(String layers);
private static native void setDriverPath(String path);
private static native void setGpuStats(String driverPackageName, String driverVersionName,
- long driverVersionCode, String appPackageName);
+ long driverVersionCode, String driverBuildDate, String appPackageName);
private static native void setAngleInfo(String path, String appPackage, String devOptIn,
FileDescriptor rulesFd, long rulesOffset, long rulesLength);
private static native boolean getShouldUseAngle(String packageName);
diff --git a/core/java/android/os/IPowerManager.aidl b/core/java/android/os/IPowerManager.aidl
index bdef575..483c41a 100644
--- a/core/java/android/os/IPowerManager.aidl
+++ b/core/java/android/os/IPowerManager.aidl
@@ -74,4 +74,7 @@
// controls whether PowerManager should doze after the screen turns off or not
void setDozeAfterScreenOff(boolean on);
+
+ // Forces the system to suspend even if there are held wakelocks.
+ boolean forceSuspend();
}
diff --git a/core/java/android/os/PowerManager.java b/core/java/android/os/PowerManager.java
index cfe2d28..6bd1f2b 100644
--- a/core/java/android/os/PowerManager.java
+++ b/core/java/android/os/PowerManager.java
@@ -363,10 +363,15 @@
public static final int USER_ACTIVITY_FLAG_INDIRECT = 1 << 1;
/**
+ * @hide
+ */
+ public static final int GO_TO_SLEEP_REASON_MIN = 0;
+
+ /**
* Go to sleep reason code: Going to sleep due by application request.
* @hide
*/
- public static final int GO_TO_SLEEP_REASON_APPLICATION = 0;
+ public static final int GO_TO_SLEEP_REASON_APPLICATION = GO_TO_SLEEP_REASON_MIN;
/**
* Go to sleep reason code: Going to sleep due by request of the
@@ -412,6 +417,17 @@
public static final int GO_TO_SLEEP_REASON_ACCESSIBILITY = 7;
/**
+ * Go to sleep reason code: Going to sleep due to force-suspend.
+ * @hide
+ */
+ public static final int GO_TO_SLEEP_REASON_FORCE_SUSPEND = 8;
+
+ /**
+ * @hide
+ */
+ public static final int GO_TO_SLEEP_REASON_MAX = GO_TO_SLEEP_REASON_FORCE_SUSPEND;
+
+ /**
* @hide
*/
public static String sleepReasonToString(int sleepReason) {
@@ -424,6 +440,7 @@
case GO_TO_SLEEP_REASON_HDMI: return "hdmi";
case GO_TO_SLEEP_REASON_SLEEP_BUTTON: return "sleep_button";
case GO_TO_SLEEP_REASON_ACCESSIBILITY: return "accessibility";
+ case GO_TO_SLEEP_REASON_FORCE_SUSPEND: return "force_suspend";
default: return Integer.toString(sleepReason);
}
}
@@ -1853,6 +1870,32 @@
}
/**
+ * Forces the device to go to suspend, even if there are currently wakelocks being held.
+ * <b>Caution</b>
+ * This is a very dangerous command as it puts the device to sleep immediately. Apps and parts
+ * of the system will not be notified and will not have an opportunity to save state prior to
+ * the device going to suspend.
+ * This method should only be used in very rare circumstances where the device is intended
+ * to appear as completely off to the user and they have a well understood, reliable way of
+ * re-enabling it.
+ * </p><p>
+ * Requires the {@link android.Manifest.permission#DEVICE_POWER} permission.
+ * </p>
+ *
+ * @return true on success, false otherwise.
+ * @hide
+ */
+ @SystemApi
+ @RequiresPermission(android.Manifest.permission.DEVICE_POWER)
+ public boolean forceSuspend() {
+ try {
+ return mService.forceSuspend();
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
* Intent that is broadcast when the state of {@link #isPowerSaveMode()} changes.
* This broadcast is only sent to registered receivers.
*/
diff --git a/core/java/android/os/ZygoteProcess.java b/core/java/android/os/ZygoteProcess.java
index ee3d354..1de8117 100644
--- a/core/java/android/os/ZygoteProcess.java
+++ b/core/java/android/os/ZygoteProcess.java
@@ -21,6 +21,7 @@
import android.content.pm.ApplicationInfo;
import android.net.LocalSocket;
import android.net.LocalSocketAddress;
+import android.provider.DeviceConfig;
import android.util.Log;
import android.util.Slog;
@@ -66,16 +67,6 @@
/**
* @hide for internal use only.
*/
- public static final String ZYGOTE_SOCKET_NAME = "zygote";
-
- /**
- * @hide for internal use only.
- */
- public static final String ZYGOTE_SECONDARY_SOCKET_NAME = "zygote_secondary";
-
- /**
- * @hide for internal use only.
- */
public static final int ZYGOTE_CONNECT_TIMEOUT_MS = 20000;
/**
@@ -89,19 +80,14 @@
/**
* @hide for internal use only
*/
- public static final String BLASTULA_POOL_SOCKET_NAME = "blastula_pool";
-
- /**
- * @hide for internal use only
- */
- public static final String BLASTULA_POOL_SECONDARY_SOCKET_NAME = "blastula_pool_secondary";
-
- /**
- * @hide for internal use only
- */
private static final String LOG_TAG = "ZygoteProcess";
/**
+ * The default value for enabling the blastula pool.
+ */
+ private static final String BLASTULA_POOL_ENABLED_DEFAULT = "false";
+
+ /**
* The name of the socket used to communicate with the primary zygote.
*/
private final LocalSocketAddress mZygoteSocketAddress;
@@ -110,6 +96,7 @@
* The name of the secondary (alternate ABI) zygote socket.
*/
private final LocalSocketAddress mZygoteSecondarySocketAddress;
+
/**
* The name of the socket used to communicate with the primary blastula pool.
*/
@@ -122,17 +109,21 @@
public ZygoteProcess() {
mZygoteSocketAddress =
- new LocalSocketAddress(ZYGOTE_SOCKET_NAME, LocalSocketAddress.Namespace.RESERVED);
+ new LocalSocketAddress(Zygote.PRIMARY_SOCKET_NAME,
+ LocalSocketAddress.Namespace.RESERVED);
mZygoteSecondarySocketAddress =
- new LocalSocketAddress(ZYGOTE_SECONDARY_SOCKET_NAME,
+ new LocalSocketAddress(Zygote.SECONDARY_SOCKET_NAME,
LocalSocketAddress.Namespace.RESERVED);
mBlastulaPoolSocketAddress =
- new LocalSocketAddress(BLASTULA_POOL_SOCKET_NAME,
+ new LocalSocketAddress(Zygote.BLASTULA_POOL_PRIMARY_SOCKET_NAME,
LocalSocketAddress.Namespace.RESERVED);
mBlastulaPoolSecondarySocketAddress =
- new LocalSocketAddress(BLASTULA_POOL_SECONDARY_SOCKET_NAME,
+ new LocalSocketAddress(Zygote.BLASTULA_POOL_SECONDARY_SOCKET_NAME,
LocalSocketAddress.Namespace.RESERVED);
+
+ // TODO (chriswailes): Uncomment when the blastula pool can be enabled.
+// fetchBlastulaPoolEnabledProp();
}
public ZygoteProcess(LocalSocketAddress primarySocketAddress,
@@ -272,6 +263,15 @@
private ZygoteState secondaryZygoteState;
/**
+ * If the blastula pool should be created and used to start applications.
+ *
+ * Setting this value to false will disable the creation, maintenance, and use of the blastula
+ * pool. When the blastula pool is disabled the application lifecycle will be identical to
+ * previous versions of Android.
+ */
+ private boolean mBlastulaPoolEnabled = false;
+
+ /**
* Start a new process.
*
* <p>If processes are enabled, a new process is created and the
@@ -327,6 +327,14 @@
@Nullable String sandboxId,
boolean useBlastulaPool,
@Nullable String[] zygoteArgs) {
+ if (fetchBlastulaPoolEnabledProp()) {
+ // TODO (chriswailes): Send the appropriate command to the zygotes
+ Log.i(LOG_TAG, "Blastula pool enabled property set to: " + mBlastulaPoolEnabled);
+
+ // This can't be enabled yet, but we do want to test this code path.
+ mBlastulaPoolEnabled = false;
+ }
+
try {
return startViaZygote(processClass, niceName, uid, gid, gids,
runtimeFlags, mountExternal, targetSdkVersion, seInfo,
@@ -407,7 +415,7 @@
Process.ProcessStartResult result = new Process.ProcessStartResult();
// TODO (chriswailes): Move branch body into separate function.
- if (useBlastulaPool && Zygote.BLASTULA_POOL_ENABLED && isValidBlastulaCommand(args)) {
+ if (useBlastulaPool && isValidBlastulaCommand(args)) {
LocalSocket blastulaSessionSocket = null;
try {
@@ -620,6 +628,7 @@
final StringBuilder sb = new StringBuilder();
sb.append("--packages-for-uid=");
+ // TODO (chriswailes): Replace with String.join
for (int i = 0; i < packagesForUid.length; ++i) {
if (i != 0) {
sb.append(',');
@@ -656,11 +665,42 @@
synchronized(mLock) {
return zygoteSendArgsAndGetResult(openZygoteSocketIfNeeded(abi),
- useBlastulaPool,
+ useBlastulaPool && mBlastulaPoolEnabled,
argsForZygote);
}
}
+ private boolean fetchBlastulaPoolEnabledProp() {
+ boolean origVal = mBlastulaPoolEnabled;
+
+ final String propertyString =
+ Zygote.getSystemProperty(
+ DeviceConfig.RuntimeNative.BLASTULA_POOL_ENABLED,
+ BLASTULA_POOL_ENABLED_DEFAULT);
+
+ if (!propertyString.isEmpty()) {
+ mBlastulaPoolEnabled =
+ Zygote.getSystemPropertyBoolean(
+ DeviceConfig.RuntimeNative.BLASTULA_POOL_ENABLED,
+ Boolean.parseBoolean(BLASTULA_POOL_ENABLED_DEFAULT));
+ }
+
+ return origVal != mBlastulaPoolEnabled;
+ }
+
+ private long mLastPropCheckTimestamp = 0;
+
+ private boolean fetchBlastulaPoolEnabledPropWithMinInterval() {
+ final long currentTimestamp = SystemClock.elapsedRealtime();
+
+ if (currentTimestamp - mLastPropCheckTimestamp >= Zygote.PROPERTY_CHECK_INTERVAL) {
+ mLastPropCheckTimestamp = currentTimestamp;
+ return fetchBlastulaPoolEnabledProp();
+ }
+
+ return false;
+ }
+
/**
* Closes the connections to the zygote, if they exist.
*/
@@ -940,7 +980,7 @@
/**
* Try connecting to the Zygote over and over again until we hit a time-out.
- * @param socketName The name of the socket to connect to.
+ * @param zygoteSocketName The name of the socket to connect to.
*/
public static void waitForConnectionToZygote(String zygoteSocketName) {
final LocalSocketAddress zygoteSocketAddress =
@@ -950,7 +990,7 @@
/**
* Try connecting to the Zygote over and over again until we hit a time-out.
- * @param address The name of the socket to connect to.
+ * @param zygoteSocketAddress The name of the socket to connect to.
*/
public static void waitForConnectionToZygote(LocalSocketAddress zygoteSocketAddress) {
int numRetries = ZYGOTE_CONNECT_TIMEOUT_MS / ZYGOTE_CONNECT_RETRY_DELAY_MS;
diff --git a/core/java/android/os/storage/StorageManager.java b/core/java/android/os/storage/StorageManager.java
index 43c9064..90a5f76 100644
--- a/core/java/android/os/storage/StorageManager.java
+++ b/core/java/android/os/storage/StorageManager.java
@@ -38,6 +38,7 @@
import android.content.pm.PackageManager;
import android.content.res.ObbInfo;
import android.content.res.ObbScanner;
+import android.net.Uri;
import android.os.Binder;
import android.os.Environment;
import android.os.FileUtils;
@@ -55,6 +56,7 @@
import android.os.ServiceManager;
import android.os.ServiceManager.ServiceNotFoundException;
import android.os.SystemProperties;
+import android.provider.MediaStore;
import android.provider.Settings;
import android.sysprop.VoldProperties;
import android.system.ErrnoException;
@@ -1096,12 +1098,32 @@
}
/**
- * Return the {@link StorageVolume} that contains the given file, or {@code null} if none.
+ * Return the {@link StorageVolume} that contains the given file, or
+ * {@code null} if none.
*/
public @Nullable StorageVolume getStorageVolume(File file) {
return getStorageVolume(getVolumeList(), file);
}
+ /**
+ * Return the {@link StorageVolume} that contains the given
+ * {@link MediaStore} item.
+ */
+ public @NonNull StorageVolume getStorageVolume(@NonNull Uri uri) {
+ final String volumeName = MediaStore.getVolumeName(uri);
+ switch (volumeName) {
+ case MediaStore.VOLUME_EXTERNAL:
+ return getPrimaryStorageVolume();
+ default:
+ for (StorageVolume vol : getStorageVolumes()) {
+ if (Objects.equals(vol.getNormalizedUuid(), volumeName)) {
+ return vol;
+ }
+ }
+ }
+ throw new IllegalStateException("Unknown volume for " + uri);
+ }
+
/** {@hide} */
public static @Nullable StorageVolume getStorageVolume(File file, int userId) {
return getStorageVolume(getVolumeList(userId, 0), file);
@@ -1539,7 +1561,13 @@
return SystemProperties.getBoolean(PROP_HAS_ADOPTABLE, false);
}
- /** {@hide} */
+ /**
+ * Return if the currently booted device has the "isolated storage" feature
+ * flag enabled. This will eventually be fully enabled in the final
+ * {@link android.os.Build.VERSION_CODES#Q} release.
+ *
+ * @hide
+ */
@SystemApi
@TestApi
public static boolean hasIsolatedStorage() {
diff --git a/core/java/android/permission/PermissionControllerManager.java b/core/java/android/permission/PermissionControllerManager.java
index addfe3d..d62bc6c5 100644
--- a/core/java/android/permission/PermissionControllerManager.java
+++ b/core/java/android/permission/PermissionControllerManager.java
@@ -51,6 +51,7 @@
import android.os.UserHandle;
import android.util.ArrayMap;
import android.util.Log;
+import android.util.SparseArray;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.infra.AbstractMultiplePendingRequestsRemoteService;
@@ -85,9 +86,11 @@
private static final Object sLock = new Object();
- /** App global remote service used by all {@link PermissionControllerManager managers} */
+ /**
+ * Global remote services (per user) used by all {@link PermissionControllerManager managers}
+ */
@GuardedBy("sLock")
- private static RemoteService sRemoteService;
+ private static SparseArray<RemoteService> sRemoteServices = new SparseArray<>(1);
/**
* The key for retrieving the result from the returned bundle.
@@ -203,6 +206,7 @@
}
private final @NonNull Context mContext;
+ private final @NonNull RemoteService mRemoteService;
/**
* Create a new {@link PermissionControllerManager}.
@@ -213,14 +217,18 @@
*/
public PermissionControllerManager(@NonNull Context context) {
synchronized (sLock) {
- if (sRemoteService == null) {
+ RemoteService remoteService = sRemoteServices.get(context.getUserId(), null);
+ if (remoteService == null) {
Intent intent = new Intent(SERVICE_INTERFACE);
intent.setPackage(context.getPackageManager().getPermissionControllerPackageName());
ResolveInfo serviceInfo = context.getPackageManager().resolveService(intent, 0);
- sRemoteService = new RemoteService(context.getApplicationContext(),
- serviceInfo.getComponentInfo().getComponentName());
+ remoteService = new RemoteService(context.getApplicationContext(),
+ serviceInfo.getComponentInfo().getComponentName(), context.getUser());
+ sRemoteServices.put(context.getUserId(), remoteService);
}
+
+ mRemoteService = remoteService;
}
mContext = context;
@@ -255,7 +263,7 @@
+ " required");
}
- sRemoteService.scheduleRequest(new PendingRevokeRuntimePermissionRequest(sRemoteService,
+ mRemoteService.scheduleRequest(new PendingRevokeRuntimePermissionRequest(mRemoteService,
request, doDryRun, reason, mContext.getPackageName(), executor, callback));
}
@@ -276,7 +284,7 @@
checkNotNull(executor);
checkNotNull(callback);
- sRemoteService.scheduleRequest(new PendingGetRuntimePermissionBackup(sRemoteService,
+ mRemoteService.scheduleRequest(new PendingGetRuntimePermissionBackup(mRemoteService,
user, executor, callback));
}
@@ -294,8 +302,8 @@
checkNotNull(backup);
checkNotNull(user);
- sRemoteService.scheduleAsyncRequest(
- new PendingRestoreRuntimePermissionBackup(sRemoteService, backup, user));
+ mRemoteService.scheduleAsyncRequest(
+ new PendingRestoreRuntimePermissionBackup(mRemoteService, backup, user));
}
/**
@@ -318,8 +326,8 @@
checkNotNull(executor);
checkNotNull(callback);
- sRemoteService.scheduleRequest(
- new PendingRestoreDelayedRuntimePermissionBackup(sRemoteService, packageName,
+ mRemoteService.scheduleRequest(
+ new PendingRestoreDelayedRuntimePermissionBackup(mRemoteService, packageName,
user, executor, callback));
}
@@ -338,8 +346,8 @@
checkNotNull(packageName);
checkNotNull(callback);
- sRemoteService.scheduleRequest(new PendingGetAppPermissionRequest(sRemoteService,
- packageName, callback, handler == null ? sRemoteService.getHandler() : handler));
+ mRemoteService.scheduleRequest(new PendingGetAppPermissionRequest(mRemoteService,
+ packageName, callback, handler == null ? mRemoteService.getHandler() : handler));
}
/**
@@ -356,7 +364,7 @@
checkNotNull(packageName);
checkNotNull(permissionName);
- sRemoteService.scheduleAsyncRequest(new PendingRevokeAppPermissionRequest(packageName,
+ mRemoteService.scheduleAsyncRequest(new PendingRevokeAppPermissionRequest(packageName,
permissionName));
}
@@ -379,9 +387,9 @@
checkFlagsArgument(flags, COUNT_WHEN_SYSTEM | COUNT_ONLY_WHEN_GRANTED);
checkNotNull(callback);
- sRemoteService.scheduleRequest(new PendingCountPermissionAppsRequest(sRemoteService,
+ mRemoteService.scheduleRequest(new PendingCountPermissionAppsRequest(mRemoteService,
permissionNames, flags, callback,
- handler == null ? sRemoteService.getHandler() : handler));
+ handler == null ? mRemoteService.getHandler() : handler));
}
/**
@@ -402,7 +410,7 @@
checkNotNull(executor);
checkNotNull(callback);
- sRemoteService.scheduleRequest(new PendingGetPermissionUsagesRequest(sRemoteService,
+ mRemoteService.scheduleRequest(new PendingGetPermissionUsagesRequest(mRemoteService,
countSystem, numMillis, executor, callback));
}
@@ -424,8 +432,8 @@
checkNotNull(executor);
checkNotNull(callback);
- sRemoteService.scheduleRequest(new PendingIsApplicationQualifiedForRoleRequest(
- sRemoteService, roleName, packageName, executor, callback));
+ mRemoteService.scheduleRequest(new PendingIsApplicationQualifiedForRoleRequest(
+ mRemoteService, roleName, packageName, executor, callback));
}
/**
@@ -441,11 +449,12 @@
*
* @param context A context to use
* @param componentName The component of the service to connect to
+ * @param user User the remote service should be connected as
*/
- RemoteService(@NonNull Context context, @NonNull ComponentName componentName) {
- super(context, SERVICE_INTERFACE, componentName, UserHandle.myUserId(),
- service -> Log.e(TAG, "RuntimePermPresenterService " + service + " died"),
- false, false, 1);
+ RemoteService(@NonNull Context context, @NonNull ComponentName componentName,
+ @NonNull UserHandle user) {
+ super(context, SERVICE_INTERFACE, componentName, user.getIdentifier(),
+ service -> Log.e(TAG, "RemoteService " + service + " died"), false, false, 1);
}
/**
diff --git a/core/java/android/provider/DeviceConfig.java b/core/java/android/provider/DeviceConfig.java
index 7eb0300..f6a8388 100644
--- a/core/java/android/provider/DeviceConfig.java
+++ b/core/java/android/provider/DeviceConfig.java
@@ -145,6 +145,38 @@
@SystemApi
public interface RuntimeNative {
String NAMESPACE = "runtime_native";
+
+ /**
+ * Zygote flags. See {@link com.internal.os.Zygote}.
+ */
+
+ /**
+ * If {@code true}, enables the blastula pool feature.
+ *
+ * @hide for internal use only
+ */
+ String BLASTULA_POOL_ENABLED = "blastula_pool_enabled";
+
+ /**
+ * The maximum number of processes to keep in the blastula pool.
+ *
+ * @hide for internal use only
+ */
+ String BLASTULA_POOL_SIZE_MAX = "blastula_pool_size_max";
+
+ /**
+ * The minimum number of processes to keep in the blastula pool.
+ *
+ * @hide for internal use only
+ */
+ String BLASTULA_POOL_SIZE_MIN = "blastula_pool_size_max";
+
+ /**
+ * The threshold used to determine if the pool should be refilled.
+ *
+ * @hide for internal use only
+ */
+ String BLASTULA_POOL_REFILL_THRESHOLD = "blastula_refill_threshold";
}
/**
diff --git a/core/java/android/provider/DocumentsContract.java b/core/java/android/provider/DocumentsContract.java
index 5708342..d282967 100644
--- a/core/java/android/provider/DocumentsContract.java
+++ b/core/java/android/provider/DocumentsContract.java
@@ -1281,8 +1281,9 @@
* @see DocumentsProvider#openDocumentThumbnail(String, Point,
* android.os.CancellationSignal)
*/
- public static Bitmap getDocumentThumbnail(ContentInterface content, Uri documentUri, Point size,
- CancellationSignal signal) throws FileNotFoundException {
+ public static @Nullable Bitmap getDocumentThumbnail(@NonNull ContentResolver content,
+ @NonNull Uri documentUri, @NonNull Point size, @Nullable CancellationSignal signal)
+ throws FileNotFoundException {
try {
return ContentResolver.loadThumbnail(content, documentUri, Point.convert(size), signal,
ImageDecoder.ALLOCATOR_SOFTWARE);
@@ -1295,12 +1296,6 @@
}
}
- @Deprecated
- public static Bitmap getDocumentThumbnail(ContentResolver content, Uri documentUri, Point size,
- CancellationSignal signal) throws FileNotFoundException {
- return getDocumentThumbnail((ContentInterface) content, documentUri, size, signal);
- }
-
/**
* Create a new document with given MIME type and display name.
*
@@ -1309,8 +1304,9 @@
* @param displayName name of new document
* @return newly created document, or {@code null} if failed
*/
- public static Uri createDocument(ContentInterface content, Uri parentDocumentUri,
- String mimeType, String displayName) throws FileNotFoundException {
+ public static @Nullable Uri createDocument(@NonNull ContentResolver content,
+ @NonNull Uri parentDocumentUri, @NonNull String mimeType, @NonNull String displayName)
+ throws FileNotFoundException {
try {
final Bundle in = new Bundle();
in.putParcelable(DocumentsContract.EXTRA_URI, parentDocumentUri);
@@ -1327,12 +1323,6 @@
}
}
- @Deprecated
- public static Uri createDocument(ContentResolver content, Uri parentDocumentUri,
- String mimeType, String displayName) throws FileNotFoundException {
- return createDocument((ContentInterface) content, parentDocumentUri, mimeType, displayName);
- }
-
/**
* Test if a document is descendant (child, grandchild, etc) from the given
* parent.
@@ -1342,7 +1332,7 @@
* @return if given document is a descendant of the given parent.
* @see Root#FLAG_SUPPORTS_IS_CHILD
*/
- public static boolean isChildDocument(@NonNull ContentInterface content,
+ public static boolean isChildDocument(@NonNull ContentResolver content,
@NonNull Uri parentDocumentUri, @NonNull Uri childDocumentUri)
throws FileNotFoundException {
Preconditions.checkNotNull(content, "content can not be null");
@@ -1369,12 +1359,6 @@
}
}
- @Deprecated
- public static boolean isChildDocument(ContentResolver content, Uri parentDocumentUri,
- Uri childDocumentUri) throws FileNotFoundException {
- return isChildDocument((ContentInterface) content, parentDocumentUri, childDocumentUri);
- }
-
/**
* Change the display name of an existing document.
* <p>
@@ -1388,8 +1372,8 @@
* @return the existing or new document after the rename, or {@code null} if
* failed.
*/
- public static Uri renameDocument(ContentInterface content, Uri documentUri,
- String displayName) throws FileNotFoundException {
+ public static @Nullable Uri renameDocument(@NonNull ContentResolver content,
+ @NonNull Uri documentUri, @NonNull String displayName) throws FileNotFoundException {
try {
final Bundle in = new Bundle();
in.putParcelable(DocumentsContract.EXTRA_URI, documentUri);
@@ -1406,19 +1390,13 @@
}
}
- @Deprecated
- public static Uri renameDocument(ContentResolver content, Uri documentUri,
- String displayName) throws FileNotFoundException {
- return renameDocument((ContentInterface) content, documentUri, displayName);
- }
-
/**
* Delete the given document.
*
* @param documentUri document with {@link Document#FLAG_SUPPORTS_DELETE}
* @return if the document was deleted successfully.
*/
- public static boolean deleteDocument(ContentInterface content, Uri documentUri)
+ public static boolean deleteDocument(@NonNull ContentResolver content, @NonNull Uri documentUri)
throws FileNotFoundException {
try {
final Bundle in = new Bundle();
@@ -1434,12 +1412,6 @@
}
}
- @Deprecated
- public static boolean deleteDocument(ContentResolver content, Uri documentUri)
- throws FileNotFoundException {
- return deleteDocument((ContentInterface) content, documentUri);
- }
-
/**
* Copies the given document.
*
@@ -1448,8 +1420,9 @@
* document's copy.
* @return the copied document, or {@code null} if failed.
*/
- public static Uri copyDocument(ContentInterface content, Uri sourceDocumentUri,
- Uri targetParentDocumentUri) throws FileNotFoundException {
+ public static @Nullable Uri copyDocument(@NonNull ContentResolver content,
+ @NonNull Uri sourceDocumentUri, @NonNull Uri targetParentDocumentUri)
+ throws FileNotFoundException {
try {
final Bundle in = new Bundle();
in.putParcelable(DocumentsContract.EXTRA_URI, sourceDocumentUri);
@@ -1465,12 +1438,6 @@
}
}
- @Deprecated
- public static Uri copyDocument(ContentResolver content, Uri sourceDocumentUri,
- Uri targetParentDocumentUri) throws FileNotFoundException {
- return copyDocument((ContentInterface) content, sourceDocumentUri, targetParentDocumentUri);
- }
-
/**
* Moves the given document under a new parent.
*
@@ -1480,8 +1447,9 @@
* document.
* @return the moved document, or {@code null} if failed.
*/
- public static Uri moveDocument(ContentInterface content, Uri sourceDocumentUri,
- Uri sourceParentDocumentUri, Uri targetParentDocumentUri) throws FileNotFoundException {
+ public static @Nullable Uri moveDocument(@NonNull ContentResolver content,
+ @NonNull Uri sourceDocumentUri, @NonNull Uri sourceParentDocumentUri,
+ @NonNull Uri targetParentDocumentUri) throws FileNotFoundException {
try {
final Bundle in = new Bundle();
in.putParcelable(DocumentsContract.EXTRA_URI, sourceDocumentUri);
@@ -1498,13 +1466,6 @@
}
}
- @Deprecated
- public static Uri moveDocument(ContentResolver content, Uri sourceDocumentUri,
- Uri sourceParentDocumentUri, Uri targetParentDocumentUri) throws FileNotFoundException {
- return moveDocument((ContentInterface) content, sourceDocumentUri, sourceParentDocumentUri,
- targetParentDocumentUri);
- }
-
/**
* Removes the given document from a parent directory.
*
@@ -1515,8 +1476,8 @@
* @param parentDocumentUri parent document of the document to remove.
* @return true if the document was removed successfully.
*/
- public static boolean removeDocument(ContentInterface content, Uri documentUri,
- Uri parentDocumentUri) throws FileNotFoundException {
+ public static boolean removeDocument(@NonNull ContentResolver content, @NonNull Uri documentUri,
+ @NonNull Uri parentDocumentUri) throws FileNotFoundException {
try {
final Bundle in = new Bundle();
in.putParcelable(DocumentsContract.EXTRA_URI, documentUri);
@@ -1532,34 +1493,23 @@
}
}
- @Deprecated
- public static boolean removeDocument(ContentResolver content, Uri documentUri,
- Uri parentDocumentUri) throws FileNotFoundException {
- return removeDocument((ContentInterface) content, documentUri, parentDocumentUri);
- }
-
/**
* Ejects the given root. It throws {@link IllegalStateException} when ejection failed.
*
* @param rootUri root with {@link Root#FLAG_SUPPORTS_EJECT} to be ejected
*/
- public static void ejectRoot(ContentInterface content, Uri rootUri) {
+ public static void ejectRoot(@NonNull ContentResolver content, @NonNull Uri rootUri) {
try {
final Bundle in = new Bundle();
in.putParcelable(DocumentsContract.EXTRA_URI, rootUri);
content.call(rootUri.getAuthority(),
METHOD_EJECT_ROOT, null, in);
- } catch (RemoteException e) {
- e.rethrowAsRuntimeException();
+ } catch (Exception e) {
+ Log.w(TAG, "Failed to eject", e);
}
}
- @Deprecated
- public static void ejectRoot(ContentResolver content, Uri rootUri) {
- ejectRoot((ContentInterface) content, rootUri);
- }
-
/**
* Returns metadata associated with the document. The type of metadata returned
* is specific to the document type. For example the data returned for an image
@@ -1590,7 +1540,7 @@
* @param documentUri a Document URI
* @return a Bundle of Bundles.
*/
- public static @Nullable Bundle getDocumentMetadata(@NonNull ContentInterface content,
+ public static @Nullable Bundle getDocumentMetadata(@NonNull ContentResolver content,
@NonNull Uri documentUri) throws FileNotFoundException {
Preconditions.checkNotNull(content, "content can not be null");
Preconditions.checkNotNull(documentUri, "documentUri can not be null");
@@ -1607,12 +1557,6 @@
}
}
- @Deprecated
- public static Bundle getDocumentMetadata(ContentResolver content, Uri documentUri)
- throws FileNotFoundException {
- return getDocumentMetadata((ContentInterface) content, documentUri);
- }
-
/**
* Finds the canonical path from the top of the document tree.
*
@@ -1626,8 +1570,8 @@
* @return the path of the document, or {@code null} if failed.
* @see DocumentsProvider#findDocumentPath(String, String)
*/
- public static Path findDocumentPath(ContentInterface content, Uri treeUri)
- throws FileNotFoundException {
+ public static @Nullable Path findDocumentPath(@NonNull ContentResolver content,
+ @NonNull Uri treeUri) throws FileNotFoundException {
try {
final Bundle in = new Bundle();
in.putParcelable(DocumentsContract.EXTRA_URI, treeUri);
@@ -1642,12 +1586,6 @@
}
}
- @Deprecated
- public static Path findDocumentPath(ContentResolver content, Uri treeUri)
- throws FileNotFoundException {
- return findDocumentPath((ContentInterface) content, treeUri);
- }
-
/**
* Creates an intent for obtaining a web link for the specified document.
*
@@ -1699,8 +1637,8 @@
* @see DocumentsProvider#createWebLinkIntent(String, Bundle)
* @see Intent#EXTRA_EMAIL
*/
- public static IntentSender createWebLinkIntent(ContentInterface content, Uri uri,
- Bundle options) throws FileNotFoundException {
+ public static @Nullable IntentSender createWebLinkIntent(@NonNull ContentResolver content,
+ @NonNull Uri uri, @Nullable Bundle options) throws FileNotFoundException {
try {
final Bundle in = new Bundle();
in.putParcelable(DocumentsContract.EXTRA_URI, uri);
@@ -1721,12 +1659,6 @@
}
}
- @Deprecated
- public static IntentSender createWebLinkIntent(ContentResolver content, Uri uri,
- Bundle options) throws FileNotFoundException {
- return createWebLinkIntent((ContentInterface) content, uri, options);
- }
-
/**
* Open the given image for thumbnail purposes, using any embedded EXIF
* thumbnail if available, and providing orientation hints from the parent
diff --git a/core/java/android/provider/MediaStore.java b/core/java/android/provider/MediaStore.java
index 1b10bef..643307e 100644
--- a/core/java/android/provider/MediaStore.java
+++ b/core/java/android/provider/MediaStore.java
@@ -17,6 +17,8 @@
package android.provider;
import android.annotation.BytesLong;
+import android.annotation.CurrentTimeMillisLong;
+import android.annotation.CurrentTimeSecondsLong;
import android.annotation.DurationMillisLong;
import android.annotation.IntRange;
import android.annotation.NonNull;
@@ -40,7 +42,9 @@
import android.database.DatabaseUtils;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
+import android.graphics.ImageDecoder;
import android.graphics.Point;
+import android.graphics.PostProcessor;
import android.media.ExifInterface;
import android.net.Uri;
import android.os.Bundle;
@@ -78,8 +82,15 @@
import java.util.regex.Pattern;
/**
- * The Media provider contains meta data for all available media on both internal
- * and external storage devices.
+ * The contract between the media provider and applications. Contains
+ * definitions for the supported URIs and columns.
+ * <p>
+ * The media provider provides an indexed collection of common media types, such
+ * as {@link Audio}, {@link Video}, and {@link Images}, from any attached
+ * storage devices. Each collection is organized based on the primary MIME type
+ * of the underlying content; for example, {@code image/*} content is indexed
+ * under {@link Images}. The {@link Files} collection provides a broad view
+ * across all collections, and does not filter by MIME type.
*/
public final class MediaStore {
private final static String TAG = "MediaStore";
@@ -847,11 +858,11 @@
}
/**
- * Common fields for most MediaProvider tables
+ * Common media metadata columns.
*/
public interface MediaColumns extends BaseColumns {
/**
- * Path to the file on disk.
+ * Path to the media item on disk.
* <p>
* Note that apps may not have filesystem permissions to directly access
* this path. Instead of trying to open this path directly, apps should
@@ -871,7 +882,7 @@
public static final String DATA = "_data";
/**
- * Hash of the file on disk.
+ * Hash of the media item on disk.
* <p>
* Contains a 20-byte binary blob which is the SHA-1 hash of the file as
* persisted on disk. For performance reasons, the hash may not be
@@ -890,35 +901,35 @@
public static final String HASH = "_hash";
/**
- * The size of the file in bytes
+ * The size of the media item.
*/
+ @BytesLong
@Column(value = Cursor.FIELD_TYPE_INTEGER, readOnly = true)
public static final String SIZE = "_size";
/**
- * The display name of the file
+ * The display name of the media item.
*/
@Column(Cursor.FIELD_TYPE_STRING)
public static final String DISPLAY_NAME = "_display_name";
/**
- * The title of the content
+ * The title of the media item.
*/
@Column(value = Cursor.FIELD_TYPE_STRING, readOnly = true)
public static final String TITLE = "title";
/**
- * The time the file was added to the media provider
- * Units are seconds since 1970.
+ * The time the media item was first added.
*/
+ @CurrentTimeSecondsLong
@Column(value = Cursor.FIELD_TYPE_INTEGER, readOnly = true)
public static final String DATE_ADDED = "date_added";
/**
- * The time the file was last modified
- * Units are seconds since 1970.
- * NOTE: This is for internal use by the media scanner. Do not modify this field.
+ * The time the media item was last modified.
*/
+ @CurrentTimeSecondsLong
@Column(value = Cursor.FIELD_TYPE_INTEGER, readOnly = true)
public static final String DATE_MODIFIED = "date_modified";
@@ -986,23 +997,25 @@
public static final String IS_TRASHED = "is_trashed";
/**
- * The time the file should be considered expired. Units are seconds
- * since 1970. Typically only meaningful in the context of
- * {@link #IS_PENDING} or {@link #IS_TRASHED}.
+ * The time the media item should be considered expired. Typically only
+ * meaningful in the context of {@link #IS_PENDING} or
+ * {@link #IS_TRASHED}.
+ *
* @removed
*/
@Deprecated
+ @CurrentTimeSecondsLong
@Column(Cursor.FIELD_TYPE_INTEGER)
public static final String DATE_EXPIRES = "date_expires";
/**
- * The width of the image/video in pixels.
+ * The width of the media item, in pixels.
*/
@Column(value = Cursor.FIELD_TYPE_INTEGER, readOnly = true)
public static final String WIDTH = "width";
/**
- * The height of the image/video in pixels.
+ * The height of the media item, in pixels.
*/
@Column(value = Cursor.FIELD_TYPE_INTEGER, readOnly = true)
public static final String HEIGHT = "height";
@@ -1151,8 +1164,7 @@
}
/**
- * Fields for master table for all media files.
- * Table also contains MediaColumns._ID, DATA, SIZE and DATE_MODIFIED.
+ * File metadata columns.
*/
public interface FileColumns extends MediaColumns {
/**
@@ -1179,15 +1191,26 @@
public static final String PARENT = "parent";
/**
- * The MIME type of the file
- * <P>Type: TEXT</P>
+ * The MIME type of the media item.
+ * <p>
+ * This is typically defined based on the file extension of the media
+ * item. However, it may be the value of the {@code format} attribute
+ * defined by the <em>Dublin Core Media Initiative</em> standard,
+ * extracted from any XMP metadata contained within this media item.
+ * <p class="note">
+ * Note: the {@code format} attribute may be ignored if the top-level
+ * MIME type disagrees with the file extension. For example, it's
+ * reasonable for an {@code image/jpeg} file to declare a {@code format}
+ * of {@code image/vnd.google.panorama360+jpg}, but declaring a
+ * {@code format} of {@code audio/ogg} would be ignored.
+ * <p>
+ * This is a read-only column that is automatically computed.
*/
@Column(Cursor.FIELD_TYPE_STRING)
public static final String MIME_TYPE = "mime_type";
/**
- * The title of the content
- * <P>Type: TEXT</P>
+ * The title of the media item.
*/
@Column(value = Cursor.FIELD_TYPE_STRING, readOnly = true)
public static final String TITLE = "title";
@@ -1245,10 +1268,12 @@
public static final Point MICRO_SIZE = new Point(96, 96);
}
- /** Column fields for downloaded files used in {@link Downloads} table */
+ /**
+ * Download metadata columns.
+ */
public interface DownloadColumns extends MediaColumns {
/**
- * Uri indicating where the file has been downloaded from.
+ * Uri indicating where the item has been downloaded from.
*/
@Column(Cursor.FIELD_TYPE_STRING)
String DOWNLOAD_URI = "download_uri";
@@ -1422,9 +1447,12 @@
}
/**
- * Contains meta data for all available images.
+ * Collection of all media with MIME type of {@code image/*}.
*/
public static final class Images {
+ /**
+ * Image metadata columns.
+ */
public interface ImageColumns extends MediaColumns {
/**
* The description of the image
@@ -1473,9 +1501,9 @@
public static final String LONGITUDE = "longitude";
/**
- * The date & time that the image was taken in units
- * of milliseconds since jan 1, 1970.
+ * The time the media item was taken.
*/
+ @CurrentTimeMillisLong
@Column(value = Cursor.FIELD_TYPE_INTEGER, readOnly = true)
public static final String DATE_TAKEN = "datetaken";
@@ -1531,16 +1559,34 @@
}
public static final class Media implements ImageColumns {
+ /**
+ * @deprecated all queries should be performed through
+ * {@link ContentResolver} directly, which offers modern
+ * features like {@link CancellationSignal}.
+ */
+ @Deprecated
public static final Cursor query(ContentResolver cr, Uri uri, String[] projection) {
return cr.query(uri, projection, null, null, DEFAULT_SORT_ORDER);
}
+ /**
+ * @deprecated all queries should be performed through
+ * {@link ContentResolver} directly, which offers modern
+ * features like {@link CancellationSignal}.
+ */
+ @Deprecated
public static final Cursor query(ContentResolver cr, Uri uri, String[] projection,
String where, String orderBy) {
return cr.query(uri, projection, where,
null, orderBy == null ? DEFAULT_SORT_ORDER : orderBy);
}
+ /**
+ * @deprecated all queries should be performed through
+ * {@link ContentResolver} directly, which offers modern
+ * features like {@link CancellationSignal}.
+ */
+ @Deprecated
public static final Cursor query(ContentResolver cr, Uri uri, String[] projection,
String selection, String [] selectionArgs, String orderBy) {
return cr.query(uri, projection, selection,
@@ -1552,9 +1598,12 @@
*
* @param cr The content resolver to use
* @param url The url of the image
- * @throws FileNotFoundException
- * @throws IOException
+ * @deprecated loading of images should be performed through
+ * {@link ImageDecoder#createSource(ContentResolver, Uri)},
+ * which offers modern features like
+ * {@link PostProcessor}.
*/
+ @Deprecated
public static final Bitmap getBitmap(ContentResolver cr, Uri url)
throws FileNotFoundException, IOException {
InputStream input = cr.openInputStream(url);
@@ -1571,8 +1620,11 @@
* @param name The name of the image
* @param description The description of the image
* @return The URL to the newly created image
- * @throws FileNotFoundException
+ * @deprecated inserting of images should be performed through
+ * {@link MediaStore#createPending(Context, PendingParams)},
+ * which offers richer control over lifecycle.
*/
+ @Deprecated
public static final String insertImage(ContentResolver cr, String imagePath,
String name, String description) throws FileNotFoundException {
// Check if file exists with a FileInputStream
@@ -1599,7 +1651,11 @@
* @param description The description of the image
* @return The URL to the newly created image, or <code>null</code> if the image failed to be stored
* for any reason.
+ * @deprecated inserting of images should be performed through
+ * {@link MediaStore#createPending(Context, PendingParams)},
+ * which offers richer control over lifecycle.
*/
+ @Deprecated
public static final String insertImage(ContentResolver cr, Bitmap source,
String title, String description) {
ContentValues values = new ContentValues();
@@ -1694,15 +1750,33 @@
*/
@Deprecated
public static class Thumbnails implements BaseColumns {
+ /**
+ * @deprecated all queries should be performed through
+ * {@link ContentResolver} directly, which offers modern
+ * features like {@link CancellationSignal}.
+ */
+ @Deprecated
public static final Cursor query(ContentResolver cr, Uri uri, String[] projection) {
return cr.query(uri, projection, null, null, DEFAULT_SORT_ORDER);
}
+ /**
+ * @deprecated all queries should be performed through
+ * {@link ContentResolver} directly, which offers modern
+ * features like {@link CancellationSignal}.
+ */
+ @Deprecated
public static final Cursor queryMiniThumbnails(ContentResolver cr, Uri uri, int kind,
String[] projection) {
return cr.query(uri, projection, "kind = " + kind, null, DEFAULT_SORT_ORDER);
}
+ /**
+ * @deprecated all queries should be performed through
+ * {@link ContentResolver} directly, which offers modern
+ * features like {@link CancellationSignal}.
+ */
+ @Deprecated
public static final Cursor queryMiniThumbnail(ContentResolver cr, long origId, int kind,
String[] projection) {
return cr.query(EXTERNAL_CONTENT_URI, projection,
@@ -1885,11 +1959,11 @@
}
/**
- * Container for all audio content.
+ * Collection of all media with MIME type of {@code audio/*}.
*/
public static final class Audio {
/**
- * Columns for audio file that show up in multiple tables.
+ * Audio metadata columns.
*/
public interface AudioColumns extends MediaColumns {
@@ -1901,15 +1975,17 @@
public static final String TITLE_KEY = "title_key";
/**
- * The duration of the audio file, in ms
+ * The duration of the audio item.
*/
+ @DurationMillisLong
@Column(value = Cursor.FIELD_TYPE_INTEGER, readOnly = true)
public static final String DURATION = "duration";
/**
- * The position, in ms, playback was at when playback for this file
- * was last stopped.
+ * The position within the audio item at which playback should be
+ * resumed.
*/
+ @DurationMillisLong
@Column(Cursor.FIELD_TYPE_INTEGER)
public static final String BOOKMARK = "bookmark";
@@ -2187,7 +2263,7 @@
}
/**
- * Columns representing an audio genre
+ * Audio genre metadata columns.
*/
public interface GenresColumns {
/**
@@ -2290,7 +2366,7 @@
}
/**
- * Columns representing a playlist
+ * Audio playlist metadata columns.
*/
public interface PlaylistsColumns {
/**
@@ -2321,17 +2397,16 @@
public static final String DATA = "_data";
/**
- * The time the file was added to the media provider
- * Units are seconds since 1970.
+ * The time the media item was first added.
*/
+ @CurrentTimeSecondsLong
@Column(value = Cursor.FIELD_TYPE_INTEGER, readOnly = true)
public static final String DATE_ADDED = "date_added";
/**
- * The time the file was last modified
- * Units are seconds since 1970.
- * NOTE: This is for internal use by the media scanner. Do not modify this field.
+ * The time the media item was last modified.
*/
+ @CurrentTimeSecondsLong
@Column(value = Cursor.FIELD_TYPE_INTEGER, readOnly = true)
public static final String DATE_MODIFIED = "date_modified";
}
@@ -2450,7 +2525,7 @@
}
/**
- * Columns representing an artist
+ * Audio artist metadata columns.
*/
public interface ArtistColumns {
/**
@@ -2537,7 +2612,7 @@
}
/**
- * Columns representing an album
+ * Audio album metadata columns.
*/
public interface AlbumColumns {
@@ -2707,6 +2782,9 @@
}
}
+ /**
+ * Collection of all media with MIME type of {@code video/*}.
+ */
public static final class Video {
/**
@@ -2714,15 +2792,25 @@
*/
public static final String DEFAULT_SORT_ORDER = MediaColumns.DISPLAY_NAME;
+ /**
+ * @deprecated all queries should be performed through
+ * {@link ContentResolver} directly, which offers modern
+ * features like {@link CancellationSignal}.
+ */
+ @Deprecated
public static final Cursor query(ContentResolver cr, Uri uri, String[] projection) {
return cr.query(uri, projection, null, null, DEFAULT_SORT_ORDER);
}
+ /**
+ * Video metadata columns.
+ */
public interface VideoColumns extends MediaColumns {
/**
- * The duration of the video file, in ms
+ * The duration of the video item.
*/
+ @DurationMillisLong
@Column(value = Cursor.FIELD_TYPE_INTEGER, readOnly = true)
public static final String DURATION = "duration";
@@ -2799,9 +2887,9 @@
public static final String LONGITUDE = "longitude";
/**
- * The date & time that the video was taken in units
- * of milliseconds since jan 1, 1970.
+ * The time the media item was taken.
*/
+ @CurrentTimeMillisLong
@Column(value = Cursor.FIELD_TYPE_INTEGER, readOnly = true)
public static final String DATE_TAKEN = "datetaken";
@@ -2849,11 +2937,10 @@
public static final String GROUP_ID = "group_id";
/**
- * The bookmark for the video. Time in ms. Represents the location in the video that the
- * video should start playing at the next time it is opened. If the value is null or
- * out of the range 0..DURATION-1 then the video should start playing from the
- * beginning.
+ * The position within the video item at which playback should be
+ * resumed.
*/
+ @DurationMillisLong
@Column(Cursor.FIELD_TYPE_INTEGER)
public static final String BOOKMARK = "bookmark";
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index d925d7e..a465b32 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -11731,6 +11731,14 @@
public static final String APP_IDLE_CONSTANTS = "app_idle_constants";
/**
+ * Enable ART bytecode verification verifications for debuggable apps.
+ * 0 = disable, 1 = enable.
+ * @hide
+ */
+ public static final String ART_VERIFIER_VERIFY_DEBUGGABLE =
+ "art_verifier_verify_debuggable";
+
+ /**
* Power manager specific settings.
* This is encoded as a key=value list, separated by commas. Ex:
*
@@ -12393,6 +12401,14 @@
public static final String GAME_DRIVER_WHITELIST = "game_driver_whitelist";
/**
+ * List of libraries in sphal accessible by Game Driver
+ * The string is a list of library names, separated by colon.
+ * i.e. <lib1>:<lib2>:...:<libN>
+ * @hide
+ */
+ public static final String GAME_DRIVER_SPHAL_LIBRARIES = "game_driver_sphal_libraries";
+
+ /**
* Ordered GPU debug layer list for Vulkan
* i.e. <layer1>:<layer2>:...:<layerN>
* @hide
diff --git a/core/java/android/service/autofill/augmented/AugmentedAutofillService.java b/core/java/android/service/autofill/augmented/AugmentedAutofillService.java
index 8695da2..ce83a57 100644
--- a/core/java/android/service/autofill/augmented/AugmentedAutofillService.java
+++ b/core/java/android/service/autofill/augmented/AugmentedAutofillService.java
@@ -126,6 +126,14 @@
}
/**
+ * Called when the Android system connects to service.
+ *
+ * <p>You should generally do initialization here rather than in {@link #onCreate}.
+ */
+ public void onConnected() {
+ }
+
+ /**
* Asks the service to handle an "augmented" autofill request.
*
* <p>This method is called when the "stantard" autofill service cannot handle a request, which
@@ -158,6 +166,14 @@
@NonNull FillCallback callback) {
}
+ /**
+ * Called when the Android system disconnects from the service.
+ *
+ * <p> At this point this service may no longer be an active {@link AugmentedAutofillService}.
+ */
+ public void onDisconnected() {
+ }
+
private void handleOnFillRequest(int sessionId, @NonNull IBinder client, int taskId,
@NonNull ComponentName componentName, @NonNull AutofillId focusedId,
@Nullable AutofillValue focusedValue, long requestTime,
diff --git a/core/java/android/service/contentcapture/ContentCaptureService.java b/core/java/android/service/contentcapture/ContentCaptureService.java
index ae70775..d361a2c 100644
--- a/core/java/android/service/contentcapture/ContentCaptureService.java
+++ b/core/java/android/service/contentcapture/ContentCaptureService.java
@@ -34,6 +34,7 @@
import android.os.RemoteException;
import android.service.autofill.AutofillService;
import android.util.ArrayMap;
+import android.util.ArraySet;
import android.util.Log;
import android.util.Slog;
import android.view.contentcapture.ContentCaptureContext;
@@ -171,16 +172,11 @@
@Deprecated
public final void setContentCaptureWhitelist(@Nullable List<String> packages,
@Nullable List<ComponentName> activities) {
- final IContentCaptureServiceCallback callback = mCallback;
- if (callback == null) {
- Log.w(TAG, "setContentCaptureWhitelist(): no server callback");
- return;
- }
- try {
- callback.setContentCaptureWhitelist(packages, activities);
- } catch (RemoteException e) {
- e.rethrowFromSystemServer();
- }
+ setContentCaptureWhitelist(toSet(packages), toSet(activities));
+ }
+
+ private <T> ArraySet<T> toSet(@Nullable List<T> set) {
+ return set == null ? null : new ArraySet<T>(set);
}
/**
@@ -197,7 +193,17 @@
*/
public final void setContentCaptureWhitelist(@Nullable Set<String> packages,
@Nullable Set<ComponentName> activities) {
- setContentCaptureWhitelist(toList(packages), toList(activities));
+ final IContentCaptureServiceCallback callback = mCallback;
+ if (callback == null) {
+ Log.w(TAG, "setContentCaptureWhitelist(): no server callback");
+ return;
+ }
+
+ try {
+ callback.setContentCaptureWhitelist(toList(packages), toList(activities));
+ } catch (RemoteException e) {
+ e.rethrowFromSystemServer();
+ }
}
private <T> ArrayList<T> toList(@Nullable Set<T> set) {
@@ -278,6 +284,24 @@
}
/**
+ * Disables the Content Capture service for the given user.
+ */
+ public final void disableContentCaptureServices() {
+ if (DEBUG) Log.d(TAG, "disableContentCaptureServices()");
+
+ final IContentCaptureServiceCallback callback = mCallback;
+ if (callback == null) {
+ Log.w(TAG, "disableContentCaptureServices(): no server callback");
+ return;
+ }
+ try {
+ callback.disableSelf();
+ } catch (RemoteException e) {
+ e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
* Called when the Android system disconnects from the service.
*
* <p> At this point this service may no longer be an active {@link AutofillService}.
diff --git a/core/java/android/service/contentcapture/IContentCaptureServiceCallback.aidl b/core/java/android/service/contentcapture/IContentCaptureServiceCallback.aidl
index 2a729b6..8bc8def 100644
--- a/core/java/android/service/contentcapture/IContentCaptureServiceCallback.aidl
+++ b/core/java/android/service/contentcapture/IContentCaptureServiceCallback.aidl
@@ -17,7 +17,6 @@
package android.service.contentcapture;
import android.content.ComponentName;
-import com.android.internal.os.IResultReceiver;
import java.util.List;
@@ -28,4 +27,5 @@
*/
oneway interface IContentCaptureServiceCallback {
void setContentCaptureWhitelist(in List<String> packages, in List<ComponentName> activities);
-}
+ void disableSelf();
+ }
diff --git a/core/java/android/service/notification/Adjustment.java b/core/java/android/service/notification/Adjustment.java
index 2961426..bddc5ef 100644
--- a/core/java/android/service/notification/Adjustment.java
+++ b/core/java/android/service/notification/Adjustment.java
@@ -20,9 +20,17 @@
import android.os.Bundle;
import android.os.Parcel;
import android.os.Parcelable;
+import android.os.UserHandle;
/**
* Ranking updates from the Assistant.
+ *
+ * The updates are provides as a {@link Bundle} of signals, using the keys provided in this
+ * class.
+ * Each {@code KEY} specifies what type of data it supports and what kind of Adjustment it
+ * realizes on the notification rankings.
+ *
+ * Notifications affected by the Adjustment will be re-ranked if necessary.
*/
public final class Adjustment implements Parcelable {
private final String mPackage;
@@ -103,7 +111,9 @@
* @param signals A bundle of signals that should inform notification display, ordering, and
* interruptiveness.
* @param explanation A human-readable justification for the adjustment.
+ * @hide
*/
+ @SystemApi
public Adjustment(String pkg, String key, Bundle signals, CharSequence explanation, int user) {
mPackage = pkg;
mKey = key;
@@ -113,6 +123,25 @@
}
/**
+ * Create a notification adjustment.
+ *
+ * @param pkg The package of the notification.
+ * @param key The notification key.
+ * @param signals A bundle of signals that should inform notification display, ordering, and
+ * interruptiveness.
+ * @param explanation A human-readable justification for the adjustment.
+ * @param userHandle User handle for for whose the adjustments will be applied.
+ */
+ public Adjustment(String pkg, String key, Bundle signals, CharSequence explanation,
+ UserHandle userHandle) {
+ mPackage = pkg;
+ mKey = key;
+ mSignals = signals;
+ mExplanation = explanation;
+ mUser = userHandle.getIdentifier();
+ }
+
+ /**
* @hide
*/
@SystemApi
@@ -164,10 +193,16 @@
return mSignals;
}
+ /** @hide */
+ @SystemApi
public int getUser() {
return mUser;
}
+ public UserHandle getUserHandle() {
+ return UserHandle.of(mUser);
+ }
+
@Override
public int describeContents() {
return 0;
diff --git a/core/java/android/service/wallpaper/WallpaperService.java b/core/java/android/service/wallpaper/WallpaperService.java
index b197c8a..c042a8c 100644
--- a/core/java/android/service/wallpaper/WallpaperService.java
+++ b/core/java/android/service/wallpaper/WallpaperService.java
@@ -1068,9 +1068,13 @@
* For multiple display environment, multiple engines can be created to render on each
* display, but these displays may have different densities. Use this context to get the
* corresponding resources for currently display, avoiding the context of the service.
+ * <p>
+ * The display context will never be {@code null} after
+ * {@link Engine#onCreate(SurfaceHolder)} has been called.
*
* @return A {@link Context} for current display.
*/
+ @Nullable
public Context getDisplayContext() {
return mDisplayContext;
}
diff --git a/core/java/android/util/FeatureFlagUtils.java b/core/java/android/util/FeatureFlagUtils.java
index 1ca6398..67a4015 100644
--- a/core/java/android/util/FeatureFlagUtils.java
+++ b/core/java/android/util/FeatureFlagUtils.java
@@ -54,9 +54,7 @@
DEFAULT_FLAGS.put("settings_network_and_internet_v2", "false");
DEFAULT_FLAGS.put("settings_slice_injection", "true");
DEFAULT_FLAGS.put("settings_systemui_theme", "true");
- DEFAULT_FLAGS.put("settings_wifi_dpp", "true");
DEFAULT_FLAGS.put("settings_wifi_mac_randomization", "true");
- DEFAULT_FLAGS.put("settings_wifi_sharing", "true");
DEFAULT_FLAGS.put("settings_mainline_module", "false");
DEFAULT_FLAGS.put(SEAMLESS_TRANSFER, "false");
DEFAULT_FLAGS.put(HEARING_AID_SETTINGS, "false");
diff --git a/core/java/android/view/Window.java b/core/java/android/view/Window.java
index 097f368..3544a87 100644
--- a/core/java/android/view/Window.java
+++ b/core/java/android/view/Window.java
@@ -622,11 +622,10 @@
/** @hide */
public interface WindowControllerCallback {
/**
- * Moves the activity from
- * Moves the activity from {@link WindowConfiguration#WINDOWING_MODE_FREEFORM} windowing
- * mode to {@link WindowConfiguration#WINDOWING_MODE_FULLSCREEN}.
+ * Moves the activity between {@link WindowConfiguration#WINDOWING_MODE_FREEFORM} windowing
+ * mode and {@link WindowConfiguration#WINDOWING_MODE_FULLSCREEN}.
*/
- void exitFreeformMode() throws RemoteException;
+ void toggleFreeformWindowingMode() throws RemoteException;
/**
* Puts the activity in picture-in-picture mode if the activity supports.
diff --git a/core/java/android/view/WindowManagerGlobal.java b/core/java/android/view/WindowManagerGlobal.java
index e3833c0..453c5e3 100644
--- a/core/java/android/view/WindowManagerGlobal.java
+++ b/core/java/android/view/WindowManagerGlobal.java
@@ -17,6 +17,7 @@
package android.view;
import android.animation.ValueAnimator;
+import android.annotation.NonNull;
import android.annotation.UnsupportedAppUsage;
import android.app.ActivityManager;
import android.content.ComponentCallbacks2;
@@ -269,6 +270,16 @@
return views;
}
+ /**
+ * @return the list of all views attached to the global window manager
+ */
+ @NonNull
+ public ArrayList<View> getWindowViews() {
+ synchronized (mLock) {
+ return new ArrayList<>(mViews);
+ }
+ }
+
public View getWindowView(IBinder windowToken) {
synchronized (mLock) {
final int numViews = mViews.size();
diff --git a/core/java/android/view/contentcapture/ContentCaptureManager.java b/core/java/android/view/contentcapture/ContentCaptureManager.java
index 9906308..87e358c 100644
--- a/core/java/android/view/contentcapture/ContentCaptureManager.java
+++ b/core/java/android/view/contentcapture/ContentCaptureManager.java
@@ -327,39 +327,8 @@
case RESULT_CODE_NOT_SERVICE:
throw new SecurityException("caller is not user's ContentCapture service");
default:
- throw new IllegalStateException("received invalid result: " + resultCode);
- }
- }
-
- /**
- * Sets whether Content Capture is enabled for the given user.
- *
- * @throws SecurityException if caller is not the app that owns the Content Capture service
- * associated with the user.
- *
- * @hide
- */
- @SystemApi
- @TestApi
- public void setContentCaptureFeatureEnabled(boolean enabled) {
- if (sDebug) Log.d(TAG, "setContentCaptureFeatureEnabled(): setting to " + enabled);
-
- final SyncResultReceiver resultReceiver = new SyncResultReceiver(SYNC_CALLS_TIMEOUT_MS);
- final int resultCode;
- try {
- mService.setContentCaptureFeatureEnabled(enabled, resultReceiver);
- resultCode = resultReceiver.getIntResult();
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- }
- switch (resultCode) {
- case RESULT_CODE_TRUE:
- // Our work is done here, in our void existance...
- return;
- case RESULT_CODE_NOT_SERVICE:
- throw new SecurityException("caller is not user's ContentCapture service");
- default:
- throw new IllegalStateException("received invalid result: " + resultCode);
+ Log.wtf(TAG, "received invalid result: " + resultCode);
+ return false;
}
}
diff --git a/core/java/android/view/contentcapture/ContentCaptureSession.java b/core/java/android/view/contentcapture/ContentCaptureSession.java
index ec3b44a..1e051a43 100644
--- a/core/java/android/view/contentcapture/ContentCaptureSession.java
+++ b/core/java/android/view/contentcapture/ContentCaptureSession.java
@@ -120,6 +120,13 @@
*/
public static final int STATE_INTERNAL_ERROR = 0x100;
+ /**
+ * Session is disabled because service didn't whitelist package.
+ *
+ * @hide
+ */
+ public static final int STATE_PACKAGE_NOT_WHITELISTED = 0x200;
+
private static final int INITIAL_CHILDREN_CAPACITY = 5;
/** @hide */
diff --git a/core/java/android/view/contentcapture/IContentCaptureManager.aidl b/core/java/android/view/contentcapture/IContentCaptureManager.aidl
index 26cf34c..e3b0372 100644
--- a/core/java/android/view/contentcapture/IContentCaptureManager.aidl
+++ b/core/java/android/view/contentcapture/IContentCaptureManager.aidl
@@ -67,9 +67,4 @@
* Returns whether the content capture feature is enabled for the calling user.
*/
void isContentCaptureFeatureEnabled(in IResultReceiver result);
-
- /**
- * Sets whether the content capture feature is enabled for the given user.
- */
- void setContentCaptureFeatureEnabled(boolean enabled, in IResultReceiver result);
}
diff --git a/core/java/android/view/inspector/WindowInspector.java b/core/java/android/view/inspector/WindowInspector.java
new file mode 100644
index 0000000..69d004e
--- /dev/null
+++ b/core/java/android/view/inspector/WindowInspector.java
@@ -0,0 +1,40 @@
+/*
+ * 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.view.inspector;
+
+import android.annotation.NonNull;
+import android.view.View;
+import android.view.WindowManagerGlobal;
+
+import java.util.List;
+
+/**
+ * Provides access to window inspection information.
+ */
+public final class WindowInspector {
+ private WindowInspector() {
+ // Non-instantiable.
+ }
+
+ /**
+ * @return the list of all window views attached to the current process
+ */
+ @NonNull
+ public static List<View> getGlobalWindowViews() {
+ return WindowManagerGlobal.getInstance().getWindowViews();
+ }
+}
diff --git a/core/java/android/widget/SearchView.java b/core/java/android/widget/SearchView.java
index 630c38a..172f1d8 100644
--- a/core/java/android/widget/SearchView.java
+++ b/core/java/android/widget/SearchView.java
@@ -2078,6 +2078,11 @@
return ic;
}
+ @Override
+ public boolean checkInputConnectionProxy(View view) {
+ return view == mSearchView;
+ }
+
private void showSoftInputIfNecessary() {
if (mHasPendingShowSoftInputRequest) {
final InputMethodManager imm =
diff --git a/core/java/com/android/internal/app/ChooserActivity.java b/core/java/com/android/internal/app/ChooserActivity.java
index 2009fd50..0fbd4dc 100644
--- a/core/java/com/android/internal/app/ChooserActivity.java
+++ b/core/java/com/android/internal/app/ChooserActivity.java
@@ -72,6 +72,7 @@
import android.os.UserManager;
import android.os.storage.StorageManager;
import android.provider.DocumentsContract;
+import android.provider.Downloads;
import android.provider.OpenableColumns;
import android.service.chooser.ChooserTarget;
import android.service.chooser.ChooserTargetService;
@@ -620,29 +621,41 @@
}
}
+ /**
+ * Wrapping the ContentResolver call to expose for easier mocking,
+ * and to avoid mocking Android core classes.
+ */
+ @VisibleForTesting
+ public Cursor queryResolver(ContentResolver resolver, Uri uri) {
+ return resolver.query(uri, null, null, null, null);
+ }
+
private FileInfo extractFileInfo(Uri uri, ContentResolver resolver) {
String fileName = null;
boolean hasThumbnail = false;
- Cursor cursor = null;
- try {
- cursor = resolver.query(uri, null, null, null, null);
+ try (Cursor cursor = queryResolver(resolver, uri)) {
+ if (cursor != null && cursor.getCount() > 0) {
+ int nameIndex = cursor.getColumnIndex(OpenableColumns.DISPLAY_NAME);
+ int titleIndex = cursor.getColumnIndex(Downloads.Impl.COLUMN_TITLE);
+ int flagsIndex = cursor.getColumnIndex(DocumentsContract.Document.COLUMN_FLAGS);
+
+ cursor.moveToFirst();
+ if (nameIndex != -1) {
+ fileName = cursor.getString(nameIndex);
+ } else if (titleIndex != -1) {
+ fileName = cursor.getString(titleIndex);
+ }
+
+ if (flagsIndex != -1) {
+ hasThumbnail = (cursor.getInt(flagsIndex)
+ & DocumentsContract.Document.FLAG_SUPPORTS_THUMBNAIL) != 0;
+ }
+ }
} catch (SecurityException e) {
Log.w(TAG, "Error loading file preview", e);
}
- if (cursor != null && cursor.getCount() > 0) {
- int nameIndex = cursor.getColumnIndex(OpenableColumns.DISPLAY_NAME);
- int flagsIndex = cursor.getColumnIndex(DocumentsContract.Document.COLUMN_FLAGS);
-
- cursor.moveToFirst();
- fileName = cursor.getString(nameIndex);
- if (flagsIndex != -1) {
- hasThumbnail = (cursor.getInt(flagsIndex)
- & DocumentsContract.Document.FLAG_SUPPORTS_THUMBNAIL) != 0;
- }
- }
-
if (TextUtils.isEmpty(fileName)) {
fileName = uri.getPath();
int index = fileName.lastIndexOf('/');
diff --git a/core/java/com/android/internal/app/IAppOpsService.aidl b/core/java/com/android/internal/app/IAppOpsService.aidl
index c4ab91f..8a90cad 100644
--- a/core/java/com/android/internal/app/IAppOpsService.aidl
+++ b/core/java/com/android/internal/app/IAppOpsService.aidl
@@ -44,9 +44,9 @@
int checkPackage(int uid, String packageName);
List<AppOpsManager.PackageOps> getPackagesForOps(in int[] ops);
List<AppOpsManager.PackageOps> getOpsForPackage(int uid, String packageName, in int[] ops);
- void getHistoricalOps(int uid, String packageName, in String[] ops, long beginTimeMillis,
+ void getHistoricalOps(int uid, String packageName, in List<String> ops, long beginTimeMillis,
long endTimeMillis, in RemoteCallback callback);
- void getHistoricalOpsFromDiskRaw(int uid, String packageName, in String[] ops,
+ void getHistoricalOpsFromDiskRaw(int uid, String packageName, in List<String> ops,
long beginTimeMillis, long endTimeMillis, in RemoteCallback callback);
void offsetHistory(long duration);
void setHistoryParameters(int mode, long baseSnapshotInterval, int compressionStep);
diff --git a/core/java/com/android/internal/colorextraction/ColorExtractor.java b/core/java/com/android/internal/colorextraction/ColorExtractor.java
index 258d081..d9fd3b5 100644
--- a/core/java/com/android/internal/colorextraction/ColorExtractor.java
+++ b/core/java/com/android/internal/colorextraction/ColorExtractor.java
@@ -21,7 +21,7 @@
import android.app.WallpaperColors;
import android.app.WallpaperManager;
import android.content.Context;
-import android.os.Trace;
+import android.os.AsyncTask;
import android.util.Log;
import android.util.SparseArray;
@@ -53,11 +53,11 @@
protected WallpaperColors mLockColors;
public ColorExtractor(Context context) {
- this(context, new Tonal(context));
+ this(context, new Tonal(context), true /* immediately */);
}
@VisibleForTesting
- public ColorExtractor(Context context, ExtractionType extractionType) {
+ public ColorExtractor(Context context, ExtractionType extractionType, boolean immediately) {
mContext = context;
mExtractionType = extractionType;
@@ -71,23 +71,48 @@
}
mOnColorsChangedListeners = new ArrayList<>();
- GradientColors[] systemColors = mGradientColors.get(WallpaperManager.FLAG_SYSTEM);
- GradientColors[] lockColors = mGradientColors.get(WallpaperManager.FLAG_LOCK);
WallpaperManager wallpaperManager = mContext.getSystemService(WallpaperManager.class);
if (wallpaperManager == null) {
Log.w(TAG, "Can't listen to color changes!");
} else {
wallpaperManager.addOnColorsChangedListener(this, null /* handler */);
+ initExtractColors(wallpaperManager, immediately);
+ }
+ }
- // Initialize all gradients with the current colors
- Trace.beginSection("ColorExtractor#getWallpaperColors");
+ private void initExtractColors(WallpaperManager wallpaperManager, boolean immediately) {
+ if (immediately) {
mSystemColors = wallpaperManager.getWallpaperColors(WallpaperManager.FLAG_SYSTEM);
mLockColors = wallpaperManager.getWallpaperColors(WallpaperManager.FLAG_LOCK);
- Trace.endSection();
+ extractWallpaperColors();
+ } else {
+ new LoadWallpaperColors().executeOnExecutor(
+ AsyncTask.THREAD_POOL_EXECUTOR, wallpaperManager);
}
+ }
- // Initialize all gradients with the current colors
+ private class LoadWallpaperColors extends AsyncTask<WallpaperManager, Void, Void> {
+ private WallpaperColors mSystemColors;
+ private WallpaperColors mLockColors;
+ @Override
+ protected Void doInBackground(WallpaperManager... params) {
+ mSystemColors = params[0].getWallpaperColors(WallpaperManager.FLAG_SYSTEM);
+ mLockColors = params[0].getWallpaperColors(WallpaperManager.FLAG_LOCK);
+ return null;
+ }
+ @Override
+ protected void onPostExecute(Void b) {
+ ColorExtractor.this.mSystemColors = mSystemColors;
+ ColorExtractor.this.mLockColors = mLockColors;
+ extractWallpaperColors();
+ triggerColorsChanged(WallpaperManager.FLAG_SYSTEM | WallpaperManager.FLAG_LOCK);
+ }
+ }
+
+ private void extractWallpaperColors() {
+ GradientColors[] systemColors = mGradientColors.get(WallpaperManager.FLAG_SYSTEM);
+ GradientColors[] lockColors = mGradientColors.get(WallpaperManager.FLAG_LOCK);
extractInto(mSystemColors,
systemColors[TYPE_NORMAL],
systemColors[TYPE_DARK],
diff --git a/core/java/com/android/internal/os/Zygote.java b/core/java/com/android/internal/os/Zygote.java
index 40d7868..22884ac 100644
--- a/core/java/com/android/internal/os/Zygote.java
+++ b/core/java/com/android/internal/os/Zygote.java
@@ -29,6 +29,7 @@
import android.os.Process;
import android.os.SystemProperties;
import android.os.Trace;
+import android.provider.DeviceConfig;
import android.system.ErrnoException;
import android.system.Os;
import android.util.Log;
@@ -129,21 +130,6 @@
public static final int BLASTULA_MANAGEMENT_MESSAGE_BYTES = 8;
/**
- * If the blastula pool should be created and used to start applications.
- *
- * Setting this value to false will disable the creation, maintenance, and use of the blastula
- * pool. When the blastula pool is disabled the application lifecycle will be identical to
- * previous versions of Android.
- */
- public static final boolean BLASTULA_POOL_ENABLED = false;
-
- /**
- * File descriptor used for communication between the signal handler and the ZygoteServer poll
- * loop.
- * */
- protected static FileDescriptor sBlastulaPoolEventFD;
-
- /**
* 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
* should listen for connections on.
@@ -174,44 +160,40 @@
private static final String ANDROID_SOCKET_PREFIX = "ANDROID_SOCKET_";
/**
- * The maximum value that the sBlastulaPoolMax variable may take. This value
- * is a mirror of BLASTULA_POOL_MAX_LIMIT found in com_android_internal_os_Zygote.cpp.
+ * The duration to wait before re-checking Zygote related system properties.
+ *
+ * Five minutes in milliseconds.
*/
- static final int BLASTULA_POOL_MAX_LIMIT = 10;
-
- /**
- * The minimum value that the sBlastulaPoolMin variable may take.
- */
- static final int BLASTULA_POOL_MIN_LIMIT = 1;
-
- /**
- * The runtime-adjustable maximum Blastula pool size.
- */
- static int sBlastulaPoolMax = BLASTULA_POOL_MAX_LIMIT;
-
- /**
- * The runtime-adjustable minimum Blastula pool size.
- */
- static int sBlastulaPoolMin = BLASTULA_POOL_MIN_LIMIT;
-
- /**
- * The runtime-adjustable value used to determine when to re-fill the
- * blastula pool. The pool will be re-filled when
- * (sBlastulaPoolMax - gBlastulaPoolCount) >= sBlastulaPoolRefillThreshold.
- */
- // TODO (chriswailes): This must be updated at the same time as sBlastulaPoolMax.
- static int sBlastulaPoolRefillThreshold = (sBlastulaPoolMax / 2);
+ public static final long PROPERTY_CHECK_INTERVAL = 300000;
/**
* @hide for internal use only
*/
public static final int SOCKET_BUFFER_SIZE = 256;
- private static LocalServerSocket sBlastulaPoolSocket = null;
-
/** a prototype instance for a future List.toArray() */
protected static final int[][] INT_ARRAY_2D = new int[0][0];
+ /**
+ * @hide for internal use only.
+ */
+ public static final String PRIMARY_SOCKET_NAME = "zygote";
+
+ /**
+ * @hide for internal use only.
+ */
+ public static final String SECONDARY_SOCKET_NAME = "zygote_secondary";
+
+ /**
+ * @hide for internal use only
+ */
+ public static final String BLASTULA_POOL_PRIMARY_SOCKET_NAME = "blastula_pool";
+
+ /**
+ * @hide for internal use only
+ */
+ public static final String BLASTULA_POOL_SECONDARY_SOCKET_NAME = "blastula_pool_secondary";
+
private Zygote() {}
/** Called for some security initialization before any fork. */
@@ -428,70 +410,47 @@
protected static native void nativeGetSocketFDs(boolean isPrimary);
/**
- * Initialize the blastula pool and fill it with the desired number of
- * processes.
+ * Returns the raw string value of a system property.
+ *
+ * Note that Device Config is not available without an application so SystemProperties is used
+ * instead.
+ *
+ * TODO (chriswailes): Cache the system property location in native code and then write a JNI
+ * function to fetch it.
*/
- protected static Runnable initBlastulaPool() {
- if (BLASTULA_POOL_ENABLED) {
- sBlastulaPoolEventFD = getBlastulaPoolEventFD();
-
- return fillBlastulaPool(null);
- } else {
- return null;
- }
+ public static String getSystemProperty(String propertyName, String defaultValue) {
+ return SystemProperties.get(
+ String.join(".",
+ "persist.device_config",
+ DeviceConfig.RuntimeNative.NAMESPACE,
+ propertyName),
+ defaultValue);
}
/**
- * Checks to see if the current policy says that pool should be refilled, and spawns new
- * blastulas if necessary.
+ * Returns the value of a system property converted to a boolean using specific logic.
*
- * NOTE: This function doesn't need to be guarded with BLASTULA_POOL_ENABLED because it is
- * only called from contexts that are only valid if the pool is enabled.
+ * Note that Device Config is not available without an application so SystemProperties is used
+ * instead.
*
- * @param sessionSocketRawFDs Anonymous session sockets that are currently open
- * @return In the Zygote process this function will always return null; in blastula processes
- * this function will return a Runnable object representing the new application that is
- * passed up from blastulaMain.
+ * @see SystemProperties.getBoolean
+ *
+ * TODO (chriswailes): Cache the system property location in native code and then write a JNI
+ * function to fetch it.
*/
- protected static Runnable fillBlastulaPool(int[] sessionSocketRawFDs) {
- Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "Zygote:FillBlastulaPool");
-
- int blastulaPoolCount = getBlastulaPoolCount();
-
- int numBlastulasToSpawn = sBlastulaPoolMax - blastulaPoolCount;
-
- if (blastulaPoolCount < sBlastulaPoolMin
- || numBlastulasToSpawn >= sBlastulaPoolRefillThreshold) {
-
- // Disable some VM functionality and reset some system values
- // before forking.
- ZygoteHooks.preFork();
- resetNicePriority();
-
- while (blastulaPoolCount++ < sBlastulaPoolMax) {
- Runnable caller = forkBlastula(sessionSocketRawFDs);
-
- if (caller != null) {
- return caller;
- }
- }
-
- // Re-enable runtime services for the Zygote. Blastula services
- // are re-enabled in specializeBlastula.
- ZygoteHooks.postForkCommon();
-
- Log.i("zygote", "Filled the blastula pool. New blastulas: " + numBlastulasToSpawn);
- }
-
- Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
-
- return null;
+ public static boolean getSystemPropertyBoolean(String propertyName, Boolean defaultValue) {
+ return SystemProperties.getBoolean(
+ String.join(".",
+ "persist.device_config",
+ DeviceConfig.RuntimeNative.NAMESPACE,
+ propertyName),
+ defaultValue);
}
/**
* @return Number of blastulas currently in the pool
*/
- private static int getBlastulaPoolCount() {
+ static int getBlastulaPoolCount() {
return nativeGetBlastulaPoolCount();
}
@@ -501,7 +460,7 @@
* @return The event FD used for communication between the signal handler and the ZygoteServer
* poll loop
*/
- private static FileDescriptor getBlastulaPoolEventFD() {
+ static FileDescriptor getBlastulaPoolEventFD() {
FileDescriptor fd = new FileDescriptor();
fd.setInt$(nativeGetBlastulaPoolEventFD());
@@ -518,7 +477,8 @@
* this function will return a Runnable object representing the new application that is
* passed up from blastulaMain.
*/
- private static Runnable forkBlastula(int[] sessionSocketRawFDs) {
+ static Runnable forkBlastula(LocalServerSocket blastulaPoolSocket,
+ int[] sessionSocketRawFDs) {
FileDescriptor[] pipeFDs = null;
try {
@@ -532,7 +492,7 @@
if (pid == 0) {
IoUtils.closeQuietly(pipeFDs[0]);
- return blastulaMain(pipeFDs[1]);
+ return blastulaMain(blastulaPoolSocket, pipeFDs[1]);
} else {
// The read-end of the pipe will be closed by the native code.
// See removeBlastulaTableEntry();
@@ -553,7 +513,8 @@
* of the ZygoteServer.
* @return A runnable oject representing the new application.
*/
- static Runnable blastulaMain(FileDescriptor writePipe) {
+ private static Runnable blastulaMain(LocalServerSocket blastulaPoolSocket,
+ FileDescriptor writePipe) {
final int pid = Process.myPid();
LocalSocket sessionSocket = null;
@@ -563,7 +524,7 @@
while (true) {
try {
- sessionSocket = sBlastulaPoolSocket.accept();
+ sessionSocket = blastulaPoolSocket.accept();
BufferedReader blastulaReader =
new BufferedReader(new InputStreamReader(sessionSocket.getInputStream()));
@@ -611,7 +572,7 @@
System.exit(-1);
} finally {
IoUtils.closeQuietly(sessionSocket);
- IoUtils.closeQuietly(sBlastulaPoolSocket);
+ IoUtils.closeQuietly(blastulaPoolSocket);
}
try {
@@ -660,7 +621,7 @@
* exception if an invalid arugment is encountered.
* @param args The arguments to test
*/
- static void validateBlastulaCommand(ZygoteArguments args) {
+ private static void validateBlastulaCommand(ZygoteArguments args) {
if (args.mAbiListQuery) {
throw new IllegalArgumentException(BLASTULA_ERROR_PREFIX + "--query-abi-list");
} else if (args.mPidQuery) {
@@ -851,20 +812,6 @@
}
/**
- * Creates a managed object representing the Blastula pool socket that has
- * already been initialized and bound by init.
- *
- * TODO (chriswailes): Move the name selection logic into this function.
- *
- * @throws RuntimeException when open fails
- */
- static void createBlastulaSocket(String socketName) {
- if (BLASTULA_POOL_ENABLED && sBlastulaPoolSocket == null) {
- sBlastulaPoolSocket = createManagedSocketFromInitSocket(socketName);
- }
- }
-
- /**
* Creates a managed LocalServerSocket object using a file descriptor
* created by an init.rc script. The init scripts that specify the
* sockets name can be found in system/core/rootdir. The socket is bound
diff --git a/core/java/com/android/internal/os/ZygoteConnection.java b/core/java/com/android/internal/os/ZygoteConnection.java
index 9cf7e27..8a878e2 100644
--- a/core/java/com/android/internal/os/ZygoteConnection.java
+++ b/core/java/com/android/internal/os/ZygoteConnection.java
@@ -338,13 +338,25 @@
private final MetricsLogger mMetricsLogger = new MetricsLogger();
private static HiddenApiUsageLogger sInstance = new HiddenApiUsageLogger();
+ private int mHiddenApiAccessLogSampleRate = 0;
+
+ public static void setHiddenApiAccessLogSampleRate(int sampleRate) {
+ sInstance.mHiddenApiAccessLogSampleRate = sampleRate;
+ }
public static HiddenApiUsageLogger getInstance() {
return HiddenApiUsageLogger.sInstance;
}
- public void hiddenApiUsed(String packageName, String signature,
+ public void hiddenApiUsed(int sampledValue, String packageName, String signature,
int accessMethod, boolean accessDenied) {
+ if (sampledValue < mHiddenApiAccessLogSampleRate) {
+ logUsage(packageName, signature, accessMethod, accessDenied);
+ }
+ }
+
+ private void logUsage(String packageName, String signature, int accessMethod,
+ boolean accessDenied) {
int accessMethodMetric = HiddenApiUsageLogger.ACCESS_METHOD_NONE;
switch(accessMethod) {
case HiddenApiUsageLogger.ACCESS_METHOD_NONE:
@@ -375,6 +387,7 @@
private void handleHiddenApiAccessLogSampleRate(int samplingRate) {
try {
ZygoteInit.setHiddenApiAccessLogSampleRate(samplingRate);
+ HiddenApiUsageLogger.setHiddenApiAccessLogSampleRate(samplingRate);
ZygoteInit.setHiddenApiUsageLogger(HiddenApiUsageLogger.getInstance());
mSocketOutStream.writeInt(0);
} catch (IOException ioe) {
diff --git a/core/java/com/android/internal/os/ZygoteInit.java b/core/java/com/android/internal/os/ZygoteInit.java
index e132abd..7cddf75 100644
--- a/core/java/com/android/internal/os/ZygoteInit.java
+++ b/core/java/com/android/internal/os/ZygoteInit.java
@@ -755,7 +755,7 @@
}
public static void main(String argv[]) {
- ZygoteServer zygoteServer = new ZygoteServer();
+ ZygoteServer zygoteServer = null;
// Mark zygote start. This ensures that thread creation will throw
// an error.
@@ -783,7 +783,7 @@
RuntimeInit.enableDdms();
boolean startSystemServer = false;
- String socketName = "zygote";
+ String zygoteSocketName = "zygote";
String abiList = null;
boolean enableLazyPreload = false;
for (int i = 1; i < argv.length; i++) {
@@ -794,26 +794,19 @@
} else if (argv[i].startsWith(ABI_LIST_ARG)) {
abiList = argv[i].substring(ABI_LIST_ARG.length());
} else if (argv[i].startsWith(SOCKET_NAME_ARG)) {
- socketName = argv[i].substring(SOCKET_NAME_ARG.length());
+ zygoteSocketName = argv[i].substring(SOCKET_NAME_ARG.length());
} else {
throw new RuntimeException("Unknown command line argument: " + argv[i]);
}
}
+ final boolean isPrimaryZygote = zygoteSocketName.equals(Zygote.PRIMARY_SOCKET_NAME);
+
if (abiList == null) {
throw new RuntimeException("No ABI list supplied.");
}
- // TODO (chriswailes): Wrap these three calls in a helper function?
- final String blastulaSocketName =
- socketName.equals(ZygoteProcess.ZYGOTE_SOCKET_NAME)
- ? ZygoteProcess.BLASTULA_POOL_SOCKET_NAME
- : ZygoteProcess.BLASTULA_POOL_SECONDARY_SOCKET_NAME;
-
- zygoteServer.createZygoteSocket(socketName);
- Zygote.createBlastulaSocket(blastulaSocketName);
-
- Zygote.getSocketFDs(socketName.equals(ZygoteProcess.ZYGOTE_SOCKET_NAME));
+ Zygote.getSocketFDs(isPrimaryZygote);
// In some configurations, we avoid preloading resources and classes eagerly.
// In such cases, we will preload things prior to our first fork.
@@ -846,8 +839,10 @@
ZygoteHooks.stopZygoteNoThreadCreation();
+ zygoteServer = new ZygoteServer(isPrimaryZygote);
+
if (startSystemServer) {
- Runnable r = forkSystemServer(abiList, socketName, zygoteServer);
+ Runnable r = forkSystemServer(abiList, zygoteSocketName, zygoteServer);
// {@code r == null} in the parent (zygote) process, and {@code r != null} in the
// child (system_server) process.
@@ -857,23 +852,18 @@
}
}
- // If the return value is null then this is the zygote process
- // returning to the normal control flow. If it returns a Runnable
- // object then this is a blastula that has finished specializing.
- caller = Zygote.initBlastulaPool();
+ Log.i(TAG, "Accepting command socket connections");
- if (caller == null) {
- Log.i(TAG, "Accepting command socket connections");
-
- // The select loop returns early in the child process after a fork and
- // loops forever in the zygote.
- caller = zygoteServer.runSelectLoop(abiList);
- }
+ // The select loop returns early in the child process after a fork and
+ // loops forever in the zygote.
+ caller = zygoteServer.runSelectLoop(abiList);
} catch (Throwable ex) {
Log.e(TAG, "System zygote died with exception", ex);
throw ex;
} finally {
- zygoteServer.closeServerSocket();
+ if (zygoteServer != null) {
+ zygoteServer.closeServerSocket();
+ }
}
// We're in the child process and have exited the select loop. Proceed to execute the
@@ -894,8 +884,8 @@
}
private static void waitForSecondaryZygote(String socketName) {
- String otherZygoteName = ZygoteProcess.ZYGOTE_SOCKET_NAME.equals(socketName)
- ? ZygoteProcess.ZYGOTE_SECONDARY_SOCKET_NAME : ZygoteProcess.ZYGOTE_SOCKET_NAME;
+ String otherZygoteName = Zygote.PRIMARY_SOCKET_NAME.equals(socketName)
+ ? Zygote.SECONDARY_SOCKET_NAME : Zygote.PRIMARY_SOCKET_NAME;
ZygoteProcess.waitForConnectionToZygote(otherZygoteName);
}
diff --git a/core/java/com/android/internal/os/ZygoteServer.java b/core/java/com/android/internal/os/ZygoteServer.java
index a78c095..2c17540 100644
--- a/core/java/com/android/internal/os/ZygoteServer.java
+++ b/core/java/com/android/internal/os/ZygoteServer.java
@@ -20,12 +20,17 @@
import android.net.LocalServerSocket;
import android.net.LocalSocket;
+import android.os.SystemClock;
+import android.os.Trace;
+import android.provider.DeviceConfig;
import android.system.ErrnoException;
import android.system.Os;
import android.system.StructPollfd;
import android.util.Log;
import android.util.Slog;
+import dalvik.system.ZygoteHooks;
+
import java.io.ByteArrayInputStream;
import java.io.DataInputStream;
import java.io.FileDescriptor;
@@ -38,7 +43,7 @@
* Provides functions to wait for commands on a UNIX domain socket, and fork
* off child processes that inherit the initial state of the VM.%
*
- * Please see {@link ZygoteConnection.Arguments} for documentation on the
+ * Please see {@link ZygoteArguments} for documentation on the
* client protocol.
*/
class ZygoteServer {
@@ -46,11 +51,48 @@
public static final String TAG = "ZygoteServer";
/**
+ * The maximim value that will be accepted from the BLASTULA_POOL_SIZE_MAX device property.
+ * is a mirror of BLASTULA_POOL_MAX_LIMIT found in com_android_internal_os_Zygote.cpp.
+ */
+ private static final int BLASTULA_POOL_SIZE_MAX_LIMIT = 100;
+
+ /**
+ * The minimum value that will be accepted from the BLASTULA_POOL_SIZE_MIN device property.
+ */
+ private static final int BLASTULA_POOL_SIZE_MIN_LIMIT = 1;
+
+ /** The default value used for the BLASTULA_POOL_SIZE_MAX device property */
+ private static final String BLASTULA_POOL_SIZE_MAX_DEFAULT = "10";
+
+ /** The default value used for the BLASTULA_POOL_SIZE_MIN device property */
+ private static final String BLASTULA_POOL_SIZE_MIN_DEFAULT = "1";
+
+ /**
+ * If the blastula pool should be created and used to start applications.
+ *
+ * Setting this value to false will disable the creation, maintenance, and use of the blastula
+ * pool. When the blastula pool is disabled the application lifecycle will be identical to
+ * previous versions of Android.
+ */
+ private boolean mBlastulaPoolEnabled = false;
+
+ /**
* Listening socket that accepts new server connections.
*/
private LocalServerSocket mZygoteSocket;
/**
+ * The name of the blastula socket to use if the blastula pool is enabled.
+ */
+ private LocalServerSocket mBlastulaPoolSocket;
+
+ /**
+ * File descriptor used for communication between the signal handler and the ZygoteServer poll
+ * loop.
+ * */
+ private FileDescriptor mBlastulaPoolEventFD;
+
+ /**
* Whether or not mZygoteSocket's underlying FD should be closed directly.
* If mZygoteSocket is created with an existing FD, closing the socket does
* not close the FD and it must be closed explicitly. If the socket is created
@@ -64,25 +106,55 @@
*/
private boolean mIsForkChild;
- ZygoteServer() { }
+ /**
+ * The runtime-adjustable maximum Blastula pool size.
+ */
+ private int mBlastulaPoolSizeMax = 0;
- void setForkChild() {
- mIsForkChild = true;
+ /**
+ * The runtime-adjustable minimum Blastula pool size.
+ */
+ private int mBlastulaPoolSizeMin = 0;
+
+ /**
+ * The runtime-adjustable value used to determine when to re-fill the
+ * blastula pool. The pool will be re-filled when
+ * (sBlastulaPoolMax - gBlastulaPoolCount) >= sBlastulaPoolRefillThreshold.
+ */
+ private int mBlastulaPoolRefillThreshold = 0;
+
+ ZygoteServer() {
+ mBlastulaPoolEventFD = null;
+ mZygoteSocket = null;
+ mBlastulaPoolSocket = null;
}
/**
- * Creates a managed object representing the Zygote socket that has already
- * been initialized and bound by init.
+ * Initialize the Zygote server with the Zygote server socket, blastula pool server socket,
+ * and blastula pool event FD.
*
- * TODO (chriswailes): Move the name selection logic into this function.
- *
- * @throws RuntimeException when open fails
+ * @param isPrimaryZygote If this is the primary Zygote or not.
*/
- void createZygoteSocket(String socketName) {
- if (mZygoteSocket == null) {
- mZygoteSocket = Zygote.createManagedSocketFromInitSocket(socketName);
- mCloseSocketFd = true;
+ ZygoteServer(boolean isPrimaryZygote) {
+ mBlastulaPoolEventFD = Zygote.getBlastulaPoolEventFD();
+
+ if (isPrimaryZygote) {
+ mZygoteSocket = Zygote.createManagedSocketFromInitSocket(Zygote.PRIMARY_SOCKET_NAME);
+ mBlastulaPoolSocket =
+ Zygote.createManagedSocketFromInitSocket(
+ Zygote.BLASTULA_POOL_PRIMARY_SOCKET_NAME);
+ } else {
+ mZygoteSocket = Zygote.createManagedSocketFromInitSocket(Zygote.SECONDARY_SOCKET_NAME);
+ mBlastulaPoolSocket =
+ Zygote.createManagedSocketFromInitSocket(
+ Zygote.BLASTULA_POOL_SECONDARY_SOCKET_NAME);
}
+
+ fetchBlastulaPoolPolicyProps();
+ }
+
+ void setForkChild() {
+ mIsForkChild = true;
}
/**
@@ -151,6 +223,102 @@
return mZygoteSocket.getFileDescriptor();
}
+ private void fetchBlastulaPoolPolicyProps() {
+ final String blastulaPoolSizeMaxPropString =
+ Zygote.getSystemProperty(
+ DeviceConfig.RuntimeNative.BLASTULA_POOL_SIZE_MAX,
+ BLASTULA_POOL_SIZE_MAX_DEFAULT);
+
+ if (!blastulaPoolSizeMaxPropString.isEmpty()) {
+ mBlastulaPoolSizeMax =
+ Integer.min(
+ Integer.parseInt(blastulaPoolSizeMaxPropString),
+ BLASTULA_POOL_SIZE_MAX_LIMIT);
+ }
+
+ final String blastulaPoolSizeMinPropString =
+ Zygote.getSystemProperty(
+ DeviceConfig.RuntimeNative.BLASTULA_POOL_SIZE_MIN,
+ BLASTULA_POOL_SIZE_MIN_DEFAULT);
+
+ if (!blastulaPoolSizeMinPropString.isEmpty()) {
+ mBlastulaPoolSizeMin =
+ Integer.max(
+ Integer.parseInt(blastulaPoolSizeMinPropString),
+ BLASTULA_POOL_SIZE_MIN_LIMIT);
+ }
+
+ final String blastulaPoolRefillThresholdPropString =
+ Zygote.getSystemProperty(
+ DeviceConfig.RuntimeNative.BLASTULA_POOL_REFILL_THRESHOLD,
+ Integer.toString(mBlastulaPoolSizeMax / 2));
+
+ if (!blastulaPoolRefillThresholdPropString.isEmpty()) {
+ mBlastulaPoolRefillThreshold =
+ Integer.min(
+ Integer.parseInt(blastulaPoolRefillThresholdPropString),
+ mBlastulaPoolSizeMax);
+ }
+
+ }
+
+ private long mLastPropCheckTimestamp = 0;
+
+ private void fetchBlastulaPoolPolicyPropsWithMinInterval() {
+ final long currentTimestamp = SystemClock.elapsedRealtime();
+
+ if (currentTimestamp - mLastPropCheckTimestamp >= Zygote.PROPERTY_CHECK_INTERVAL) {
+ fetchBlastulaPoolPolicyProps();
+ mLastPropCheckTimestamp = currentTimestamp;
+ }
+ }
+
+ /**
+ * Checks to see if the current policy says that pool should be refilled, and spawns new
+ * blastulas if necessary.
+ *
+ * @param sessionSocketRawFDs Anonymous session sockets that are currently open
+ * @return In the Zygote process this function will always return null; in blastula processes
+ * this function will return a Runnable object representing the new application that is
+ * passed up from blastulaMain.
+ */
+ private Runnable fillBlastulaPool(int[] sessionSocketRawFDs) {
+ if (mBlastulaPoolEnabled) {
+ Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "Zygote:FillBlastulaPool");
+
+ int blastulaPoolCount = Zygote.getBlastulaPoolCount();
+ int numBlastulasToSpawn = mBlastulaPoolSizeMax - blastulaPoolCount;
+
+ if (blastulaPoolCount < mBlastulaPoolSizeMin
+ || numBlastulasToSpawn >= mBlastulaPoolRefillThreshold) {
+
+ // Disable some VM functionality and reset some system values
+ // before forking.
+ ZygoteHooks.preFork();
+ Zygote.resetNicePriority();
+
+ while (blastulaPoolCount++ < mBlastulaPoolSizeMax) {
+ Runnable caller = Zygote.forkBlastula(mBlastulaPoolSocket, sessionSocketRawFDs);
+
+ if (caller != null) {
+ return caller;
+ }
+ }
+
+ // Re-enable runtime services for the Zygote. Blastula services
+ // are re-enabled in specializeBlastula.
+ ZygoteHooks.postForkCommon();
+
+ Log.i("zygote",
+ "Filled the blastula pool. New blastulas: " + numBlastulasToSpawn);
+ }
+
+ Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
+ }
+
+ return null;
+ }
+
/**
* Runs the zygote process's select loop. Accepts new connections as
* they happen, and reads commands from connections one spawn-request's
@@ -164,6 +332,8 @@
peers.add(null);
while (true) {
+ fetchBlastulaPoolPolicyPropsWithMinInterval();
+
int[] blastulaPipeFDs = Zygote.getBlastulaPipeFDs();
// Space for all of the socket FDs, the Blastula Pool Event FD, and
@@ -181,7 +351,7 @@
final int blastulaPoolEventFDIndex = pollIndex;
pollFDs[pollIndex] = new StructPollfd();
- pollFDs[pollIndex].fd = Zygote.sBlastulaPoolEventFD;
+ pollFDs[pollIndex].fd = mBlastulaPoolEventFD;
pollFDs[pollIndex].events = (short) POLLIN;
++pollIndex;
@@ -316,7 +486,7 @@
.mapToInt(fd -> fd.getInt$())
.toArray();
- final Runnable command = Zygote.fillBlastulaPool(sessionSocketRawFDs);
+ final Runnable command = fillBlastulaPool(sessionSocketRawFDs);
if (command != null) {
return command;
diff --git a/core/java/com/android/internal/policy/DividerSnapAlgorithm.java b/core/java/com/android/internal/policy/DividerSnapAlgorithm.java
index a8ad810..c46f867 100644
--- a/core/java/com/android/internal/policy/DividerSnapAlgorithm.java
+++ b/core/java/com/android/internal/policy/DividerSnapAlgorithm.java
@@ -137,6 +137,7 @@
mDismissStartTarget = mTargets.get(0);
mDismissEndTarget = mTargets.get(mTargets.size() - 1);
mMiddleTarget = mTargets.get(mTargets.size() / 2);
+ mMiddleTarget.isMiddleTarget = true;
}
/**
@@ -438,6 +439,8 @@
public final int flag;
+ public boolean isMiddleTarget;
+
/**
* Multiplier used to calculate distance to snap position. The lower this value, the harder
* it's to snap on this target
diff --git a/core/java/com/android/internal/widget/DecorCaptionView.java b/core/java/com/android/internal/widget/DecorCaptionView.java
index 21558d3..e90a8d5 100644
--- a/core/java/com/android/internal/widget/DecorCaptionView.java
+++ b/core/java/com/android/internal/widget/DecorCaptionView.java
@@ -329,13 +329,13 @@
}
/**
- * Maximize the window by moving it to the maximized workspace stack.
+ * Maximize or restore the window by moving it to the maximized or freeform workspace stack.
**/
- private void maximizeWindow() {
+ private void toggleFreeformWindowingMode() {
Window.WindowControllerCallback callback = mOwner.getWindowControllerCallback();
if (callback != null) {
try {
- callback.exitFreeformMode();
+ callback.toggleFreeformWindowingMode();
} catch (RemoteException ex) {
Log.e(TAG, "Cannot change task workspace.");
}
@@ -395,7 +395,7 @@
@Override
public boolean onSingleTapUp(MotionEvent e) {
if (mClickTarget == mMaximize) {
- maximizeWindow();
+ toggleFreeformWindowingMode();
} else if (mClickTarget == mClose) {
mOwner.dispatchOnWindowDismissed(
true /*finishTask*/, false /*suppressWindowTransition*/);
diff --git a/core/jni/Android.bp b/core/jni/Android.bp
index 7406136..30e9937 100644
--- a/core/jni/Android.bp
+++ b/core/jni/Android.bp
@@ -163,6 +163,7 @@
"android_media_AudioSystem.cpp",
"android_media_AudioTrack.cpp",
"android_media_AudioAttributes.cpp",
+ "android_media_AudioProductStrategies.cpp",
"android_media_DeviceCallback.cpp",
"android_media_JetPlayer.cpp",
"android_media_MediaMetricsJNI.cpp",
diff --git a/core/jni/AndroidRuntime.cpp b/core/jni/AndroidRuntime.cpp
index d69d416..019ade9 100644
--- a/core/jni/AndroidRuntime.cpp
+++ b/core/jni/AndroidRuntime.cpp
@@ -109,6 +109,7 @@
extern int register_android_media_AudioSystem(JNIEnv *env);
extern int register_android_media_AudioTrack(JNIEnv *env);
extern int register_android_media_AudioAttributes(JNIEnv *env);
+extern int register_android_media_AudioProductStrategies(JNIEnv *env);
extern int register_android_media_MicrophoneInfo(JNIEnv *env);
extern int register_android_media_JetPlayer(JNIEnv *env);
extern int register_android_media_ToneGenerator(JNIEnv *env);
@@ -232,8 +233,15 @@
// Namespace for Android Runtime flags applied during boot time.
static const char* RUNTIME_NATIVE_BOOT_NAMESPACE = "runtime_native_boot";
-// Feature flag name for Garbage Collector type.
-static const char* GCTYPE = "gctype";
+// Feature flag name to enable/disable generational garbage collection in ART's
+// Concurrent Copying (CC) garbage collector.
+static const char* ENABLE_GENERATIONAL_CC = "enable_generational_cc";
+// Runtime option enabling generational garbage collection in ART's Concurrent
+// Copying (CC) garbage collector.
+static const char* kGenerationalCCRuntimeOption = "-Xgc:generational_cc";
+// Runtime option disabling generational garbage collection in ART's Concurrent
+// Copying (CC) garbage collector.
+static const char* kNoGenerationalCCRuntimeOption = "-Xgc:nogenerational_cc";
static AndroidRuntime* gCurRuntime = NULL;
@@ -667,6 +675,11 @@
char methodTraceFileSizeBuf[sizeof("-Xmethod-trace-file-size:") + PROPERTY_VALUE_MAX];
std::string fingerprintBuf;
char jdwpProviderBuf[sizeof("-XjdwpProvider:") - 1 + PROPERTY_VALUE_MAX];
+ char bootImageBuf[sizeof("-Ximage:") - 1 + PROPERTY_VALUE_MAX];
+
+ if (parseRuntimeOption("dalvik.vm.boot-image", bootImageBuf, "-Ximage:")) {
+ ALOGI("Boot image: '%s'\n", bootImageBuf);
+ }
bool checkJni = false;
property_get("dalvik.vm.checkjni", propBuf, "");
@@ -780,17 +793,21 @@
addOption("-XX:LowMemoryMode");
}
- std::string gc_type_override =
- server_configurable_flags::GetServerConfigurableFlag(RUNTIME_NATIVE_BOOT_NAMESPACE,
- GCTYPE,
- /*default_value=*/ "");
- std::string gc_type_override_temp;
- if (gc_type_override.empty()) {
- parseRuntimeOption("dalvik.vm.gctype", gctypeOptsBuf, "-Xgc:");
- } else {
- // Copy the string so it doesn't go out of scope since addOption does not make a copy.
- gc_type_override_temp = "-Xgc:" + gc_type_override;
- addOption(gc_type_override_temp.c_str());
+ /*
+ * Garbage-collection related options.
+ */
+ parseRuntimeOption("dalvik.vm.gctype", gctypeOptsBuf, "-Xgc:");
+
+ // If it set, honor the "enable_generational_cc" device configuration;
+ // otherwise, let the runtime use its default behavior.
+ std::string enable_generational_cc =
+ server_configurable_flags::GetServerConfigurableFlag(RUNTIME_NATIVE_BOOT_NAMESPACE,
+ ENABLE_GENERATIONAL_CC,
+ /*default_value=*/ "");
+ if (enable_generational_cc == "true") {
+ addOption(kGenerationalCCRuntimeOption);
+ } else if (enable_generational_cc == "false") {
+ addOption(kNoGenerationalCCRuntimeOption);
}
parseRuntimeOption("dalvik.vm.backgroundgctype", backgroundgcOptsBuf, "-XX:BackgroundGC=");
@@ -1490,6 +1507,7 @@
REG_JNI(register_android_media_AudioRecord),
REG_JNI(register_android_media_AudioTrack),
REG_JNI(register_android_media_AudioAttributes),
+ REG_JNI(register_android_media_AudioProductStrategies),
REG_JNI(register_android_media_JetPlayer),
REG_JNI(register_android_media_MicrophoneInfo),
REG_JNI(register_android_media_RemoteDisplay),
diff --git a/core/jni/android_media_AudioProductStrategies.cpp b/core/jni/android_media_AudioProductStrategies.cpp
new file mode 100644
index 0000000..a18e80a4
--- /dev/null
+++ b/core/jni/android_media_AudioProductStrategies.cpp
@@ -0,0 +1,242 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+//#define LOG_NDEBUG 0
+
+#define LOG_TAG "AudioProductStrategies-JNI"
+
+#include <inttypes.h>
+#include <jni.h>
+#include <nativehelper/JNIHelp.h>
+#include "core_jni_helpers.h"
+
+#include <utils/Log.h>
+#include <vector>
+
+#include <media/AudioSystem.h>
+#include <media/AudioPolicy.h>
+
+#include <nativehelper/ScopedUtfChars.h>
+
+#include "android_media_AudioAttributes.h"
+#include "android_media_AudioErrors.h"
+
+// ----------------------------------------------------------------------------
+
+using namespace android;
+
+// ----------------------------------------------------------------------------
+static const char* const kClassPathName = "android/media/audiopolicy/AudioProductStrategies";
+static const char* const kAudioProductStrategyClassPathName =
+ "android/media/audiopolicy/AudioProductStrategy";
+
+static const char* const kAudioAttributesGroupsClassPathName =
+ "android/media/audiopolicy/AudioProductStrategy$AudioAttributesGroup";
+
+static jclass gAudioProductStrategyClass;
+static jmethodID gAudioProductStrategyCstor;
+static struct {
+ jfieldID mAudioAttributesGroups;
+ jfieldID mName;
+ jfieldID mId;
+} gAudioProductStrategyFields;
+
+static jclass gAudioAttributesGroupClass;
+static jmethodID gAudioAttributesGroupCstor;
+static struct {
+ jfieldID mGroupId;
+ jfieldID mLegacyStreamType;
+ jfieldID mAudioAttributes;
+} gAudioAttributesGroupsFields;
+
+static jclass gArrayListClass;
+static struct {
+ jmethodID add;
+ jmethodID toArray;
+} gArrayListMethods;
+
+
+static jint convertAudioProductStrategiesFromNative(
+ JNIEnv *env, jobject *jAudioStrategy, const AudioProductStrategy &strategy)
+{
+ jint jStatus = (jint)AUDIO_JAVA_SUCCESS;
+ jobjectArray jAudioAttributesGroups = NULL;
+ jobjectArray jAudioAttributes = NULL;
+ jobject jAudioAttribute = NULL;
+ jstring jName = NULL;
+ jint jStrategyId = NULL;
+ jint numAttributesGroups;
+ size_t indexGroup = 0;
+
+ jName = env->NewStringUTF(strategy.getName().c_str());
+ jStrategyId = static_cast<jint>(strategy.getId());
+
+ // Audio Attributes Group array
+ std::map<int, std::vector<AudioAttributes> > groups;
+ for (const auto &attr : strategy.getAudioAttributes()) {
+ int attrGroupId = attr.getGroupId();
+ groups[attrGroupId].push_back(attr);
+ }
+ numAttributesGroups = groups.size();
+
+ jAudioAttributesGroups = env->NewObjectArray(numAttributesGroups, gAudioAttributesGroupClass, NULL);
+
+ for (const auto &iter : groups) {
+ std::vector<AudioAttributes> audioAttributesGroups = iter.second;
+ jint numAttributes = audioAttributesGroups.size();
+ jint jGroupId = iter.first;
+ jint jLegacyStreamType = audioAttributesGroups.front().getStreamType();
+
+ jStatus = JNIAudioAttributeHelper::getJavaArray(env, &jAudioAttributes, numAttributes);
+ if (jStatus != (jint)AUDIO_JAVA_SUCCESS) {
+ goto exit;
+ }
+ for (size_t j = 0; j < static_cast<size_t>(numAttributes); j++) {
+ auto attributes = audioAttributesGroups[j].getAttributes();
+
+ jStatus = JNIAudioAttributeHelper::nativeToJava(env, &jAudioAttribute, attributes);
+ if (jStatus != AUDIO_JAVA_SUCCESS) {
+ goto exit;
+ }
+ env->SetObjectArrayElement(jAudioAttributes, j, jAudioAttribute);
+ }
+ jobject jAudioAttributesGroup = env->NewObject(gAudioAttributesGroupClass,
+ gAudioAttributesGroupCstor,
+ jGroupId,
+ jLegacyStreamType,
+ jAudioAttributes);
+ env->SetObjectArrayElement(jAudioAttributesGroups, indexGroup++, jAudioAttributesGroup);
+
+ if (jAudioAttributes != NULL) {
+ env->DeleteLocalRef(jAudioAttributes);
+ jAudioAttributes = NULL;
+ }
+ if (jAudioAttribute != NULL) {
+ env->DeleteLocalRef(jAudioAttribute);
+ jAudioAttribute = NULL;
+ }
+ if (jAudioAttributesGroup != NULL) {
+ env->DeleteLocalRef(jAudioAttributesGroup);
+ jAudioAttributesGroup = NULL;
+ }
+ }
+ *jAudioStrategy = env->NewObject(gAudioProductStrategyClass, gAudioProductStrategyCstor,
+ jName,
+ jStrategyId,
+ jAudioAttributesGroups);
+exit:
+ if (jAudioAttributes != NULL) {
+ env->DeleteLocalRef(jAudioAttributes);
+ }
+ if (jAudioAttribute != NULL) {
+ env->DeleteLocalRef(jAudioAttribute);
+ jAudioAttribute = NULL;
+ }
+ if (jAudioAttributesGroups != NULL) {
+ env->DeleteLocalRef(jAudioAttributesGroups);
+ }
+ if (jName != NULL) {
+ env->DeleteLocalRef(jName);
+ }
+ return jStatus;
+}
+
+static jint
+android_media_AudioSystem_listAudioProductStrategies(JNIEnv *env, jobject clazz,
+ jobject jStrategies)
+{
+ if (env == NULL) {
+ return AUDIO_JAVA_DEAD_OBJECT;
+ }
+ if (jStrategies == NULL) {
+ ALOGE("listAudioProductStrategies NULL AudioProductStrategies");
+ return (jint)AUDIO_JAVA_BAD_VALUE;
+ }
+ if (!env->IsInstanceOf(jStrategies, gArrayListClass)) {
+ ALOGE("listAudioProductStrategies not an arraylist");
+ return (jint)AUDIO_JAVA_BAD_VALUE;
+ }
+
+ status_t status;
+ AudioProductStrategyVector strategies;
+ jint jStatus;
+ jobject jStrategy = NULL;
+
+ status = AudioSystem::listAudioProductStrategies(strategies);
+ if (status != NO_ERROR) {
+ ALOGE("AudioSystem::listAudioProductStrategies error %d", status);
+ return nativeToJavaStatus(status);
+ }
+ for (const auto &strategy : strategies) {
+ jStatus = convertAudioProductStrategiesFromNative(env, &jStrategy, strategy);
+ if (jStatus != AUDIO_JAVA_SUCCESS) {
+ goto exit;
+ }
+ env->CallBooleanMethod(jStrategies, gArrayListMethods.add, jStrategy);
+ }
+exit:
+ if (jStrategy != NULL) {
+ env->DeleteLocalRef(jStrategy);
+ }
+ return jStatus;
+}
+
+/*
+ * JNI registration.
+ */
+static const JNINativeMethod gMethods[] = {
+ {"native_list_audio_product_strategies", "(Ljava/util/ArrayList;)I",
+ (void *)android_media_AudioSystem_listAudioProductStrategies},
+};
+
+int register_android_media_AudioProductStrategies(JNIEnv *env)
+{
+ jclass arrayListClass = FindClassOrDie(env, "java/util/ArrayList");
+ gArrayListClass = MakeGlobalRefOrDie(env, arrayListClass);
+ gArrayListMethods.add = GetMethodIDOrDie(env, arrayListClass, "add", "(Ljava/lang/Object;)Z");
+ gArrayListMethods.toArray = GetMethodIDOrDie(env, arrayListClass,
+ "toArray", "()[Ljava/lang/Object;");
+
+ jclass audioProductStrategyClass = FindClassOrDie(env, kAudioProductStrategyClassPathName);
+ gAudioProductStrategyClass = MakeGlobalRefOrDie(env, audioProductStrategyClass);
+ gAudioProductStrategyCstor = GetMethodIDOrDie(
+ env, audioProductStrategyClass, "<init>",
+ "(Ljava/lang/String;I[Landroid/media/audiopolicy/AudioProductStrategy$AudioAttributesGroup;)V");
+ gAudioProductStrategyFields.mAudioAttributesGroups = GetFieldIDOrDie(
+ env, audioProductStrategyClass, "mAudioAttributesGroups",
+ "[Landroid/media/audiopolicy/AudioProductStrategy$AudioAttributesGroup;");
+ gAudioProductStrategyFields.mName = GetFieldIDOrDie(
+ env, audioProductStrategyClass, "mName", "Ljava/lang/String;");
+ gAudioProductStrategyFields.mId = GetFieldIDOrDie(
+ env, audioProductStrategyClass, "mId", "I");
+
+ jclass audioAttributesGroupClass = FindClassOrDie(env, kAudioAttributesGroupsClassPathName);
+ gAudioAttributesGroupClass = MakeGlobalRefOrDie(env, audioAttributesGroupClass);
+ gAudioAttributesGroupCstor = GetMethodIDOrDie(env, audioAttributesGroupClass, "<init>",
+ "(II[Landroid/media/AudioAttributes;)V");
+ gAudioAttributesGroupsFields.mGroupId = GetFieldIDOrDie(
+ env, audioAttributesGroupClass, "mGroupId", "I");
+ gAudioAttributesGroupsFields.mLegacyStreamType = GetFieldIDOrDie(
+ env, audioAttributesGroupClass, "mLegacyStreamType", "I");
+ gAudioAttributesGroupsFields.mAudioAttributes = GetFieldIDOrDie(
+ env, audioAttributesGroupClass, "mAudioAttributes",
+ "[Landroid/media/AudioAttributes;");
+
+ env->DeleteLocalRef(audioProductStrategyClass);
+ env->DeleteLocalRef(audioAttributesGroupClass);
+
+ return RegisterMethodsOrDie(env, kClassPathName, gMethods, NELEM(gMethods));
+}
diff --git a/core/jni/android_os_Debug.cpp b/core/jni/android_os_Debug.cpp
index e9035ed..195fe58 100644
--- a/core/jni/android_os_Debug.cpp
+++ b/core/jni/android_os_Debug.cpp
@@ -737,6 +737,25 @@
return env->NewStringUTF(s.c_str());
}
+static jlong android_os_Debug_getFreeZramKb(JNIEnv* env, jobject clazz) {
+
+ jlong zramFreeKb = 0;
+
+ std::string status_path = android::base::StringPrintf("/proc/meminfo");
+ UniqueFile file = MakeUniqueFile(status_path.c_str(), "re");
+
+ char line[256];
+ while (file != nullptr && fgets(line, sizeof(line), file.get())) {
+ jlong v;
+ if (sscanf(line, "SwapFree: %" SCNd64 " kB", &v) == 1) {
+ zramFreeKb = v;
+ break;
+ }
+ }
+
+ return zramFreeKb;
+}
+
/*
* JNI registration.
*/
@@ -778,6 +797,8 @@
(void*)android_os_Debug_dumpNativeBacktraceToFileTimeout },
{ "getUnreachableMemory", "(IZ)Ljava/lang/String;",
(void*)android_os_Debug_getUnreachableMemory },
+ { "getZramFreeKb", "()J",
+ (void*)android_os_Debug_getFreeZramKb },
};
int register_android_os_Debug(JNIEnv *env)
diff --git a/core/jni/android_os_GraphicsEnvironment.cpp b/core/jni/android_os_GraphicsEnvironment.cpp
index 95f99b7..0ccc327 100644
--- a/core/jni/android_os_GraphicsEnvironment.cpp
+++ b/core/jni/android_os_GraphicsEnvironment.cpp
@@ -34,13 +34,16 @@
void setGpuStats_native(JNIEnv* env, jobject clazz, jstring driverPackageName,
jstring driverVersionName, jlong driverVersionCode,
- jstring appPackageName) {
+ jstring driverBuildDate, jstring appPackageName) {
ScopedUtfChars driverPackageNameChars(env, driverPackageName);
ScopedUtfChars driverVersionNameChars(env, driverVersionName);
+ ScopedUtfChars driverBuildDateChars(env, driverBuildDate);
ScopedUtfChars appPackageNameChars(env, appPackageName);
android::GraphicsEnv::getInstance().setGpuStats(driverPackageNameChars.c_str(),
driverVersionNameChars.c_str(),
- driverVersionCode, appPackageNameChars.c_str());
+ driverVersionCode,
+ driverBuildDateChars.c_str(),
+ appPackageNameChars.c_str());
}
void setAngleInfo_native(JNIEnv* env, jobject clazz, jstring path, jstring appName, jstring devOptIn,
@@ -84,7 +87,7 @@
const JNINativeMethod g_methods[] = {
{ "getCanLoadSystemLibraries", "()I", reinterpret_cast<void*>(getCanLoadSystemLibraries_native) },
{ "setDriverPath", "(Ljava/lang/String;)V", reinterpret_cast<void*>(setDriverPath) },
- { "setGpuStats", "(Ljava/lang/String;Ljava/lang/String;JLjava/lang/String;)V", reinterpret_cast<void*>(setGpuStats_native) },
+ { "setGpuStats", "(Ljava/lang/String;Ljava/lang/String;JLjava/lang/String;Ljava/lang/String;)V", reinterpret_cast<void*>(setGpuStats_native) },
{ "setAngleInfo", "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/io/FileDescriptor;JJ)V", reinterpret_cast<void*>(setAngleInfo_native) },
{ "getShouldUseAngle", "(Ljava/lang/String;)Z", reinterpret_cast<void*>(shouldUseAngle_native) },
{ "setLayerPaths", "(Ljava/lang/ClassLoader;Ljava/lang/String;)V", reinterpret_cast<void*>(setLayerPaths_native) },
diff --git a/core/jni/android_view_ThreadedRenderer.cpp b/core/jni/android_view_ThreadedRenderer.cpp
index 2aa5cb4..ecc2dd0 100644
--- a/core/jni/android_view_ThreadedRenderer.cpp
+++ b/core/jni/android_view_ThreadedRenderer.cpp
@@ -1029,6 +1029,10 @@
proxy->setForceDark(enable);
}
+static void android_view_ThreadedRenderer_preload(JNIEnv*, jclass) {
+ RenderProxy::preload();
+}
+
// ----------------------------------------------------------------------------
// FrameMetricsObserver
// ----------------------------------------------------------------------------
@@ -1144,6 +1148,7 @@
{ "nSetContextPriority", "(I)V", (void*)android_view_ThreadedRenderer_setContextPriority },
{ "nAllocateBuffers", "(J)V", (void*)android_view_ThreadedRenderer_allocateBuffers },
{ "nSetForceDark", "(JZ)V", (void*)android_view_ThreadedRenderer_setForceDark },
+ { "preload", "()V", (void*)android_view_ThreadedRenderer_preload },
};
static JavaVM* mJvm = nullptr;
diff --git a/core/jni/com_android_internal_os_Zygote.cpp b/core/jni/com_android_internal_os_Zygote.cpp
index 7b4e4ea..15ceca9 100644
--- a/core/jni/com_android_internal_os_Zygote.cpp
+++ b/core/jni/com_android_internal_os_Zygote.cpp
@@ -666,7 +666,7 @@
fail_fn(CREATE_ERROR("Failed to fstatat on %s/%s: %s",
parentDirPath.c_str(), dirName.c_str(), strerror(errno)));
}
- if (TEMP_FAILURE_RETRY(mkdirat(dirfd, dirName.c_str(), 0700)) == -1) {
+ if (TEMP_FAILURE_RETRY(mkdirat(dirfd, dirName.c_str(), 0700)) == -1 && errno != EEXIST) {
fail_fn(CREATE_ERROR("Failed to mkdirat on %s/%s: %s",
parentDirPath.c_str(), dirName.c_str(), strerror(errno)));
}
@@ -686,7 +686,8 @@
fail_fn(CREATE_ERROR("Failed to unlink %s: %s",
androidDir.c_str(), strerror(errno)));
}
- if (TEMP_FAILURE_RETRY(mkdir(androidDir.c_str(), 0700)) == -1) {
+ if (TEMP_FAILURE_RETRY(mkdir(androidDir.c_str(), 0700)) == -1
+ && errno != EEXIST) {
fail_fn(CREATE_ERROR("Failed to mkdir %s: %s",
androidDir.c_str(), strerror(errno)));
}
@@ -732,7 +733,7 @@
fail_fn(CREATE_ERROR("Failed to stat %s: %s",
sandboxSource.c_str(), strerror(errno)));
}
- if (TEMP_FAILURE_RETRY(mkdir(sandboxSource.c_str(), 0700)) == -1) {
+ if (TEMP_FAILURE_RETRY(mkdir(sandboxSource.c_str(), 0700)) == -1 && errno != EEXIST) {
fail_fn(CREATE_ERROR("Failed to mkdir %s: %s",
sandboxSource.c_str(), strerror(errno)));
}
@@ -1357,6 +1358,9 @@
SetSchedulerPolicy(fail_fn);
+ __android_log_close();
+ stats_log_close();
+
const char* se_info_ptr = se_info.has_value() ? se_info.value().c_str() : nullptr;
const char* nice_name_ptr = nice_name.has_value() ? nice_name.value().c_str() : nullptr;
diff --git a/core/jni/runtime_native_boot-flags-test.sh b/core/jni/runtime_native_boot-flags-test.sh
index 66e18bb..01f37f0 100755
--- a/core/jni/runtime_native_boot-flags-test.sh
+++ b/core/jni/runtime_native_boot-flags-test.sh
@@ -172,12 +172,14 @@
done
}
-# test_android_runtime_flag FLAG VALUE
-# ------------------------------------
-# Test device configuration FLAG with VALUE.
+# test_android_runtime_flag FLAG VALUE GC_RUNTIME_OPTION
+# ------------------------------------------------------
+# Test device configuration FLAG with VALUE. Check that GC_RUNTIME_OPTION is
+# passed as GC Runtime option by the zygote.
function test_android_runtime_flag {
local flag=$1
local value=$2
+ local gc_runtime_option=$3
# Persistent system property (set after a reboot) associated with the device
# configuration flag.
@@ -196,21 +198,21 @@
local context="Flag set, before reboot"
check_device_config_flag "$context" "$flag" "$value"
check_system_property "$context" "$prop" "$value"
- check_no_zygote_gc_runtime_option "$context" "$value"
+ check_no_zygote_gc_runtime_option "$context" "$gc_runtime_option"
# Reboot device for the flag value to take effect.
reboot_and_wait_for_device
context="Flag set, after 1st reboot"
check_device_config_flag "$context" "$flag" "$value"
check_system_property "$context" "$prop" "$value"
- check_zygote_gc_runtime_option "$context" "$value"
+ check_zygote_gc_runtime_option "$context" "$gc_runtime_option"
# Reboot device a second time and check that the state has persisted.
reboot_and_wait_for_device
context="Flag set, after 2nd reboot"
check_device_config_flag "$context" "$flag" "$value"
check_system_property "$context" "$prop" "$value"
- check_zygote_gc_runtime_option "$context" "$value"
+ check_zygote_gc_runtime_option "$context" "$gc_runtime_option"
say "Unsetting device configuration flag..."
adb shell device_config delete "$namespace" "$flag" >/dev/null
@@ -222,7 +224,7 @@
context="Flag unset, after 3rd reboot"
check_no_device_config_flag "$context" "$flag"
check_no_system_property "$context" "$prop"
- check_no_zygote_gc_runtime_option "$context" "$value"
+ check_no_zygote_gc_runtime_option "$context" "$gc_runtime_option"
}
# Enumerate Zygote processes.
@@ -232,9 +234,9 @@
(zygote32_64|zygote64_32) zygotes="zygote zygote64";;
esac
-# Test "gctype" flag values.
-test_android_runtime_flag gctype nogenerational_cc
-test_android_runtime_flag gctype generational_cc
+# Test "enable_generational_cc" flag values.
+test_android_runtime_flag enable_generational_cc false nogenerational_cc
+test_android_runtime_flag enable_generational_cc true generational_cc
if [[ "$exit_status" -eq 0 ]]; then
banner "All tests passed."
diff --git a/core/proto/android/providers/settings/global.proto b/core/proto/android/providers/settings/global.proto
index c9957f3..cccb40d 100644
--- a/core/proto/android/providers/settings/global.proto
+++ b/core/proto/android/providers/settings/global.proto
@@ -453,6 +453,8 @@
optional SettingProto game_driver_blacklists = 14;
// ANGLE - Show a dialog box when ANGLE is selected for the currently running PKG
optional SettingProto show_angle_in_use_dialog = 15;
+ // Game Driver - List of libraries in sphal accessible by Game Driver
+ optional SettingProto game_driver_sphal_libraries = 16;
}
optional Gpu gpu = 59;
diff --git a/core/res/res/layout/notification_material_media_seekbar.xml b/core/res/res/layout/notification_material_media_seekbar.xml
index 1b691d6..c23ca83 100644
--- a/core/res/res/layout/notification_material_media_seekbar.xml
+++ b/core/res/res/layout/notification_material_media_seekbar.xml
@@ -30,6 +30,7 @@
android:maxHeight="3dp"
android:paddingTop="24dp"
android:paddingBottom="24dp"
+ android:clickable="true"
android:layout_marginBottom="-24dp"
android:layout_marginTop="-12dp"
android:splitTrack="false"
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index 224f54c..088669d 100644
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -8004,7 +8004,8 @@
<!-- Indicates that this wallpaper service can support multiple engines to render on each
surface independently. An example use case is a multi-display set-up where the
- wallpaper service can render surfaces to each of the connected displays. -->
+ wallpaper service can render surfaces to each of the connected displays. Corresponds to
+ {@link android.app.WallpaperInfo#supportsMultipleDisplays()} -->
<attr name="supportsMultipleDisplays" format="boolean" />
</declare-styleable>
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 5948f29..09fb663 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -4291,6 +4291,13 @@
<!-- Title text to append when the display is secure. [CHAR LIMIT=30] -->
<string name="display_manager_overlay_display_secure_suffix">, secure</string>
+ <!-- Activity starter -->
+ <!-- Toast message for blocking background activity starts feature running in permissive mode -->
+ <string name="activity_starter_block_bg_activity_starts_permissive">This background activity start from <xliff:g id="packageName" example="com.example">%1$s</xliff:g> will be blocked in future Q builds. See go/q-bg-block.</string>
+
+ <!-- Toast message for blocking background activity starts feature running in enforcing mode -->
+ <string name="activity_starter_block_bg_activity_starts_enforcing">Background activity start from <xliff:g id="packageName" example="com.example">%1$s</xliff:g> blocked. See go/q-bg-block. </string>
+
<!-- Keyguard strings -->
<!-- Message shown in pattern unlock after some number of unsuccessful attempts -->
<string name="kg_forgot_pattern_button_text">Forgot Pattern</string>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 7ef5e02..1ebd6e9 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -763,6 +763,8 @@
<java-symbol type="string" name="display_manager_hdmi_display_name" />
<java-symbol type="string" name="display_manager_overlay_display_name" />
<java-symbol type="string" name="display_manager_overlay_display_secure_suffix" />
+ <java-symbol type="string" name="activity_starter_block_bg_activity_starts_permissive" />
+ <java-symbol type="string" name="activity_starter_block_bg_activity_starts_enforcing" />
<java-symbol type="string" name="display_manager_overlay_display_title" />
<java-symbol type="string" name="double_tap_toast" />
<java-symbol type="string" name="elapsed_time_short_format_h_mm_ss" />
diff --git a/core/tests/coretests/src/android/net/UriTest.java b/core/tests/coretests/src/android/net/UriTest.java
index a33de7b..a71000b 100644
--- a/core/tests/coretests/src/android/net/UriTest.java
+++ b/core/tests/coretests/src/android/net/UriTest.java
@@ -182,8 +182,7 @@
uri = Uri.parse("http://bob%40lee%3ajr@local%68ost:4%32");
assertEquals("bob@lee:jr", uri.getUserInfo());
- assertEquals("localhost", uri.getHost());
- assertEquals(42, uri.getPort());
+ assertEquals("localhost:42", uri.getHost());
uri = Uri.parse("http://localhost");
assertEquals("localhost", uri.getHost());
diff --git a/core/tests/coretests/src/android/provider/DocumentsProviderTest.java b/core/tests/coretests/src/android/provider/DocumentsProviderTest.java
index 02a9adf..bff6b5f 100644
--- a/core/tests/coretests/src/android/provider/DocumentsProviderTest.java
+++ b/core/tests/coretests/src/android/provider/DocumentsProviderTest.java
@@ -60,7 +60,8 @@
DocumentsContract.buildDocumentUri(TestDocumentsProvider.AUTHORITY, DOCUMENT_ID);
try (ContentProviderClient client =
mResolver.acquireUnstableContentProviderClient(docUri)) {
- final Path actual = DocumentsContract.findDocumentPath(client, docUri);
+ final Path actual = DocumentsContract.findDocumentPath(
+ ContentResolver.wrap(client), docUri);
assertEquals(expected, actual);
}
}
diff --git a/core/tests/coretests/src/android/provider/SettingsBackupTest.java b/core/tests/coretests/src/android/provider/SettingsBackupTest.java
index c57b609..46cac7a 100644
--- a/core/tests/coretests/src/android/provider/SettingsBackupTest.java
+++ b/core/tests/coretests/src/android/provider/SettingsBackupTest.java
@@ -122,6 +122,7 @@
Settings.Global.APP_OPS_CONSTANTS,
Settings.Global.APP_STANDBY_ENABLED,
Settings.Global.APP_TIME_LIMIT_USAGE_SOURCE,
+ Settings.Global.ART_VERIFIER_VERIFY_DEBUGGABLE,
Settings.Global.ASSISTED_GPS_ENABLED,
Settings.Global.AUDIO_SAFE_VOLUME_STATE,
Settings.Global.AUTOFILL_COMPAT_MODE_ALLOWED_PACKAGES,
@@ -494,6 +495,7 @@
Settings.Global.GAME_DRIVER_BLACKLISTS,
Settings.Global.GAME_DRIVER_BLACKLIST,
Settings.Global.GAME_DRIVER_WHITELIST,
+ Settings.Global.GAME_DRIVER_SPHAL_LIBRARIES,
Settings.Global.GLOBAL_SETTINGS_SHOW_ANGLE_IN_USE_DIALOG_BOX,
Settings.Global.GPU_DEBUG_LAYER_APP,
Settings.Global.ENABLE_GNSS_RAW_MEAS_FULL_TRACKING,
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 7f104b1..f27f3f9 100644
--- a/core/tests/coretests/src/com/android/internal/app/ChooserActivityTest.java
+++ b/core/tests/coretests/src/com/android/internal/app/ChooserActivityTest.java
@@ -30,6 +30,7 @@
import static org.hamcrest.CoreMatchers.notNullValue;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.mockito.Mockito.atLeastOnce;
+import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@@ -41,6 +42,7 @@
import android.content.Context;
import android.content.Intent;
import android.content.pm.ResolveInfo;
+import android.database.Cursor;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
@@ -651,6 +653,59 @@
onView(withId(R.id.content_preview_file_icon)).check(matches(isDisplayed()));
}
+ @Test
+ public void contentProviderThrowSecurityException() throws InterruptedException {
+ Uri uri = Uri.parse("content://com.android.frameworks.coretests/app.pdf");
+
+ ArrayList<Uri> uris = new ArrayList<>();
+ uris.add(uri);
+
+ Intent sendIntent = createSendUriIntentWithPreview(uris);
+
+ List<ResolvedComponentInfo> resolvedComponentInfos = createResolvedComponentsForTest(2);
+ when(sOverrides.resolverListController.getResolversForIntent(Mockito.anyBoolean(),
+ Mockito.anyBoolean(),
+ Mockito.isA(List.class))).thenReturn(resolvedComponentInfos);
+
+ sOverrides.resolverForceException = true;
+
+ mActivityRule.launchActivity(Intent.createChooser(sendIntent, null));
+ waitForIdle();
+ onView(withId(R.id.content_preview_filename)).check(matches(isDisplayed()));
+ onView(withId(R.id.content_preview_filename)).check(matches(withText("app.pdf")));
+ onView(withId(R.id.content_preview_file_icon)).check(matches(isDisplayed()));
+ }
+
+ @Test
+ public void contentProviderReturnsNoColumns() throws InterruptedException {
+ Uri uri = Uri.parse("content://com.android.frameworks.coretests/app.pdf");
+
+ ArrayList<Uri> uris = new ArrayList<>();
+ uris.add(uri);
+ uris.add(uri);
+
+ Intent sendIntent = createSendUriIntentWithPreview(uris);
+
+ List<ResolvedComponentInfo> resolvedComponentInfos = createResolvedComponentsForTest(2);
+ when(sOverrides.resolverListController.getResolversForIntent(Mockito.anyBoolean(),
+ Mockito.anyBoolean(),
+ Mockito.isA(List.class))).thenReturn(resolvedComponentInfos);
+
+ Cursor cursor = mock(Cursor.class);
+ when(cursor.getCount()).thenReturn(1);
+ Mockito.doNothing().when(cursor).close();
+ when(cursor.moveToFirst()).thenReturn(true);
+ when(cursor.getColumnIndex(Mockito.anyString())).thenReturn(-1);
+
+ sOverrides.resolverCursor = cursor;
+
+ mActivityRule.launchActivity(Intent.createChooser(sendIntent, null));
+ waitForIdle();
+ onView(withId(R.id.content_preview_filename)).check(matches(isDisplayed()));
+ onView(withId(R.id.content_preview_filename)).check(matches(withText("app.pdf + 1 file")));
+ onView(withId(R.id.content_preview_file_icon)).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/ChooserWrapperActivity.java b/core/tests/coretests/src/com/android/internal/app/ChooserWrapperActivity.java
index 096b78b..57c84ff 100644
--- a/core/tests/coretests/src/com/android/internal/app/ChooserWrapperActivity.java
+++ b/core/tests/coretests/src/com/android/internal/app/ChooserWrapperActivity.java
@@ -19,8 +19,10 @@
import static org.mockito.Mockito.mock;
import android.app.usage.UsageStatsManager;
+import android.content.ContentResolver;
import android.content.Context;
import android.content.pm.PackageManager;
+import android.database.Cursor;
import android.graphics.Bitmap;
import android.net.Uri;
import android.util.Size;
@@ -97,6 +99,19 @@
return sOverrides.metricsLogger;
}
+ @Override
+ public Cursor queryResolver(ContentResolver resolver, Uri uri) {
+ if (sOverrides.resolverCursor != null) {
+ return sOverrides.resolverCursor;
+ }
+
+ if (sOverrides.resolverForceException) {
+ throw new SecurityException("Test exception handling");
+ }
+
+ return super.queryResolver(resolver, uri);
+ }
+
/**
* We cannot directly mock the activity created since instrumentation creates it.
* <p>
@@ -109,6 +124,8 @@
public ResolverListController resolverListController;
public Boolean isVoiceInteraction;
public boolean isImageType;
+ public Cursor resolverCursor;
+ public boolean resolverForceException;
public Bitmap previewThumbnail;
public MetricsLogger metricsLogger;
@@ -118,6 +135,8 @@
createPackageManager = null;
previewThumbnail = null;
isImageType = false;
+ resolverCursor = null;
+ resolverForceException = false;
resolverListController = mock(ResolverListController.class);
metricsLogger = mock(MetricsLogger.class);
}
diff --git a/data/etc/privapp-permissions-platform.xml b/data/etc/privapp-permissions-platform.xml
index 915cf95..f19e44c 100644
--- a/data/etc/privapp-permissions-platform.xml
+++ b/data/etc/privapp-permissions-platform.xml
@@ -207,7 +207,7 @@
<permission name="android.permission.USE_RESERVED_DISK"/>
</privapp-permissions>
- <privapp-permissions package="com.android.mainline.networkstack">
+ <privapp-permissions package="com.android.networkstack">
<permission name="android.permission.ACCESS_NETWORK_CONDITIONS"/>
<permission name="android.permission.CONNECTIVITY_INTERNAL"/>
<permission name="android.permission.CONNECTIVITY_USE_RESTRICTED_NETWORKS"/>
diff --git a/graphics/java/android/graphics/HardwareRenderer.java b/graphics/java/android/graphics/HardwareRenderer.java
index 99d8c1b..b020556 100644
--- a/graphics/java/android/graphics/HardwareRenderer.java
+++ b/graphics/java/android/graphics/HardwareRenderer.java
@@ -1027,6 +1027,18 @@
*/
public static native void disableVsync();
+ /**
+ * Start render thread and initialize EGL or Vulkan.
+ *
+ * Initializing EGL involves loading and initializing the graphics driver. Some drivers take
+ * several 10s of milliseconds to do this, so doing it on-demand when an app tries to render
+ * its first frame adds directly to user-visible app launch latency.
+ *
+ * Should only be called after GraphicsEnvironment.chooseDriver().
+ * @hide
+ */
+ public static native void preload();
+
/** @hide */
protected static native void setupShadersDiskCache(String cacheFile, String skiaCacheFile);
diff --git a/graphics/java/android/graphics/Typeface.java b/graphics/java/android/graphics/Typeface.java
index ef9255f..e93e757 100644
--- a/graphics/java/android/graphics/Typeface.java
+++ b/graphics/java/android/graphics/Typeface.java
@@ -128,7 +128,8 @@
// Following two fields are not used but left for hiddenapi private list
/**
- * Use {@link SystemFonts#getAvailableFonts()} instead.
+ * sSystemFontMap is read only and unmodifiable.
+ * Use public API {@link #create(String, int)} to get the typeface for given familyName.
*/
@UnsupportedAppUsage(trackingBug = 123769347)
static final Map<String, Typeface> sSystemFontMap;
diff --git a/libs/hwui/Android.bp b/libs/hwui/Android.bp
index 0335a7c..793dd8d 100644
--- a/libs/hwui/Android.bp
+++ b/libs/hwui/Android.bp
@@ -318,6 +318,7 @@
"tests/unit/RenderNodeDrawableTests.cpp",
"tests/unit/RenderNodeTests.cpp",
"tests/unit/RenderPropertiesTests.cpp",
+ "tests/unit/RenderThreadTests.cpp",
"tests/unit/ShaderCacheTests.cpp",
"tests/unit/SkiaBehaviorTests.cpp",
"tests/unit/SkiaDisplayListTests.cpp",
diff --git a/libs/hwui/renderthread/RenderProxy.cpp b/libs/hwui/renderthread/RenderProxy.cpp
index 720c603..34f76d9 100644
--- a/libs/hwui/renderthread/RenderProxy.cpp
+++ b/libs/hwui/renderthread/RenderProxy.cpp
@@ -381,6 +381,14 @@
});
}
+void RenderProxy::preload() {
+ // Create RenderThread object and start the thread. Then preload Vulkan/EGL driver.
+ auto& thread = RenderThread::getInstance();
+ thread.queue().post([&thread]() {
+ thread.preload();
+ });
+}
+
} /* namespace renderthread */
} /* namespace uirenderer */
} /* namespace android */
diff --git a/libs/hwui/renderthread/RenderProxy.h b/libs/hwui/renderthread/RenderProxy.h
index 6e1bfd7..a1a5551 100644
--- a/libs/hwui/renderthread/RenderProxy.h
+++ b/libs/hwui/renderthread/RenderProxy.h
@@ -131,6 +131,8 @@
ANDROID_API static void disableVsync();
+ ANDROID_API static void preload();
+
static void repackVectorDrawableAtlas();
static void releaseVDAtlasEntries();
diff --git a/libs/hwui/renderthread/RenderThread.cpp b/libs/hwui/renderthread/RenderThread.cpp
index fc63819..08edd20 100644
--- a/libs/hwui/renderthread/RenderThread.cpp
+++ b/libs/hwui/renderthread/RenderThread.cpp
@@ -41,6 +41,7 @@
#include <utils/Condition.h>
#include <utils/Log.h>
#include <utils/Mutex.h>
+#include <thread>
namespace android {
namespace uirenderer {
@@ -175,9 +176,6 @@
mRenderState = new RenderState(*this);
mVkManager = new VulkanManager();
mCacheManager = new CacheManager(mDisplayInfo);
- if (Properties::getRenderPipelineType() == RenderPipelineType::SkiaVulkan) {
- requireVkContext();
- }
}
void RenderThread::requireGlContext() {
@@ -346,6 +344,7 @@
bool RenderThread::threadLoop() {
setpriority(PRIO_PROCESS, 0, PRIORITY_DISPLAY);
+ Looper::setForThread(mLooper);
if (gOnStartHook) {
gOnStartHook("RenderThread");
}
@@ -408,6 +407,17 @@
return gettid() == getInstance().getTid();
}
+void RenderThread::preload() {
+ std::thread eglInitThread([]() {
+ //TODO: don't load EGL drivers for Vulkan, when HW bitmap uploader is refactored.
+ eglGetDisplay(EGL_DEFAULT_DISPLAY);
+ });
+ eglInitThread.detach();
+ if (Properties::getRenderPipelineType() == RenderPipelineType::SkiaVulkan) {
+ requireVkContext();
+ }
+}
+
} /* namespace renderthread */
} /* namespace uirenderer */
} /* namespace android */
diff --git a/libs/hwui/renderthread/RenderThread.h b/libs/hwui/renderthread/RenderThread.h
index 419e7c7..329b4b9 100644
--- a/libs/hwui/renderthread/RenderThread.h
+++ b/libs/hwui/renderthread/RenderThread.h
@@ -115,6 +115,8 @@
void requireVkContext();
void destroyRenderingContext();
+ void preload();
+
/**
* isCurrent provides a way to query, if the caller is running on
* the render thread.
diff --git a/libs/hwui/renderthread/VulkanManager.cpp b/libs/hwui/renderthread/VulkanManager.cpp
index 1e685ab..3b43f12 100644
--- a/libs/hwui/renderthread/VulkanManager.cpp
+++ b/libs/hwui/renderthread/VulkanManager.cpp
@@ -360,7 +360,7 @@
}
}
-sk_sp<GrContext> VulkanManager::createContext(GrContextOptions options) {
+sk_sp<GrContext> VulkanManager::createContext(const GrContextOptions& options) {
auto getProc = [] (const char* proc_name, VkInstance instance, VkDevice device) {
if (device != VK_NULL_HANDLE) {
return vkGetDeviceProcAddr(device, proc_name);
diff --git a/libs/hwui/renderthread/VulkanManager.h b/libs/hwui/renderthread/VulkanManager.h
index 9763686..95c9630 100644
--- a/libs/hwui/renderthread/VulkanManager.h
+++ b/libs/hwui/renderthread/VulkanManager.h
@@ -150,7 +150,7 @@
// Returned pointers are owned by VulkanManager.
VkFunctorInitParams getVkFunctorInitParams() const;
- sk_sp<GrContext> createContext(GrContextOptions options);
+ sk_sp<GrContext> createContext(const GrContextOptions& options);
private:
// Sets up the VkInstance and VkDevice objects. Also fills out the passed in
diff --git a/libs/hwui/tests/unit/RenderThreadTests.cpp b/libs/hwui/tests/unit/RenderThreadTests.cpp
new file mode 100644
index 0000000..af8ae78
--- /dev/null
+++ b/libs/hwui/tests/unit/RenderThreadTests.cpp
@@ -0,0 +1,29 @@
+/*
+ * 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 <gtest/gtest.h>
+
+#include "tests/common/TestUtils.h"
+#include <utils/Looper.h>
+
+using namespace android;
+using namespace android::uirenderer;
+using namespace android::uirenderer::renderthread;
+
+RENDERTHREAD_TEST(RenderThread, isLooper) {
+ ASSERT_TRUE(Looper::getForThread() != nullptr);
+}
+
diff --git a/media/OWNERS b/media/OWNERS
index 03b751c..eb26367 100644
--- a/media/OWNERS
+++ b/media/OWNERS
@@ -11,3 +11,6 @@
marcone@google.com
sungsoo@google.com
wjia@google.com
+
+# For maintaining sync with AndroidX code
+per-file ExifInterface.java = jinpark@google.com, sungsoo@google.com
diff --git a/media/apex/java/android/media/MediaController2.java b/media/apex/java/android/media/MediaController2.java
index e85d997..4ea384a 100644
--- a/media/apex/java/android/media/MediaController2.java
+++ b/media/apex/java/android/media/MediaController2.java
@@ -317,7 +317,9 @@
isCanceled = !mRequestedCommandSeqNumbers.remove(seq);
}
if (isCanceled) {
- resultReceiver.send(RESULT_INFO_SKIPPED, null);
+ if (resultReceiver != null) {
+ resultReceiver.send(RESULT_INFO_SKIPPED, null);
+ }
return;
}
Session2Command.Result result = mCallback.onSessionCommand(
diff --git a/media/apex/java/android/media/MediaSession2.java b/media/apex/java/android/media/MediaSession2.java
index fdd07fd..4c6945a 100644
--- a/media/apex/java/android/media/MediaSession2.java
+++ b/media/apex/java/android/media/MediaSession2.java
@@ -259,6 +259,20 @@
}
}
+ /**
+ * Gets the list of the connected controllers
+ *
+ * @return list of the connected controllers.
+ */
+ @NonNull
+ public List<ControllerInfo> getConnectedControllers() {
+ List<ControllerInfo> controllers = new ArrayList<>();
+ synchronized (mLock) {
+ controllers.addAll(mConnectedControllers.values());
+ }
+ return controllers;
+ }
+
boolean isClosed() {
synchronized (mLock) {
return mClosed;
@@ -317,13 +331,6 @@
if (DEBUG) {
Log.d(TAG, "Accepting connection: " + controllerInfo);
}
- synchronized (mLock) {
- if (mConnectedControllers.containsKey(controller)) {
- Log.w(TAG, "Controller " + controllerInfo + " has sent connection"
- + " request multiple times");
- }
- mConnectedControllers.put(controller, controllerInfo);
- }
// If connection is accepted, notify the current state to the controller.
// It's needed because we cannot call synchronous calls between
// session/controller.
@@ -339,6 +346,14 @@
return;
}
controllerInfo.notifyConnected(connectionResult);
+ synchronized (mLock) {
+ if (mConnectedControllers.containsKey(controller)) {
+ Log.w(TAG, "Controller " + controllerInfo + " has sent connection"
+ + " request multiple times");
+ }
+ mConnectedControllers.put(controller, controllerInfo);
+ }
+ mCallback.onPostConnect(MediaSession2.this, controllerInfo);
connected = true;
} finally {
if (!connected) {
@@ -417,14 +432,6 @@
controllerInfo.removeRequestedCommandSeqNumber(seq);
}
- private List<ControllerInfo> getConnectedControllers() {
- List<ControllerInfo> controllers = new ArrayList<>();
- synchronized (mLock) {
- controllers.addAll(mConnectedControllers.values());
- }
- return controllers;
- }
-
/**
* Builder for {@link MediaSession2}.
* <p>
@@ -738,6 +745,17 @@
}
/**
+ * Called immediately after a controller is connected. This is a convenient method to add
+ * custom initialization between the session and a controller.
+ *
+ * @param session the session for this event
+ * @param controller controller information.
+ */
+ public void onPostConnect(@NonNull MediaSession2 session,
+ @NonNull ControllerInfo controller) {
+ }
+
+ /**
* Called when a controller is disconnected
*
* @param session the session for this event
diff --git a/media/java/android/media/HwAudioSource.java b/media/java/android/media/HwAudioSource.java
new file mode 100644
index 0000000..8bdb8a6
--- /dev/null
+++ b/media/java/android/media/HwAudioSource.java
@@ -0,0 +1,228 @@
+/*
+ * 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.media;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.SystemApi;
+
+import com.android.internal.util.Preconditions;
+
+/**
+ * The HwAudioSource represents the audio playback directly from a source audio device.
+ * It currently supports {@link HwAudioSource#start()} and {@link HwAudioSource#stop()} only
+ * corresponding to {@link AudioSystem#startAudioSource(AudioPortConfig, AudioAttributes)}
+ * and {@link AudioSystem#stopAudioSource(int)}.
+ *
+ * @hide
+ */
+@SystemApi
+public class HwAudioSource extends PlayerBase {
+ private final AudioDeviceInfo mAudioDeviceInfo;
+ private final AudioAttributes mAudioAttributes;
+
+ private int mNativeHandle;
+
+ /**
+ * Class constructor for a hardware audio source based player.
+ *
+ * Use the {@link Builder} class to construct a {@link HwAudioSource} instance.
+ *
+ * @param device {@link AudioDeviceInfo} instance of the source audio device.
+ * @param attributes {@link AudioAttributes} instance for this player.
+ */
+ private HwAudioSource(@NonNull AudioDeviceInfo device, @NonNull AudioAttributes attributes) {
+ super(attributes, AudioPlaybackConfiguration.PLAYER_TYPE_HW_SOURCE);
+ Preconditions.checkNotNull(device);
+ Preconditions.checkNotNull(attributes);
+ Preconditions.checkArgument(device.isSource(), "Requires a source device");
+ mAudioDeviceInfo = device;
+ mAudioAttributes = attributes;
+ baseRegisterPlayer();
+ }
+
+ /**
+ * TODO: sets the gain on {@link #mAudioDeviceInfo}.
+ *
+ * @param muting if true, the player is to be muted, and the volume values can be ignored
+ * @param leftVolume the left volume to use if muting is false
+ * @param rightVolume the right volume to use if muting is false
+ */
+ @Override
+ void playerSetVolume(boolean muting, float leftVolume, float rightVolume) {
+ }
+
+ /**
+ * TODO: applies {@link VolumeShaper} on {@link #mAudioDeviceInfo}.
+ *
+ * @param configuration a {@code VolumeShaper.Configuration} object
+ * created by {@link VolumeShaper.Configuration.Builder} or
+ * an created from a {@code VolumeShaper} id
+ * by the {@link VolumeShaper.Configuration} constructor.
+ * @param operation a {@code VolumeShaper.Operation}.
+ * @return
+ */
+ @Override
+ int playerApplyVolumeShaper(
+ @NonNull VolumeShaper.Configuration configuration,
+ @NonNull VolumeShaper.Operation operation) {
+ return 0;
+ }
+
+ /**
+ * TODO: gets the {@link VolumeShaper} by a given id.
+ *
+ * @param id the {@code VolumeShaper} id returned from
+ * sending a fully specified {@code VolumeShaper.Configuration}
+ * through {@link #playerApplyVolumeShaper}
+ * @return
+ */
+ @Override
+ @Nullable
+ VolumeShaper.State playerGetVolumeShaperState(int id) {
+ return new VolumeShaper.State(1f, 1f);
+ }
+
+ /**
+ * TODO: sets the level on {@link #mAudioDeviceInfo}.
+ *
+ * @param muting
+ * @param level
+ * @return
+ */
+ @Override
+ int playerSetAuxEffectSendLevel(boolean muting, float level) {
+ return AudioSystem.SUCCESS;
+ }
+
+ @Override
+ void playerStart() {
+ start();
+ }
+
+ @Override
+ void playerPause() {
+ // Pause is equivalent to stop for hardware audio source based players.
+ stop();
+ }
+
+ @Override
+ void playerStop() {
+ stop();
+ }
+
+ /**
+ * Starts the playback from {@link AudioDeviceInfo}.
+ */
+ public void start() {
+ baseStart();
+ mNativeHandle = AudioSystem.startAudioSource(
+ mAudioDeviceInfo.getPort().activeConfig(),
+ mAudioAttributes);
+ }
+
+ /**
+ * Stops the playback from {@link AudioDeviceInfo}.
+ */
+ public void stop() {
+ baseStop();
+ if (mNativeHandle > 0) {
+ AudioSystem.stopAudioSource(mNativeHandle);
+ mNativeHandle = 0;
+ }
+ }
+
+ /**
+ * Builder class for {@link HwAudioSource} objects.
+ * Use this class to configure and create a <code>HwAudioSource</code> instance.
+ * <p>Here is an example where <code>Builder</code> is used to specify an audio
+ * playback directly from a source device as media usage, to be used by a new
+ * <code>HwAudioSource</code> instance:
+ *
+ * <pre class="prettyprint">
+ * HwAudioSource player = new HwAudioSource.Builder()
+ * .setAudioAttributes(new AudioAttributes.Builder()
+ * .setUsage(AudioAttributes.USAGE_MEDIA)
+ * .build())
+ * .setAudioDeviceInfo(device)
+ * .build()
+ * </pre>
+ * <p>
+ * If the audio attributes are not set with {@link #setAudioAttributes(AudioAttributes)},
+ * attributes comprising {@link AudioAttributes#USAGE_MEDIA} will be used.
+ */
+ public static class Builder {
+ private AudioAttributes mAudioAttributes;
+ private AudioDeviceInfo mAudioDeviceInfo;
+
+ /**
+ * Constructs a new Builder with default values.
+ */
+ public Builder() {
+ }
+
+ /**
+ * Sets the {@link AudioAttributes}.
+ * @param attributes a non-null {@link AudioAttributes} instance that describes the audio
+ * data to be played.
+ * @return the same Builder instance.
+ */
+ public @NonNull Builder setAudioAttributes(@NonNull AudioAttributes attributes) {
+ Preconditions.checkNotNull(attributes);
+ mAudioAttributes = attributes;
+ return this;
+ }
+
+ /**
+ * Sets the {@link AudioDeviceInfo}.
+ * @param info a non-null {@link AudioDeviceInfo} instance that describes the audio
+ * data come from.
+ * @return the same Builder instance.
+ */
+ public @NonNull Builder setAudioDeviceInfo(@NonNull AudioDeviceInfo info) {
+ Preconditions.checkNotNull(info);
+ Preconditions.checkArgument(info.isSource());
+ mAudioDeviceInfo = info;
+ return this;
+ }
+
+ /**
+ * Builds an {@link HwAudioSource} instance initialized with all the parameters set
+ * on this <code>Builder</code>.
+ * @return a new successfully initialized {@link HwAudioSource} instance.
+ */
+ public @NonNull HwAudioSource build() {
+ Preconditions.checkNotNull(mAudioDeviceInfo);
+ if (mAudioAttributes == null) {
+ mAudioAttributes = new AudioAttributes.Builder()
+ .setUsage(AudioAttributes.USAGE_MEDIA)
+ .build();
+ }
+ return new HwAudioSource(mAudioDeviceInfo, mAudioAttributes);
+ }
+ }
+
+ /**
+ * Eliminate {@link #deprecateStreamTypeForPlayback(int, String, String)} in API list.
+ * TODO: remove this pseudo-override function
+ * @hide
+ */
+ public static void deprecateStreamTypeForPlayback(int streamType, String className,
+ String opName) throws IllegalArgumentException {
+ // Do nothing.
+ }
+}
diff --git a/media/java/android/media/ThumbnailUtils.java b/media/java/android/media/ThumbnailUtils.java
index ccf49bd..21b194d 100644
--- a/media/java/android/media/ThumbnailUtils.java
+++ b/media/java/android/media/ThumbnailUtils.java
@@ -122,6 +122,9 @@
* @param filePath The audio file.
* @param kind The desired thumbnail kind, such as
* {@link android.provider.MediaStore.Images.Thumbnails#MINI_KIND}.
+ * @deprecated Callers should migrate to using
+ * {@link #createAudioThumbnail(File, Size, CancellationSignal)},
+ * as it offers more control over resizing and cancellation.
*/
@Deprecated
public static @Nullable Bitmap createAudioThumbnail(@NonNull String filePath, int kind) {
@@ -211,6 +214,9 @@
* @param filePath The image file.
* @param kind The desired thumbnail kind, such as
* {@link android.provider.MediaStore.Images.Thumbnails#MINI_KIND}.
+ * @deprecated Callers should migrate to using
+ * {@link #createImageThumbnail(File, Size, CancellationSignal)},
+ * as it offers more control over resizing and cancellation.
*/
@Deprecated
public static @Nullable Bitmap createImageThumbnail(@NonNull String filePath, int kind) {
@@ -270,6 +276,9 @@
* @param filePath The video file.
* @param kind The desired thumbnail kind, such as
* {@link android.provider.MediaStore.Images.Thumbnails#MINI_KIND}.
+ * @deprecated Callers should migrate to using
+ * {@link #createVideoThumbnail(File, Size, CancellationSignal)},
+ * as it offers more control over resizing and cancellation.
*/
@Deprecated
public static @Nullable Bitmap createVideoThumbnail(@NonNull String filePath, int kind) {
diff --git a/media/java/android/media/audiopolicy/AudioProductStrategies.aidl b/media/java/android/media/audiopolicy/AudioProductStrategies.aidl
new file mode 100644
index 0000000..bec11bc
--- /dev/null
+++ b/media/java/android/media/audiopolicy/AudioProductStrategies.aidl
@@ -0,0 +1,18 @@
+/* Copyright 2018, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+
+package android.media.audiopolicy;
+
+parcelable AudioProductStrategies;
diff --git a/media/java/android/media/audiopolicy/AudioProductStrategies.java b/media/java/android/media/audiopolicy/AudioProductStrategies.java
new file mode 100644
index 0000000..b836409
--- /dev/null
+++ b/media/java/android/media/audiopolicy/AudioProductStrategies.java
@@ -0,0 +1,201 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.media.audiopolicy;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.SystemApi;
+import android.media.AudioAttributes;
+import android.media.AudioSystem;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.util.Log;
+
+import com.android.internal.util.Preconditions;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+
+/**
+ * @hide
+ * A class to encapsulate a collection of {@link AudioProductStrategy}.
+ * Provides helper functions to easily retrieve the {@link AudioAttributes} for a given product
+ * strategy or legacy stream type.
+ */
+@SystemApi
+public final class AudioProductStrategies implements Iterable<AudioProductStrategy>, Parcelable {
+
+ private final ArrayList<AudioProductStrategy> mAudioProductStrategyList;
+
+ private static final String TAG = "AudioProductStrategies";
+
+ public AudioProductStrategies() {
+ ArrayList<AudioProductStrategy> apsList = new ArrayList<AudioProductStrategy>();
+ int status = native_list_audio_product_strategies(apsList);
+ if (status != AudioSystem.SUCCESS) {
+ Log.w(TAG, ": createAudioProductStrategies failed");
+ }
+ mAudioProductStrategyList = apsList;
+ }
+
+ private AudioProductStrategies(ArrayList<AudioProductStrategy> audioProductStrategy) {
+ mAudioProductStrategyList = audioProductStrategy;
+ }
+
+ /**
+ * @hide
+ * @return number of {@link AudioProductStrategy} objects
+ */
+ @SystemApi
+ public int size() {
+ return mAudioProductStrategyList.size();
+ }
+
+ /**
+ * @hide
+ * @return the matching {@link AudioProductStrategy} objects with the given id,
+ * null object if not found.
+ */
+ @SystemApi
+ public @Nullable AudioProductStrategy getById(int productStrategyId) {
+ for (final AudioProductStrategy avg : this) {
+ if (avg.getId() == productStrategyId) {
+ return avg;
+ }
+ }
+ Log.e(TAG, ": invalid product strategy id: " + productStrategyId + " requested");
+ return null;
+ }
+
+ /**
+ * Returns an {@link Iterator}
+ */
+ @Override
+ public Iterator<AudioProductStrategy> iterator() {
+ return mAudioProductStrategyList.iterator();
+ }
+
+ @Override
+ public boolean equals(@Nullable Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+
+ AudioProductStrategies that = (AudioProductStrategies) o;
+
+ return mAudioProductStrategyList.equals(that.mAudioProductStrategyList);
+ }
+
+ /**
+ * @hide
+ * @param aps {@link AudioProductStrategy} (which is the generalisation of Car Audio Usage /
+ * legacy routing_strategy linked to {@link AudioAttributes#getUsage()} )
+ * @return the {@link AudioAttributes} relevant for the given product strategy.
+ * If none is found, it builds the default attributes.
+ * TODO: shall the helper collection be able to identify the platform default?
+ */
+ @SystemApi
+ @NonNull
+ public AudioAttributes getAudioAttributesForProductStrategy(@NonNull AudioProductStrategy aps) {
+ Preconditions.checkNotNull(aps, "AudioProductStrategy must not be null");
+ for (final AudioProductStrategy audioProductStrategy : this) {
+ if (audioProductStrategy.equals(aps)) {
+ return audioProductStrategy.getAudioAttributes();
+ }
+ }
+ return new AudioAttributes.Builder()
+ .setContentType(AudioAttributes.CONTENT_TYPE_UNKNOWN)
+ .setUsage(AudioAttributes.USAGE_UNKNOWN).build();
+ }
+
+ /**
+ * @hide
+ * @param streamType legacy stream type used for volume operation only
+ * @return the {@link AudioAttributes} relevant for the given streamType.
+ * If none is found, it builds the default attributes.
+ */
+ @SystemApi
+ public @NonNull AudioAttributes getAudioAttributesForLegacyStreamType(int streamType) {
+ for (final AudioProductStrategy productStrategy : this) {
+ AudioAttributes aa = productStrategy.getAudioAttributesForLegacyStreamType(streamType);
+ if (aa != null) {
+ return aa;
+ }
+ }
+ return new AudioAttributes.Builder()
+ .setContentType(AudioAttributes.CONTENT_TYPE_UNKNOWN)
+ .setUsage(AudioAttributes.USAGE_UNKNOWN).build();
+ }
+
+ /**
+ * @hide
+ * @param aa the {@link AudioAttributes} for which stream type is requested
+ * @return the legacy stream type relevant for the given {@link AudioAttributes}.
+ * If the product strategy is not associated to any stream, it returns STREAM_MUSIC.
+ * If no product strategy supports the stream type, it returns STREAM_MUSIC.
+ */
+ @SystemApi
+ public int getLegacyStreamTypeForAudioAttributes(@NonNull AudioAttributes aa) {
+ Preconditions.checkNotNull(aa, "AudioAttributes must not be null");
+ for (final AudioProductStrategy productStrategy : this) {
+ if (productStrategy.supportsAudioAttributes(aa)) {
+ int streamType = productStrategy.getLegacyStreamTypeForAudioAttributes(aa);
+ if (streamType == AudioSystem.STREAM_DEFAULT) {
+ Log.w(TAG, "Attributes " + aa.toString() + " ported by strategy "
+ + productStrategy.name() + " has no stream type associated, "
+ + "DO NOT USE STREAM TO CONTROL THE VOLUME");
+ return AudioSystem.STREAM_MUSIC;
+ }
+ return streamType;
+ }
+ }
+ return AudioSystem.STREAM_MUSIC;
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(@NonNull Parcel dest, int flags) {
+ dest.writeInt(size());
+ for (final AudioProductStrategy productStrategy : this) {
+ productStrategy.writeToParcel(dest, flags);
+ }
+ }
+
+ public static final Parcelable.Creator<AudioProductStrategies> CREATOR =
+ new Parcelable.Creator<AudioProductStrategies>() {
+ @Override
+ public AudioProductStrategies createFromParcel(@NonNull Parcel in) {
+ ArrayList<AudioProductStrategy> apsList = new ArrayList<AudioProductStrategy>();
+ int size = in.readInt();
+ for (int index = 0; index < size; index++) {
+ apsList.add(AudioProductStrategy.CREATOR.createFromParcel(in));
+ }
+ return new AudioProductStrategies(apsList);
+ }
+
+ @Override
+ public @NonNull AudioProductStrategies[] newArray(int size) {
+ return new AudioProductStrategies[size];
+ }
+ };
+
+ private static native int native_list_audio_product_strategies(
+ ArrayList<AudioProductStrategy> strategies);
+}
diff --git a/media/java/android/media/audiopolicy/AudioProductStrategy.aidl b/media/java/android/media/audiopolicy/AudioProductStrategy.aidl
new file mode 100644
index 0000000..5ead30b
--- /dev/null
+++ b/media/java/android/media/audiopolicy/AudioProductStrategy.aidl
@@ -0,0 +1,18 @@
+/* Copyright 2018, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+
+package android.media.audiopolicy;
+
+parcelable AudioProductStrategy;
diff --git a/media/java/android/media/audiopolicy/AudioProductStrategy.java b/media/java/android/media/audiopolicy/AudioProductStrategy.java
new file mode 100644
index 0000000..af6e8bf
--- /dev/null
+++ b/media/java/android/media/audiopolicy/AudioProductStrategy.java
@@ -0,0 +1,378 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.media.audiopolicy;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.SystemApi;
+import android.media.AudioAttributes;
+import android.media.AudioSystem;
+import android.media.MediaRecorder;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.text.TextUtils;
+
+import com.android.internal.util.Preconditions;
+
+/**
+ * @hide
+ * A class to encapsulate a collection of attributes associated to a given product strategy
+ * (and for legacy reason, keep the association with the stream type).
+ */
+@SystemApi
+public final class AudioProductStrategy implements Parcelable {
+ /**
+ * group value to use when introspection API fails.
+ * @hide
+ */
+ public static final int DEFAULT_GROUP = -1;
+
+ private final AudioAttributesGroup[] mAudioAttributesGroups;
+ private final String mName;
+ /**
+ * Unique identifier of a product strategy.
+ * This Id can be assimilated to Car Audio Usage and even more generally to usage.
+ * For legacy platforms, the product strategy id is the routing_strategy, which was hidden to
+ * upper layer but was transpiring in the {@link AudioAttributes#getUsage()}.
+ */
+ private int mId;
+
+ @Override
+ public boolean equals(@Nullable Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+
+ AudioProductStrategy thatStrategy = (AudioProductStrategy) o;
+
+ return mName == thatStrategy.mName && mId == thatStrategy.mId
+ && mAudioAttributesGroups.equals(thatStrategy.mAudioAttributesGroups);
+ }
+
+ /**
+ * @param name of the product strategy
+ * @param id of the product strategy
+ * @param audioAttributes {@link AudioAttributes} associated to the given product strategy
+ * @param legacyStreamTypes associated to the given product strategy.
+ */
+ private AudioProductStrategy(@NonNull String name, int id,
+ @NonNull AudioAttributesGroup[] aag) {
+ Preconditions.checkNotNull(name, "name must not be null");
+ Preconditions.checkNotNull(aag, "AudioAttributesGroups must not be null");
+ mName = name;
+ mId = id;
+ mAudioAttributesGroups = aag;
+ }
+
+ /**
+ * @hide
+ * @return human-readable name of this product strategy, which is similar to a usage
+ */
+ @SystemApi
+ public @NonNull String name() {
+ return mName;
+ }
+
+ /**
+ * @hide
+ * @return the product strategy ID (which is the generalisation of Car Audio Usage / legacy
+ * routing_strategy linked to {@link AudioAttributes#getUsage()}).
+ */
+ @SystemApi
+ public int getId() {
+ return mId;
+ }
+
+ /**
+ * @hide
+ * @return first {@link AudioAttributes} associated to this product strategy.
+ */
+ @SystemApi
+ public @NonNull AudioAttributes getAudioAttributes() {
+ // We need a choice, so take the first one
+ return mAudioAttributesGroups.length == 0 ? (new AudioAttributes.Builder().build())
+ : mAudioAttributesGroups[0].getAudioAttributes();
+ }
+
+ /**
+ * @hide
+ * @param streamType legacy stream type used for volume operation only
+ * @return the {@link AudioAttributes} relevant for the given streamType.
+ * If none is found, it builds the default attributes.
+ */
+ public @Nullable AudioAttributes getAudioAttributesForLegacyStreamType(int streamType) {
+ for (final AudioAttributesGroup aag : mAudioAttributesGroups) {
+ if (aag.supportsStreamType(streamType)) {
+ return aag.getAudioAttributes();
+ }
+ }
+ return null;
+ }
+
+ /**
+ * @hide
+ * @param aa the {@link AudioAttributes} to be considered
+ * @return the legacy stream type relevant for the given {@link AudioAttributes}.
+ * If none is found, it return DEFAULT stream type.
+ */
+ public int getLegacyStreamTypeForAudioAttributes(@NonNull AudioAttributes aa) {
+ Preconditions.checkNotNull(aa, "AudioAttributes must not be null");
+ for (final AudioAttributesGroup aag : mAudioAttributesGroups) {
+ if (aag.supportsAttributes(aa)) {
+ return aag.getStreamType();
+ }
+ }
+ return AudioSystem.STREAM_DEFAULT;
+ }
+
+ /**
+ * @hide
+ * @param aa the {@link AudioAttributes} to be considered
+ * @return true if the {@link AudioProductStrategy} supports the given {@link AudioAttributes},
+ * false otherwise.
+ */
+ public boolean supportsAudioAttributes(@NonNull AudioAttributes aa) {
+ Preconditions.checkNotNull(aa, "AudioAttributes must not be null");
+ for (final AudioAttributesGroup aag : mAudioAttributesGroups) {
+ if (aag.supportsAttributes(aa)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * @hide
+ * @param streamType legacy stream type used for volume operation only
+ * @return the {@link AudioAttributes} relevant for the given streamType.
+ * If none is found, it builds the default attributes.
+ */
+ public int getGroupIdForLegacyStreamType(int streamType) {
+ for (final AudioAttributesGroup aag : mAudioAttributesGroups) {
+ if (aag.supportsStreamType(streamType)) {
+ return aag.getGroupId();
+ }
+ }
+ return DEFAULT_GROUP;
+ }
+
+ /**
+ * @hide
+ * @param aa the {@link AudioAttributes} to be considered
+ * @return the group id associated with the given audio attributes if found,
+ * default value otherwise.
+ */
+ public int getGroupIdForAudioAttributes(@NonNull AudioAttributes aa) {
+ Preconditions.checkNotNull(aa, "AudioAttributes must not be null");
+ for (final AudioAttributesGroup aag : mAudioAttributesGroups) {
+ if (aag.supportsAttributes(aa)) {
+ return aag.getGroupId();
+ }
+ }
+ return DEFAULT_GROUP;
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(@NonNull Parcel dest, int flags) {
+ dest.writeString(mName);
+ dest.writeInt(mId);
+ dest.writeInt(mAudioAttributesGroups.length);
+ for (AudioAttributesGroup aag : mAudioAttributesGroups) {
+ aag.writeToParcel(dest, flags);
+ }
+ }
+
+ public static final Parcelable.Creator<AudioProductStrategy> CREATOR =
+ new Parcelable.Creator<AudioProductStrategy>() {
+ @Override
+ public AudioProductStrategy createFromParcel(@NonNull Parcel in) {
+ String name = in.readString();
+ int id = in.readInt();
+ int nbAttributesGroups = in.readInt();
+ AudioAttributesGroup[] aag = new AudioAttributesGroup[nbAttributesGroups];
+ for (int index = 0; index < nbAttributesGroups; index++) {
+ aag[index] = AudioAttributesGroup.CREATOR.createFromParcel(in);
+ }
+ return new AudioProductStrategy(name, id, aag);
+ }
+
+ @Override
+ public @NonNull AudioProductStrategy[] newArray(int size) {
+ return new AudioProductStrategy[size];
+ }
+ };
+
+ @Override
+ public String toString() {
+ StringBuilder s = new StringBuilder();
+ s.append("\n Name: ");
+ s.append(mName);
+ s.append(" Id: ");
+ s.append(Integer.toString(mId));
+ for (AudioAttributesGroup aag : mAudioAttributesGroups) {
+ s.append(aag.toString());
+ }
+ return s.toString();
+ }
+
+ /**
+ * @hide
+ * Default attributes, with default source to be aligned with native.
+ */
+ public static final @NonNull AudioAttributes sDefaultAttributes =
+ new AudioAttributes.Builder().setCapturePreset(MediaRecorder.AudioSource.DEFAULT)
+ .build();
+
+ /**
+ * To avoid duplicating the logic in java and native, we shall make use of
+ * native API native_get_product_strategies_from_audio_attributes
+ * @param refAttr {@link AudioAttributes} to be taken as the reference
+ * @param attr {@link AudioAttributes} of the requester.
+ */
+ private static boolean attributesMatches(@NonNull AudioAttributes refAttr,
+ @NonNull AudioAttributes attr) {
+ Preconditions.checkNotNull(refAttr, "refAttr must not be null");
+ Preconditions.checkNotNull(attr, "attr must not be null");
+ String refFormattedTags = TextUtils.join(";", refAttr.getTags());
+ String cliFormattedTags = TextUtils.join(";", attr.getTags());
+ if (refAttr.equals(sDefaultAttributes)) {
+ return false;
+ }
+ return ((refAttr.getUsage() == AudioAttributes.USAGE_UNKNOWN)
+ || (attr.getUsage() == refAttr.getUsage()))
+ && ((refAttr.getContentType() == AudioAttributes.CONTENT_TYPE_UNKNOWN)
+ || (attr.getContentType() == refAttr.getContentType()))
+ && ((refAttr.getAllFlags() == 0)
+ || (attr.getAllFlags() != 0
+ && (attr.getAllFlags() & refAttr.getAllFlags()) == attr.getAllFlags()))
+ && ((refFormattedTags.length() == 0) || refFormattedTags.equals(cliFormattedTags));
+ }
+
+
+ private static final class AudioAttributesGroup implements Parcelable {
+ private int mGroupId;
+ private int mLegacyStreamType;
+ private final AudioAttributes[] mAudioAttributes;
+
+ AudioAttributesGroup(int groupId, int streamType,
+ @NonNull AudioAttributes[] audioAttributes) {
+ mGroupId = groupId;
+ mLegacyStreamType = streamType;
+ mAudioAttributes = audioAttributes;
+ }
+
+ @Override
+ public boolean equals(@Nullable Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+
+ AudioAttributesGroup thatAag = (AudioAttributesGroup) o;
+
+ return mGroupId == thatAag.mGroupId
+ && mLegacyStreamType == thatAag.mLegacyStreamType
+ && mAudioAttributes.equals(thatAag.mAudioAttributes);
+ }
+
+ public int getStreamType() {
+ return mLegacyStreamType;
+ }
+
+ public int getGroupId() {
+ return mGroupId;
+ }
+
+ public @NonNull AudioAttributes getAudioAttributes() {
+ // We need a choice, so take the first one
+ return mAudioAttributes.length == 0 ? (new AudioAttributes.Builder().build())
+ : mAudioAttributes[0];
+ }
+
+ /**
+ * Checks if a {@link AudioAttributes} is supported by this product strategy.
+ * @param {@link AudioAttributes} to check upon support
+ * @return true if the {@link AudioAttributes} follows this product strategy,
+ false otherwise.
+ */
+ public boolean supportsAttributes(@NonNull AudioAttributes attributes) {
+ for (final AudioAttributes refAa : mAudioAttributes) {
+ if (refAa.equals(attributes) || attributesMatches(refAa, attributes)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public boolean supportsStreamType(int streamType) {
+ return mLegacyStreamType == streamType;
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(@NonNull Parcel dest, int flags) {
+ dest.writeInt(mGroupId);
+ dest.writeInt(mLegacyStreamType);
+ dest.writeInt(mAudioAttributes.length);
+ for (AudioAttributes attributes : mAudioAttributes) {
+ attributes.writeToParcel(dest, flags | AudioAttributes.FLATTEN_TAGS/*flags*/);
+ }
+ }
+
+ public static final Parcelable.Creator<AudioAttributesGroup> CREATOR =
+ new Parcelable.Creator<AudioAttributesGroup>() {
+ @Override
+ public AudioAttributesGroup createFromParcel(@NonNull Parcel in) {
+ int groupId = in.readInt();
+ int streamType = in.readInt();
+ int nbAttributes = in.readInt();
+ AudioAttributes[] aa = new AudioAttributes[nbAttributes];
+ for (int index = 0; index < nbAttributes; index++) {
+ aa[index] = AudioAttributes.CREATOR.createFromParcel(in);
+ }
+ return new AudioAttributesGroup(groupId, streamType, aa);
+ }
+
+ @Override
+ public @NonNull AudioAttributesGroup[] newArray(int size) {
+ return new AudioAttributesGroup[size];
+ }
+ };
+
+
+ @Override
+ public @NonNull String toString() {
+ StringBuilder s = new StringBuilder();
+ s.append("\n Legacy Stream Type: ");
+ s.append(Integer.toString(mLegacyStreamType));
+ s.append(" Group Id: ");
+ s.append(Integer.toString(mGroupId));
+
+ for (AudioAttributes attribute : mAudioAttributes) {
+ s.append("\n -");
+ s.append(attribute.toString());
+ }
+ return s.toString();
+ }
+ }
+}
diff --git a/packages/BackupRestoreConfirmation/Android.bp b/packages/BackupRestoreConfirmation/Android.bp
new file mode 100644
index 0000000..b0222da
--- /dev/null
+++ b/packages/BackupRestoreConfirmation/Android.bp
@@ -0,0 +1,23 @@
+//
+// Copyright (C) 2011 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT 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_app {
+ name: "BackupRestoreConfirmation",
+ srcs: ["src/**/*.java"],
+ platform_apis: true,
+ certificate: "platform",
+ privileged: true,
+}
diff --git a/packages/BackupRestoreConfirmation/Android.mk b/packages/BackupRestoreConfirmation/Android.mk
deleted file mode 100644
index 532d272..0000000
--- a/packages/BackupRestoreConfirmation/Android.mk
+++ /dev/null
@@ -1,33 +0,0 @@
-#
-# Copyright (C) 2011 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-LOCAL_PATH := $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_TAGS := optional
-
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-
-LOCAL_PACKAGE_NAME := BackupRestoreConfirmation
-LOCAL_PRIVATE_PLATFORM_APIS := true
-LOCAL_CERTIFICATE := platform
-LOCAL_PRIVILEGED_MODULE := true
-
-include $(BUILD_PACKAGE)
-
-########################
-include $(call all-makefiles-under,$(LOCAL_PATH))
-
diff --git a/packages/CarSystemUI/src/com/android/systemui/notifications/NotificationsUI.java b/packages/CarSystemUI/src/com/android/systemui/notifications/NotificationsUI.java
index ca343d1..8077431 100644
--- a/packages/CarSystemUI/src/com/android/systemui/notifications/NotificationsUI.java
+++ b/packages/CarSystemUI/src/com/android/systemui/notifications/NotificationsUI.java
@@ -24,13 +24,17 @@
import android.car.Car;
import android.car.CarNotConnectedException;
import android.car.drivingstate.CarUxRestrictionsManager;
+import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
import android.content.ServiceConnection;
import android.content.res.Configuration;
import android.graphics.PixelFormat;
import android.os.IBinder;
import android.os.ServiceManager;
+import android.os.UserHandle;
import android.util.Log;
import android.view.ContextThemeWrapper;
import android.view.GestureDetector;
@@ -91,12 +95,28 @@
private static int sSettleOpenPercentage;
private static int sSettleClosePercentage;
+ private final BroadcastReceiver mIntentReceiver = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ String action = intent.getAction();
+ if (action.equals(Intent.ACTION_USER_SWITCHED)) {
+ mCarNotificationListener.registerAsSystemService(mContext,
+ mCarUxRestrictionManagerWrapper,
+ mClickHandlerFactory);
+ inflateNotificationContent();
+ }
+ }
+ };
+
/**
* Inits the window that hosts the notifications and establishes the connections
* to the car related services.
*/
@Override
public void start() {
+ IntentFilter filter = new IntentFilter();
+ filter.addAction(Intent.ACTION_USER_SWITCHED);
+ mContext.registerReceiverAsUser(mIntentReceiver, UserHandle.ALL, filter, null, null);
sSettleOpenPercentage = mContext.getResources().getInteger(
R.integer.notification_settle_open_percentage);
sSettleClosePercentage = mContext.getResources().getInteger(
@@ -117,8 +137,7 @@
closeCarNotifications(DEFAULT_FLING_VELOCITY);
}
});
- mCarNotificationListener.registerAsSystemService(mContext, mCarUxRestrictionManagerWrapper,
- mClickHandlerFactory);
+
mCar = Car.createCar(mContext, mCarConnectionListener);
mCar.connect();
NotificationGestureListener gestureListener = new NotificationGestureListener();
@@ -131,8 +150,6 @@
mCarNotificationWindow
.setBackgroundColor(mContext.getColor(R.color.notification_shade_background_color));
- inflateNotificationContent();
-
WindowManager.LayoutParams layoutParams = new WindowManager.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT,
WindowManager.LayoutParams.TYPE_DISPLAY_OVERLAY,
diff --git a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java
index c5a951c..369bb9f 100644
--- a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java
+++ b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java
@@ -512,29 +512,49 @@
}
@Override
+ public void setLockscreenUser(int newUserId) {
+ super.setLockscreenUser(newUserId);
+ // Try to dismiss the keyguard after every user switch.
+ dismissKeyguardWhenUserSwitcherNotDisplayed();
+ }
+
+ @Override
public void onStateChanged(int newState) {
super.onStateChanged(newState);
startSwitchToGuestTimerIfDrivingOnKeyguard();
- if (mFullscreenUserSwitcher == null) {
- return; // Not using the full screen user switcher.
- }
-
- if (newState == StatusBarState.FULLSCREEN_USER_SWITCHER) {
- if (!mFullscreenUserSwitcher.isVisible()) {
- // Current execution path continues to set state after this, thus we deffer the
- // dismissal to the next execution cycle.
- postDismissKeyguard(); // Dismiss the keyguard if switcher is not visible.
- }
+ if (newState != StatusBarState.FULLSCREEN_USER_SWITCHER) {
+ hideUserSwitcher();
} else {
+ dismissKeyguardWhenUserSwitcherNotDisplayed();
+ }
+ }
+
+ /** Makes the full screen user switcher visible, if applicable. */
+ public void showUserSwitcher() {
+ if (mFullscreenUserSwitcher != null && mState == StatusBarState.FULLSCREEN_USER_SWITCHER) {
+ mFullscreenUserSwitcher.show(); // Makes the switcher visible.
+ }
+ }
+
+ private void hideUserSwitcher() {
+ if (mFullscreenUserSwitcher != null) {
mFullscreenUserSwitcher.hide();
}
}
- public void showUserSwitcher() {
- if (mFullscreenUserSwitcher != null && mState == StatusBarState.FULLSCREEN_USER_SWITCHER) {
- mFullscreenUserSwitcher.show(); // Makes the switcher visible.
+ // We automatically dismiss keyguard unless user switcher is being shown on the keyguard.
+ private void dismissKeyguardWhenUserSwitcherNotDisplayed() {
+ if (mFullscreenUserSwitcher == null) {
+ return; // Not using the full screen user switcher.
+ }
+
+ if (mState == StatusBarState.FULLSCREEN_USER_SWITCHER
+ && !mFullscreenUserSwitcher.isVisible()) {
+ // Current execution path continues to set state after this, thus we deffer the
+ // dismissal to the next execution cycle.
+ postDismissKeyguard(); // Dismiss the keyguard if switcher is not visible.
}
}
diff --git a/packages/CarrierDefaultApp/Android.bp b/packages/CarrierDefaultApp/Android.bp
new file mode 100644
index 0000000..c1b0b2d
--- /dev/null
+++ b/packages/CarrierDefaultApp/Android.bp
@@ -0,0 +1,6 @@
+android_app {
+ name: "CarrierDefaultApp",
+ srcs: ["src/**/*.java"],
+ platform_apis: true,
+ certificate: "platform",
+}
diff --git a/packages/CarrierDefaultApp/Android.mk b/packages/CarrierDefaultApp/Android.mk
deleted file mode 100644
index df88afd..0000000
--- a/packages/CarrierDefaultApp/Android.mk
+++ /dev/null
@@ -1,15 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_TAGS := optional
-
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-
-LOCAL_PACKAGE_NAME := CarrierDefaultApp
-LOCAL_PRIVATE_PLATFORM_APIS := true
-LOCAL_CERTIFICATE := platform
-
-include $(BUILD_PACKAGE)
-
-# This finds and builds the test apk as well, so a single make does both.
-include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/packages/CarrierDefaultApp/tests/Android.mk b/packages/CarrierDefaultApp/tests/Android.mk
deleted file mode 100644
index 6ebb575..0000000
--- a/packages/CarrierDefaultApp/tests/Android.mk
+++ /dev/null
@@ -1,25 +0,0 @@
-# Copyright 2016, The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-LOCAL_PATH := $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_CERTIFICATE := platform
-
-# Include all makefiles in subdirectories
-include $(call all-makefiles-under,$(LOCAL_PATH))
-
-
-
-
diff --git a/packages/CarrierDefaultApp/tests/unit/Android.bp b/packages/CarrierDefaultApp/tests/unit/Android.bp
new file mode 100644
index 0000000..96144cf
--- /dev/null
+++ b/packages/CarrierDefaultApp/tests/unit/Android.bp
@@ -0,0 +1,31 @@
+// Copyright 2016, The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+android_test {
+ name: "CarrierDefaultAppUnitTests",
+ certificate: "platform",
+ libs: [
+ "android.test.runner",
+ "telephony-common",
+ "android.test.base",
+ ],
+ static_libs: [
+ "androidx.test.rules",
+ "mockito-target-minus-junit4",
+ ],
+ // Include all test java files.
+ srcs: ["src/**/*.java"],
+ platform_apis: true,
+ instrumentation_for: "CarrierDefaultApp",
+}
diff --git a/packages/CarrierDefaultApp/tests/unit/Android.mk b/packages/CarrierDefaultApp/tests/unit/Android.mk
deleted file mode 100644
index 4c638811..0000000
--- a/packages/CarrierDefaultApp/tests/unit/Android.mk
+++ /dev/null
@@ -1,35 +0,0 @@
-# Copyright 2016, The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-# We only want this apk build for tests.
-LOCAL_MODULE_TAGS := tests
-LOCAL_CERTIFICATE := platform
-
-LOCAL_JAVA_LIBRARIES := android.test.runner telephony-common android.test.base
-
-LOCAL_STATIC_JAVA_LIBRARIES := androidx.test.rules mockito-target-minus-junit4
-
-# Include all test java files.
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-
-LOCAL_PACKAGE_NAME := CarrierDefaultAppUnitTests
-LOCAL_PRIVATE_PLATFORM_APIS := true
-
-LOCAL_INSTRUMENTATION_FOR := CarrierDefaultApp
-
-include $(BUILD_PACKAGE)
-
diff --git a/packages/CompanionDeviceManager/Android.bp b/packages/CompanionDeviceManager/Android.bp
new file mode 100644
index 0000000..a379bfc
--- /dev/null
+++ b/packages/CompanionDeviceManager/Android.bp
@@ -0,0 +1,19 @@
+// Copyright (C) 2017 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+android_app {
+ name: "CompanionDeviceManager",
+ srcs: ["src/**/*.java"],
+ platform_apis: true,
+}
diff --git a/packages/CompanionDeviceManager/Android.mk b/packages/CompanionDeviceManager/Android.mk
deleted file mode 100644
index 7ec6e11..0000000
--- a/packages/CompanionDeviceManager/Android.mk
+++ /dev/null
@@ -1,28 +0,0 @@
-# Copyright (C) 2017 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-LOCAL_PATH:= $(call my-dir)
-
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_TAGS := optional
-
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-
-LOCAL_PACKAGE_NAME := CompanionDeviceManager
-LOCAL_PRIVATE_PLATFORM_APIS := true
-
-include $(BUILD_PACKAGE)
-
-include $(call all-makefiles-under, $(LOCAL_PATH))
diff --git a/packages/CompanionDeviceManager/res/values-af/strings.xml b/packages/CompanionDeviceManager/res/values-af/strings.xml
new file mode 100644
index 0000000..824cc69
--- /dev/null
+++ b/packages/CompanionDeviceManager/res/values-af/strings.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2017 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_label" msgid="4470785958457506021">"Metgeseltoestel-bestuurder"</string>
+ <string name="chooser_title" msgid="4958797271463138976">"Koppel met <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong>"</string>
+ <string name="confirmation_title" msgid="5683126664999349196">"Koppel <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> met <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong>"</string>
+</resources>
diff --git a/packages/CompanionDeviceManager/res/values-am/strings.xml b/packages/CompanionDeviceManager/res/values-am/strings.xml
new file mode 100644
index 0000000..5d89504
--- /dev/null
+++ b/packages/CompanionDeviceManager/res/values-am/strings.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2017 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_label" msgid="4470785958457506021">"አጃቢ የመሣሪያ አስተዳዳሪ"</string>
+ <string name="chooser_title" msgid="4958797271463138976">"ከ<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> ጋር አገናኝ"</string>
+ <string name="confirmation_title" msgid="5683126664999349196">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> ከ <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> አገናኝ"</string>
+</resources>
diff --git a/packages/CompanionDeviceManager/res/values-ar/strings.xml b/packages/CompanionDeviceManager/res/values-ar/strings.xml
new file mode 100644
index 0000000..9199986
--- /dev/null
+++ b/packages/CompanionDeviceManager/res/values-ar/strings.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2017 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_label" msgid="4470785958457506021">"تطبيق \"مدير الجهاز المصاحب\""</string>
+ <string name="chooser_title" msgid="4958797271463138976">"الربط باستخدام تطبيق <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong>"</string>
+ <string name="confirmation_title" msgid="5683126664999349196">"ربط تطبيق <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> بجهاز <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong>"</string>
+</resources>
diff --git a/packages/CompanionDeviceManager/res/values-as/strings.xml b/packages/CompanionDeviceManager/res/values-as/strings.xml
new file mode 100644
index 0000000..2bd6d7e
--- /dev/null
+++ b/packages/CompanionDeviceManager/res/values-as/strings.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2017 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_label" msgid="4470785958457506021">"কম্পেনিয়ন ডিভাইচ মেনেজাৰ"</string>
+ <string name="chooser_title" msgid="4958797271463138976">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong>ৰ সৈতে লিংক কৰক"</string>
+ <string name="confirmation_title" msgid="5683126664999349196">"<strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong>ৰ সৈতে <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> লিংক কৰক"</string>
+</resources>
diff --git a/packages/CompanionDeviceManager/res/values-az/strings.xml b/packages/CompanionDeviceManager/res/values-az/strings.xml
new file mode 100644
index 0000000..c992cfd
--- /dev/null
+++ b/packages/CompanionDeviceManager/res/values-az/strings.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2017 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_label" msgid="4470785958457506021">"Kompanyon Cihaz Meneceri"</string>
+ <string name="chooser_title" msgid="4958797271463138976">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> ilə əlaqələndirin"</string>
+ <string name="confirmation_title" msgid="5683126664999349196">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> tətbiqini <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> ilə əlaqələndirin"</string>
+</resources>
diff --git a/packages/CompanionDeviceManager/res/values-b+sr+Latn/strings.xml b/packages/CompanionDeviceManager/res/values-b+sr+Latn/strings.xml
new file mode 100644
index 0000000..8a388a4
--- /dev/null
+++ b/packages/CompanionDeviceManager/res/values-b+sr+Latn/strings.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2017 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_label" msgid="4470785958457506021">"Menadžer pridruženog uređaja"</string>
+ <string name="chooser_title" msgid="4958797271463138976">"Povežite sa aplikacijom <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong>"</string>
+ <string name="confirmation_title" msgid="5683126664999349196">"Povežite aplikaciju <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> i uređaj <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong>"</string>
+</resources>
diff --git a/packages/CompanionDeviceManager/res/values-be/strings.xml b/packages/CompanionDeviceManager/res/values-be/strings.xml
new file mode 100644
index 0000000..e1b8016
--- /dev/null
+++ b/packages/CompanionDeviceManager/res/values-be/strings.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2017 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_label" msgid="4470785958457506021">"Менеджар спадарожнай прылады"</string>
+ <string name="chooser_title" msgid="4958797271463138976">"Звяжыце з праграмай <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong>"</string>
+ <string name="confirmation_title" msgid="5683126664999349196">"Звяжыце праграму <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> з прыладай <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong>"</string>
+</resources>
diff --git a/packages/CompanionDeviceManager/res/values-bg/strings.xml b/packages/CompanionDeviceManager/res/values-bg/strings.xml
new file mode 100644
index 0000000..8748e20
--- /dev/null
+++ b/packages/CompanionDeviceManager/res/values-bg/strings.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2017 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_label" msgid="4470785958457506021">"Companion Device Manager"</string>
+ <string name="chooser_title" msgid="4958797271463138976">"Свързване с(ъс) <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong>"</string>
+ <string name="confirmation_title" msgid="5683126664999349196">"Свържете <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> с(ъс) <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong>"</string>
+</resources>
diff --git a/packages/CompanionDeviceManager/res/values-bn/strings.xml b/packages/CompanionDeviceManager/res/values-bn/strings.xml
new file mode 100644
index 0000000..a9fb9ff
--- /dev/null
+++ b/packages/CompanionDeviceManager/res/values-bn/strings.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2017 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_label" msgid="4470785958457506021">"Companion Device Manager"</string>
+ <string name="chooser_title" msgid="4958797271463138976">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong>-এর সাথে লিঙ্ক করুন"</string>
+ <string name="confirmation_title" msgid="5683126664999349196">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong>-এর সাথে <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> লিঙ্ক করুন"</string>
+</resources>
diff --git a/packages/CompanionDeviceManager/res/values-bs/strings.xml b/packages/CompanionDeviceManager/res/values-bs/strings.xml
new file mode 100644
index 0000000..220553c
--- /dev/null
+++ b/packages/CompanionDeviceManager/res/values-bs/strings.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2017 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_label" msgid="4470785958457506021">"Prateći upravitelj uređaja"</string>
+ <string name="chooser_title" msgid="4958797271463138976">"Povežite se s aplikacijom <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong>"</string>
+ <string name="confirmation_title" msgid="5683126664999349196">"Povežite aplikaciju <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> s uređajem <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong>"</string>
+</resources>
diff --git a/packages/CompanionDeviceManager/res/values-ca/strings.xml b/packages/CompanionDeviceManager/res/values-ca/strings.xml
new file mode 100644
index 0000000..0ad921a
--- /dev/null
+++ b/packages/CompanionDeviceManager/res/values-ca/strings.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2017 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_label" msgid="4470785958457506021">"Aplicació Gestor de dispositius complementaris"</string>
+ <string name="chooser_title" msgid="4958797271463138976">"Enllaça amb <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong>"</string>
+ <string name="confirmation_title" msgid="5683126664999349196">"Enllaça <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> amb <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong>"</string>
+</resources>
diff --git a/packages/CompanionDeviceManager/res/values-cs/strings.xml b/packages/CompanionDeviceManager/res/values-cs/strings.xml
new file mode 100644
index 0000000..ebd9cb1
--- /dev/null
+++ b/packages/CompanionDeviceManager/res/values-cs/strings.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2017 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_label" msgid="4470785958457506021">"Správce doprovodných zařízení"</string>
+ <string name="chooser_title" msgid="4958797271463138976">"Propojení s aplikací <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong>"</string>
+ <string name="confirmation_title" msgid="5683126664999349196">"Propojení aplikace <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> se zařízením <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong>"</string>
+</resources>
diff --git a/packages/CompanionDeviceManager/res/values-da/strings.xml b/packages/CompanionDeviceManager/res/values-da/strings.xml
new file mode 100644
index 0000000..7601e40
--- /dev/null
+++ b/packages/CompanionDeviceManager/res/values-da/strings.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2017 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_label" msgid="4470785958457506021">"Medfølgende enhedshåndtering"</string>
+ <string name="chooser_title" msgid="4958797271463138976">"Tilknyt <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong>"</string>
+ <string name="confirmation_title" msgid="5683126664999349196">"Knyt <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> til <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong>"</string>
+</resources>
diff --git a/packages/CompanionDeviceManager/res/values-de/strings.xml b/packages/CompanionDeviceManager/res/values-de/strings.xml
new file mode 100644
index 0000000..b58f2c5
--- /dev/null
+++ b/packages/CompanionDeviceManager/res/values-de/strings.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2017 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_label" msgid="4470785958457506021">"Begleitgerät-Manager"</string>
+ <string name="chooser_title" msgid="4958797271463138976">"Mit <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> verknüpfen"</string>
+ <string name="confirmation_title" msgid="5683126664999349196">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> mit <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> verknüpfen"</string>
+</resources>
diff --git a/packages/CompanionDeviceManager/res/values-el/strings.xml b/packages/CompanionDeviceManager/res/values-el/strings.xml
new file mode 100644
index 0000000..2d56213
--- /dev/null
+++ b/packages/CompanionDeviceManager/res/values-el/strings.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2017 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_label" msgid="4470785958457506021">"Διαχείριση συνοδευτικής εφαρμογής"</string>
+ <string name="chooser_title" msgid="4958797271463138976">"Σύνδεση με <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong>"</string>
+ <string name="confirmation_title" msgid="5683126664999349196">"Σύνδεση <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> με <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong>"</string>
+</resources>
diff --git a/packages/CompanionDeviceManager/res/values-en-rAU/strings.xml b/packages/CompanionDeviceManager/res/values-en-rAU/strings.xml
new file mode 100644
index 0000000..91c7643
--- /dev/null
+++ b/packages/CompanionDeviceManager/res/values-en-rAU/strings.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2017 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_label" msgid="4470785958457506021">"Companion Device Manager"</string>
+ <string name="chooser_title" msgid="4958797271463138976">"Link with <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong>"</string>
+ <string name="confirmation_title" msgid="5683126664999349196">"Link <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> with <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong>"</string>
+</resources>
diff --git a/packages/CompanionDeviceManager/res/values-en-rCA/strings.xml b/packages/CompanionDeviceManager/res/values-en-rCA/strings.xml
new file mode 100644
index 0000000..91c7643
--- /dev/null
+++ b/packages/CompanionDeviceManager/res/values-en-rCA/strings.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2017 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_label" msgid="4470785958457506021">"Companion Device Manager"</string>
+ <string name="chooser_title" msgid="4958797271463138976">"Link with <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong>"</string>
+ <string name="confirmation_title" msgid="5683126664999349196">"Link <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> with <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong>"</string>
+</resources>
diff --git a/packages/CompanionDeviceManager/res/values-en-rGB/strings.xml b/packages/CompanionDeviceManager/res/values-en-rGB/strings.xml
new file mode 100644
index 0000000..91c7643
--- /dev/null
+++ b/packages/CompanionDeviceManager/res/values-en-rGB/strings.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2017 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_label" msgid="4470785958457506021">"Companion Device Manager"</string>
+ <string name="chooser_title" msgid="4958797271463138976">"Link with <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong>"</string>
+ <string name="confirmation_title" msgid="5683126664999349196">"Link <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> with <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong>"</string>
+</resources>
diff --git a/packages/CompanionDeviceManager/res/values-en-rIN/strings.xml b/packages/CompanionDeviceManager/res/values-en-rIN/strings.xml
new file mode 100644
index 0000000..91c7643
--- /dev/null
+++ b/packages/CompanionDeviceManager/res/values-en-rIN/strings.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2017 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_label" msgid="4470785958457506021">"Companion Device Manager"</string>
+ <string name="chooser_title" msgid="4958797271463138976">"Link with <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong>"</string>
+ <string name="confirmation_title" msgid="5683126664999349196">"Link <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> with <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong>"</string>
+</resources>
diff --git a/packages/CompanionDeviceManager/res/values-en-rXC/strings.xml b/packages/CompanionDeviceManager/res/values-en-rXC/strings.xml
new file mode 100644
index 0000000..e052e61
--- /dev/null
+++ b/packages/CompanionDeviceManager/res/values-en-rXC/strings.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2017 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_label" msgid="4470785958457506021">"Companion Device Manager"</string>
+ <string name="chooser_title" msgid="4958797271463138976">"Link with <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong>"</string>
+ <string name="confirmation_title" msgid="5683126664999349196">"Link <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> with <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong>"</string>
+</resources>
diff --git a/packages/CompanionDeviceManager/res/values-es-rUS/strings.xml b/packages/CompanionDeviceManager/res/values-es-rUS/strings.xml
new file mode 100644
index 0000000..0552ee7
--- /dev/null
+++ b/packages/CompanionDeviceManager/res/values-es-rUS/strings.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2017 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_label" msgid="4470785958457506021">"Administrador de dispositivo complementario"</string>
+ <string name="chooser_title" msgid="4958797271463138976">"Vincular con <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong>"</string>
+ <string name="confirmation_title" msgid="5683126664999349196">"Vincular <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> con <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong>"</string>
+</resources>
diff --git a/packages/CompanionDeviceManager/res/values-es/strings.xml b/packages/CompanionDeviceManager/res/values-es/strings.xml
new file mode 100644
index 0000000..c9e218e
--- /dev/null
+++ b/packages/CompanionDeviceManager/res/values-es/strings.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2017 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_label" msgid="4470785958457506021">"Gestor de dispositivos complementario"</string>
+ <string name="chooser_title" msgid="4958797271463138976">"Vincular con <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong>"</string>
+ <string name="confirmation_title" msgid="5683126664999349196">"Vincular <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> con <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong>"</string>
+</resources>
diff --git a/packages/CompanionDeviceManager/res/values-et/strings.xml b/packages/CompanionDeviceManager/res/values-et/strings.xml
new file mode 100644
index 0000000..1ac26f7
--- /dev/null
+++ b/packages/CompanionDeviceManager/res/values-et/strings.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2017 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_label" msgid="4470785958457506021">"Kaasseadme haldur"</string>
+ <string name="chooser_title" msgid="4958797271463138976">"Linkimine rakendusega <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong>"</string>
+ <string name="confirmation_title" msgid="5683126664999349196">"Rakenduse <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> linkimine seadmega <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong>"</string>
+</resources>
diff --git a/packages/CompanionDeviceManager/res/values-eu/strings.xml b/packages/CompanionDeviceManager/res/values-eu/strings.xml
new file mode 100644
index 0000000..26e1979
--- /dev/null
+++ b/packages/CompanionDeviceManager/res/values-eu/strings.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2017 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_label" msgid="4470785958457506021">"Gailu osagarriaren kudeatzailea"</string>
+ <string name="chooser_title" msgid="4958797271463138976">"Lotu <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> aplikazioarekin"</string>
+ <string name="confirmation_title" msgid="5683126664999349196">"Lotu <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> gailuarekin"</string>
+</resources>
diff --git a/packages/CompanionDeviceManager/res/values-fa/strings.xml b/packages/CompanionDeviceManager/res/values-fa/strings.xml
new file mode 100644
index 0000000..b43fe29
--- /dev/null
+++ b/packages/CompanionDeviceManager/res/values-fa/strings.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2017 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_label" msgid="4470785958457506021">"مدیر دستگاه مرتبط"</string>
+ <string name="chooser_title" msgid="4958797271463138976">"پیوند با <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong>"</string>
+ <string name="confirmation_title" msgid="5683126664999349196">"پیوند <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> با <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong>"</string>
+</resources>
diff --git a/packages/CompanionDeviceManager/res/values-fi/strings.xml b/packages/CompanionDeviceManager/res/values-fi/strings.xml
new file mode 100644
index 0000000..fbc18f6
--- /dev/null
+++ b/packages/CompanionDeviceManager/res/values-fi/strings.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2017 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_label" msgid="4470785958457506021">"Companion Device Manager"</string>
+ <string name="chooser_title" msgid="4958797271463138976">"Linkitä <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong>"</string>
+ <string name="confirmation_title" msgid="5683126664999349196">"Linkitä <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> ja <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong>"</string>
+</resources>
diff --git a/packages/CompanionDeviceManager/res/values-fr-rCA/strings.xml b/packages/CompanionDeviceManager/res/values-fr-rCA/strings.xml
new file mode 100644
index 0000000..05e3402
--- /dev/null
+++ b/packages/CompanionDeviceManager/res/values-fr-rCA/strings.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2017 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_label" msgid="4470785958457506021">"Gestionnaire d\'appareil compagnon"</string>
+ <string name="chooser_title" msgid="4958797271463138976">"Lier à <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong>"</string>
+ <string name="confirmation_title" msgid="5683126664999349196">"Lier <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> à <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong>"</string>
+</resources>
diff --git a/packages/CompanionDeviceManager/res/values-fr/strings.xml b/packages/CompanionDeviceManager/res/values-fr/strings.xml
new file mode 100644
index 0000000..881d6aa
--- /dev/null
+++ b/packages/CompanionDeviceManager/res/values-fr/strings.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2017 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_label" msgid="4470785958457506021">"Gestionnaire d\'appareils associés"</string>
+ <string name="chooser_title" msgid="4958797271463138976">"Associer à l\'application <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong>"</string>
+ <string name="confirmation_title" msgid="5683126664999349196">"Associer l\'application <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> à l\'appareil <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong>"</string>
+</resources>
diff --git a/packages/CompanionDeviceManager/res/values-gl/strings.xml b/packages/CompanionDeviceManager/res/values-gl/strings.xml
new file mode 100644
index 0000000..6f85022
--- /dev/null
+++ b/packages/CompanionDeviceManager/res/values-gl/strings.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2017 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_label" msgid="4470785958457506021">"Xestor de dispositivos complementarios"</string>
+ <string name="chooser_title" msgid="4958797271463138976">"Vincular con <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong>"</string>
+ <string name="confirmation_title" msgid="5683126664999349196">"Vincular <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> con <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong>"</string>
+</resources>
diff --git a/packages/CompanionDeviceManager/res/values-gu/strings.xml b/packages/CompanionDeviceManager/res/values-gu/strings.xml
new file mode 100644
index 0000000..5088507
--- /dev/null
+++ b/packages/CompanionDeviceManager/res/values-gu/strings.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2017 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_label" msgid="4470785958457506021">"કમ્પેનિયન ડિવાઇસ મેનેજર"</string>
+ <string name="chooser_title" msgid="4958797271463138976">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> સાથે લિંક કરો"</string>
+ <string name="confirmation_title" msgid="5683126664999349196">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong>ને <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> સાથે લિંક કરો"</string>
+</resources>
diff --git a/packages/CompanionDeviceManager/res/values-hi/strings.xml b/packages/CompanionDeviceManager/res/values-hi/strings.xml
new file mode 100644
index 0000000..4afcb63
--- /dev/null
+++ b/packages/CompanionDeviceManager/res/values-hi/strings.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2017 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_label" msgid="4470785958457506021">"सहयोगी डिवाइस मैनेजर"</string>
+ <string name="chooser_title" msgid="4958797271463138976">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> से लिंक करें"</string>
+ <string name="confirmation_title" msgid="5683126664999349196">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> को <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> से लिंक करें"</string>
+</resources>
diff --git a/packages/CompanionDeviceManager/res/values-hr/strings.xml b/packages/CompanionDeviceManager/res/values-hr/strings.xml
new file mode 100644
index 0000000..7b71939
--- /dev/null
+++ b/packages/CompanionDeviceManager/res/values-hr/strings.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2017 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_label" msgid="4470785958457506021">"Companion Device Manager"</string>
+ <string name="chooser_title" msgid="4958797271463138976">"Povežite s aplikacijom <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong>"</string>
+ <string name="confirmation_title" msgid="5683126664999349196">"Povežite aplikaciju <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> s uređajem <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong>"</string>
+</resources>
diff --git a/packages/CompanionDeviceManager/res/values-hu/strings.xml b/packages/CompanionDeviceManager/res/values-hu/strings.xml
new file mode 100644
index 0000000..19920b2
--- /dev/null
+++ b/packages/CompanionDeviceManager/res/values-hu/strings.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2017 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_label" msgid="4470785958457506021">"Társeszközök kezelője"</string>
+ <string name="chooser_title" msgid="4958797271463138976">"Összekapcsolás a(z) <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> alkalmazással"</string>
+ <string name="confirmation_title" msgid="5683126664999349196">"A(z) <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> alkalmazás és a(z) <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> eszköz összekapcsolása"</string>
+</resources>
diff --git a/packages/CompanionDeviceManager/res/values-hy/strings.xml b/packages/CompanionDeviceManager/res/values-hy/strings.xml
new file mode 100644
index 0000000..8dee4a3
--- /dev/null
+++ b/packages/CompanionDeviceManager/res/values-hy/strings.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2017 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_label" msgid="4470785958457506021">"Companion Device Manager"</string>
+ <string name="chooser_title" msgid="4958797271463138976">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> հավելվածի հետ կապում"</string>
+ <string name="confirmation_title" msgid="5683126664999349196">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> հավելվածի կապում <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> սարքի հետ"</string>
+</resources>
diff --git a/packages/CompanionDeviceManager/res/values-in/strings.xml b/packages/CompanionDeviceManager/res/values-in/strings.xml
new file mode 100644
index 0000000..efd77fe7
--- /dev/null
+++ b/packages/CompanionDeviceManager/res/values-in/strings.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2017 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_label" msgid="4470785958457506021">"Pengelola Perangkat Pendamping"</string>
+ <string name="chooser_title" msgid="4958797271463138976">"Tautkan dengan <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong>"</string>
+ <string name="confirmation_title" msgid="5683126664999349196">"Tautkan <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> dengan <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong>"</string>
+</resources>
diff --git a/packages/CompanionDeviceManager/res/values-is/strings.xml b/packages/CompanionDeviceManager/res/values-is/strings.xml
new file mode 100644
index 0000000..4bf9447
--- /dev/null
+++ b/packages/CompanionDeviceManager/res/values-is/strings.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2017 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_label" msgid="4470785958457506021">"Stjórnun fylgdartækja"</string>
+ <string name="chooser_title" msgid="4958797271463138976">"Tengjast við <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong>"</string>
+ <string name="confirmation_title" msgid="5683126664999349196">"Tengja <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> við <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong>"</string>
+</resources>
diff --git a/packages/CompanionDeviceManager/res/values-it/strings.xml b/packages/CompanionDeviceManager/res/values-it/strings.xml
new file mode 100644
index 0000000..a602061
--- /dev/null
+++ b/packages/CompanionDeviceManager/res/values-it/strings.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2017 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_label" msgid="4470785958457506021">"Gestione dispositivi companion"</string>
+ <string name="chooser_title" msgid="4958797271463138976">"Collega con <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong>"</string>
+ <string name="confirmation_title" msgid="5683126664999349196">"Collega <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> con <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong>"</string>
+</resources>
diff --git a/packages/CompanionDeviceManager/res/values-iw/strings.xml b/packages/CompanionDeviceManager/res/values-iw/strings.xml
new file mode 100644
index 0000000..b95fae5
--- /dev/null
+++ b/packages/CompanionDeviceManager/res/values-iw/strings.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2017 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_label" msgid="4470785958457506021">"ניהול מכשיר מותאם"</string>
+ <string name="chooser_title" msgid="4958797271463138976">"קישור אל <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong>"</string>
+ <string name="confirmation_title" msgid="5683126664999349196">"קישור <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> אל <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong>"</string>
+</resources>
diff --git a/packages/CompanionDeviceManager/res/values-ja/strings.xml b/packages/CompanionDeviceManager/res/values-ja/strings.xml
new file mode 100644
index 0000000..8c39e70
--- /dev/null
+++ b/packages/CompanionDeviceManager/res/values-ja/strings.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2017 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_label" msgid="4470785958457506021">"コンパニオン デバイス マネージャ"</string>
+ <string name="chooser_title" msgid="4958797271463138976">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> とのリンク"</string>
+ <string name="confirmation_title" msgid="5683126664999349196">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> と <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> とのリンク"</string>
+</resources>
diff --git a/packages/CompanionDeviceManager/res/values-ka/strings.xml b/packages/CompanionDeviceManager/res/values-ka/strings.xml
new file mode 100644
index 0000000..6fa899a
--- /dev/null
+++ b/packages/CompanionDeviceManager/res/values-ka/strings.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2017 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_label" msgid="4470785958457506021">"კომპანიონი მოწყობილობების მენეჯერი"</string>
+ <string name="chooser_title" msgid="4958797271463138976">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong>-თან მიბმა"</string>
+ <string name="confirmation_title" msgid="5683126664999349196">"მიაბით ერთმანეთს <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> და <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong>"</string>
+</resources>
diff --git a/packages/CompanionDeviceManager/res/values-kk/strings.xml b/packages/CompanionDeviceManager/res/values-kk/strings.xml
new file mode 100644
index 0000000..18ab5e6f
--- /dev/null
+++ b/packages/CompanionDeviceManager/res/values-kk/strings.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2017 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_label" msgid="4470785958457506021">"Companion Device Manager"</string>
+ <string name="chooser_title" msgid="4958797271463138976">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> қолданбасымен байланыстыру"</string>
+ <string name="confirmation_title" msgid="5683126664999349196">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> қолданбасымен және <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> құрылғысымен байланыстыру"</string>
+</resources>
diff --git a/packages/CompanionDeviceManager/res/values-km/strings.xml b/packages/CompanionDeviceManager/res/values-km/strings.xml
new file mode 100644
index 0000000..42efac4
--- /dev/null
+++ b/packages/CompanionDeviceManager/res/values-km/strings.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2017 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_label" msgid="4470785958457506021">"កម្មវិធីគ្រប់គ្រងឧបករណ៍ដៃគូ"</string>
+ <string name="chooser_title" msgid="4958797271463138976">"ភ្ជាប់ជាមួយ <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong>"</string>
+ <string name="confirmation_title" msgid="5683126664999349196">"ភ្ជាប់ <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> ជាមួយ <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong>"</string>
+</resources>
diff --git a/packages/CompanionDeviceManager/res/values-kn/strings.xml b/packages/CompanionDeviceManager/res/values-kn/strings.xml
new file mode 100644
index 0000000..e21bb02
--- /dev/null
+++ b/packages/CompanionDeviceManager/res/values-kn/strings.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2017 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_label" msgid="4470785958457506021">"ಕಂಪ್ಯಾನಿಯನ್ ಸಾಧನ ನಿರ್ವಾಹಕರು"</string>
+ <string name="chooser_title" msgid="4958797271463138976">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> ನ ಜೊತೆಗೆ ಲಿಂಕ್ ಮಾಡಿ"</string>
+ <string name="confirmation_title" msgid="5683126664999349196">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> ಅನ್ನು <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> ನ ಜೊತೆಗೆ ಲಿಂಕ್ ಮಾಡಿ"</string>
+</resources>
diff --git a/packages/CompanionDeviceManager/res/values-ko/strings.xml b/packages/CompanionDeviceManager/res/values-ko/strings.xml
new file mode 100644
index 0000000..17702f5
--- /dev/null
+++ b/packages/CompanionDeviceManager/res/values-ko/strings.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2017 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_label" msgid="4470785958457506021">"부속 기기 관리자"</string>
+ <string name="chooser_title" msgid="4958797271463138976">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> 연결"</string>
+ <string name="confirmation_title" msgid="5683126664999349196">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong>을(를) <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong>에 연결"</string>
+</resources>
diff --git a/packages/CompanionDeviceManager/res/values-ky/strings.xml b/packages/CompanionDeviceManager/res/values-ky/strings.xml
new file mode 100644
index 0000000..63efea7
--- /dev/null
+++ b/packages/CompanionDeviceManager/res/values-ky/strings.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2017 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_label" msgid="4470785958457506021">"Companion Device Manager"</string>
+ <string name="chooser_title" msgid="4958797271463138976">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> колдонмосу менен байланыштыруу"</string>
+ <string name="confirmation_title" msgid="5683126664999349196">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> колдонмосун <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> түзмөгү менен байланыштыруу"</string>
+</resources>
diff --git a/packages/CompanionDeviceManager/res/values-lo/strings.xml b/packages/CompanionDeviceManager/res/values-lo/strings.xml
new file mode 100644
index 0000000..f637551
--- /dev/null
+++ b/packages/CompanionDeviceManager/res/values-lo/strings.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2017 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_label" msgid="4470785958457506021">"ຕົວຈັດການອຸປະກອນປະກອບ"</string>
+ <string name="chooser_title" msgid="4958797271463138976">"ເຊື່ອມຕໍ່ກັບ <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong>"</string>
+ <string name="confirmation_title" msgid="5683126664999349196">"ເຊື່ອມຕໍ່ <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> ກັບ <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong>"</string>
+</resources>
diff --git a/packages/CompanionDeviceManager/res/values-lt/strings.xml b/packages/CompanionDeviceManager/res/values-lt/strings.xml
new file mode 100644
index 0000000..ddaa601
--- /dev/null
+++ b/packages/CompanionDeviceManager/res/values-lt/strings.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2017 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_label" msgid="4470785958457506021">"Companion Device Manager"</string>
+ <string name="chooser_title" msgid="4958797271463138976">"Susieti su pr. <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong>"</string>
+ <string name="confirmation_title" msgid="5683126664999349196">"Susieti programą <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> su <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> įrenginiu"</string>
+</resources>
diff --git a/packages/CompanionDeviceManager/res/values-lv/strings.xml b/packages/CompanionDeviceManager/res/values-lv/strings.xml
new file mode 100644
index 0000000..ba8840c
--- /dev/null
+++ b/packages/CompanionDeviceManager/res/values-lv/strings.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2017 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_label" msgid="4470785958457506021">"Palīgierīču pārzinis"</string>
+ <string name="chooser_title" msgid="4958797271463138976">"Saistīšana ar lietotni <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong>"</string>
+ <string name="confirmation_title" msgid="5683126664999349196">"Lietotnes <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> saistīšana ar ierīci <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong>"</string>
+</resources>
diff --git a/packages/CompanionDeviceManager/res/values-mk/strings.xml b/packages/CompanionDeviceManager/res/values-mk/strings.xml
new file mode 100644
index 0000000..4c2e4117
--- /dev/null
+++ b/packages/CompanionDeviceManager/res/values-mk/strings.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2017 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_label" msgid="4470785958457506021">"Companion Device Manager"</string>
+ <string name="chooser_title" msgid="4958797271463138976">"Поврзување со <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong>"</string>
+ <string name="confirmation_title" msgid="5683126664999349196">"Поврзување на <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> со <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong>"</string>
+</resources>
diff --git a/packages/CompanionDeviceManager/res/values-ml/strings.xml b/packages/CompanionDeviceManager/res/values-ml/strings.xml
new file mode 100644
index 0000000..950e4e4
--- /dev/null
+++ b/packages/CompanionDeviceManager/res/values-ml/strings.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2017 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_label" msgid="4470785958457506021">"കമ്പാനിയൻ ഉപകരണ മാനേജർ"</string>
+ <string name="chooser_title" msgid="4958797271463138976">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> ഉപയോഗിച്ച് ലിങ്ക് ചെയ്യുക"</string>
+ <string name="confirmation_title" msgid="5683126664999349196">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> with <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> ലിങ്ക് ചെയ്യുക"</string>
+</resources>
diff --git a/packages/CompanionDeviceManager/res/values-mn/strings.xml b/packages/CompanionDeviceManager/res/values-mn/strings.xml
new file mode 100644
index 0000000..5add54a
--- /dev/null
+++ b/packages/CompanionDeviceManager/res/values-mn/strings.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2017 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_label" msgid="4470785958457506021">"Companion Device Manager"</string>
+ <string name="chooser_title" msgid="4958797271463138976">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong>-тай холбох"</string>
+ <string name="confirmation_title" msgid="5683126664999349196">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong>-г <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong>-тай холбох"</string>
+</resources>
diff --git a/packages/CompanionDeviceManager/res/values-mr/strings.xml b/packages/CompanionDeviceManager/res/values-mr/strings.xml
new file mode 100644
index 0000000..45348c0
--- /dev/null
+++ b/packages/CompanionDeviceManager/res/values-mr/strings.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2017 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_label" msgid="4470785958457506021">"सहयोगी डिव्हाइस व्यवस्थापक"</string>
+ <string name="chooser_title" msgid="4958797271463138976">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g><strong> सह लिंक करा"</string>
+ <string name="confirmation_title" msgid="5683126664999349196">"<strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> ला <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> शी लिंक करा"</string>
+</resources>
diff --git a/packages/CompanionDeviceManager/res/values-ms/strings.xml b/packages/CompanionDeviceManager/res/values-ms/strings.xml
new file mode 100644
index 0000000..5a50f15
--- /dev/null
+++ b/packages/CompanionDeviceManager/res/values-ms/strings.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2017 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_label" msgid="4470785958457506021">"Pengurus Peranti Rakan"</string>
+ <string name="chooser_title" msgid="4958797271463138976">"Paut dengan <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong>"</string>
+ <string name="confirmation_title" msgid="5683126664999349196">"Paut <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> dengan <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong>"</string>
+</resources>
diff --git a/packages/CompanionDeviceManager/res/values-my/strings.xml b/packages/CompanionDeviceManager/res/values-my/strings.xml
new file mode 100644
index 0000000..3fba5ff
--- /dev/null
+++ b/packages/CompanionDeviceManager/res/values-my/strings.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2017 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_label" msgid="4470785958457506021">"တွဲဖက်ကိရိယာ မန်နေဂျာ"</string>
+ <string name="chooser_title" msgid="4958797271463138976">"<xliff:g id="APP_NAME">%1$s</xliff:g></strong> ဖြင့် ချိတ်ဆက်ရန်<strong>"</string>
+ <string name="confirmation_title" msgid="5683126664999349196">"<xliff:g id="APP_NAME">%1$s</xliff:g> ကို <xliff:g id="DEVICE_NAME">%2$s</xliff:g> ဖြင့် ချိတ်ဆက်ခြင်း <strong>"</string>
+</resources>
diff --git a/packages/CompanionDeviceManager/res/values-nb/strings.xml b/packages/CompanionDeviceManager/res/values-nb/strings.xml
new file mode 100644
index 0000000..0b49f47
--- /dev/null
+++ b/packages/CompanionDeviceManager/res/values-nb/strings.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2017 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_label" msgid="4470785958457506021">"Companion Device Manager"</string>
+ <string name="chooser_title" msgid="4958797271463138976">"Knytt til <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong>"</string>
+ <string name="confirmation_title" msgid="5683126664999349196">"Knytt <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> til <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong>"</string>
+</resources>
diff --git a/packages/CompanionDeviceManager/res/values-ne/strings.xml b/packages/CompanionDeviceManager/res/values-ne/strings.xml
new file mode 100644
index 0000000..348104f
--- /dev/null
+++ b/packages/CompanionDeviceManager/res/values-ne/strings.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2017 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_label" msgid="4470785958457506021">"सहयोगी यन्त्रको प्रबन्धक"</string>
+ <string name="chooser_title" msgid="4958797271463138976">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> सँग लिंक गर्नुहोस्"</string>
+ <string name="confirmation_title" msgid="5683126664999349196">"<strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> सँग <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> लाई लिंक गर्नुहोस्"</string>
+</resources>
diff --git a/packages/CompanionDeviceManager/res/values-nl/strings.xml b/packages/CompanionDeviceManager/res/values-nl/strings.xml
new file mode 100644
index 0000000..12177ca
--- /dev/null
+++ b/packages/CompanionDeviceManager/res/values-nl/strings.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2017 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_label" msgid="4470785958457506021">"Companion Device Manager"</string>
+ <string name="chooser_title" msgid="4958797271463138976">"Koppelen met <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong>"</string>
+ <string name="confirmation_title" msgid="5683126664999349196">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> met <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> koppelen"</string>
+</resources>
diff --git a/packages/CompanionDeviceManager/res/values-or/strings.xml b/packages/CompanionDeviceManager/res/values-or/strings.xml
new file mode 100644
index 0000000..b5a9e1c
--- /dev/null
+++ b/packages/CompanionDeviceManager/res/values-or/strings.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2017 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_label" msgid="4470785958457506021">"ସହଯୋଗୀ ଡିଭାଇସ୍ ପରିଚାଳକ"</string>
+ <string name="chooser_title" msgid="4958797271463138976">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> ସହ ଲିଙ୍କ୍ କରନ୍ତୁ"</string>
+ <string name="confirmation_title" msgid="5683126664999349196">"<strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> ସହିତ <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> ଲିଙ୍କ୍ କରନ୍ତୁ"</string>
+</resources>
diff --git a/packages/CompanionDeviceManager/res/values-pa/strings.xml b/packages/CompanionDeviceManager/res/values-pa/strings.xml
new file mode 100644
index 0000000..70a408f
--- /dev/null
+++ b/packages/CompanionDeviceManager/res/values-pa/strings.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2017 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_label" msgid="4470785958457506021">"ਸੰਬੰਧੀ ਡੀਵਾਈਸ ਪ੍ਰਬੰਧਕ"</string>
+ <string name="chooser_title" msgid="4958797271463138976">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> ਨਾਲ ਲਿੰਕ ਕਰੋ"</string>
+ <string name="confirmation_title" msgid="5683126664999349196">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> ਨੂੰ <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> ਨਾਲ ਲਿੰਕ ਕਰੋ"</string>
+</resources>
diff --git a/packages/CompanionDeviceManager/res/values-pl/strings.xml b/packages/CompanionDeviceManager/res/values-pl/strings.xml
new file mode 100644
index 0000000..c622cedc
--- /dev/null
+++ b/packages/CompanionDeviceManager/res/values-pl/strings.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2017 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_label" msgid="4470785958457506021">"Menedżer urządzeń towarzyszących"</string>
+ <string name="chooser_title" msgid="4958797271463138976">"Połącz z: <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong>"</string>
+ <string name="confirmation_title" msgid="5683126664999349196">"Połącz: <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> z: <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong>"</string>
+</resources>
diff --git a/packages/CompanionDeviceManager/res/values-pt-rBR/strings.xml b/packages/CompanionDeviceManager/res/values-pt-rBR/strings.xml
new file mode 100644
index 0000000..b18c3ad
--- /dev/null
+++ b/packages/CompanionDeviceManager/res/values-pt-rBR/strings.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2017 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_label" msgid="4470785958457506021">"Gerenciador de dispositivos complementar"</string>
+ <string name="chooser_title" msgid="4958797271463138976">"Vincular a <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong>"</string>
+ <string name="confirmation_title" msgid="5683126664999349196">"Vincular <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> a <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong>"</string>
+</resources>
diff --git a/packages/CompanionDeviceManager/res/values-pt-rPT/strings.xml b/packages/CompanionDeviceManager/res/values-pt-rPT/strings.xml
new file mode 100644
index 0000000..a64c544
--- /dev/null
+++ b/packages/CompanionDeviceManager/res/values-pt-rPT/strings.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2017 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_label" msgid="4470785958457506021">"Gestor de dispositivos associados"</string>
+ <string name="chooser_title" msgid="4958797271463138976">"Associe à aplicação <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong>"</string>
+ <string name="confirmation_title" msgid="5683126664999349196">"Associe a aplicação <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> ao dispositivo <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong>"</string>
+</resources>
diff --git a/packages/CompanionDeviceManager/res/values-pt/strings.xml b/packages/CompanionDeviceManager/res/values-pt/strings.xml
new file mode 100644
index 0000000..b18c3ad
--- /dev/null
+++ b/packages/CompanionDeviceManager/res/values-pt/strings.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2017 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_label" msgid="4470785958457506021">"Gerenciador de dispositivos complementar"</string>
+ <string name="chooser_title" msgid="4958797271463138976">"Vincular a <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong>"</string>
+ <string name="confirmation_title" msgid="5683126664999349196">"Vincular <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> a <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong>"</string>
+</resources>
diff --git a/packages/CompanionDeviceManager/res/values-ro/strings.xml b/packages/CompanionDeviceManager/res/values-ro/strings.xml
new file mode 100644
index 0000000..1c78602
--- /dev/null
+++ b/packages/CompanionDeviceManager/res/values-ro/strings.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2017 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_label" msgid="4470785958457506021">"Manager de dispozitiv Companion"</string>
+ <string name="chooser_title" msgid="4958797271463138976">"Conectați cu <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong>"</string>
+ <string name="confirmation_title" msgid="5683126664999349196">"Conectați <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> cu <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong>"</string>
+</resources>
diff --git a/packages/CompanionDeviceManager/res/values-ru/strings.xml b/packages/CompanionDeviceManager/res/values-ru/strings.xml
new file mode 100644
index 0000000..74b9100
--- /dev/null
+++ b/packages/CompanionDeviceManager/res/values-ru/strings.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2017 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_label" msgid="4470785958457506021">"Управление подключенными устройствами"</string>
+ <string name="chooser_title" msgid="4958797271463138976">"Подключение к приложению <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong>"</string>
+ <string name="confirmation_title" msgid="5683126664999349196">"Подключение приложения <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> к устройству <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong>"</string>
+</resources>
diff --git a/packages/CompanionDeviceManager/res/values-si/strings.xml b/packages/CompanionDeviceManager/res/values-si/strings.xml
new file mode 100644
index 0000000..89f4409
--- /dev/null
+++ b/packages/CompanionDeviceManager/res/values-si/strings.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2017 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_label" msgid="4470785958457506021">"සහායක උපාංග කළමනාකරු"</string>
+ <string name="chooser_title" msgid="4958797271463138976">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> සමඟ සම්බන්ධ කරන්න"</string>
+ <string name="confirmation_title" msgid="5683126664999349196">"<strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> සමඟ <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> සම්බන්ධ කරන්න"</string>
+</resources>
diff --git a/packages/CompanionDeviceManager/res/values-sk/strings.xml b/packages/CompanionDeviceManager/res/values-sk/strings.xml
new file mode 100644
index 0000000..21b3b30
--- /dev/null
+++ b/packages/CompanionDeviceManager/res/values-sk/strings.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2017 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_label" msgid="4470785958457506021">"Správca sprievodných zariadení"</string>
+ <string name="chooser_title" msgid="4958797271463138976">"Prepojenie s aplikáciou <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong>"</string>
+ <string name="confirmation_title" msgid="5683126664999349196">"Prepojenie <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> so zariadením <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong>"</string>
+</resources>
diff --git a/packages/CompanionDeviceManager/res/values-sl/strings.xml b/packages/CompanionDeviceManager/res/values-sl/strings.xml
new file mode 100644
index 0000000..5645fb1
--- /dev/null
+++ b/packages/CompanionDeviceManager/res/values-sl/strings.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2017 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_label" msgid="4470785958457506021">"Upravitelj spremljevalnih naprav"</string>
+ <string name="chooser_title" msgid="4958797271463138976">"Povezava z aplikacijo <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong>"</string>
+ <string name="confirmation_title" msgid="5683126664999349196">"Povezava aplikacije <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> z napravo <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong>"</string>
+</resources>
diff --git a/packages/CompanionDeviceManager/res/values-sq/strings.xml b/packages/CompanionDeviceManager/res/values-sq/strings.xml
new file mode 100644
index 0000000..793554f
--- /dev/null
+++ b/packages/CompanionDeviceManager/res/values-sq/strings.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2017 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_label" msgid="4470785958457506021">"Menaxheri i pajisjes shoqëruese"</string>
+ <string name="chooser_title" msgid="4958797271463138976">"Lidh me <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong>"</string>
+ <string name="confirmation_title" msgid="5683126664999349196">"Lidh <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> me <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong>"</string>
+</resources>
diff --git a/packages/CompanionDeviceManager/res/values-sr/strings.xml b/packages/CompanionDeviceManager/res/values-sr/strings.xml
new file mode 100644
index 0000000..eac6805
--- /dev/null
+++ b/packages/CompanionDeviceManager/res/values-sr/strings.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2017 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_label" msgid="4470785958457506021">"Менаџер придруженог уређаја"</string>
+ <string name="chooser_title" msgid="4958797271463138976">"Повежите са апликацијом <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong>"</string>
+ <string name="confirmation_title" msgid="5683126664999349196">"Повежите апликацију <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> и уређај <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong>"</string>
+</resources>
diff --git a/packages/CompanionDeviceManager/res/values-sv/strings.xml b/packages/CompanionDeviceManager/res/values-sv/strings.xml
new file mode 100644
index 0000000..7d2ad85
--- /dev/null
+++ b/packages/CompanionDeviceManager/res/values-sv/strings.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2017 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_label" msgid="4470785958457506021">"Companion Device Manager"</string>
+ <string name="chooser_title" msgid="4958797271463138976">"Länka med <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong>"</string>
+ <string name="confirmation_title" msgid="5683126664999349196">"Länka <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> till <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong>"</string>
+</resources>
diff --git a/packages/CompanionDeviceManager/res/values-sw/strings.xml b/packages/CompanionDeviceManager/res/values-sw/strings.xml
new file mode 100644
index 0000000..8308bbd
--- /dev/null
+++ b/packages/CompanionDeviceManager/res/values-sw/strings.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2017 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_label" msgid="4470785958457506021">"Kidhibiti cha Vifaa Visaidizi"</string>
+ <string name="chooser_title" msgid="4958797271463138976">"Unganisha na <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong>"</string>
+ <string name="confirmation_title" msgid="5683126664999349196">"Ungansha <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> na <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong>"</string>
+</resources>
diff --git a/packages/CompanionDeviceManager/res/values-ta/strings.xml b/packages/CompanionDeviceManager/res/values-ta/strings.xml
new file mode 100644
index 0000000..0511037
--- /dev/null
+++ b/packages/CompanionDeviceManager/res/values-ta/strings.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2017 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_label" msgid="4470785958457506021">"கம்பேனியன் சாதன நிர்வாகி"</string>
+ <string name="chooser_title" msgid="4958797271463138976">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> ஆப்ஸுடன் இணைத்தல்"</string>
+ <string name="confirmation_title" msgid="5683126664999349196">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> ஆப்ஸை <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> சாதனத்துடன் இணைத்தல்"</string>
+</resources>
diff --git a/packages/CompanionDeviceManager/res/values-te/strings.xml b/packages/CompanionDeviceManager/res/values-te/strings.xml
new file mode 100644
index 0000000..ebcc7f5
--- /dev/null
+++ b/packages/CompanionDeviceManager/res/values-te/strings.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2017 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_label" msgid="4470785958457506021">"సహచర పరికర మేనేజర్"</string>
+ <string name="chooser_title" msgid="4958797271463138976">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong>తో లింక్ చేయండి"</string>
+ <string name="confirmation_title" msgid="5683126664999349196">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> with <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong>తో లింక్ చేయండి"</string>
+</resources>
diff --git a/packages/CompanionDeviceManager/res/values-th/strings.xml b/packages/CompanionDeviceManager/res/values-th/strings.xml
new file mode 100644
index 0000000..3240794
--- /dev/null
+++ b/packages/CompanionDeviceManager/res/values-th/strings.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2017 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_label" msgid="4470785958457506021">"Companion Device Manager"</string>
+ <string name="chooser_title" msgid="4958797271463138976">"ลิงก์กับ <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong>"</string>
+ <string name="confirmation_title" msgid="5683126664999349196">"ลิงก์ <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> กับ <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong>"</string>
+</resources>
diff --git a/packages/CompanionDeviceManager/res/values-tl/strings.xml b/packages/CompanionDeviceManager/res/values-tl/strings.xml
new file mode 100644
index 0000000..444b0d8
--- /dev/null
+++ b/packages/CompanionDeviceManager/res/values-tl/strings.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2017 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_label" msgid="4470785958457506021">"Kasamang Device Manager"</string>
+ <string name="chooser_title" msgid="4958797271463138976">"I-link sa <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong>"</string>
+ <string name="confirmation_title" msgid="5683126664999349196">"I-link ang <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> sa <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong>"</string>
+</resources>
diff --git a/packages/CompanionDeviceManager/res/values-tr/strings.xml b/packages/CompanionDeviceManager/res/values-tr/strings.xml
new file mode 100644
index 0000000..9c20ed4
--- /dev/null
+++ b/packages/CompanionDeviceManager/res/values-tr/strings.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2017 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_label" msgid="4470785958457506021">"Companion Device Manager"</string>
+ <string name="chooser_title" msgid="4958797271463138976">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> uygulamasına bağlan"</string>
+ <string name="confirmation_title" msgid="5683126664999349196">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> uygulamasını <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> cihazına bağla"</string>
+</resources>
diff --git a/packages/CompanionDeviceManager/res/values-uk/strings.xml b/packages/CompanionDeviceManager/res/values-uk/strings.xml
new file mode 100644
index 0000000..bed8d4d
--- /dev/null
+++ b/packages/CompanionDeviceManager/res/values-uk/strings.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2017 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_label" msgid="4470785958457506021">"Диспетчер супутніх пристроїв"</string>
+ <string name="chooser_title" msgid="4958797271463138976">"Налаштуйте зв’язок із додатком <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong>"</string>
+ <string name="confirmation_title" msgid="5683126664999349196">"Зв’яжіть пристрій <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> з додатком <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong>"</string>
+</resources>
diff --git a/packages/CompanionDeviceManager/res/values-ur/strings.xml b/packages/CompanionDeviceManager/res/values-ur/strings.xml
new file mode 100644
index 0000000..e9ad738
--- /dev/null
+++ b/packages/CompanionDeviceManager/res/values-ur/strings.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2017 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_label" msgid="4470785958457506021">"ساتھی آلہ مینیجر"</string>
+ <string name="chooser_title" msgid="4958797271463138976">";lt;strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong&gt& سے لنک کریں"</string>
+ <string name="confirmation_title" msgid="5683126664999349196">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> کو <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> سے لنک کریں"</string>
+</resources>
diff --git a/packages/CompanionDeviceManager/res/values-uz/strings.xml b/packages/CompanionDeviceManager/res/values-uz/strings.xml
new file mode 100644
index 0000000..c7d82ad
--- /dev/null
+++ b/packages/CompanionDeviceManager/res/values-uz/strings.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2017 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_label" msgid="4470785958457506021">"Companion Device Manager"</string>
+ <string name="chooser_title" msgid="4958797271463138976">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> ilovasiga ulash"</string>
+ <string name="confirmation_title" msgid="5683126664999349196">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> with <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong> ilovasiga ulash"</string>
+</resources>
diff --git a/packages/CompanionDeviceManager/res/values-vi/strings.xml b/packages/CompanionDeviceManager/res/values-vi/strings.xml
new file mode 100644
index 0000000..29e128c
--- /dev/null
+++ b/packages/CompanionDeviceManager/res/values-vi/strings.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2017 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_label" msgid="4470785958457506021">"Companion Device Manager"</string>
+ <string name="chooser_title" msgid="4958797271463138976">"Liên kết với <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong>"</string>
+ <string name="confirmation_title" msgid="5683126664999349196">"Liên kết <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> với <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong>"</string>
+</resources>
diff --git a/packages/CompanionDeviceManager/res/values-zh-rCN/strings.xml b/packages/CompanionDeviceManager/res/values-zh-rCN/strings.xml
new file mode 100644
index 0000000..8e962185
--- /dev/null
+++ b/packages/CompanionDeviceManager/res/values-zh-rCN/strings.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2017 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_label" msgid="4470785958457506021">"配套设备管理器"</string>
+ <string name="chooser_title" msgid="4958797271463138976">"关联 <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong>"</string>
+ <string name="confirmation_title" msgid="5683126664999349196">"将 <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> 关联到 <strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong>"</string>
+</resources>
diff --git a/packages/CompanionDeviceManager/res/values-zh-rHK/strings.xml b/packages/CompanionDeviceManager/res/values-zh-rHK/strings.xml
new file mode 100644
index 0000000..dd055d0
--- /dev/null
+++ b/packages/CompanionDeviceManager/res/values-zh-rHK/strings.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2017 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_label" msgid="4470785958457506021">"隨附裝置管理員"</string>
+ <string name="chooser_title" msgid="4958797271463138976">"使用「<xliff:g id="APP_NAME">%1$s</xliff:g>」<strong></strong>連接"</string>
+ <string name="confirmation_title" msgid="5683126664999349196">"連結「<xliff:g id="DEVICE_NAME">%2$s</xliff:g>」<strong></strong>和「<xliff:g id="APP_NAME">%1$s</xliff:g>」<strong></strong>"</string>
+</resources>
diff --git a/packages/CompanionDeviceManager/res/values-zh-rTW/strings.xml b/packages/CompanionDeviceManager/res/values-zh-rTW/strings.xml
new file mode 100644
index 0000000..2c46d59
--- /dev/null
+++ b/packages/CompanionDeviceManager/res/values-zh-rTW/strings.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2017 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_label" msgid="4470785958457506021">"隨附裝置管理員"</string>
+ <string name="chooser_title" msgid="4958797271463138976">"與「<xliff:g id="APP_NAME">%1$s</xliff:g>」<strong></strong>連結"</string>
+ <string name="confirmation_title" msgid="5683126664999349196">"為「<xliff:g id="APP_NAME">%1$s</xliff:g>」<strong></strong>與<strong></strong> <xliff:g id="DEVICE_NAME">%2$s</xliff:g> 建立連結"</string>
+</resources>
diff --git a/packages/CompanionDeviceManager/res/values-zu/strings.xml b/packages/CompanionDeviceManager/res/values-zu/strings.xml
new file mode 100644
index 0000000..80a24ff
--- /dev/null
+++ b/packages/CompanionDeviceManager/res/values-zu/strings.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2017 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_label" msgid="4470785958457506021">"Isiphathi sedivayisi esihambisanayo"</string>
+ <string name="chooser_title" msgid="4958797271463138976">"Xhuma ne-<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong>"</string>
+ <string name="confirmation_title" msgid="5683126664999349196">"Xhuma ne-<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> nge-<strong><xliff:g id="DEVICE_NAME">%2$s</xliff:g></strong>"</string>
+</resources>
diff --git a/packages/DefaultContainerService/Android.bp b/packages/DefaultContainerService/Android.bp
new file mode 100644
index 0000000..d4ba6e8
--- /dev/null
+++ b/packages/DefaultContainerService/Android.bp
@@ -0,0 +1,8 @@
+android_app {
+ name: "DefaultContainerService",
+ srcs: ["**/*.java"],
+ platform_apis: true,
+ jni_libs: ["libdefcontainer_jni"],
+ certificate: "platform",
+ privileged: true,
+}
diff --git a/packages/DefaultContainerService/Android.mk b/packages/DefaultContainerService/Android.mk
deleted file mode 100644
index 10c35c0..0000000
--- a/packages/DefaultContainerService/Android.mk
+++ /dev/null
@@ -1,17 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_TAGS := optional
-
-LOCAL_SRC_FILES := $(call all-subdir-java-files)
-
-LOCAL_PACKAGE_NAME := DefaultContainerService
-LOCAL_PRIVATE_PLATFORM_APIS := true
-
-LOCAL_JNI_SHARED_LIBRARIES := libdefcontainer_jni
-
-LOCAL_CERTIFICATE := platform
-
-LOCAL_PRIVILEGED_MODULE := true
-
-include $(BUILD_PACKAGE)
diff --git a/packages/DynamicAndroidInstallationService/AndroidManifest.xml b/packages/DynamicAndroidInstallationService/AndroidManifest.xml
index 1c1c72c..32acad4 100644
--- a/packages/DynamicAndroidInstallationService/AndroidManifest.xml
+++ b/packages/DynamicAndroidInstallationService/AndroidManifest.xml
@@ -4,7 +4,7 @@
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<uses-permission android:name="android.permission.INTERNET" />
- <uses-permission android:name="android.permission.MANAGE_DYNAMNIC_ANDROID" />
+ <uses-permission android:name="android.permission.MANAGE_DYNAMIC_ANDROID" />
<uses-permission android:name="android.permission.REBOOT" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
@@ -16,7 +16,7 @@
android:name=".DynamicAndroidInstallationService"
android:enabled="true"
android:exported="true"
- android:permission="android.permission.MANAGE_DYNAMNIC_ANDROID"
+ android:permission="android.permission.MANAGE_DYNAMIC_ANDROID"
android:process=":dynandroid">
<intent-filter>
<action android:name="android.content.action.NOTIFY_IF_IN_USE" />
@@ -26,7 +26,7 @@
<activity android:name=".VerificationActivity"
android:exported="true"
- android:permission="android.permission.MANAGE_DYNAMNIC_ANDROID"
+ android:permission="android.permission.MANAGE_DYNAMIC_ANDROID"
android:theme="@android:style/Theme.Material.Light.Dialog.NoActionBar"
android:process=":dynandroid">
<intent-filter>
diff --git a/packages/FakeOemFeatures/Android.bp b/packages/FakeOemFeatures/Android.bp
new file mode 100644
index 0000000..b265158
--- /dev/null
+++ b/packages/FakeOemFeatures/Android.bp
@@ -0,0 +1,9 @@
+android_app {
+ name: "FakeOemFeatures",
+ srcs: ["src/**/*.java"],
+ platform_apis: true,
+ certificate: "platform",
+ optimize: {
+ enabled: false,
+ },
+}
diff --git a/packages/FakeOemFeatures/Android.mk b/packages/FakeOemFeatures/Android.mk
deleted file mode 100644
index 43de8e5..0000000
--- a/packages/FakeOemFeatures/Android.mk
+++ /dev/null
@@ -1,16 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_TAGS := optional
-
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-
-LOCAL_PACKAGE_NAME := FakeOemFeatures
-LOCAL_PRIVATE_PLATFORM_APIS := true
-LOCAL_CERTIFICATE := platform
-
-LOCAL_PROGUARD_ENABLED := disabled
-
-include $(BUILD_PACKAGE)
-
-include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/packages/FusedLocation/Android.bp b/packages/FusedLocation/Android.bp
new file mode 100644
index 0000000..e794f72
--- /dev/null
+++ b/packages/FusedLocation/Android.bp
@@ -0,0 +1,22 @@
+// Copyright (C) 2012 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT 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_app {
+ name: "FusedLocation",
+ srcs: ["**/*.java"],
+ libs: ["com.android.location.provider"],
+ platform_apis: true,
+ certificate: "platform",
+ privileged: true,
+}
diff --git a/packages/LocalTransport/Android.bp b/packages/LocalTransport/Android.bp
new file mode 100644
index 0000000..2c990fe
--- /dev/null
+++ b/packages/LocalTransport/Android.bp
@@ -0,0 +1,26 @@
+//
+// Copyright (C) 2018 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+android_app {
+ name: "LocalTransport",
+ srcs: ["src/**/*.java"],
+ optimize: {
+ proguard_flags_files: ["proguard.flags"],
+ },
+ platform_apis: true,
+ certificate: "platform",
+ privileged: true,
+}
diff --git a/packages/LocalTransport/Android.mk b/packages/LocalTransport/Android.mk
deleted file mode 100644
index 3484b0f..0000000
--- a/packages/LocalTransport/Android.mk
+++ /dev/null
@@ -1,35 +0,0 @@
-#
-# Copyright (C) 2018 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-LOCAL_PATH := $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_TAGS := optional
-
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-
-LOCAL_PROGUARD_FLAG_FILES := proguard.flags
-
-LOCAL_PACKAGE_NAME := LocalTransport
-LOCAL_PRIVATE_PLATFORM_APIS := true
-LOCAL_CERTIFICATE := platform
-LOCAL_PRIVILEGED_MODULE := true
-
-include $(BUILD_PACKAGE)
-
-########################
-include $(call all-makefiles-under,$(LOCAL_PATH))
-
diff --git a/packages/NetworkStack/AndroidManifest.xml b/packages/NetworkStack/AndroidManifest.xml
index 0476712..52c209e 100644
--- a/packages/NetworkStack/AndroidManifest.xml
+++ b/packages/NetworkStack/AndroidManifest.xml
@@ -17,7 +17,7 @@
*/
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="com.android.mainline.networkstack"
+ package="com.android.networkstack"
android:sharedUserId="android.uid.networkstack">
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
diff --git a/packages/NetworkStack/src/com/android/server/connectivity/NetworkMonitor.java b/packages/NetworkStack/src/com/android/server/connectivity/NetworkMonitor.java
index ec4a479..4b846b0 100644
--- a/packages/NetworkStack/src/com/android/server/connectivity/NetworkMonitor.java
+++ b/packages/NetworkStack/src/com/android/server/connectivity/NetworkMonitor.java
@@ -1318,26 +1318,28 @@
// is needed (i.e. can't browse a 204). This could be the result of an HTTP
// proxy server.
if (httpResponseCode == 200) {
+ long contentLength = urlConnection.getContentLengthLong();
if (probeType == ValidationProbeEvent.PROBE_PAC) {
validationLog(
probeType, url, "PAC fetch 200 response interpreted as 204 response.");
httpResponseCode = CaptivePortalProbeResult.SUCCESS_CODE;
- } else if (urlConnection.getContentLengthLong() == 0) {
- // Consider 200 response with "Content-length=0" to not be a captive portal.
- // There's no point in considering this a captive portal as the user cannot
- // sign-in to an empty page. Probably the result of a broken transparent proxy.
- // See http://b/9972012.
- validationLog(probeType, url,
- "200 response with Content-length=0 interpreted as 204 response.");
- httpResponseCode = CaptivePortalProbeResult.SUCCESS_CODE;
- } else if (urlConnection.getContentLengthLong() == -1) {
- // When no Content-length (default value == -1), attempt to read a byte from the
- // response. Do not use available() as it is unreliable. See http://b/33498325.
+ } else if (contentLength == -1) {
+ // When no Content-length (default value == -1), attempt to read a byte
+ // from the response. Do not use available() as it is unreliable.
+ // See http://b/33498325.
if (urlConnection.getInputStream().read() == -1) {
- validationLog(
- probeType, url, "Empty 200 response interpreted as 204 response.");
- httpResponseCode = CaptivePortalProbeResult.SUCCESS_CODE;
+ validationLog(probeType, url,
+ "Empty 200 response interpreted as failed response.");
+ httpResponseCode = CaptivePortalProbeResult.FAILED_CODE;
}
+ } else if (contentLength <= 4) {
+ // Consider 200 response with "Content-length <= 4" to not be a captive
+ // portal. There's no point in considering this a captive portal as the
+ // user cannot sign-in to an empty page. Probably the result of a broken
+ // transparent proxy. See http://b/9972012 and http://b/122999481.
+ validationLog(probeType, url, "200 response with Content-length <= 4"
+ + " interpreted as failed response.");
+ httpResponseCode = CaptivePortalProbeResult.FAILED_CODE;
}
}
} catch (IOException e) {
diff --git a/packages/NetworkStack/tests/src/android/net/apf/ApfTest.java b/packages/NetworkStack/tests/src/android/net/apf/ApfTest.java
index af71ac5..3414397 100644
--- a/packages/NetworkStack/tests/src/android/net/apf/ApfTest.java
+++ b/packages/NetworkStack/tests/src/android/net/apf/ApfTest.java
@@ -40,9 +40,7 @@
import android.content.Context;
import android.net.LinkAddress;
import android.net.LinkProperties;
-import android.net.SocketKeepalive;
-import android.net.TcpKeepalivePacketData;
-import android.net.TcpKeepalivePacketData.TcpSocketInfo;
+import android.net.TcpKeepalivePacketDataParcelable;
import android.net.apf.ApfFilter.ApfConfiguration;
import android.net.apf.ApfGenerator.IllegalInstructionException;
import android.net.apf.ApfGenerator.Register;
@@ -1546,12 +1544,15 @@
InetAddress srcAddr = InetAddress.getByAddress(IPV4_KEEPALIVE_SRC_ADDR);
InetAddress dstAddr = InetAddress.getByAddress(IPV4_KEEPALIVE_DST_ADDR);
- final TcpSocketInfo v4Tsi = new TcpSocketInfo(
- srcAddr, srcPort, dstAddr, dstPort, seqNum, ackNum, window, windowScale);
- final TcpKeepalivePacketData ipv4TcpKeepalivePacket =
- TcpKeepalivePacketData.tcpKeepalivePacket(v4Tsi);
+ final TcpKeepalivePacketDataParcelable parcel = new TcpKeepalivePacketDataParcelable();
+ parcel.srcAddress = srcAddr.getAddress();
+ parcel.srcPort = srcPort;
+ parcel.dstAddress = dstAddr.getAddress();
+ parcel.dstPort = dstPort;
+ parcel.seq = seqNum;
+ parcel.ack = ackNum;
- apfFilter.addKeepalivePacketFilter(slot1, ipv4TcpKeepalivePacket.toStableParcelable());
+ apfFilter.addKeepalivePacketFilter(slot1, parcel);
program = cb.getApfProgram();
// Verify IPv4 keepalive ack packet is dropped
@@ -1580,11 +1581,17 @@
// dst: 2404:0:0:0:0:0:faf2, port: 54321
srcAddr = InetAddress.getByAddress(IPV6_KEEPALIVE_SRC_ADDR);
dstAddr = InetAddress.getByAddress(IPV6_KEEPALIVE_DST_ADDR);
- final TcpSocketInfo v6Tsi = new TcpSocketInfo(
- srcAddr, srcPort, dstAddr, dstPort, seqNum, ackNum, window, windowScale);
- final TcpKeepalivePacketData ipv6TcpKeepalivePacket =
- TcpKeepalivePacketData.tcpKeepalivePacket(v6Tsi);
- apfFilter.addKeepalivePacketFilter(slot1, ipv6TcpKeepalivePacket.toStableParcelable());
+
+ final TcpKeepalivePacketDataParcelable ipv6Parcel =
+ new TcpKeepalivePacketDataParcelable();
+ ipv6Parcel.srcAddress = srcAddr.getAddress();
+ ipv6Parcel.srcPort = srcPort;
+ ipv6Parcel.dstAddress = dstAddr.getAddress();
+ ipv6Parcel.dstPort = dstPort;
+ ipv6Parcel.seq = seqNum;
+ ipv6Parcel.ack = ackNum;
+
+ apfFilter.addKeepalivePacketFilter(slot1, ipv6Parcel);
program = cb.getApfProgram();
// Verify IPv6 keepalive ack packet is dropped
@@ -1606,8 +1613,8 @@
apfFilter.removeKeepalivePacketFilter(slot1);
// Verify multiple filters
- apfFilter.addKeepalivePacketFilter(slot1, ipv4TcpKeepalivePacket.toStableParcelable());
- apfFilter.addKeepalivePacketFilter(slot2, ipv6TcpKeepalivePacket.toStableParcelable());
+ apfFilter.addKeepalivePacketFilter(slot1, parcel);
+ apfFilter.addKeepalivePacketFilter(slot2, ipv6Parcel);
program = cb.getApfProgram();
// Verify IPv4 keepalive ack packet is dropped
@@ -1643,7 +1650,7 @@
// Remove keepalive filters
apfFilter.removeKeepalivePacketFilter(slot1);
apfFilter.removeKeepalivePacketFilter(slot2);
- } catch (SocketKeepalive.InvalidPacketException e) {
+ } catch (UnsupportedOperationException e) {
// TODO: support V6 packets
}
diff --git a/packages/NetworkStackPermissionStub/AndroidManifest.xml b/packages/NetworkStackPermissionStub/AndroidManifest.xml
index 2ccf5ff..a8742d7 100644
--- a/packages/NetworkStackPermissionStub/AndroidManifest.xml
+++ b/packages/NetworkStackPermissionStub/AndroidManifest.xml
@@ -17,7 +17,8 @@
*/
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="com.android.mainline.networkstack.permissionstub">
+ package="com.android.networkstack.permissionstub"
+ android:sharedUserId="android.uid.networkstack">
<!--
This package only exists to define the below permissions, and enforce that they are only
granted to apps sharing the same signature.
diff --git a/packages/OsuLogin/Android.bp b/packages/OsuLogin/Android.bp
new file mode 100644
index 0000000..ac3abac
--- /dev/null
+++ b/packages/OsuLogin/Android.bp
@@ -0,0 +1,8 @@
+android_app {
+ name: "OsuLogin",
+ static_libs: ["androidx.legacy_legacy-support-v4"],
+ resource_dirs: ["res"],
+ srcs: ["src/**/*.java"],
+ platform_apis: true,
+ certificate: "platform",
+}
diff --git a/packages/OsuLogin/Android.mk b/packages/OsuLogin/Android.mk
deleted file mode 100644
index 2c07615..0000000
--- a/packages/OsuLogin/Android.mk
+++ /dev/null
@@ -1,15 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_TAGS := optional
-LOCAL_USE_AAPT2 := true
-LOCAL_STATIC_ANDROID_LIBRARIES := androidx.legacy_legacy-support-v4
-LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res
-
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-
-LOCAL_PACKAGE_NAME := OsuLogin
-LOCAL_PRIVATE_PLATFORM_APIS := true
-LOCAL_CERTIFICATE := platform
-
-include $(BUILD_PACKAGE)
diff --git a/packages/SettingsLib/BarChartPreference/src/com/android/settingslib/widget/BarChartPreference.java b/packages/SettingsLib/BarChartPreference/src/com/android/settingslib/widget/BarChartPreference.java
index d332bac..3b87fca 100644
--- a/packages/SettingsLib/BarChartPreference/src/com/android/settingslib/widget/BarChartPreference.java
+++ b/packages/SettingsLib/BarChartPreference/src/com/android/settingslib/widget/BarChartPreference.java
@@ -87,6 +87,7 @@
};
private int mMaxBarHeight;
+ private boolean mIsLoading;
private BarChartInfo mBarChartInfo;
public BarChartPreference(Context context) {
@@ -134,12 +135,33 @@
notifyChanged();
}
+ /**
+ * Set loading state for {@link BarChartPreference}.
+ *
+ * By default, {@link BarChartPreference} doesn't care about it.
+ *
+ * But if user sets loading state to true explicitly, it means {@link BarChartPreference}
+ * needs to take some time to load data. So we won't initialize any view now.
+ *
+ * Once the state is updated to false, we will start to initialize view again.
+ *
+ * @param isLoading whether or not {@link BarChartPreference} is in loading state.
+ */
+ public void updateLoadingState(boolean isLoading) {
+ mIsLoading = isLoading;
+ notifyChanged();
+ }
+
@Override
public void onBindViewHolder(PreferenceViewHolder holder) {
super.onBindViewHolder(holder);
holder.setDividerAllowedAbove(true);
holder.setDividerAllowedBelow(true);
+ // If the state is loading, we just show a blank view.
+ if (mIsLoading) {
+ return;
+ }
// We must show title of bar chart.
bindChartTitleView(holder);
diff --git a/packages/SettingsLib/res/values-af/strings.xml b/packages/SettingsLib/res/values-af/strings.xml
index 0988cab..cfc76b7 100644
--- a/packages/SettingsLib/res/values-af/strings.xml
+++ b/packages/SettingsLib/res/values-af/strings.xml
@@ -87,8 +87,8 @@
<string name="bluetooth_profile_sap" msgid="5764222021851283125">"SIM-toegang"</string>
<string name="bluetooth_profile_a2dp_high_quality" msgid="5444517801472820055">"HD-oudio: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
<string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="8510588052415438887">"HD oudio"</string>
- <string name="bluetooth_profile_hearing_aid" msgid="7999237886427812595">"Gehoortoestel"</string>
- <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="7188282786730266159">"Gekoppel aan gehoortoestel"</string>
+ <string name="bluetooth_profile_hearing_aid" msgid="6680721080542444257">"Gehoortoestelle"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="3051944447369418317">"Gekoppel aan gehoortoestelle"</string>
<string name="bluetooth_a2dp_profile_summary_connected" msgid="963376081347721598">"Gekoppel aan media-oudio"</string>
<string name="bluetooth_headset_profile_summary_connected" msgid="7661070206715520671">"Gekoppel aan foonoudio"</string>
<string name="bluetooth_opp_profile_summary_connected" msgid="2611913495968309066">"Gekoppel aan lêeroordragbediener"</string>
@@ -105,7 +105,7 @@
<string name="bluetooth_headset_profile_summary_use_for" msgid="8705753622443862627">"Gebruik vir foonoudio"</string>
<string name="bluetooth_opp_profile_summary_use_for" msgid="1255674547144769756">"Gebruik vir lêeroordrag"</string>
<string name="bluetooth_hid_profile_summary_use_for" msgid="232727040453645139">"Gebruik vir invoer"</string>
- <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="908775281788309484">"Gebruik vir gehoortoestel"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="8843499209204010224">"Gebruik vir gehoortoestelle"</string>
<string name="bluetooth_pairing_accept" msgid="6163520056536604875">"Bind saam"</string>
<string name="bluetooth_pairing_accept_all_caps" msgid="6061699265220789149">"BIND SAAM"</string>
<string name="bluetooth_pairing_decline" msgid="4185420413578948140">"Kanselleer"</string>
@@ -136,6 +136,7 @@
<string name="process_kernel_label" msgid="3916858646836739323">"Android-bedryfstelsel"</string>
<string name="data_usage_uninstalled_apps" msgid="614263770923231598">"Verwyderde programme"</string>
<string name="data_usage_uninstalled_apps_users" msgid="7986294489899813194">"Verwyderde programme en gebruikers"</string>
+ <string name="data_usage_ota" msgid="5377889154805560860">"Stelselopdaterings"</string>
<string name="tether_settings_title_usb" msgid="6688416425801386511">"USB-verbinding"</string>
<string name="tether_settings_title_wifi" msgid="3277144155960302049">"Wi-Fi-warmkol"</string>
<string name="tether_settings_title_bluetooth" msgid="355855408317564420">"Bluetooth-verbinding"</string>
diff --git a/packages/SettingsLib/res/values-am/strings.xml b/packages/SettingsLib/res/values-am/strings.xml
index 301d609..6e6d58f 100644
--- a/packages/SettingsLib/res/values-am/strings.xml
+++ b/packages/SettingsLib/res/values-am/strings.xml
@@ -87,8 +87,8 @@
<string name="bluetooth_profile_sap" msgid="5764222021851283125">"የሲም መዳረሻ"</string>
<string name="bluetooth_profile_a2dp_high_quality" msgid="5444517801472820055">"ኤችዲ ኦዲዮ፦ <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
<string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="8510588052415438887">"ኤችዲ ኦዲዮ"</string>
- <string name="bluetooth_profile_hearing_aid" msgid="7999237886427812595">"መስሚያ አጋዥ መሣሪያ"</string>
- <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="7188282786730266159">"ከመስሚያ አጋዥ መሣሪያ ጋር ተገናኝቷል"</string>
+ <string name="bluetooth_profile_hearing_aid" msgid="6680721080542444257">"አጋዥ መስሚያዎች"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="3051944447369418317">"ከአጋዥ መስሚያዎች ጋር ተገናኝቷል"</string>
<string name="bluetooth_a2dp_profile_summary_connected" msgid="963376081347721598">"ወደ ማህደረ መረጃ አውዲዮ ተያይዟል"</string>
<string name="bluetooth_headset_profile_summary_connected" msgid="7661070206715520671">"ወደ ስልክ አውዲዮ ተያይዟል"</string>
<string name="bluetooth_opp_profile_summary_connected" msgid="2611913495968309066">"ወደ ፋይል ዝውውር አገልጋይ ተያይዟል"</string>
@@ -105,7 +105,7 @@
<string name="bluetooth_headset_profile_summary_use_for" msgid="8705753622443862627">"ለስልክ ድምፅ ተጠቀም"</string>
<string name="bluetooth_opp_profile_summary_use_for" msgid="1255674547144769756">"ለፋይል ዝውውር ተጠቀም"</string>
<string name="bluetooth_hid_profile_summary_use_for" msgid="232727040453645139">"ለውፅአት ተጠቀም"</string>
- <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="908775281788309484">"ለመስሚያ አጋዥ መሣሪያ ተጠቀም"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="8843499209204010224">"ለአጋዥ መስሚያዎች ይጠቀሙ"</string>
<string name="bluetooth_pairing_accept" msgid="6163520056536604875">"አጣምር"</string>
<string name="bluetooth_pairing_accept_all_caps" msgid="6061699265220789149">"አጣምር"</string>
<string name="bluetooth_pairing_decline" msgid="4185420413578948140">"ይቅር"</string>
@@ -136,6 +136,7 @@
<string name="process_kernel_label" msgid="3916858646836739323">"Android ስርዓተ ክወና"</string>
<string name="data_usage_uninstalled_apps" msgid="614263770923231598">"የተወገዱ መተግበሪያዎች"</string>
<string name="data_usage_uninstalled_apps_users" msgid="7986294489899813194">"የተወገዱ መተግበሪያዎች እና ተጠቃሚዎች"</string>
+ <string name="data_usage_ota" msgid="5377889154805560860">"የሥርዓት ዝማኔዎች"</string>
<string name="tether_settings_title_usb" msgid="6688416425801386511">"USB መሰካት"</string>
<string name="tether_settings_title_wifi" msgid="3277144155960302049">"ተጓጓዥ ድረስ ነጥቦች"</string>
<string name="tether_settings_title_bluetooth" msgid="355855408317564420">"ብሉቱዝ ማያያዝ"</string>
diff --git a/packages/SettingsLib/res/values-ar/strings.xml b/packages/SettingsLib/res/values-ar/strings.xml
index 91de9e3..18d47ac 100644
--- a/packages/SettingsLib/res/values-ar/strings.xml
+++ b/packages/SettingsLib/res/values-ar/strings.xml
@@ -87,8 +87,8 @@
<string name="bluetooth_profile_sap" msgid="5764222021851283125">"الوصول إلى شريحة SIM"</string>
<string name="bluetooth_profile_a2dp_high_quality" msgid="5444517801472820055">"صوت عالي الدقة: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
<string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="8510588052415438887">"صوت عالي الدقة"</string>
- <string name="bluetooth_profile_hearing_aid" msgid="7999237886427812595">"سماعة الأذن الطبية"</string>
- <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="7188282786730266159">"تم توصيل سماعة الأذن الطبية"</string>
+ <string name="bluetooth_profile_hearing_aid" msgid="6680721080542444257">"سماعات الأذن الطبية"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="3051944447369418317">"تمّ التوصيل بسماعات الأذن الطبية"</string>
<string name="bluetooth_a2dp_profile_summary_connected" msgid="963376081347721598">"متصل بالإعدادات الصوتية للوسائط"</string>
<string name="bluetooth_headset_profile_summary_connected" msgid="7661070206715520671">"متصل بالإعدادات الصوتية للهاتف"</string>
<string name="bluetooth_opp_profile_summary_connected" msgid="2611913495968309066">"متصل بخادم نقل الملف"</string>
@@ -105,7 +105,7 @@
<string name="bluetooth_headset_profile_summary_use_for" msgid="8705753622443862627">"الاستخدام لإعدادات الهاتف الصوتية"</string>
<string name="bluetooth_opp_profile_summary_use_for" msgid="1255674547144769756">"استخدامه لنقل الملفات"</string>
<string name="bluetooth_hid_profile_summary_use_for" msgid="232727040453645139">"استخدام للإدخال"</string>
- <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="908775281788309484">"استخدام سماعة الأذن الطبية"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="8843499209204010224">"استخدام سماعات الأذن الطبية"</string>
<string name="bluetooth_pairing_accept" msgid="6163520056536604875">"إقران"</string>
<string name="bluetooth_pairing_accept_all_caps" msgid="6061699265220789149">"إقران"</string>
<string name="bluetooth_pairing_decline" msgid="4185420413578948140">"إلغاء"</string>
@@ -136,6 +136,7 @@
<string name="process_kernel_label" msgid="3916858646836739323">"نظام التشغيل Android"</string>
<string name="data_usage_uninstalled_apps" msgid="614263770923231598">"التطبيقات المزالة"</string>
<string name="data_usage_uninstalled_apps_users" msgid="7986294489899813194">"التطبيقات والمستخدمون الذين تمت إزالتهم"</string>
+ <string name="data_usage_ota" msgid="5377889154805560860">"تحديثات النظام"</string>
<string name="tether_settings_title_usb" msgid="6688416425801386511">"ربط USB"</string>
<string name="tether_settings_title_wifi" msgid="3277144155960302049">"نقطة اتصال محمولة"</string>
<string name="tether_settings_title_bluetooth" msgid="355855408317564420">"ربط البلوتوث"</string>
diff --git a/packages/SettingsLib/res/values-as/strings.xml b/packages/SettingsLib/res/values-as/strings.xml
index e726ae4..f865563 100644
--- a/packages/SettingsLib/res/values-as/strings.xml
+++ b/packages/SettingsLib/res/values-as/strings.xml
@@ -38,27 +38,20 @@
<string name="connected_via_network_scorer" msgid="5713793306870815341">"%1$s মাধ্যমেদি স্বয়ংক্ৰিয়ভাৱে সংযোগ কৰা হৈছে"</string>
<string name="connected_via_network_scorer_default" msgid="7867260222020343104">"নেটৱৰ্ক ৰেটিং প্ৰদানকাৰীৰ জৰিয়তে স্বয়ং সংয়োগ কৰা হ’ল"</string>
<string name="connected_via_passpoint" msgid="2826205693803088747">"%1$s-ৰ মাধ্যমেদি সংযোগ কৰা হৈছে"</string>
- <!-- no translation found for connected_via_app (5571999941988929520) -->
- <skip />
+ <string name="connected_via_app" msgid="5571999941988929520">"<xliff:g id="NAME">%1$s</xliff:g>ৰ জৰিয়তে সংযুক্ত"</string>
<string name="available_via_passpoint" msgid="1617440946846329613">"%1$sৰ মাধ্যমেৰে উপলব্ধ"</string>
- <!-- no translation found for tap_to_sign_up (6449724763052579434) -->
- <skip />
+ <string name="tap_to_sign_up" msgid="6449724763052579434">"ছাইন আপ কৰিবলৈ টিপক"</string>
<string name="wifi_connected_no_internet" msgid="8202906332837777829">"সংযোজিত, ইণ্টাৰনেট নাই"</string>
<string name="wifi_status_no_internet" msgid="5784710974669608361">"ইণ্টাৰনেট সংযোগ নাই"</string>
<string name="wifi_status_sign_in_required" msgid="123517180404752756">"ছাইন ইন কৰা দৰকাৰী"</string>
<string name="wifi_ap_unable_to_handle_new_sta" msgid="5348824313514404541">"একচেছ পইণ্ট কিছু সময়ৰ বাবে পূৰ্ণ হৈ আছে"</string>
<string name="connected_via_carrier" msgid="7583780074526041912">"%1$sৰ যোগেৰে সংযোজিত"</string>
<string name="available_via_carrier" msgid="1469036129740799053">"%1$sৰ মাধ্যমেৰে উপলব্ধ"</string>
- <!-- no translation found for osu_opening_provider (5488997661548640424) -->
- <skip />
- <!-- no translation found for osu_connect_failed (2187750899158158934) -->
- <skip />
- <!-- no translation found for osu_completing_sign_up (9037638564719197082) -->
- <skip />
- <!-- no translation found for osu_sign_up_failed (7296159750352873260) -->
- <skip />
- <!-- no translation found for osu_sign_up_complete (8207626049093289203) -->
- <skip />
+ <string name="osu_opening_provider" msgid="5488997661548640424">"<xliff:g id="PASSPOINTPROVIDER">%1$s</xliff:g> খুলি থকা হৈছে"</string>
+ <string name="osu_connect_failed" msgid="2187750899158158934">"সংযোগ কৰিব পৰা নগ’ল"</string>
+ <string name="osu_completing_sign_up" msgid="9037638564719197082">"ছাইন আপ সম্পূৰ্ণ কৰি থকা হৈছে…"</string>
+ <string name="osu_sign_up_failed" msgid="7296159750352873260">"ছাইন আপ সম্পূৰ্ণ কৰিব পৰা নগ’ল। আকৌ চেষ্টা কৰিবলৈ টিপক।"</string>
+ <string name="osu_sign_up_complete" msgid="8207626049093289203">"ছাইন আপ সম্পূৰ্ণ হৈছে সংযোগ কৰি থকা হৈছে…"</string>
<string name="speed_label_very_slow" msgid="1867055264243608530">"অতি লেহেম"</string>
<string name="speed_label_slow" msgid="813109590815810235">"লেহেমীয়া"</string>
<string name="speed_label_okay" msgid="2331665440671174858">"ঠিক"</string>
@@ -94,8 +87,8 @@
<string name="bluetooth_profile_sap" msgid="5764222021851283125">"ছিম প্ৰৱেশ"</string>
<string name="bluetooth_profile_a2dp_high_quality" msgid="5444517801472820055">"এইচ্ছডি অডি\'অ: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
<string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="8510588052415438887">"এইচ্ছডি অডিঅ’"</string>
- <string name="bluetooth_profile_hearing_aid" msgid="7999237886427812595">"শ্ৰৱণ যন্ত্ৰ"</string>
- <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="7188282786730266159">"শ্ৰৱণ যন্ত্ৰৰ লগত সংযোগ কৰা হ’ল"</string>
+ <string name="bluetooth_profile_hearing_aid" msgid="6680721080542444257">"শ্ৰৱণ যন্ত্ৰ"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="3051944447369418317">"শ্ৰৱণ যন্ত্ৰলৈ সংযোগ কৰা হৈছে"</string>
<string name="bluetooth_a2dp_profile_summary_connected" msgid="963376081347721598">"মিডিয়া অডিঅ’লৈ সংযোগ হৈছে"</string>
<string name="bluetooth_headset_profile_summary_connected" msgid="7661070206715520671">"ফ’ন অডিঅ\'ৰ লগত সংযোগ কৰা হ’ল"</string>
<string name="bluetooth_opp_profile_summary_connected" msgid="2611913495968309066">"ফাইল ট্ৰান্সফাৰ ছাৰ্ভাৰৰ সৈতে সংযোজিত হৈ আছে"</string>
@@ -112,7 +105,7 @@
<string name="bluetooth_headset_profile_summary_use_for" msgid="8705753622443862627">"ফ\'ন অডিঅ\'ৰ বাবে ব্যৱহাৰ কৰক"</string>
<string name="bluetooth_opp_profile_summary_use_for" msgid="1255674547144769756">"ফাইল স্থানান্তৰ কৰিবলৈ ব্যৱহাৰ কৰক"</string>
<string name="bluetooth_hid_profile_summary_use_for" msgid="232727040453645139">"ইনপুটৰ বাবে ব্যৱহাৰ কৰক"</string>
- <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="908775281788309484">"শ্ৰৱণ যন্ত্ৰৰ বাবে ব্যৱহাৰ কৰক"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="8843499209204010224">"শ্ৰৱণ যন্ত্ৰৰ বাবে ব্যৱহাৰ কৰক"</string>
<string name="bluetooth_pairing_accept" msgid="6163520056536604875">"যোৰা লগাওক"</string>
<string name="bluetooth_pairing_accept_all_caps" msgid="6061699265220789149">"যোৰা লগাওক"</string>
<string name="bluetooth_pairing_decline" msgid="4185420413578948140">"বাতিল কৰক"</string>
@@ -143,8 +136,10 @@
<string name="process_kernel_label" msgid="3916858646836739323">"Android OS"</string>
<string name="data_usage_uninstalled_apps" msgid="614263770923231598">"আঁতৰোৱা এপ্সমূহ"</string>
<string name="data_usage_uninstalled_apps_users" msgid="7986294489899813194">"আঁতৰোৱা এপ্ আৰু ব্যৱহাৰকাৰীসমূহ"</string>
+ <!-- no translation found for data_usage_ota (5377889154805560860) -->
+ <skip />
<string name="tether_settings_title_usb" msgid="6688416425801386511">"ইউএছবি টেডাৰিং"</string>
- <string name="tether_settings_title_wifi" msgid="3277144155960302049">"প\'ৰ্টেবল হ\'টস্প\'ট"</string>
+ <string name="tether_settings_title_wifi" msgid="3277144155960302049">"প\'ৰ্টেবল হটস্পট"</string>
<string name="tether_settings_title_bluetooth" msgid="355855408317564420">"ব্লুটুথ টেডাৰিং"</string>
<string name="tether_settings_title_usb_bluetooth" msgid="5355828977109785001">"টেডাৰ কৰি থকা হৈছে"</string>
<string name="tether_settings_title_all" msgid="8356136101061143841">"টেডাৰিং আৰু প\'ৰ্টেবল হটস্পট"</string>
diff --git a/packages/SettingsLib/res/values-az/strings.xml b/packages/SettingsLib/res/values-az/strings.xml
index 4dd4817..8e6e07d 100644
--- a/packages/SettingsLib/res/values-az/strings.xml
+++ b/packages/SettingsLib/res/values-az/strings.xml
@@ -87,8 +87,8 @@
<string name="bluetooth_profile_sap" msgid="5764222021851283125">"SIM Girişi"</string>
<string name="bluetooth_profile_a2dp_high_quality" msgid="5444517801472820055">"HD audio: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
<string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="8510588052415438887">"HD audio"</string>
- <string name="bluetooth_profile_hearing_aid" msgid="7999237886427812595">"Qulaqlıq"</string>
- <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="7188282786730266159">"Qulaqlığa qoşuldunuz"</string>
+ <string name="bluetooth_profile_hearing_aid" msgid="6680721080542444257">"Eşitmə Aparatı"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="3051944447369418317">"Eşitmə Aparatlarına qoşuldu"</string>
<string name="bluetooth_a2dp_profile_summary_connected" msgid="963376081347721598">"Media audioya birləşdirilib"</string>
<string name="bluetooth_headset_profile_summary_connected" msgid="7661070206715520671">"Telefon audiosuna qoşulu"</string>
<string name="bluetooth_opp_profile_summary_connected" msgid="2611913495968309066">"Fayl transfer serverinə qoşulu"</string>
@@ -105,7 +105,7 @@
<string name="bluetooth_headset_profile_summary_use_for" msgid="8705753622443862627">"Telefon audiosu istifadə edin"</string>
<string name="bluetooth_opp_profile_summary_use_for" msgid="1255674547144769756">"Fayl transferi üçün istifadə edin"</string>
<string name="bluetooth_hid_profile_summary_use_for" msgid="232727040453645139">"Daxiletmə üçün istifadə edin"</string>
- <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="908775281788309484">"Qulaqlıq üçün istifadə edin"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="8843499209204010224">"Eşitmə Aparatları üçün istifadə edin"</string>
<string name="bluetooth_pairing_accept" msgid="6163520056536604875">"Birləşdir"</string>
<string name="bluetooth_pairing_accept_all_caps" msgid="6061699265220789149">"CÜTLƏNDİR"</string>
<string name="bluetooth_pairing_decline" msgid="4185420413578948140">"Ləğv et"</string>
@@ -136,6 +136,7 @@
<string name="process_kernel_label" msgid="3916858646836739323">"Android OS"</string>
<string name="data_usage_uninstalled_apps" msgid="614263770923231598">"Silinmiş tətbiqlər"</string>
<string name="data_usage_uninstalled_apps_users" msgid="7986294489899813194">"Tətbiqləri və istifadəçiləri silin"</string>
+ <string name="data_usage_ota" msgid="5377889154805560860">"Sistem güncəllənməsi"</string>
<string name="tether_settings_title_usb" msgid="6688416425801386511">"USB Birləşmə"</string>
<string name="tether_settings_title_wifi" msgid="3277144155960302049">"Portativ hotspot"</string>
<string name="tether_settings_title_bluetooth" msgid="355855408317564420">"Bluetooth birləşmə"</string>
diff --git a/packages/SettingsLib/res/values-b+sr+Latn/strings.xml b/packages/SettingsLib/res/values-b+sr+Latn/strings.xml
index dc54301..1cdd1fd 100644
--- a/packages/SettingsLib/res/values-b+sr+Latn/strings.xml
+++ b/packages/SettingsLib/res/values-b+sr+Latn/strings.xml
@@ -87,8 +87,8 @@
<string name="bluetooth_profile_sap" msgid="5764222021851283125">"Pristup SIM kartici"</string>
<string name="bluetooth_profile_a2dp_high_quality" msgid="5444517801472820055">"HD zvuk: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
<string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="8510588052415438887">"HD zvuk"</string>
- <string name="bluetooth_profile_hearing_aid" msgid="7999237886427812595">"Slušni aparat"</string>
- <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="7188282786730266159">"Povezano sa slušnim aparatom"</string>
+ <string name="bluetooth_profile_hearing_aid" msgid="6680721080542444257">"Slušni aparati"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="3051944447369418317">"Povezano sa slušnim aparatima"</string>
<string name="bluetooth_a2dp_profile_summary_connected" msgid="963376081347721598">"Povezano sa zvukom medija"</string>
<string name="bluetooth_headset_profile_summary_connected" msgid="7661070206715520671">"Povezano sa zvukom telefona"</string>
<string name="bluetooth_opp_profile_summary_connected" msgid="2611913495968309066">"Povezano sa serverom za prenos datoteka"</string>
@@ -105,7 +105,7 @@
<string name="bluetooth_headset_profile_summary_use_for" msgid="8705753622443862627">"Korišćenje za audio telefona"</string>
<string name="bluetooth_opp_profile_summary_use_for" msgid="1255674547144769756">"Korišćenje za prenos datoteka"</string>
<string name="bluetooth_hid_profile_summary_use_for" msgid="232727040453645139">"Koristi za ulaz"</string>
- <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="908775281788309484">"Koristi za slušni aparat"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="8843499209204010224">"Koristi za slušne aparate"</string>
<string name="bluetooth_pairing_accept" msgid="6163520056536604875">"Upari"</string>
<string name="bluetooth_pairing_accept_all_caps" msgid="6061699265220789149">"UPARI"</string>
<string name="bluetooth_pairing_decline" msgid="4185420413578948140">"Otkaži"</string>
@@ -136,6 +136,7 @@
<string name="process_kernel_label" msgid="3916858646836739323">"Android OS"</string>
<string name="data_usage_uninstalled_apps" msgid="614263770923231598">"Uklonjene aplikacije"</string>
<string name="data_usage_uninstalled_apps_users" msgid="7986294489899813194">"Uklonjene aplikacije i korisnici"</string>
+ <string name="data_usage_ota" msgid="5377889154805560860">"Ažuriranja sistema"</string>
<string name="tether_settings_title_usb" msgid="6688416425801386511">"USB Internet povezivanje"</string>
<string name="tether_settings_title_wifi" msgid="3277144155960302049">"Prenosni hotspot"</string>
<string name="tether_settings_title_bluetooth" msgid="355855408317564420">"Bluetooth privezivanje"</string>
diff --git a/packages/SettingsLib/res/values-be/strings.xml b/packages/SettingsLib/res/values-be/strings.xml
index 2fa2692..1a60c3d 100644
--- a/packages/SettingsLib/res/values-be/strings.xml
+++ b/packages/SettingsLib/res/values-be/strings.xml
@@ -87,8 +87,8 @@
<string name="bluetooth_profile_sap" msgid="5764222021851283125">"Доступ да SIM-карты"</string>
<string name="bluetooth_profile_a2dp_high_quality" msgid="5444517801472820055">"Аўдыя ў HD: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
<string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="8510588052415438887">"Аўдыя ў HD"</string>
- <string name="bluetooth_profile_hearing_aid" msgid="7999237886427812595">"Слыхавы апарат"</string>
- <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="7188282786730266159">"Падключана да слыхавога апарата"</string>
+ <string name="bluetooth_profile_hearing_aid" msgid="6680721080542444257">"Слыхавыя апараты"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="3051944447369418317">"Падключана да слыхавых апаратаў"</string>
<string name="bluetooth_a2dp_profile_summary_connected" msgid="963376081347721598">"Падключана да аўдыё медыа"</string>
<string name="bluetooth_headset_profile_summary_connected" msgid="7661070206715520671">"Падключана да аўдыё тэлефона"</string>
<string name="bluetooth_opp_profile_summary_connected" msgid="2611913495968309066">"Падключаны да серверу перадачы файлаў"</string>
@@ -105,7 +105,7 @@
<string name="bluetooth_headset_profile_summary_use_for" msgid="8705753622443862627">"Выкарыстоўваць для аўдыё тэлефона"</string>
<string name="bluetooth_opp_profile_summary_use_for" msgid="1255674547144769756">"Выкарыстоўваць для перадачы файлаў"</string>
<string name="bluetooth_hid_profile_summary_use_for" msgid="232727040453645139">"Выкарыстоўваць для ўводу"</string>
- <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="908775281788309484">"Выкарыстоўваць для слыхавога апарата"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="8843499209204010224">"Выкарыстоўваць для слыхавых апаратаў"</string>
<string name="bluetooth_pairing_accept" msgid="6163520056536604875">"Падлучыць"</string>
<string name="bluetooth_pairing_accept_all_caps" msgid="6061699265220789149">"СПАЛУЧЫЦЬ"</string>
<string name="bluetooth_pairing_decline" msgid="4185420413578948140">"Скасаваць"</string>
@@ -136,6 +136,7 @@
<string name="process_kernel_label" msgid="3916858646836739323">"АС Android"</string>
<string name="data_usage_uninstalled_apps" msgid="614263770923231598">"Выдаленыя прыкладанні"</string>
<string name="data_usage_uninstalled_apps_users" msgid="7986294489899813194">"Выдаленыя прыкладанні і карыстальнiкi"</string>
+ <string name="data_usage_ota" msgid="5377889154805560860">"Абнаўленні сістэмы"</string>
<string name="tether_settings_title_usb" msgid="6688416425801386511">"USB-мадэм"</string>
<string name="tether_settings_title_wifi" msgid="3277144155960302049">"Партатыўная кропка доступу"</string>
<string name="tether_settings_title_bluetooth" msgid="355855408317564420">"Bluetooth-мадэм"</string>
diff --git a/packages/SettingsLib/res/values-bg/strings.xml b/packages/SettingsLib/res/values-bg/strings.xml
index 1454118..aaedce4 100644
--- a/packages/SettingsLib/res/values-bg/strings.xml
+++ b/packages/SettingsLib/res/values-bg/strings.xml
@@ -87,8 +87,8 @@
<string name="bluetooth_profile_sap" msgid="5764222021851283125">"Достъп до SIM картата"</string>
<string name="bluetooth_profile_a2dp_high_quality" msgid="5444517801472820055">"Висококачествено аудио: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
<string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="8510588052415438887">"Висококачествено аудио"</string>
- <string name="bluetooth_profile_hearing_aid" msgid="7999237886427812595">"Слухов апарат"</string>
- <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="7188282786730266159">"Има връзка със слуховия апарат"</string>
+ <string name="bluetooth_profile_hearing_aid" msgid="6680721080542444257">"Слухови апарати"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="3051944447369418317">"Установена е връзка със слухов апарат"</string>
<string name="bluetooth_a2dp_profile_summary_connected" msgid="963376081347721598">"Установена е връзка с медийно аудио"</string>
<string name="bluetooth_headset_profile_summary_connected" msgid="7661070206715520671">"Връзка със звука на телефона"</string>
<string name="bluetooth_opp_profile_summary_connected" msgid="2611913495968309066">"Установена е връзка със сървър за трансфер на файлове"</string>
@@ -105,7 +105,7 @@
<string name="bluetooth_headset_profile_summary_use_for" msgid="8705753622443862627">"Използване на телефон за аудио"</string>
<string name="bluetooth_opp_profile_summary_use_for" msgid="1255674547144769756">"Използване на за пренос на файлове"</string>
<string name="bluetooth_hid_profile_summary_use_for" msgid="232727040453645139">"Да се използва за въвеждане"</string>
- <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="908775281788309484">"Използване за слухов апарат"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="8843499209204010224">"Използване за слухови апарати"</string>
<string name="bluetooth_pairing_accept" msgid="6163520056536604875">"Сдвояване"</string>
<string name="bluetooth_pairing_accept_all_caps" msgid="6061699265220789149">"СДВОЯВАНЕ"</string>
<string name="bluetooth_pairing_decline" msgid="4185420413578948140">"Отказ"</string>
@@ -136,6 +136,7 @@
<string name="process_kernel_label" msgid="3916858646836739323">"Android (ОС)"</string>
<string name="data_usage_uninstalled_apps" msgid="614263770923231598">"Премахнати приложения"</string>
<string name="data_usage_uninstalled_apps_users" msgid="7986294489899813194">"Премахнати приложения и потребители"</string>
+ <string name="data_usage_ota" msgid="5377889154805560860">"Системни актуализации"</string>
<string name="tether_settings_title_usb" msgid="6688416425801386511">"Тетъринг през USB"</string>
<string name="tether_settings_title_wifi" msgid="3277144155960302049">"Преносима точка за достъп"</string>
<string name="tether_settings_title_bluetooth" msgid="355855408317564420">"Тетъринг през Bluetooth"</string>
diff --git a/packages/SettingsLib/res/values-bn/strings.xml b/packages/SettingsLib/res/values-bn/strings.xml
index dbf397f..ef8dd3d 100644
--- a/packages/SettingsLib/res/values-bn/strings.xml
+++ b/packages/SettingsLib/res/values-bn/strings.xml
@@ -38,27 +38,20 @@
<string name="connected_via_network_scorer" msgid="5713793306870815341">"স্বয়ংক্রিয়ভাবে %1$s এর মাধ্যমে কানেক্ট হয়েছে"</string>
<string name="connected_via_network_scorer_default" msgid="7867260222020343104">"নেটওয়ার্কের রেটিং প্রদানকারীর মাধ্যমে অটোমেটিক কানেক্ট"</string>
<string name="connected_via_passpoint" msgid="2826205693803088747">"%1$s মাধ্যমে কানেক্ট হয়েছে"</string>
- <!-- no translation found for connected_via_app (5571999941988929520) -->
- <skip />
+ <string name="connected_via_app" msgid="5571999941988929520">"<xliff:g id="NAME">%1$s</xliff:g>-এর মাধ্যমে কানেক্ট করা আছে"</string>
<string name="available_via_passpoint" msgid="1617440946846329613">"%1$s এর মাধ্যমে উপলব্ধ"</string>
- <!-- no translation found for tap_to_sign_up (6449724763052579434) -->
- <skip />
+ <string name="tap_to_sign_up" msgid="6449724763052579434">"সাইন-আপ করতে ট্যাপ করুন"</string>
<string name="wifi_connected_no_internet" msgid="8202906332837777829">"কানেক্ট, ইন্টারনেট নেই"</string>
<string name="wifi_status_no_internet" msgid="5784710974669608361">"ইন্টারনেট কানেকশন নেই"</string>
<string name="wifi_status_sign_in_required" msgid="123517180404752756">"সাইন-ইন করা দরকার"</string>
<string name="wifi_ap_unable_to_handle_new_sta" msgid="5348824313514404541">"এই মুহূর্তে অ্যাক্সেস পয়েন্টের কোনও কানেকশন ফাঁকা নেই"</string>
<string name="connected_via_carrier" msgid="7583780074526041912">"%1$s এর মাধ্যমে কানেক্ট হয়েছে"</string>
<string name="available_via_carrier" msgid="1469036129740799053">"%1$s এর মাধ্যমে পাওয়া যাচ্ছে"</string>
- <!-- no translation found for osu_opening_provider (5488997661548640424) -->
- <skip />
- <!-- no translation found for osu_connect_failed (2187750899158158934) -->
- <skip />
- <!-- no translation found for osu_completing_sign_up (9037638564719197082) -->
- <skip />
- <!-- no translation found for osu_sign_up_failed (7296159750352873260) -->
- <skip />
- <!-- no translation found for osu_sign_up_complete (8207626049093289203) -->
- <skip />
+ <string name="osu_opening_provider" msgid="5488997661548640424">"<xliff:g id="PASSPOINTPROVIDER">%1$s</xliff:g> খোলা হচ্ছে"</string>
+ <string name="osu_connect_failed" msgid="2187750899158158934">"কানেক্ট করা যায়নি"</string>
+ <string name="osu_completing_sign_up" msgid="9037638564719197082">"সাইন-আপ সম্পূর্ণ করা হচ্ছে…"</string>
+ <string name="osu_sign_up_failed" msgid="7296159750352873260">"সাইন-আপ করা যায়নি। আবার চেষ্টা করতে ট্যাপ করুন।"</string>
+ <string name="osu_sign_up_complete" msgid="8207626049093289203">"সাইন-আপ করা হয়ে গেছে। কানেক্ট করা হচ্ছে…"</string>
<string name="speed_label_very_slow" msgid="1867055264243608530">"খুব ধীরে"</string>
<string name="speed_label_slow" msgid="813109590815810235">"ধীরে"</string>
<string name="speed_label_okay" msgid="2331665440671174858">"ঠিক আছে"</string>
@@ -94,8 +87,8 @@
<string name="bluetooth_profile_sap" msgid="5764222021851283125">"সিম -এর অ্যাক্সেস"</string>
<string name="bluetooth_profile_a2dp_high_quality" msgid="5444517801472820055">"HD অডিও: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
<string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="8510588052415438887">"HD অডিও"</string>
- <string name="bluetooth_profile_hearing_aid" msgid="7999237886427812595">"হিয়ারিং এড"</string>
- <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="7188282786730266159">"শ্রবণ যন্ত্রের সাথে কানেক্ট রয়েছে"</string>
+ <string name="bluetooth_profile_hearing_aid" msgid="6680721080542444257">"হিয়ারিং এড"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="3051944447369418317">"হিয়ারিং এডের সাথে কানেক্ট করা হয়েছে"</string>
<string name="bluetooth_a2dp_profile_summary_connected" msgid="963376081347721598">"মিডিয়া অডিওতে কানেক্ট রয়েছে"</string>
<string name="bluetooth_headset_profile_summary_connected" msgid="7661070206715520671">"ফোন অডিওতে কানেক্ট"</string>
<string name="bluetooth_opp_profile_summary_connected" msgid="2611913495968309066">"ফাইল স্থানান্তর সার্ভারের সঙ্গে কানেক্ট"</string>
@@ -112,7 +105,7 @@
<string name="bluetooth_headset_profile_summary_use_for" msgid="8705753622443862627">"ফোন অডিওয়ের জন্য ব্যবহার করুন"</string>
<string name="bluetooth_opp_profile_summary_use_for" msgid="1255674547144769756">"ফাইল স্থানান্তরের জন্য ব্যবহার করুন"</string>
<string name="bluetooth_hid_profile_summary_use_for" msgid="232727040453645139">"ইনপুটের জন্য ব্যবহার করুন"</string>
- <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="908775281788309484">"শ্রবণ যন্ত্রের জন্য ব্যবহার করুন"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="8843499209204010224">"হিয়ারিং এডের জন্য ব্যবহার করুন"</string>
<string name="bluetooth_pairing_accept" msgid="6163520056536604875">"যুক্ত করুন"</string>
<string name="bluetooth_pairing_accept_all_caps" msgid="6061699265220789149">"যুক্ত করুন"</string>
<string name="bluetooth_pairing_decline" msgid="4185420413578948140">"বাতিল করুন"</string>
@@ -143,6 +136,8 @@
<string name="process_kernel_label" msgid="3916858646836739323">"Android OS"</string>
<string name="data_usage_uninstalled_apps" msgid="614263770923231598">"সরানো অ্যাপ্লিকেশানগুলি"</string>
<string name="data_usage_uninstalled_apps_users" msgid="7986294489899813194">"সরানো অ্যাপ্লিকেশানগুলি এবং ব্যবহারকারীগণ"</string>
+ <!-- no translation found for data_usage_ota (5377889154805560860) -->
+ <skip />
<string name="tether_settings_title_usb" msgid="6688416425801386511">"USB টিথারিং"</string>
<string name="tether_settings_title_wifi" msgid="3277144155960302049">"পোর্টেবল হটস্পট"</string>
<string name="tether_settings_title_bluetooth" msgid="355855408317564420">"ব্লুটুথ টিথারিং"</string>
diff --git a/packages/SettingsLib/res/values-bs/strings.xml b/packages/SettingsLib/res/values-bs/strings.xml
index 272e797..4193d52 100644
--- a/packages/SettingsLib/res/values-bs/strings.xml
+++ b/packages/SettingsLib/res/values-bs/strings.xml
@@ -87,8 +87,8 @@
<string name="bluetooth_profile_sap" msgid="5764222021851283125">"Pristup SIM-u"</string>
<string name="bluetooth_profile_a2dp_high_quality" msgid="5444517801472820055">"HD audio: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
<string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="8510588052415438887">"HD audio"</string>
- <string name="bluetooth_profile_hearing_aid" msgid="7999237886427812595">"Slušni aparat"</string>
- <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="7188282786730266159">"Povezano na slušni aparat"</string>
+ <string name="bluetooth_profile_hearing_aid" msgid="6680721080542444257">"Slušni aparat"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="3051944447369418317">"Povezan na slušne aparate"</string>
<string name="bluetooth_a2dp_profile_summary_connected" msgid="963376081347721598">"Povezano sa zvukom medija"</string>
<string name="bluetooth_headset_profile_summary_connected" msgid="7661070206715520671">"Povezano na zvuk telefona"</string>
<string name="bluetooth_opp_profile_summary_connected" msgid="2611913495968309066">"Povezano sa serverom za prijenos podataka"</string>
@@ -105,7 +105,7 @@
<string name="bluetooth_headset_profile_summary_use_for" msgid="8705753622443862627">"Koristi za zvuk telefona"</string>
<string name="bluetooth_opp_profile_summary_use_for" msgid="1255674547144769756">"Koristi za prijenos fajlova"</string>
<string name="bluetooth_hid_profile_summary_use_for" msgid="232727040453645139">"Koristi kao ulaz"</string>
- <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="908775281788309484">"Koristi za slušni aparat"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="8843499209204010224">"Korištenje za slušne aparate"</string>
<string name="bluetooth_pairing_accept" msgid="6163520056536604875">"Upari"</string>
<string name="bluetooth_pairing_accept_all_caps" msgid="6061699265220789149">"UPARI"</string>
<string name="bluetooth_pairing_decline" msgid="4185420413578948140">"Otkaži"</string>
@@ -136,6 +136,7 @@
<string name="process_kernel_label" msgid="3916858646836739323">"Android OS"</string>
<string name="data_usage_uninstalled_apps" msgid="614263770923231598">"Uklonjene aplikacije"</string>
<string name="data_usage_uninstalled_apps_users" msgid="7986294489899813194">"Uklonjene aplikacije i korisnici"</string>
+ <string name="data_usage_ota" msgid="5377889154805560860">"Ažuriranja sistema"</string>
<string name="tether_settings_title_usb" msgid="6688416425801386511">"Povezivanje mobitela USB-om"</string>
<string name="tether_settings_title_wifi" msgid="3277144155960302049">"Prijenosna pristupna tačka"</string>
<string name="tether_settings_title_bluetooth" msgid="355855408317564420">"Dijeljenje Bluetooth veze"</string>
diff --git a/packages/SettingsLib/res/values-ca/strings.xml b/packages/SettingsLib/res/values-ca/strings.xml
index 5d2dd65..9c3e4d9 100644
--- a/packages/SettingsLib/res/values-ca/strings.xml
+++ b/packages/SettingsLib/res/values-ca/strings.xml
@@ -87,8 +87,8 @@
<string name="bluetooth_profile_sap" msgid="5764222021851283125">"Accés a la SIM"</string>
<string name="bluetooth_profile_a2dp_high_quality" msgid="5444517801472820055">"Àudio HD: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
<string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="8510588052415438887">"Àudio HD"</string>
- <string name="bluetooth_profile_hearing_aid" msgid="7999237886427812595">"Audiòfon"</string>
- <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="7188282786730266159">"S\'ha connectat a l\'audiòfon"</string>
+ <string name="bluetooth_profile_hearing_aid" msgid="6680721080542444257">"Audiòfons"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="3051944447369418317">"S\'ha connectat als audiòfons"</string>
<string name="bluetooth_a2dp_profile_summary_connected" msgid="963376081347721598">"Connectat a l\'àudio del mitjà"</string>
<string name="bluetooth_headset_profile_summary_connected" msgid="7661070206715520671">"Connectat a àudio del telèfon"</string>
<string name="bluetooth_opp_profile_summary_connected" msgid="2611913495968309066">"Connectat al servidor de transferència de fitxers"</string>
@@ -105,7 +105,7 @@
<string name="bluetooth_headset_profile_summary_use_for" msgid="8705753622443862627">"Utilitza-ho per a l\'àudio del telèfon"</string>
<string name="bluetooth_opp_profile_summary_use_for" msgid="1255674547144769756">"Utilitza per a la transferència de fitxers"</string>
<string name="bluetooth_hid_profile_summary_use_for" msgid="232727040453645139">"Utilitza per a entrada"</string>
- <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="908775281788309484">"Utilitza per a l\'audiòfon"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="8843499209204010224">"Utilitza per als audiòfons"</string>
<string name="bluetooth_pairing_accept" msgid="6163520056536604875">"Vincula"</string>
<string name="bluetooth_pairing_accept_all_caps" msgid="6061699265220789149">"VINCULA"</string>
<string name="bluetooth_pairing_decline" msgid="4185420413578948140">"Cancel·la"</string>
@@ -136,6 +136,7 @@
<string name="process_kernel_label" msgid="3916858646836739323">"Android OS"</string>
<string name="data_usage_uninstalled_apps" msgid="614263770923231598">"Aplicacions eliminades"</string>
<string name="data_usage_uninstalled_apps_users" msgid="7986294489899813194">"Aplicacions i usuaris eliminats"</string>
+ <string name="data_usage_ota" msgid="5377889154805560860">"Actualitzacions del sistema"</string>
<string name="tether_settings_title_usb" msgid="6688416425801386511">"Compartició de xarxa per USB"</string>
<string name="tether_settings_title_wifi" msgid="3277144155960302049">"Punt d\'accés Wi-Fi"</string>
<string name="tether_settings_title_bluetooth" msgid="355855408317564420">"Compartició de xarxa per Bluetooth"</string>
diff --git a/packages/SettingsLib/res/values-cs/strings.xml b/packages/SettingsLib/res/values-cs/strings.xml
index 19a042e..b6507bc 100644
--- a/packages/SettingsLib/res/values-cs/strings.xml
+++ b/packages/SettingsLib/res/values-cs/strings.xml
@@ -87,8 +87,8 @@
<string name="bluetooth_profile_sap" msgid="5764222021851283125">"Přístup k SIM kartě"</string>
<string name="bluetooth_profile_a2dp_high_quality" msgid="5444517801472820055">"HD zvuk: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
<string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="8510588052415438887">"HD zvuk"</string>
- <string name="bluetooth_profile_hearing_aid" msgid="7999237886427812595">"Naslouchátko"</string>
- <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="7188282786730266159">"Připojeno k naslouchátku"</string>
+ <string name="bluetooth_profile_hearing_aid" msgid="6680721080542444257">"Naslouchátka"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="3051944447369418317">"Připojeno k naslouchátkům"</string>
<string name="bluetooth_a2dp_profile_summary_connected" msgid="963376081347721598">"Připojeno ke zvukovému médiu"</string>
<string name="bluetooth_headset_profile_summary_connected" msgid="7661070206715520671">"Připojeno k náhlavní soupravě"</string>
<string name="bluetooth_opp_profile_summary_connected" msgid="2611913495968309066">"Připojeno k serveru pro přenos dat"</string>
@@ -105,7 +105,7 @@
<string name="bluetooth_headset_profile_summary_use_for" msgid="8705753622443862627">"Umožňuje připojení náhlavní soupravy"</string>
<string name="bluetooth_opp_profile_summary_use_for" msgid="1255674547144769756">"Použít pro přenos souborů"</string>
<string name="bluetooth_hid_profile_summary_use_for" msgid="232727040453645139">"Použít pro vstup"</string>
- <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="908775281788309484">"Použít pro naslouchátko"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="8843499209204010224">"Použít pro naslouchátka"</string>
<string name="bluetooth_pairing_accept" msgid="6163520056536604875">"Párovat"</string>
<string name="bluetooth_pairing_accept_all_caps" msgid="6061699265220789149">"PÁROVAT"</string>
<string name="bluetooth_pairing_decline" msgid="4185420413578948140">"Zrušit"</string>
@@ -136,6 +136,7 @@
<string name="process_kernel_label" msgid="3916858646836739323">"OS Android"</string>
<string name="data_usage_uninstalled_apps" msgid="614263770923231598">"Odebrané aplikace"</string>
<string name="data_usage_uninstalled_apps_users" msgid="7986294489899813194">"Odebrané aplikace a odebraní uživatelé"</string>
+ <string name="data_usage_ota" msgid="5377889154805560860">"Aktualizace systému"</string>
<string name="tether_settings_title_usb" msgid="6688416425801386511">"Připojení přes USB"</string>
<string name="tether_settings_title_wifi" msgid="3277144155960302049">"Přenosný hotspot"</string>
<string name="tether_settings_title_bluetooth" msgid="355855408317564420">"Připojení přes Bluetooth"</string>
diff --git a/packages/SettingsLib/res/values-da/strings.xml b/packages/SettingsLib/res/values-da/strings.xml
index bde67fd..a870cf8 100644
--- a/packages/SettingsLib/res/values-da/strings.xml
+++ b/packages/SettingsLib/res/values-da/strings.xml
@@ -87,8 +87,8 @@
<string name="bluetooth_profile_sap" msgid="5764222021851283125">"SIM-adgang"</string>
<string name="bluetooth_profile_a2dp_high_quality" msgid="5444517801472820055">"HD-lyd: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
<string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="8510588052415438887">"HD-lyd"</string>
- <string name="bluetooth_profile_hearing_aid" msgid="7999237886427812595">"Høreapparat"</string>
- <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="7188282786730266159">"Der er oprettet forbindelse til høreapparat"</string>
+ <string name="bluetooth_profile_hearing_aid" msgid="6680721080542444257">"Høreapparater"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="3051944447369418317">"Forbundet til høreapparater"</string>
<string name="bluetooth_a2dp_profile_summary_connected" msgid="963376081347721598">"Forbundet til medielyd"</string>
<string name="bluetooth_headset_profile_summary_connected" msgid="7661070206715520671">"Forbundet til telefonlyd"</string>
<string name="bluetooth_opp_profile_summary_connected" msgid="2611913495968309066">"Forbundet til filoverførselsserver"</string>
@@ -105,7 +105,7 @@
<string name="bluetooth_headset_profile_summary_use_for" msgid="8705753622443862627">"Brug til telefonlyd"</string>
<string name="bluetooth_opp_profile_summary_use_for" msgid="1255674547144769756">"Brug til filoverførsel"</string>
<string name="bluetooth_hid_profile_summary_use_for" msgid="232727040453645139">"Brug til input"</string>
- <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="908775281788309484">"Anvend til høreapparat"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="8843499209204010224">"Brug til høreapparater"</string>
<string name="bluetooth_pairing_accept" msgid="6163520056536604875">"Par"</string>
<string name="bluetooth_pairing_accept_all_caps" msgid="6061699265220789149">"ACCEPTÉR PARRING"</string>
<string name="bluetooth_pairing_decline" msgid="4185420413578948140">"Annuller"</string>
@@ -136,6 +136,7 @@
<string name="process_kernel_label" msgid="3916858646836739323">"Android OS"</string>
<string name="data_usage_uninstalled_apps" msgid="614263770923231598">"Fjernede apps"</string>
<string name="data_usage_uninstalled_apps_users" msgid="7986294489899813194">"Fjernede apps og brugere"</string>
+ <string name="data_usage_ota" msgid="5377889154805560860">"Systemopdateringer"</string>
<string name="tether_settings_title_usb" msgid="6688416425801386511">"Netdeling via USB"</string>
<string name="tether_settings_title_wifi" msgid="3277144155960302049">"Hotspot"</string>
<string name="tether_settings_title_bluetooth" msgid="355855408317564420">"Netdeling via Bluetooth"</string>
diff --git a/packages/SettingsLib/res/values-de/strings.xml b/packages/SettingsLib/res/values-de/strings.xml
index 543e8f8..c1d502e 100644
--- a/packages/SettingsLib/res/values-de/strings.xml
+++ b/packages/SettingsLib/res/values-de/strings.xml
@@ -87,8 +87,8 @@
<string name="bluetooth_profile_sap" msgid="5764222021851283125">"Zugriff auf SIM"</string>
<string name="bluetooth_profile_a2dp_high_quality" msgid="5444517801472820055">"HD-Audio: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
<string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="8510588052415438887">"HD-Audio"</string>
- <string name="bluetooth_profile_hearing_aid" msgid="7999237886427812595">"Hörhilfe"</string>
- <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="7188282786730266159">"Mit Hörhilfe verbunden"</string>
+ <string name="bluetooth_profile_hearing_aid" msgid="6680721080542444257">"Hörhilfen"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="3051944447369418317">"Mit Hörhilfen verbunden"</string>
<string name="bluetooth_a2dp_profile_summary_connected" msgid="963376081347721598">"Verbunden mit Medien-Audio"</string>
<string name="bluetooth_headset_profile_summary_connected" msgid="7661070206715520671">"Verbunden mit Telefon-Audio"</string>
<string name="bluetooth_opp_profile_summary_connected" msgid="2611913495968309066">"Mit Dateiübertragungsserver verbunden"</string>
@@ -105,7 +105,7 @@
<string name="bluetooth_headset_profile_summary_use_for" msgid="8705753622443862627">"Für Telefon-Audio verwenden"</string>
<string name="bluetooth_opp_profile_summary_use_for" msgid="1255674547144769756">"Für Dateiübertragung verwenden"</string>
<string name="bluetooth_hid_profile_summary_use_for" msgid="232727040453645139">"Für Eingabe verwenden"</string>
- <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="908775281788309484">"Für Hörhilfe verwenden"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="8843499209204010224">"Für Hörhilfen verwenden"</string>
<string name="bluetooth_pairing_accept" msgid="6163520056536604875">"Koppeln"</string>
<string name="bluetooth_pairing_accept_all_caps" msgid="6061699265220789149">"KOPPELN"</string>
<string name="bluetooth_pairing_decline" msgid="4185420413578948140">"Abbrechen"</string>
@@ -136,6 +136,7 @@
<string name="process_kernel_label" msgid="3916858646836739323">"Android OS"</string>
<string name="data_usage_uninstalled_apps" msgid="614263770923231598">"Entfernte Apps"</string>
<string name="data_usage_uninstalled_apps_users" msgid="7986294489899813194">"Entfernte Apps und Nutzer"</string>
+ <string name="data_usage_ota" msgid="5377889154805560860">"Systemupdates"</string>
<string name="tether_settings_title_usb" msgid="6688416425801386511">"USB-Tethering"</string>
<string name="tether_settings_title_wifi" msgid="3277144155960302049">"Mobiler Hotspot"</string>
<string name="tether_settings_title_bluetooth" msgid="355855408317564420">"Bluetooth-Tethering"</string>
diff --git a/packages/SettingsLib/res/values-el/strings.xml b/packages/SettingsLib/res/values-el/strings.xml
index f7ec12b..22c1b26 100644
--- a/packages/SettingsLib/res/values-el/strings.xml
+++ b/packages/SettingsLib/res/values-el/strings.xml
@@ -87,8 +87,8 @@
<string name="bluetooth_profile_sap" msgid="5764222021851283125">"Πρόσβαση SIM"</string>
<string name="bluetooth_profile_a2dp_high_quality" msgid="5444517801472820055">"Ήχος HD: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
<string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="8510588052415438887">"Ήχος HD"</string>
- <string name="bluetooth_profile_hearing_aid" msgid="7999237886427812595">"Βοήθημα ακοής"</string>
- <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="7188282786730266159">"Συνδέθηκε σε βοήθημα ακοής"</string>
+ <string name="bluetooth_profile_hearing_aid" msgid="6680721080542444257">"Βοηθήματα ακοής"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="3051944447369418317">"Έγινε σύνδεση σε βοηθήματα ακοής"</string>
<string name="bluetooth_a2dp_profile_summary_connected" msgid="963376081347721598">"Συνδέθηκε σε ήχο πολυμέσων"</string>
<string name="bluetooth_headset_profile_summary_connected" msgid="7661070206715520671">"Συνδεδεμένο στον ήχο τηλεφώνου"</string>
<string name="bluetooth_opp_profile_summary_connected" msgid="2611913495968309066">"Συνδεδεμένο σε διακομιστή μεταφοράς αρχείων"</string>
@@ -105,7 +105,7 @@
<string name="bluetooth_headset_profile_summary_use_for" msgid="8705753622443862627">"Χρήση για ήχο τηλεφώνου"</string>
<string name="bluetooth_opp_profile_summary_use_for" msgid="1255674547144769756">"Χρήση για τη μεταφορά αρχείων"</string>
<string name="bluetooth_hid_profile_summary_use_for" msgid="232727040453645139">"Χρήση για είσοδο"</string>
- <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="908775281788309484">"Χρήση για βοήθημα ακοής"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="8843499209204010224">"Χρήση για βοηθήματα ακοής"</string>
<string name="bluetooth_pairing_accept" msgid="6163520056536604875">"Σύζευξη"</string>
<string name="bluetooth_pairing_accept_all_caps" msgid="6061699265220789149">"ΣΥΖΕΥΞΗ"</string>
<string name="bluetooth_pairing_decline" msgid="4185420413578948140">"Ακύρωση"</string>
@@ -136,6 +136,7 @@
<string name="process_kernel_label" msgid="3916858646836739323">"Λειτουργικό σύστημα Android"</string>
<string name="data_usage_uninstalled_apps" msgid="614263770923231598">"Εφαρμογές που καταργήθηκαν"</string>
<string name="data_usage_uninstalled_apps_users" msgid="7986294489899813194">"Εφαρμογές και χρήστες που έχουν καταργηθεί"</string>
+ <string name="data_usage_ota" msgid="5377889154805560860">"Ενημερώσεις συστήματος"</string>
<string name="tether_settings_title_usb" msgid="6688416425801386511">"Πρόσδεση USB"</string>
<string name="tether_settings_title_wifi" msgid="3277144155960302049">"Φορητό σημείο πρόσβασης"</string>
<string name="tether_settings_title_bluetooth" msgid="355855408317564420">"Πρόσδεση Bluetooth"</string>
diff --git a/packages/SettingsLib/res/values-en-rAU/strings.xml b/packages/SettingsLib/res/values-en-rAU/strings.xml
index b9d3093..d4f4e5e 100644
--- a/packages/SettingsLib/res/values-en-rAU/strings.xml
+++ b/packages/SettingsLib/res/values-en-rAU/strings.xml
@@ -87,8 +87,8 @@
<string name="bluetooth_profile_sap" msgid="5764222021851283125">"SIM Access"</string>
<string name="bluetooth_profile_a2dp_high_quality" msgid="5444517801472820055">"HD audio: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
<string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="8510588052415438887">"HD audio"</string>
- <string name="bluetooth_profile_hearing_aid" msgid="7999237886427812595">"Hearing Aid"</string>
- <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="7188282786730266159">"Connected to Hearing Aid"</string>
+ <string name="bluetooth_profile_hearing_aid" msgid="6680721080542444257">"Hearing Aids"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="3051944447369418317">"Connected to Hearing Aids"</string>
<string name="bluetooth_a2dp_profile_summary_connected" msgid="963376081347721598">"Connected to media audio"</string>
<string name="bluetooth_headset_profile_summary_connected" msgid="7661070206715520671">"Connected to phone audio"</string>
<string name="bluetooth_opp_profile_summary_connected" msgid="2611913495968309066">"Connected to file-transfer server"</string>
@@ -105,7 +105,7 @@
<string name="bluetooth_headset_profile_summary_use_for" msgid="8705753622443862627">"Use for phone audio"</string>
<string name="bluetooth_opp_profile_summary_use_for" msgid="1255674547144769756">"Use for file transfer"</string>
<string name="bluetooth_hid_profile_summary_use_for" msgid="232727040453645139">"Use for input"</string>
- <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="908775281788309484">"Use for Hearing Aid"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="8843499209204010224">"Use for Hearing Aids"</string>
<string name="bluetooth_pairing_accept" msgid="6163520056536604875">"Pair"</string>
<string name="bluetooth_pairing_accept_all_caps" msgid="6061699265220789149">"PAIR"</string>
<string name="bluetooth_pairing_decline" msgid="4185420413578948140">"Cancel"</string>
@@ -136,6 +136,7 @@
<string name="process_kernel_label" msgid="3916858646836739323">"Android OS"</string>
<string name="data_usage_uninstalled_apps" msgid="614263770923231598">"Removed apps"</string>
<string name="data_usage_uninstalled_apps_users" msgid="7986294489899813194">"Removed apps and users"</string>
+ <string name="data_usage_ota" msgid="5377889154805560860">"System updates"</string>
<string name="tether_settings_title_usb" msgid="6688416425801386511">"USB tethering"</string>
<string name="tether_settings_title_wifi" msgid="3277144155960302049">"Portable hotspot"</string>
<string name="tether_settings_title_bluetooth" msgid="355855408317564420">"Bluetooth tethering"</string>
diff --git a/packages/SettingsLib/res/values-en-rCA/strings.xml b/packages/SettingsLib/res/values-en-rCA/strings.xml
index b9d3093..d4f4e5e 100644
--- a/packages/SettingsLib/res/values-en-rCA/strings.xml
+++ b/packages/SettingsLib/res/values-en-rCA/strings.xml
@@ -87,8 +87,8 @@
<string name="bluetooth_profile_sap" msgid="5764222021851283125">"SIM Access"</string>
<string name="bluetooth_profile_a2dp_high_quality" msgid="5444517801472820055">"HD audio: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
<string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="8510588052415438887">"HD audio"</string>
- <string name="bluetooth_profile_hearing_aid" msgid="7999237886427812595">"Hearing Aid"</string>
- <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="7188282786730266159">"Connected to Hearing Aid"</string>
+ <string name="bluetooth_profile_hearing_aid" msgid="6680721080542444257">"Hearing Aids"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="3051944447369418317">"Connected to Hearing Aids"</string>
<string name="bluetooth_a2dp_profile_summary_connected" msgid="963376081347721598">"Connected to media audio"</string>
<string name="bluetooth_headset_profile_summary_connected" msgid="7661070206715520671">"Connected to phone audio"</string>
<string name="bluetooth_opp_profile_summary_connected" msgid="2611913495968309066">"Connected to file-transfer server"</string>
@@ -105,7 +105,7 @@
<string name="bluetooth_headset_profile_summary_use_for" msgid="8705753622443862627">"Use for phone audio"</string>
<string name="bluetooth_opp_profile_summary_use_for" msgid="1255674547144769756">"Use for file transfer"</string>
<string name="bluetooth_hid_profile_summary_use_for" msgid="232727040453645139">"Use for input"</string>
- <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="908775281788309484">"Use for Hearing Aid"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="8843499209204010224">"Use for Hearing Aids"</string>
<string name="bluetooth_pairing_accept" msgid="6163520056536604875">"Pair"</string>
<string name="bluetooth_pairing_accept_all_caps" msgid="6061699265220789149">"PAIR"</string>
<string name="bluetooth_pairing_decline" msgid="4185420413578948140">"Cancel"</string>
@@ -136,6 +136,7 @@
<string name="process_kernel_label" msgid="3916858646836739323">"Android OS"</string>
<string name="data_usage_uninstalled_apps" msgid="614263770923231598">"Removed apps"</string>
<string name="data_usage_uninstalled_apps_users" msgid="7986294489899813194">"Removed apps and users"</string>
+ <string name="data_usage_ota" msgid="5377889154805560860">"System updates"</string>
<string name="tether_settings_title_usb" msgid="6688416425801386511">"USB tethering"</string>
<string name="tether_settings_title_wifi" msgid="3277144155960302049">"Portable hotspot"</string>
<string name="tether_settings_title_bluetooth" msgid="355855408317564420">"Bluetooth tethering"</string>
diff --git a/packages/SettingsLib/res/values-en-rGB/strings.xml b/packages/SettingsLib/res/values-en-rGB/strings.xml
index b9d3093..d4f4e5e 100644
--- a/packages/SettingsLib/res/values-en-rGB/strings.xml
+++ b/packages/SettingsLib/res/values-en-rGB/strings.xml
@@ -87,8 +87,8 @@
<string name="bluetooth_profile_sap" msgid="5764222021851283125">"SIM Access"</string>
<string name="bluetooth_profile_a2dp_high_quality" msgid="5444517801472820055">"HD audio: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
<string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="8510588052415438887">"HD audio"</string>
- <string name="bluetooth_profile_hearing_aid" msgid="7999237886427812595">"Hearing Aid"</string>
- <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="7188282786730266159">"Connected to Hearing Aid"</string>
+ <string name="bluetooth_profile_hearing_aid" msgid="6680721080542444257">"Hearing Aids"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="3051944447369418317">"Connected to Hearing Aids"</string>
<string name="bluetooth_a2dp_profile_summary_connected" msgid="963376081347721598">"Connected to media audio"</string>
<string name="bluetooth_headset_profile_summary_connected" msgid="7661070206715520671">"Connected to phone audio"</string>
<string name="bluetooth_opp_profile_summary_connected" msgid="2611913495968309066">"Connected to file-transfer server"</string>
@@ -105,7 +105,7 @@
<string name="bluetooth_headset_profile_summary_use_for" msgid="8705753622443862627">"Use for phone audio"</string>
<string name="bluetooth_opp_profile_summary_use_for" msgid="1255674547144769756">"Use for file transfer"</string>
<string name="bluetooth_hid_profile_summary_use_for" msgid="232727040453645139">"Use for input"</string>
- <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="908775281788309484">"Use for Hearing Aid"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="8843499209204010224">"Use for Hearing Aids"</string>
<string name="bluetooth_pairing_accept" msgid="6163520056536604875">"Pair"</string>
<string name="bluetooth_pairing_accept_all_caps" msgid="6061699265220789149">"PAIR"</string>
<string name="bluetooth_pairing_decline" msgid="4185420413578948140">"Cancel"</string>
@@ -136,6 +136,7 @@
<string name="process_kernel_label" msgid="3916858646836739323">"Android OS"</string>
<string name="data_usage_uninstalled_apps" msgid="614263770923231598">"Removed apps"</string>
<string name="data_usage_uninstalled_apps_users" msgid="7986294489899813194">"Removed apps and users"</string>
+ <string name="data_usage_ota" msgid="5377889154805560860">"System updates"</string>
<string name="tether_settings_title_usb" msgid="6688416425801386511">"USB tethering"</string>
<string name="tether_settings_title_wifi" msgid="3277144155960302049">"Portable hotspot"</string>
<string name="tether_settings_title_bluetooth" msgid="355855408317564420">"Bluetooth tethering"</string>
diff --git a/packages/SettingsLib/res/values-en-rIN/strings.xml b/packages/SettingsLib/res/values-en-rIN/strings.xml
index b9d3093..d4f4e5e 100644
--- a/packages/SettingsLib/res/values-en-rIN/strings.xml
+++ b/packages/SettingsLib/res/values-en-rIN/strings.xml
@@ -87,8 +87,8 @@
<string name="bluetooth_profile_sap" msgid="5764222021851283125">"SIM Access"</string>
<string name="bluetooth_profile_a2dp_high_quality" msgid="5444517801472820055">"HD audio: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
<string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="8510588052415438887">"HD audio"</string>
- <string name="bluetooth_profile_hearing_aid" msgid="7999237886427812595">"Hearing Aid"</string>
- <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="7188282786730266159">"Connected to Hearing Aid"</string>
+ <string name="bluetooth_profile_hearing_aid" msgid="6680721080542444257">"Hearing Aids"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="3051944447369418317">"Connected to Hearing Aids"</string>
<string name="bluetooth_a2dp_profile_summary_connected" msgid="963376081347721598">"Connected to media audio"</string>
<string name="bluetooth_headset_profile_summary_connected" msgid="7661070206715520671">"Connected to phone audio"</string>
<string name="bluetooth_opp_profile_summary_connected" msgid="2611913495968309066">"Connected to file-transfer server"</string>
@@ -105,7 +105,7 @@
<string name="bluetooth_headset_profile_summary_use_for" msgid="8705753622443862627">"Use for phone audio"</string>
<string name="bluetooth_opp_profile_summary_use_for" msgid="1255674547144769756">"Use for file transfer"</string>
<string name="bluetooth_hid_profile_summary_use_for" msgid="232727040453645139">"Use for input"</string>
- <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="908775281788309484">"Use for Hearing Aid"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="8843499209204010224">"Use for Hearing Aids"</string>
<string name="bluetooth_pairing_accept" msgid="6163520056536604875">"Pair"</string>
<string name="bluetooth_pairing_accept_all_caps" msgid="6061699265220789149">"PAIR"</string>
<string name="bluetooth_pairing_decline" msgid="4185420413578948140">"Cancel"</string>
@@ -136,6 +136,7 @@
<string name="process_kernel_label" msgid="3916858646836739323">"Android OS"</string>
<string name="data_usage_uninstalled_apps" msgid="614263770923231598">"Removed apps"</string>
<string name="data_usage_uninstalled_apps_users" msgid="7986294489899813194">"Removed apps and users"</string>
+ <string name="data_usage_ota" msgid="5377889154805560860">"System updates"</string>
<string name="tether_settings_title_usb" msgid="6688416425801386511">"USB tethering"</string>
<string name="tether_settings_title_wifi" msgid="3277144155960302049">"Portable hotspot"</string>
<string name="tether_settings_title_bluetooth" msgid="355855408317564420">"Bluetooth tethering"</string>
diff --git a/packages/SettingsLib/res/values-en-rXC/strings.xml b/packages/SettingsLib/res/values-en-rXC/strings.xml
index 2d3e830..98b63ee 100644
--- a/packages/SettingsLib/res/values-en-rXC/strings.xml
+++ b/packages/SettingsLib/res/values-en-rXC/strings.xml
@@ -87,8 +87,8 @@
<string name="bluetooth_profile_sap" msgid="5764222021851283125">"SIM Access"</string>
<string name="bluetooth_profile_a2dp_high_quality" msgid="5444517801472820055">"HD audio: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
<string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="8510588052415438887">"HD audio"</string>
- <string name="bluetooth_profile_hearing_aid" msgid="7999237886427812595">"Hearing Aid"</string>
- <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="7188282786730266159">"Connected to Hearing Aid"</string>
+ <string name="bluetooth_profile_hearing_aid" msgid="6680721080542444257">"Hearing Aids"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="3051944447369418317">"Connected to Hearing Aids"</string>
<string name="bluetooth_a2dp_profile_summary_connected" msgid="963376081347721598">"Connected to media audio"</string>
<string name="bluetooth_headset_profile_summary_connected" msgid="7661070206715520671">"Connected to phone audio"</string>
<string name="bluetooth_opp_profile_summary_connected" msgid="2611913495968309066">"Connected to file transfer server"</string>
@@ -105,7 +105,7 @@
<string name="bluetooth_headset_profile_summary_use_for" msgid="8705753622443862627">"Use for phone audio"</string>
<string name="bluetooth_opp_profile_summary_use_for" msgid="1255674547144769756">"Use for file transfer"</string>
<string name="bluetooth_hid_profile_summary_use_for" msgid="232727040453645139">"Use for input"</string>
- <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="908775281788309484">"Use for Hearing Aid"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="8843499209204010224">"Use for Hearing Aids"</string>
<string name="bluetooth_pairing_accept" msgid="6163520056536604875">"Pair"</string>
<string name="bluetooth_pairing_accept_all_caps" msgid="6061699265220789149">"PAIR"</string>
<string name="bluetooth_pairing_decline" msgid="4185420413578948140">"Cancel"</string>
@@ -136,6 +136,7 @@
<string name="process_kernel_label" msgid="3916858646836739323">"Android OS"</string>
<string name="data_usage_uninstalled_apps" msgid="614263770923231598">"Removed apps"</string>
<string name="data_usage_uninstalled_apps_users" msgid="7986294489899813194">"Removed apps and users"</string>
+ <string name="data_usage_ota" msgid="5377889154805560860">"System updates"</string>
<string name="tether_settings_title_usb" msgid="6688416425801386511">"USB tethering"</string>
<string name="tether_settings_title_wifi" msgid="3277144155960302049">"Portable hotspot"</string>
<string name="tether_settings_title_bluetooth" msgid="355855408317564420">"Bluetooth tethering"</string>
diff --git a/packages/SettingsLib/res/values-es-rUS/strings.xml b/packages/SettingsLib/res/values-es-rUS/strings.xml
index 00f85e6..e803abd 100644
--- a/packages/SettingsLib/res/values-es-rUS/strings.xml
+++ b/packages/SettingsLib/res/values-es-rUS/strings.xml
@@ -87,8 +87,8 @@
<string name="bluetooth_profile_sap" msgid="5764222021851283125">"Acceso SIM"</string>
<string name="bluetooth_profile_a2dp_high_quality" msgid="5444517801472820055">"Audio en HD: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
<string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="8510588052415438887">"Audio en HD"</string>
- <string name="bluetooth_profile_hearing_aid" msgid="7999237886427812595">"Audífonos"</string>
- <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="7188282786730266159">"Conectado a un audífono"</string>
+ <string name="bluetooth_profile_hearing_aid" msgid="6680721080542444257">"Audífonos"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="3051944447369418317">"Conectado a audífonos"</string>
<string name="bluetooth_a2dp_profile_summary_connected" msgid="963376081347721598">"Conectado al audio multimedia"</string>
<string name="bluetooth_headset_profile_summary_connected" msgid="7661070206715520671">"Conectado al audio del dispositivo"</string>
<string name="bluetooth_opp_profile_summary_connected" msgid="2611913495968309066">"Conectado al servidor de transferencia de archivo"</string>
@@ -105,7 +105,7 @@
<string name="bluetooth_headset_profile_summary_use_for" msgid="8705753622443862627">"Utilizar para el audio del dispositivo"</string>
<string name="bluetooth_opp_profile_summary_use_for" msgid="1255674547144769756">"Utilizar para la transferencia de archivos"</string>
<string name="bluetooth_hid_profile_summary_use_for" msgid="232727040453645139">"Utilizar para entrada"</string>
- <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="908775281788309484">"Usar con audífonos"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="8843499209204010224">"Usar para audífonos"</string>
<string name="bluetooth_pairing_accept" msgid="6163520056536604875">"Vincular"</string>
<string name="bluetooth_pairing_accept_all_caps" msgid="6061699265220789149">"SINCRONIZAR"</string>
<string name="bluetooth_pairing_decline" msgid="4185420413578948140">"Cancelar"</string>
@@ -136,6 +136,7 @@
<string name="process_kernel_label" msgid="3916858646836739323">"SO Android"</string>
<string name="data_usage_uninstalled_apps" msgid="614263770923231598">"Aplicaciones eliminadas"</string>
<string name="data_usage_uninstalled_apps_users" msgid="7986294489899813194">"Aplicaciones y usuarios eliminados"</string>
+ <string name="data_usage_ota" msgid="5377889154805560860">"Actualizaciones del sistema"</string>
<string name="tether_settings_title_usb" msgid="6688416425801386511">"Conexión mediante USB"</string>
<string name="tether_settings_title_wifi" msgid="3277144155960302049">"Hotspot portátil"</string>
<string name="tether_settings_title_bluetooth" msgid="355855408317564420">"Conexión mediante Bluetooth"</string>
diff --git a/packages/SettingsLib/res/values-es/strings.xml b/packages/SettingsLib/res/values-es/strings.xml
index b21b7d1..293eff1 100644
--- a/packages/SettingsLib/res/values-es/strings.xml
+++ b/packages/SettingsLib/res/values-es/strings.xml
@@ -87,8 +87,8 @@
<string name="bluetooth_profile_sap" msgid="5764222021851283125">"Acceso a tarjeta SIM"</string>
<string name="bluetooth_profile_a2dp_high_quality" msgid="5444517801472820055">"Audio HD: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
<string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="8510588052415438887">"Audio HD"</string>
- <string name="bluetooth_profile_hearing_aid" msgid="7999237886427812595">"Audífonos"</string>
- <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="7188282786730266159">"Conectado a audífono"</string>
+ <string name="bluetooth_profile_hearing_aid" msgid="6680721080542444257">"Audífonos"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="3051944447369418317">"Conectado a audífonos"</string>
<string name="bluetooth_a2dp_profile_summary_connected" msgid="963376081347721598">"Conectado al audio del medio"</string>
<string name="bluetooth_headset_profile_summary_connected" msgid="7661070206715520671">"Conectado al audio del teléfono"</string>
<string name="bluetooth_opp_profile_summary_connected" msgid="2611913495968309066">"Conectado con el servidor de transferencia de archivos"</string>
@@ -105,7 +105,7 @@
<string name="bluetooth_headset_profile_summary_use_for" msgid="8705753622443862627">"Utilizar para audio del teléfono"</string>
<string name="bluetooth_opp_profile_summary_use_for" msgid="1255674547144769756">"Uso de la transferencia de archivos"</string>
<string name="bluetooth_hid_profile_summary_use_for" msgid="232727040453645139">"Usar para entrada"</string>
- <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="908775281788309484">"Usar con audífonos"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="8843499209204010224">"Usar con audífonos"</string>
<string name="bluetooth_pairing_accept" msgid="6163520056536604875">"Vincular"</string>
<string name="bluetooth_pairing_accept_all_caps" msgid="6061699265220789149">"VINCULAR"</string>
<string name="bluetooth_pairing_decline" msgid="4185420413578948140">"Cancelar"</string>
@@ -136,6 +136,7 @@
<string name="process_kernel_label" msgid="3916858646836739323">"SO Android"</string>
<string name="data_usage_uninstalled_apps" msgid="614263770923231598">"Aplicaciones eliminadas"</string>
<string name="data_usage_uninstalled_apps_users" msgid="7986294489899813194">"Usuarios y aplicaciones eliminados"</string>
+ <string name="data_usage_ota" msgid="5377889154805560860">"Actualizaciones del sistema"</string>
<string name="tether_settings_title_usb" msgid="6688416425801386511">"Compartir conexión por USB"</string>
<string name="tether_settings_title_wifi" msgid="3277144155960302049">"Zona Wi-Fi portátil"</string>
<string name="tether_settings_title_bluetooth" msgid="355855408317564420">"Compartir conexión por Bluetooth"</string>
diff --git a/packages/SettingsLib/res/values-et/strings.xml b/packages/SettingsLib/res/values-et/strings.xml
index fab1375..14ac827 100644
--- a/packages/SettingsLib/res/values-et/strings.xml
+++ b/packages/SettingsLib/res/values-et/strings.xml
@@ -87,8 +87,8 @@
<string name="bluetooth_profile_sap" msgid="5764222021851283125">"SIM-kaardi juurdepääs"</string>
<string name="bluetooth_profile_a2dp_high_quality" msgid="5444517801472820055">"HD-heli: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
<string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="8510588052415438887">"HD-heli"</string>
- <string name="bluetooth_profile_hearing_aid" msgid="7999237886427812595">"Kuuldeaparaat"</string>
- <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="7188282786730266159">"Kuuldeaparaadiga ühendatud"</string>
+ <string name="bluetooth_profile_hearing_aid" msgid="6680721080542444257">"Kuuldeaparaadid"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="3051944447369418317">"Kuuldeaparaatidega ühendatud"</string>
<string name="bluetooth_a2dp_profile_summary_connected" msgid="963376081347721598">"Ühendatud meediumiheliga"</string>
<string name="bluetooth_headset_profile_summary_connected" msgid="7661070206715520671">"Ühendatud telefoniheliga"</string>
<string name="bluetooth_opp_profile_summary_connected" msgid="2611913495968309066">"Ühendatud failiedastuse serveriga"</string>
@@ -105,7 +105,7 @@
<string name="bluetooth_headset_profile_summary_use_for" msgid="8705753622443862627">"Kasuta telefoniheli jaoks"</string>
<string name="bluetooth_opp_profile_summary_use_for" msgid="1255674547144769756">"Kasutage failide edastamiseks"</string>
<string name="bluetooth_hid_profile_summary_use_for" msgid="232727040453645139">"Kasutage sisendi jaoks"</string>
- <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="908775281788309484">"Kuuldeaparaadiga kasutamiseks"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="8843499209204010224">"Kasuta kuulmisaparaatide puhul"</string>
<string name="bluetooth_pairing_accept" msgid="6163520056536604875">"Seo"</string>
<string name="bluetooth_pairing_accept_all_caps" msgid="6061699265220789149">"SEO"</string>
<string name="bluetooth_pairing_decline" msgid="4185420413578948140">"Tühista"</string>
@@ -136,6 +136,7 @@
<string name="process_kernel_label" msgid="3916858646836739323">"Android OS"</string>
<string name="data_usage_uninstalled_apps" msgid="614263770923231598">"Eemaldatud rakendused"</string>
<string name="data_usage_uninstalled_apps_users" msgid="7986294489899813194">"Eemaldatud rakendused ja kasutajad"</string>
+ <string name="data_usage_ota" msgid="5377889154805560860">"Süsteemivärskendused"</string>
<string name="tether_settings_title_usb" msgid="6688416425801386511">"USB jagamine"</string>
<string name="tether_settings_title_wifi" msgid="3277144155960302049">"Mobiilne kuumkoht"</string>
<string name="tether_settings_title_bluetooth" msgid="355855408317564420">"Jagamine Bluetoothiga"</string>
diff --git a/packages/SettingsLib/res/values-eu/strings.xml b/packages/SettingsLib/res/values-eu/strings.xml
index 7d3e1f3..04710c7 100644
--- a/packages/SettingsLib/res/values-eu/strings.xml
+++ b/packages/SettingsLib/res/values-eu/strings.xml
@@ -87,8 +87,8 @@
<string name="bluetooth_profile_sap" msgid="5764222021851283125">"SIM txartelerako sarbidea"</string>
<string name="bluetooth_profile_a2dp_high_quality" msgid="5444517801472820055">"Kalitate handiko audioa: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
<string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="8510588052415438887">"Kalitate handiko audioa"</string>
- <string name="bluetooth_profile_hearing_aid" msgid="7999237886427812595">"Audiofonoa"</string>
- <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="7188282786730266159">"Audiofonora konektatuta"</string>
+ <string name="bluetooth_profile_hearing_aid" msgid="6680721080542444257">"Audifonoak"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="3051944447369418317">"Audifonoetara konektatuta"</string>
<string name="bluetooth_a2dp_profile_summary_connected" msgid="963376081347721598">"Euskarriaren audiora konektatuta"</string>
<string name="bluetooth_headset_profile_summary_connected" msgid="7661070206715520671">"Telefonoaren audiora konektatuta"</string>
<string name="bluetooth_opp_profile_summary_connected" msgid="2611913495968309066">"Fitxategi-transferentziako zerbitzarira konektatuta"</string>
@@ -105,7 +105,7 @@
<string name="bluetooth_headset_profile_summary_use_for" msgid="8705753622443862627">"Erabili telefonoaren audiorako"</string>
<string name="bluetooth_opp_profile_summary_use_for" msgid="1255674547144769756">"Erabili fitxategi-transferentziarako"</string>
<string name="bluetooth_hid_profile_summary_use_for" msgid="232727040453645139">"Erabili idazketarako"</string>
- <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="908775281788309484">"Erabili audiofonorako"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="8843499209204010224">"Erabili audifonoak"</string>
<string name="bluetooth_pairing_accept" msgid="6163520056536604875">"Parekatu"</string>
<string name="bluetooth_pairing_accept_all_caps" msgid="6061699265220789149">"PAREKATU"</string>
<string name="bluetooth_pairing_decline" msgid="4185420413578948140">"Utzi"</string>
@@ -121,8 +121,8 @@
<string name="bluetooth_talkback_headphone" msgid="26580326066627664">"Aurikularra"</string>
<string name="bluetooth_talkback_input_peripheral" msgid="5165842622743212268">"Idazteko gailua"</string>
<string name="bluetooth_talkback_bluetooth" msgid="5615463912185280812">"Bluetooth gailua"</string>
- <string name="bluetooth_hearingaid_left_pairing_message" msgid="7378813500862148102">"Ezkerreko audiofonoa parekatzen…"</string>
- <string name="bluetooth_hearingaid_right_pairing_message" msgid="1550373802309160891">"Eskuineko audiofonoa parekatzen…"</string>
+ <string name="bluetooth_hearingaid_left_pairing_message" msgid="7378813500862148102">"Ezkerreko audifonoa parekatzen…"</string>
+ <string name="bluetooth_hearingaid_right_pairing_message" msgid="1550373802309160891">"Eskuineko audifonoa parekatzen…"</string>
<string name="bluetooth_hearingaid_left_battery_level" msgid="8797811465352097562">"Ezkerrekoa. Bateria: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
<string name="bluetooth_hearingaid_right_battery_level" msgid="7309476148173459677">"Eskuinekoa. Bateria: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
<string name="accessibility_wifi_off" msgid="1166761729660614716">"Desaktibatuta dago Wi-Fi konexioa."</string>
@@ -136,6 +136,7 @@
<string name="process_kernel_label" msgid="3916858646836739323">"Android sistema eragilea"</string>
<string name="data_usage_uninstalled_apps" msgid="614263770923231598">"Kendutako aplikazioak"</string>
<string name="data_usage_uninstalled_apps_users" msgid="7986294489899813194">"Kendutako aplikazioak eta erabiltzaileak"</string>
+ <string name="data_usage_ota" msgid="5377889154805560860">"Sistemaren eguneratzeak"</string>
<string name="tether_settings_title_usb" msgid="6688416425801386511">"Konexioa partekatzea (USB)"</string>
<string name="tether_settings_title_wifi" msgid="3277144155960302049">"Sare publiko eramangarria"</string>
<string name="tether_settings_title_bluetooth" msgid="355855408317564420">"Konexioa partekatzea (Bluetooth)"</string>
diff --git a/packages/SettingsLib/res/values-fa/strings.xml b/packages/SettingsLib/res/values-fa/strings.xml
index 293c463..8f55092 100644
--- a/packages/SettingsLib/res/values-fa/strings.xml
+++ b/packages/SettingsLib/res/values-fa/strings.xml
@@ -87,8 +87,8 @@
<string name="bluetooth_profile_sap" msgid="5764222021851283125">"دسترسی سیمکارت"</string>
<string name="bluetooth_profile_a2dp_high_quality" msgid="5444517801472820055">"صدای HD: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
<string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="8510588052415438887">"صدای HD"</string>
- <string name="bluetooth_profile_hearing_aid" msgid="7999237886427812595">"سمعک"</string>
- <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="7188282786730266159">"متصل به سمعک"</string>
+ <string name="bluetooth_profile_hearing_aid" msgid="6680721080542444257">"سمعکها"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="3051944447369418317">"متصل به سمعکها"</string>
<string name="bluetooth_a2dp_profile_summary_connected" msgid="963376081347721598">"به رسانه صوتی متصل شد"</string>
<string name="bluetooth_headset_profile_summary_connected" msgid="7661070206715520671">"به تلفن صوتی متصل شد"</string>
<string name="bluetooth_opp_profile_summary_connected" msgid="2611913495968309066">"به سرور انتقال فایل متصل شد"</string>
@@ -105,7 +105,7 @@
<string name="bluetooth_headset_profile_summary_use_for" msgid="8705753622443862627">"استفاده برای تلفن صوتی"</string>
<string name="bluetooth_opp_profile_summary_use_for" msgid="1255674547144769756">"استفاده برای انتقال فایل"</string>
<string name="bluetooth_hid_profile_summary_use_for" msgid="232727040453645139">"استفاده برای چاپ"</string>
- <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="908775281788309484">"استفاده برای سمعک"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="8843499209204010224">"استفاده برای سمعکها"</string>
<string name="bluetooth_pairing_accept" msgid="6163520056536604875">"مرتبطسازی"</string>
<string name="bluetooth_pairing_accept_all_caps" msgid="6061699265220789149">"مرتبطسازی"</string>
<string name="bluetooth_pairing_decline" msgid="4185420413578948140">"لغو"</string>
@@ -136,6 +136,7 @@
<string name="process_kernel_label" msgid="3916858646836739323">"سیستم عامل Android"</string>
<string name="data_usage_uninstalled_apps" msgid="614263770923231598">"برنامههای حذف شده"</string>
<string name="data_usage_uninstalled_apps_users" msgid="7986294489899813194">"برنامهها و کاربران حذف شده"</string>
+ <string name="data_usage_ota" msgid="5377889154805560860">"بهروزرسانیهای سیستم"</string>
<string name="tether_settings_title_usb" msgid="6688416425801386511">"اتصال داده با سیم USB"</string>
<string name="tether_settings_title_wifi" msgid="3277144155960302049">"نقطه اتصال قابل حمل"</string>
<string name="tether_settings_title_bluetooth" msgid="355855408317564420">"اتصال اینترنت با تلفن همراه بلوتوث"</string>
diff --git a/packages/SettingsLib/res/values-fi/strings.xml b/packages/SettingsLib/res/values-fi/strings.xml
index f335eb9..5802a03 100644
--- a/packages/SettingsLib/res/values-fi/strings.xml
+++ b/packages/SettingsLib/res/values-fi/strings.xml
@@ -87,8 +87,8 @@
<string name="bluetooth_profile_sap" msgid="5764222021851283125">"SIM-kortin käyttö"</string>
<string name="bluetooth_profile_a2dp_high_quality" msgid="5444517801472820055">"HD-ääni: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
<string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="8510588052415438887">"HD-ääni"</string>
- <string name="bluetooth_profile_hearing_aid" msgid="7999237886427812595">"Kuulolaite"</string>
- <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="7188282786730266159">"Kuulolaite yhdistetty"</string>
+ <string name="bluetooth_profile_hearing_aid" msgid="6680721080542444257">"Kuulolaitteet"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="3051944447369418317">"Yhdistetty kuulolaitteisiin"</string>
<string name="bluetooth_a2dp_profile_summary_connected" msgid="963376081347721598">"Yhdistetty median ääneen"</string>
<string name="bluetooth_headset_profile_summary_connected" msgid="7661070206715520671">"Yhdistetty puhelimen ääneen"</string>
<string name="bluetooth_opp_profile_summary_connected" msgid="2611913495968309066">"Yhdistetty tiedostonsiirtopalvelimeen"</string>
@@ -105,7 +105,7 @@
<string name="bluetooth_headset_profile_summary_use_for" msgid="8705753622443862627">"Käytä puhelimen äänille"</string>
<string name="bluetooth_opp_profile_summary_use_for" msgid="1255674547144769756">"Käytä tiedostojen siirtoon"</string>
<string name="bluetooth_hid_profile_summary_use_for" msgid="232727040453645139">"Käytä syöttöön"</string>
- <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="908775281788309484">"Käytä kuulolaitteen kanssa"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="8843499209204010224">"Käytä kuulolaitteilla"</string>
<string name="bluetooth_pairing_accept" msgid="6163520056536604875">"Muodosta laitepari"</string>
<string name="bluetooth_pairing_accept_all_caps" msgid="6061699265220789149">"MUODOSTA LAITEPARI"</string>
<string name="bluetooth_pairing_decline" msgid="4185420413578948140">"Peruuta"</string>
@@ -136,6 +136,7 @@
<string name="process_kernel_label" msgid="3916858646836739323">"Android-käyttöjärjestelmä"</string>
<string name="data_usage_uninstalled_apps" msgid="614263770923231598">"Poistetut sovellukset"</string>
<string name="data_usage_uninstalled_apps_users" msgid="7986294489899813194">"Poistetut sovellukset ja käyttäjät"</string>
+ <string name="data_usage_ota" msgid="5377889154805560860">"Järjestelmäpäivitykset"</string>
<string name="tether_settings_title_usb" msgid="6688416425801386511">"Jaettu yhteys USB:n kautta"</string>
<string name="tether_settings_title_wifi" msgid="3277144155960302049">"Kannettava yhteyspiste"</string>
<string name="tether_settings_title_bluetooth" msgid="355855408317564420">"Jaettu Bluetooth-yhteys"</string>
diff --git a/packages/SettingsLib/res/values-fr-rCA/strings.xml b/packages/SettingsLib/res/values-fr-rCA/strings.xml
index 4959103..ec8d6b0 100644
--- a/packages/SettingsLib/res/values-fr-rCA/strings.xml
+++ b/packages/SettingsLib/res/values-fr-rCA/strings.xml
@@ -87,8 +87,8 @@
<string name="bluetooth_profile_sap" msgid="5764222021851283125">"Accès à la carte SIM"</string>
<string name="bluetooth_profile_a2dp_high_quality" msgid="5444517801472820055">"Audio HD : <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
<string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="8510588052415438887">"Audio HD"</string>
- <string name="bluetooth_profile_hearing_aid" msgid="7999237886427812595">"Prothèse auditive"</string>
- <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="7188282786730266159">"Connecté à la prothèse auditive"</string>
+ <string name="bluetooth_profile_hearing_aid" msgid="6680721080542444257">"Prothèses auditives"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="3051944447369418317">"Connecté aux prothèses auditives"</string>
<string name="bluetooth_a2dp_profile_summary_connected" msgid="963376081347721598">"Connecté aux paramètres audio du média"</string>
<string name="bluetooth_headset_profile_summary_connected" msgid="7661070206715520671">"Connecté à l\'audio du téléphone"</string>
<string name="bluetooth_opp_profile_summary_connected" msgid="2611913495968309066">"Connexion au serveur de transfert de fichiers"</string>
@@ -105,7 +105,7 @@
<string name="bluetooth_headset_profile_summary_use_for" msgid="8705753622443862627">"Utiliser pour les paramètres audio du téléphone"</string>
<string name="bluetooth_opp_profile_summary_use_for" msgid="1255674547144769756">"Utiliser pour le transfert de fichiers"</string>
<string name="bluetooth_hid_profile_summary_use_for" msgid="232727040453645139">"Utiliser comme entrée"</string>
- <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="908775281788309484">"Utiliser avec la prothèse auditive"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="8843499209204010224">"Utiliser avec les prothèses auditives"</string>
<string name="bluetooth_pairing_accept" msgid="6163520056536604875">"Associer"</string>
<string name="bluetooth_pairing_accept_all_caps" msgid="6061699265220789149">"ASSOCIER"</string>
<string name="bluetooth_pairing_decline" msgid="4185420413578948140">"Annuler"</string>
@@ -136,6 +136,7 @@
<string name="process_kernel_label" msgid="3916858646836739323">"Système d\'exploitation Android"</string>
<string name="data_usage_uninstalled_apps" msgid="614263770923231598">"Applications supprimées"</string>
<string name="data_usage_uninstalled_apps_users" msgid="7986294489899813194">"Applications et utilisateurs supprimés"</string>
+ <string name="data_usage_ota" msgid="5377889154805560860">"Mises à jour système"</string>
<string name="tether_settings_title_usb" msgid="6688416425801386511">"Partage de connexion par USB"</string>
<string name="tether_settings_title_wifi" msgid="3277144155960302049">"Point d\'accès Wi-Fi mobile"</string>
<string name="tether_settings_title_bluetooth" msgid="355855408317564420">"Partage connexion Bluetooth"</string>
diff --git a/packages/SettingsLib/res/values-fr/strings.xml b/packages/SettingsLib/res/values-fr/strings.xml
index 1f071de..0b620d8 100644
--- a/packages/SettingsLib/res/values-fr/strings.xml
+++ b/packages/SettingsLib/res/values-fr/strings.xml
@@ -87,8 +87,8 @@
<string name="bluetooth_profile_sap" msgid="5764222021851283125">"Accès à la carte SIM"</string>
<string name="bluetooth_profile_a2dp_high_quality" msgid="5444517801472820055">"Audio HD : <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
<string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="8510588052415438887">"Audio HD"</string>
- <string name="bluetooth_profile_hearing_aid" msgid="7999237886427812595">"Assistance auditive"</string>
- <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="7188282786730266159">"Connecté à la prothèse auditive"</string>
+ <string name="bluetooth_profile_hearing_aid" msgid="6680721080542444257">"Appareils auditifs"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="3051944447369418317">"Connexion établie avec les appareils auditifs"</string>
<string name="bluetooth_a2dp_profile_summary_connected" msgid="963376081347721598">"Connecté aux paramètres audio du média"</string>
<string name="bluetooth_headset_profile_summary_connected" msgid="7661070206715520671">"Connecté aux paramètres audio du téléphone"</string>
<string name="bluetooth_opp_profile_summary_connected" msgid="2611913495968309066">"Connexion au serveur de transfert de fichiers"</string>
@@ -105,7 +105,7 @@
<string name="bluetooth_headset_profile_summary_use_for" msgid="8705753622443862627">"Utiliser pour les paramètres audio du téléphone"</string>
<string name="bluetooth_opp_profile_summary_use_for" msgid="1255674547144769756">"Utiliser pour le transfert de fichiers"</string>
<string name="bluetooth_hid_profile_summary_use_for" msgid="232727040453645139">"Utiliser comme entrée"</string>
- <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="908775281788309484">"Utiliser pour l\'assistance auditive"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="8843499209204010224">"Utiliser pour les appareils auditifs"</string>
<string name="bluetooth_pairing_accept" msgid="6163520056536604875">"Associer"</string>
<string name="bluetooth_pairing_accept_all_caps" msgid="6061699265220789149">"ASSOCIER"</string>
<string name="bluetooth_pairing_decline" msgid="4185420413578948140">"Annuler"</string>
@@ -136,6 +136,7 @@
<string name="process_kernel_label" msgid="3916858646836739323">"Plate-forme Android"</string>
<string name="data_usage_uninstalled_apps" msgid="614263770923231598">"Applications supprimées"</string>
<string name="data_usage_uninstalled_apps_users" msgid="7986294489899813194">"Applications et utilisateurs supprimés"</string>
+ <string name="data_usage_ota" msgid="5377889154805560860">"Mises à jour du système"</string>
<string name="tether_settings_title_usb" msgid="6688416425801386511">"Partage connexion Bluetooth par USB"</string>
<string name="tether_settings_title_wifi" msgid="3277144155960302049">"Point d\'accès Wi-Fi mobile"</string>
<string name="tether_settings_title_bluetooth" msgid="355855408317564420">"Partage connexion Bluetooth"</string>
diff --git a/packages/SettingsLib/res/values-gl/strings.xml b/packages/SettingsLib/res/values-gl/strings.xml
index 06faf00..b4d7fcb 100644
--- a/packages/SettingsLib/res/values-gl/strings.xml
+++ b/packages/SettingsLib/res/values-gl/strings.xml
@@ -87,8 +87,8 @@
<string name="bluetooth_profile_sap" msgid="5764222021851283125">"Acceso á SIM"</string>
<string name="bluetooth_profile_a2dp_high_quality" msgid="5444517801472820055">"Audio en HD: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
<string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="8510588052415438887">"Audio en HD"</string>
- <string name="bluetooth_profile_hearing_aid" msgid="7999237886427812595">"Audiófonos"</string>
- <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="7188282786730266159">"Conectouse ao audiófono"</string>
+ <string name="bluetooth_profile_hearing_aid" msgid="6680721080542444257">"Audiófonos"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="3051944447369418317">"Conectado a audiófonos"</string>
<string name="bluetooth_a2dp_profile_summary_connected" msgid="963376081347721598">"Conectado ao audio multimedia"</string>
<string name="bluetooth_headset_profile_summary_connected" msgid="7661070206715520671">"Conectado ao audio do teléfono"</string>
<string name="bluetooth_opp_profile_summary_connected" msgid="2611913495968309066">"Conectado ao servidor de transferencia de ficheiros"</string>
@@ -105,7 +105,7 @@
<string name="bluetooth_headset_profile_summary_use_for" msgid="8705753622443862627">"Utilízase para o audio do teléfono"</string>
<string name="bluetooth_opp_profile_summary_use_for" msgid="1255674547144769756">"Utilízase para a transferencia de ficheiros"</string>
<string name="bluetooth_hid_profile_summary_use_for" msgid="232727040453645139">"Utilízase para a entrada"</string>
- <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="908775281788309484">"Usar con audiófonos"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="8843499209204010224">"Utilizar para audiófonos"</string>
<string name="bluetooth_pairing_accept" msgid="6163520056536604875">"Sincronizar"</string>
<string name="bluetooth_pairing_accept_all_caps" msgid="6061699265220789149">"SINCRONIZAR"</string>
<string name="bluetooth_pairing_decline" msgid="4185420413578948140">"Cancelar"</string>
@@ -136,6 +136,7 @@
<string name="process_kernel_label" msgid="3916858646836739323">"SO Android"</string>
<string name="data_usage_uninstalled_apps" msgid="614263770923231598">"Aplicacións eliminadas"</string>
<string name="data_usage_uninstalled_apps_users" msgid="7986294489899813194">"Aplicacións e usuarios eliminados"</string>
+ <string name="data_usage_ota" msgid="5377889154805560860">"Actualizacións do sistema"</string>
<string name="tether_settings_title_usb" msgid="6688416425801386511">"Conexión compart. por USB"</string>
<string name="tether_settings_title_wifi" msgid="3277144155960302049">"Zona wifi portátil"</string>
<string name="tether_settings_title_bluetooth" msgid="355855408317564420">"Conexión por Bluetooth"</string>
diff --git a/packages/SettingsLib/res/values-gu/strings.xml b/packages/SettingsLib/res/values-gu/strings.xml
index 232dea9..97b9036 100644
--- a/packages/SettingsLib/res/values-gu/strings.xml
+++ b/packages/SettingsLib/res/values-gu/strings.xml
@@ -87,8 +87,8 @@
<string name="bluetooth_profile_sap" msgid="5764222021851283125">"સિમ ઍક્સેસ"</string>
<string name="bluetooth_profile_a2dp_high_quality" msgid="5444517801472820055">"HD ઑડિઓ: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
<string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="8510588052415438887">"HD ઑડિઓ"</string>
- <string name="bluetooth_profile_hearing_aid" msgid="7999237886427812595">"સાંભળવામાં સહાય આપતું યંત્ર"</string>
- <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="7188282786730266159">"સાંભળવામાં સહાય આપતા યંત્ર સાથે કનેક્ટ કરેલ"</string>
+ <string name="bluetooth_profile_hearing_aid" msgid="6680721080542444257">"શ્રવણ યંત્રો"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="3051944447369418317">"શ્રવણ યંત્રો સાથે કનેક્ટ કરેલું છે"</string>
<string name="bluetooth_a2dp_profile_summary_connected" msgid="963376081347721598">"મીડિયા ઑડિઓ સાથે કનેક્ટ કર્યુ"</string>
<string name="bluetooth_headset_profile_summary_connected" msgid="7661070206715520671">"ફોન ઑડિઓ સાથે કનેક્ટ થયાં"</string>
<string name="bluetooth_opp_profile_summary_connected" msgid="2611913495968309066">"ફાઇલ સ્થાનાંતરણ સેવાથી કનેક્ટ થયાં"</string>
@@ -105,7 +105,7 @@
<string name="bluetooth_headset_profile_summary_use_for" msgid="8705753622443862627">"ફોન ઑડિઓ માટે ઉપયોગ કરો"</string>
<string name="bluetooth_opp_profile_summary_use_for" msgid="1255674547144769756">"ફાઇલ સ્થાનાંતર માટે ઉપયોગ કરો"</string>
<string name="bluetooth_hid_profile_summary_use_for" msgid="232727040453645139">"ઇનપુટ માટે ઉપયોગ કરો"</string>
- <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="908775281788309484">"સાંભળવામાં સહાય આપતા યંત્ર માટે ઉપયોગ કરો"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="8843499209204010224">"શ્રવણ યંત્રો માટે ઉપયોગ કરો"</string>
<string name="bluetooth_pairing_accept" msgid="6163520056536604875">"જોડી"</string>
<string name="bluetooth_pairing_accept_all_caps" msgid="6061699265220789149">"જોડાણ બનાવો"</string>
<string name="bluetooth_pairing_decline" msgid="4185420413578948140">"રદ કરો"</string>
@@ -136,6 +136,8 @@
<string name="process_kernel_label" msgid="3916858646836739323">"Android OS"</string>
<string name="data_usage_uninstalled_apps" msgid="614263770923231598">"દૂર કરેલી ઍપ્લિકેશનો"</string>
<string name="data_usage_uninstalled_apps_users" msgid="7986294489899813194">"દૂર કરેલી ઍપ્લિકેશનો અને વપરાશકર્તાઓ"</string>
+ <!-- no translation found for data_usage_ota (5377889154805560860) -->
+ <skip />
<string name="tether_settings_title_usb" msgid="6688416425801386511">"USB ટિથરિંગ"</string>
<string name="tether_settings_title_wifi" msgid="3277144155960302049">"પોર્ટેબલ હૉટસ્પૉટ"</string>
<string name="tether_settings_title_bluetooth" msgid="355855408317564420">"બ્લૂટૂથ ટિથરિંગ"</string>
diff --git a/packages/SettingsLib/res/values-hi/strings.xml b/packages/SettingsLib/res/values-hi/strings.xml
index 2f03eb1..8b1ca93 100644
--- a/packages/SettingsLib/res/values-hi/strings.xml
+++ b/packages/SettingsLib/res/values-hi/strings.xml
@@ -87,8 +87,8 @@
<string name="bluetooth_profile_sap" msgid="5764222021851283125">"सिम ऐक्सेस"</string>
<string name="bluetooth_profile_a2dp_high_quality" msgid="5444517801472820055">"HD ऑडियो: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
<string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="8510588052415438887">"HD ऑडियो"</string>
- <string name="bluetooth_profile_hearing_aid" msgid="7999237886427812595">"सुनने में मददगार डिवाइस"</string>
- <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="7188282786730266159">"सुनने में मददगार डिवाइस से जाेड़ा गया"</string>
+ <string name="bluetooth_profile_hearing_aid" msgid="6680721080542444257">"सुनने में मदद करने वाले डिवाइस"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="3051944447369418317">"सुनने में मदद करने वाले डिवाइस से कनेक्ट है"</string>
<string name="bluetooth_a2dp_profile_summary_connected" msgid="963376081347721598">"मीडिया ऑडियो से कनेक्ट किया गया"</string>
<string name="bluetooth_headset_profile_summary_connected" msgid="7661070206715520671">"फ़ोन ऑडियो से कनेक्ट किया गया"</string>
<string name="bluetooth_opp_profile_summary_connected" msgid="2611913495968309066">"फ़ाइल स्थानांतरण सर्वर से कनेक्ट किया गया"</string>
@@ -105,7 +105,7 @@
<string name="bluetooth_headset_profile_summary_use_for" msgid="8705753622443862627">"फ़ोन ऑडियो के लिए उपयोग करें"</string>
<string name="bluetooth_opp_profile_summary_use_for" msgid="1255674547144769756">"फ़ाइल स्थानांतरण के लिए उपयोग करें"</string>
<string name="bluetooth_hid_profile_summary_use_for" msgid="232727040453645139">"इनपुट के लिए उपयोग करें"</string>
- <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="908775281788309484">"सुनने में मददगार डिवाइस के लिए इस्तेमाल करें"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="8843499209204010224">"सुनने में मदद करने वाले डिवाइस के लिए इस्तेमाल करें"</string>
<string name="bluetooth_pairing_accept" msgid="6163520056536604875">"जोड़ें"</string>
<string name="bluetooth_pairing_accept_all_caps" msgid="6061699265220789149">"जोड़ें"</string>
<string name="bluetooth_pairing_decline" msgid="4185420413578948140">"रद्द करें"</string>
@@ -136,6 +136,7 @@
<string name="process_kernel_label" msgid="3916858646836739323">"Android OS"</string>
<string name="data_usage_uninstalled_apps" msgid="614263770923231598">"निकाले गए ऐप्स"</string>
<string name="data_usage_uninstalled_apps_users" msgid="7986294489899813194">"ऐप्स और उपयोगकर्ताओं को निकालें"</string>
+ <string name="data_usage_ota" msgid="5377889154805560860">"सिस्टम अपडेट"</string>
<string name="tether_settings_title_usb" msgid="6688416425801386511">"यूएसबी से टेदरिंग"</string>
<string name="tether_settings_title_wifi" msgid="3277144155960302049">"पोर्टेबल हॉटस्पॉट"</string>
<string name="tether_settings_title_bluetooth" msgid="355855408317564420">"ब्लूटूथ टेदरिंग"</string>
diff --git a/packages/SettingsLib/res/values-hr/strings.xml b/packages/SettingsLib/res/values-hr/strings.xml
index bb14b06..b4cbbdb 100644
--- a/packages/SettingsLib/res/values-hr/strings.xml
+++ b/packages/SettingsLib/res/values-hr/strings.xml
@@ -87,8 +87,8 @@
<string name="bluetooth_profile_sap" msgid="5764222021851283125">"Pristup SIM-u"</string>
<string name="bluetooth_profile_a2dp_high_quality" msgid="5444517801472820055">"HD audio: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
<string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="8510588052415438887">"HD audio"</string>
- <string name="bluetooth_profile_hearing_aid" msgid="7999237886427812595">"Slušni aparat"</string>
- <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="7188282786730266159">"Povezano sa slušnim aparatom"</string>
+ <string name="bluetooth_profile_hearing_aid" msgid="6680721080542444257">"Slušni aparati"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="3051944447369418317">"Povezano sa Slušnim aparatima"</string>
<string name="bluetooth_a2dp_profile_summary_connected" msgid="963376081347721598">"Povezano s medijskim zvukom"</string>
<string name="bluetooth_headset_profile_summary_connected" msgid="7661070206715520671">"Povezano sa telefonskim zvukom"</string>
<string name="bluetooth_opp_profile_summary_connected" msgid="2611913495968309066">"Povezano s poslužiteljem za prijenos datoteka"</string>
@@ -105,7 +105,7 @@
<string name="bluetooth_headset_profile_summary_use_for" msgid="8705753622443862627">"Koristi za telefonski zvuk"</string>
<string name="bluetooth_opp_profile_summary_use_for" msgid="1255674547144769756">"Koristi za prijenos datoteke"</string>
<string name="bluetooth_hid_profile_summary_use_for" msgid="232727040453645139">"Upotrijebi za ulaz"</string>
- <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="908775281788309484">"Upotrebljavaj za slušni aparat"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="8843499209204010224">"Upotrijebi za Slušne aparate"</string>
<string name="bluetooth_pairing_accept" msgid="6163520056536604875">"Upari"</string>
<string name="bluetooth_pairing_accept_all_caps" msgid="6061699265220789149">"UPARI"</string>
<string name="bluetooth_pairing_decline" msgid="4185420413578948140">"Odustani"</string>
@@ -136,6 +136,7 @@
<string name="process_kernel_label" msgid="3916858646836739323">"Android OS"</string>
<string name="data_usage_uninstalled_apps" msgid="614263770923231598">"Uklonjene aplikacije"</string>
<string name="data_usage_uninstalled_apps_users" msgid="7986294489899813194">"Uklonjene aplikacije i korisnici"</string>
+ <string name="data_usage_ota" msgid="5377889154805560860">"Ažuriranja sustava"</string>
<string name="tether_settings_title_usb" msgid="6688416425801386511">"USB dijeljenje veze"</string>
<string name="tether_settings_title_wifi" msgid="3277144155960302049">"Prijen. pristupna točka"</string>
<string name="tether_settings_title_bluetooth" msgid="355855408317564420">"Dijeljenje Bluetoothom veze"</string>
diff --git a/packages/SettingsLib/res/values-hu/strings.xml b/packages/SettingsLib/res/values-hu/strings.xml
index 14d8c78..589eb59 100644
--- a/packages/SettingsLib/res/values-hu/strings.xml
+++ b/packages/SettingsLib/res/values-hu/strings.xml
@@ -87,8 +87,8 @@
<string name="bluetooth_profile_sap" msgid="5764222021851283125">"SIM-elérés"</string>
<string name="bluetooth_profile_a2dp_high_quality" msgid="5444517801472820055">"HD audio: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
<string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="8510588052415438887">"HD audio"</string>
- <string name="bluetooth_profile_hearing_aid" msgid="7999237886427812595">"Hallókészülék"</string>
- <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="7188282786730266159">"Csatlakoztatva a hallókészülékhez"</string>
+ <string name="bluetooth_profile_hearing_aid" msgid="6680721080542444257">"Hallókészülékek"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="3051944447369418317">"Hallókészülékhez csatlakoztatva"</string>
<string name="bluetooth_a2dp_profile_summary_connected" msgid="963376081347721598">"Csatlakoztatva az eszköz hangjához"</string>
<string name="bluetooth_headset_profile_summary_connected" msgid="7661070206715520671">"Csatlakoztatva a telefon hangjához"</string>
<string name="bluetooth_opp_profile_summary_connected" msgid="2611913495968309066">"Csatlakozva a fájlküldő szerverhez"</string>
@@ -105,7 +105,7 @@
<string name="bluetooth_headset_profile_summary_use_for" msgid="8705753622443862627">"Felhasználás a telefon hangjához"</string>
<string name="bluetooth_opp_profile_summary_use_for" msgid="1255674547144769756">"Felhasználás fájlátvitelre"</string>
<string name="bluetooth_hid_profile_summary_use_for" msgid="232727040453645139">"Használat beviteli eszközként"</string>
- <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="908775281788309484">"Használat hallókészülékhez"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="8843499209204010224">"Hallókészülékkel való használat"</string>
<string name="bluetooth_pairing_accept" msgid="6163520056536604875">"Párosítás"</string>
<string name="bluetooth_pairing_accept_all_caps" msgid="6061699265220789149">"PÁROSÍTÁS"</string>
<string name="bluetooth_pairing_decline" msgid="4185420413578948140">"Mégse"</string>
@@ -136,6 +136,7 @@
<string name="process_kernel_label" msgid="3916858646836739323">"Android OS"</string>
<string name="data_usage_uninstalled_apps" msgid="614263770923231598">"Eltávolított alkalmazások"</string>
<string name="data_usage_uninstalled_apps_users" msgid="7986294489899813194">"Eltávolított alkalmazások és felhasználók"</string>
+ <string name="data_usage_ota" msgid="5377889154805560860">"Rendszerfrissítések"</string>
<string name="tether_settings_title_usb" msgid="6688416425801386511">"USB-megosztás"</string>
<string name="tether_settings_title_wifi" msgid="3277144155960302049">"Hordozható hotspot"</string>
<string name="tether_settings_title_bluetooth" msgid="355855408317564420">"Bluetooth megosztása"</string>
diff --git a/packages/SettingsLib/res/values-hy/strings.xml b/packages/SettingsLib/res/values-hy/strings.xml
index 28ebe4f..736b4c3 100644
--- a/packages/SettingsLib/res/values-hy/strings.xml
+++ b/packages/SettingsLib/res/values-hy/strings.xml
@@ -87,8 +87,8 @@
<string name="bluetooth_profile_sap" msgid="5764222021851283125">"SIM քարտի հասանելիություն"</string>
<string name="bluetooth_profile_a2dp_high_quality" msgid="5444517801472820055">"HD աուդիո՝ <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
<string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="8510588052415438887">"HD աուդիո"</string>
- <string name="bluetooth_profile_hearing_aid" msgid="7999237886427812595">"Լսողական ապարատ"</string>
- <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="7188282786730266159">"Միացված է լսողական ապարատին"</string>
+ <string name="bluetooth_profile_hearing_aid" msgid="6680721080542444257">"Լսողական ապարատ"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="3051944447369418317">"Լսողական ապարատը միացված է"</string>
<string name="bluetooth_a2dp_profile_summary_connected" msgid="963376081347721598">"Միացված է մեդիա աուդիոյին"</string>
<string name="bluetooth_headset_profile_summary_connected" msgid="7661070206715520671">"Միացված է հեռախոսի ձայնային տվյալներին"</string>
<string name="bluetooth_opp_profile_summary_connected" msgid="2611913495968309066">"Միացված է ֆայլերի փոխանցման սերվերին"</string>
@@ -105,7 +105,7 @@
<string name="bluetooth_headset_profile_summary_use_for" msgid="8705753622443862627">"Օգտագործել հեռախոսի աուդիոյի համար"</string>
<string name="bluetooth_opp_profile_summary_use_for" msgid="1255674547144769756">"Օգտագործել ֆայլի փոխանցման համար"</string>
<string name="bluetooth_hid_profile_summary_use_for" msgid="232727040453645139">"Օգտագործել ներմուծման համար"</string>
- <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="908775281788309484">"Օգտագործել լսողական ապարատի համար"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="8843499209204010224">"Օգտագործել լսողական ապարատի համար"</string>
<string name="bluetooth_pairing_accept" msgid="6163520056536604875">"Զուգավորել"</string>
<string name="bluetooth_pairing_accept_all_caps" msgid="6061699265220789149">"Զուգավորել"</string>
<string name="bluetooth_pairing_decline" msgid="4185420413578948140">"Չեղարկել"</string>
@@ -136,6 +136,7 @@
<string name="process_kernel_label" msgid="3916858646836739323">"Android OS"</string>
<string name="data_usage_uninstalled_apps" msgid="614263770923231598">"Հեռացված ծրագրեր"</string>
<string name="data_usage_uninstalled_apps_users" msgid="7986294489899813194">"Հեռացված հավելվածներն ու օգտատերերը"</string>
+ <string name="data_usage_ota" msgid="5377889154805560860">"Համակարգի թարմացումներ"</string>
<string name="tether_settings_title_usb" msgid="6688416425801386511">"USB մոդեմ"</string>
<string name="tether_settings_title_wifi" msgid="3277144155960302049">"Դյուրակիր թեժ կետ"</string>
<string name="tether_settings_title_bluetooth" msgid="355855408317564420">"Bluetooth մոդեմ"</string>
diff --git a/packages/SettingsLib/res/values-in/strings.xml b/packages/SettingsLib/res/values-in/strings.xml
index 182e523..c5d8f30 100644
--- a/packages/SettingsLib/res/values-in/strings.xml
+++ b/packages/SettingsLib/res/values-in/strings.xml
@@ -87,8 +87,8 @@
<string name="bluetooth_profile_sap" msgid="5764222021851283125">"Akses SIM"</string>
<string name="bluetooth_profile_a2dp_high_quality" msgid="5444517801472820055">"Audio HD: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
<string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="8510588052415438887">"Audio HD"</string>
- <string name="bluetooth_profile_hearing_aid" msgid="7999237886427812595">"Alat Bantu Dengar"</string>
- <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="7188282786730266159">"Terhubung ke Alat Bantu Dengar"</string>
+ <string name="bluetooth_profile_hearing_aid" msgid="6680721080542444257">"Alat Bantu Dengar"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="3051944447369418317">"Terhubung ke Alat Bantu Dengar"</string>
<string name="bluetooth_a2dp_profile_summary_connected" msgid="963376081347721598">"Tersambung ke media audio"</string>
<string name="bluetooth_headset_profile_summary_connected" msgid="7661070206715520671">"Tersambung ke audio ponsel"</string>
<string name="bluetooth_opp_profile_summary_connected" msgid="2611913495968309066">"Sambungkan ke server transfer file"</string>
@@ -105,7 +105,7 @@
<string name="bluetooth_headset_profile_summary_use_for" msgid="8705753622443862627">"Gunakan untuk audio ponsel"</string>
<string name="bluetooth_opp_profile_summary_use_for" msgid="1255674547144769756">"Gunakan untuk transfer file"</string>
<string name="bluetooth_hid_profile_summary_use_for" msgid="232727040453645139">"Gunakan untuk masukan"</string>
- <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="908775281788309484">"Gunakan untuk Alat Bantu Dengar"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="8843499209204010224">"Gunakan untuk Alat Bantu Dengar"</string>
<string name="bluetooth_pairing_accept" msgid="6163520056536604875">"Sandingkan"</string>
<string name="bluetooth_pairing_accept_all_caps" msgid="6061699265220789149">"SANDINGKAN"</string>
<string name="bluetooth_pairing_decline" msgid="4185420413578948140">"Batal"</string>
@@ -136,6 +136,7 @@
<string name="process_kernel_label" msgid="3916858646836739323">"OS Android"</string>
<string name="data_usage_uninstalled_apps" msgid="614263770923231598">"Aplikasi dihapus"</string>
<string name="data_usage_uninstalled_apps_users" msgid="7986294489899813194">"Aplikasi dan pengguna yang dihapus"</string>
+ <string name="data_usage_ota" msgid="5377889154805560860">"Update sistem"</string>
<string name="tether_settings_title_usb" msgid="6688416425801386511">"Tethering USB"</string>
<string name="tether_settings_title_wifi" msgid="3277144155960302049">"Hotspot portabel"</string>
<string name="tether_settings_title_bluetooth" msgid="355855408317564420">"Tethering bluetooth"</string>
diff --git a/packages/SettingsLib/res/values-is/strings.xml b/packages/SettingsLib/res/values-is/strings.xml
index 577b7ae..58505f5 100644
--- a/packages/SettingsLib/res/values-is/strings.xml
+++ b/packages/SettingsLib/res/values-is/strings.xml
@@ -87,8 +87,8 @@
<string name="bluetooth_profile_sap" msgid="5764222021851283125">"Aðgangur að SIM-korti"</string>
<string name="bluetooth_profile_a2dp_high_quality" msgid="5444517801472820055">"HD-hljóð: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
<string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="8510588052415438887">"HD-hljóð"</string>
- <string name="bluetooth_profile_hearing_aid" msgid="7999237886427812595">"Heyrnatæki"</string>
- <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="7188282786730266159">"Tengt við heyrnartæki"</string>
+ <string name="bluetooth_profile_hearing_aid" msgid="6680721080542444257">"Heyrnartæki"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="3051944447369418317">"Tengt við heyrnartæki"</string>
<string name="bluetooth_a2dp_profile_summary_connected" msgid="963376081347721598">"Tengt við hljóðspilun efnis"</string>
<string name="bluetooth_headset_profile_summary_connected" msgid="7661070206715520671">"Tengt við hljóð símans"</string>
<string name="bluetooth_opp_profile_summary_connected" msgid="2611913495968309066">"Tengt við skráaflutningsþjón"</string>
@@ -105,7 +105,7 @@
<string name="bluetooth_headset_profile_summary_use_for" msgid="8705753622443862627">"Nota fyrir hljóð símans"</string>
<string name="bluetooth_opp_profile_summary_use_for" msgid="1255674547144769756">"Nota við skráaflutning"</string>
<string name="bluetooth_hid_profile_summary_use_for" msgid="232727040453645139">"Nota fyrir inntak"</string>
- <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="908775281788309484">"Nota fyrir heyrnartæki"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="8843499209204010224">"Nota fyrir heyrnartæki"</string>
<string name="bluetooth_pairing_accept" msgid="6163520056536604875">"Para"</string>
<string name="bluetooth_pairing_accept_all_caps" msgid="6061699265220789149">"PARA"</string>
<string name="bluetooth_pairing_decline" msgid="4185420413578948140">"Hætta við"</string>
@@ -136,6 +136,7 @@
<string name="process_kernel_label" msgid="3916858646836739323">"Android stýrikerfið"</string>
<string name="data_usage_uninstalled_apps" msgid="614263770923231598">"Fjarlægð forrit"</string>
<string name="data_usage_uninstalled_apps_users" msgid="7986294489899813194">"Fjarlægð forrit og notendur"</string>
+ <string name="data_usage_ota" msgid="5377889154805560860">"Kerfisuppfærslur"</string>
<string name="tether_settings_title_usb" msgid="6688416425801386511">"USB-tjóðrun"</string>
<string name="tether_settings_title_wifi" msgid="3277144155960302049">"Heitur reitur"</string>
<string name="tether_settings_title_bluetooth" msgid="355855408317564420">"Bluetooth-tjóðrun"</string>
diff --git a/packages/SettingsLib/res/values-it/strings.xml b/packages/SettingsLib/res/values-it/strings.xml
index 9fc32949..6d863aa 100644
--- a/packages/SettingsLib/res/values-it/strings.xml
+++ b/packages/SettingsLib/res/values-it/strings.xml
@@ -87,8 +87,8 @@
<string name="bluetooth_profile_sap" msgid="5764222021851283125">"Accesso alla SIM"</string>
<string name="bluetooth_profile_a2dp_high_quality" msgid="5444517801472820055">"Audio HD: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
<string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="8510588052415438887">"Audio HD"</string>
- <string name="bluetooth_profile_hearing_aid" msgid="7999237886427812595">"Apparecchio acustico"</string>
- <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="7188282786730266159">"Connesso all\'apparecchio acustico"</string>
+ <string name="bluetooth_profile_hearing_aid" msgid="6680721080542444257">"Apparecchi acustici"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="3051944447369418317">"Connessione con gli apparecchi acustici stabilita"</string>
<string name="bluetooth_a2dp_profile_summary_connected" msgid="963376081347721598">"Collegato ad audio media"</string>
<string name="bluetooth_headset_profile_summary_connected" msgid="7661070206715520671">"Collegato ad audio telefono"</string>
<string name="bluetooth_opp_profile_summary_connected" msgid="2611913495968309066">"Collegato al server di trasferimento file"</string>
@@ -105,7 +105,7 @@
<string name="bluetooth_headset_profile_summary_use_for" msgid="8705753622443862627">"Usa per audio telefono"</string>
<string name="bluetooth_opp_profile_summary_use_for" msgid="1255674547144769756">"Usa per trasferimento file"</string>
<string name="bluetooth_hid_profile_summary_use_for" msgid="232727040453645139">"Utilizza per l\'input"</string>
- <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="908775281788309484">"Usa per l\'apparecchio acustico"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="8843499209204010224">"Utilizza per gli apparecchi acustici"</string>
<string name="bluetooth_pairing_accept" msgid="6163520056536604875">"Accoppia"</string>
<string name="bluetooth_pairing_accept_all_caps" msgid="6061699265220789149">"ACCOPPIA"</string>
<string name="bluetooth_pairing_decline" msgid="4185420413578948140">"Annulla"</string>
@@ -136,6 +136,7 @@
<string name="process_kernel_label" msgid="3916858646836739323">"Sistema operativo Android"</string>
<string name="data_usage_uninstalled_apps" msgid="614263770923231598">"Applicazioni rimosse"</string>
<string name="data_usage_uninstalled_apps_users" msgid="7986294489899813194">"App e utenti rimossi"</string>
+ <string name="data_usage_ota" msgid="5377889154805560860">"Aggiornamenti di sistema"</string>
<string name="tether_settings_title_usb" msgid="6688416425801386511">"Tethering USB"</string>
<string name="tether_settings_title_wifi" msgid="3277144155960302049">"Hotspot portatile"</string>
<string name="tether_settings_title_bluetooth" msgid="355855408317564420">"Tethering Bluetooth"</string>
diff --git a/packages/SettingsLib/res/values-iw/strings.xml b/packages/SettingsLib/res/values-iw/strings.xml
index 8ee11e4..6e37c9a 100644
--- a/packages/SettingsLib/res/values-iw/strings.xml
+++ b/packages/SettingsLib/res/values-iw/strings.xml
@@ -87,8 +87,8 @@
<string name="bluetooth_profile_sap" msgid="5764222021851283125">"גישה ל-SIM"</string>
<string name="bluetooth_profile_a2dp_high_quality" msgid="5444517801472820055">"אודיו באיכות HD: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
<string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="8510588052415438887">"אודיו באיכות HD"</string>
- <string name="bluetooth_profile_hearing_aid" msgid="7999237886427812595">"מכשיר שמיעה"</string>
- <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="7188282786730266159">"מחובר למכשיר שמיעה"</string>
+ <string name="bluetooth_profile_hearing_aid" msgid="6680721080542444257">"מכשירי שמיעה"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="3051944447369418317">"מחובר אל מכשירי שמיעה"</string>
<string name="bluetooth_a2dp_profile_summary_connected" msgid="963376081347721598">"מחובר לאודיו של מדיה"</string>
<string name="bluetooth_headset_profile_summary_connected" msgid="7661070206715520671">"מחובר לאודיו של הטלפון"</string>
<string name="bluetooth_opp_profile_summary_connected" msgid="2611913495968309066">"מחובר לשרת העברת קבצים"</string>
@@ -105,7 +105,7 @@
<string name="bluetooth_headset_profile_summary_use_for" msgid="8705753622443862627">"השתמש עבור האודיו של הטלפון"</string>
<string name="bluetooth_opp_profile_summary_use_for" msgid="1255674547144769756">"השתמש להעברת קבצים"</string>
<string name="bluetooth_hid_profile_summary_use_for" msgid="232727040453645139">"השתמש לקלט"</string>
- <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="908775281788309484">"יש להשתמש עבור מכשיר שמיעה"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="8843499209204010224">"שימוש בשביל מכשירי שמיעה"</string>
<string name="bluetooth_pairing_accept" msgid="6163520056536604875">"התאם"</string>
<string name="bluetooth_pairing_accept_all_caps" msgid="6061699265220789149">"התאם"</string>
<string name="bluetooth_pairing_decline" msgid="4185420413578948140">"ביטול"</string>
@@ -136,6 +136,8 @@
<string name="process_kernel_label" msgid="3916858646836739323">"Android OS"</string>
<string name="data_usage_uninstalled_apps" msgid="614263770923231598">"אפליקציות שהוסרו"</string>
<string name="data_usage_uninstalled_apps_users" msgid="7986294489899813194">"אפליקציות ומשתמשים שהוסרו"</string>
+ <!-- no translation found for data_usage_ota (5377889154805560860) -->
+ <skip />
<string name="tether_settings_title_usb" msgid="6688416425801386511">"שיתוף אינטרנט דרך USB"</string>
<string name="tether_settings_title_wifi" msgid="3277144155960302049">"נקודה לשיתוף אינטרנט"</string>
<string name="tether_settings_title_bluetooth" msgid="355855408317564420">"שיתוף אינטרנט דרך Bluetooth"</string>
diff --git a/packages/SettingsLib/res/values-ja/strings.xml b/packages/SettingsLib/res/values-ja/strings.xml
index 4efd61b..233e8e8 100644
--- a/packages/SettingsLib/res/values-ja/strings.xml
+++ b/packages/SettingsLib/res/values-ja/strings.xml
@@ -87,8 +87,8 @@
<string name="bluetooth_profile_sap" msgid="5764222021851283125">"SIMアクセス"</string>
<string name="bluetooth_profile_a2dp_high_quality" msgid="5444517801472820055">"HD オーディオ: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
<string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="8510588052415438887">"HD オーディオ"</string>
- <string name="bluetooth_profile_hearing_aid" msgid="7999237886427812595">"補聴器"</string>
- <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="7188282786730266159">"補聴器に接続済み"</string>
+ <string name="bluetooth_profile_hearing_aid" msgid="6680721080542444257">"補聴器"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="3051944447369418317">"補聴器に接続"</string>
<string name="bluetooth_a2dp_profile_summary_connected" msgid="963376081347721598">"メディアの音声に接続"</string>
<string name="bluetooth_headset_profile_summary_connected" msgid="7661070206715520671">"携帯電話の音声に接続"</string>
<string name="bluetooth_opp_profile_summary_connected" msgid="2611913495968309066">"ファイル転送サーバーに接続"</string>
@@ -105,7 +105,7 @@
<string name="bluetooth_headset_profile_summary_use_for" msgid="8705753622443862627">"携帯電話の音声に使用"</string>
<string name="bluetooth_opp_profile_summary_use_for" msgid="1255674547144769756">"ファイル転送に使用"</string>
<string name="bluetooth_hid_profile_summary_use_for" msgid="232727040453645139">"入力に使用"</string>
- <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="908775281788309484">"補聴器に使用"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="8843499209204010224">"補聴器に使用"</string>
<string name="bluetooth_pairing_accept" msgid="6163520056536604875">"ペア設定する"</string>
<string name="bluetooth_pairing_accept_all_caps" msgid="6061699265220789149">"ペア設定する"</string>
<string name="bluetooth_pairing_decline" msgid="4185420413578948140">"キャンセル"</string>
@@ -136,6 +136,7 @@
<string name="process_kernel_label" msgid="3916858646836739323">"Android OS"</string>
<string name="data_usage_uninstalled_apps" msgid="614263770923231598">"削除したアプリケーション"</string>
<string name="data_usage_uninstalled_apps_users" msgid="7986294489899813194">"削除されたアプリとユーザー"</string>
+ <string name="data_usage_ota" msgid="5377889154805560860">"システム アップデート"</string>
<string name="tether_settings_title_usb" msgid="6688416425801386511">"USB テザリング"</string>
<string name="tether_settings_title_wifi" msgid="3277144155960302049">"ポータブルアクセスポイント"</string>
<string name="tether_settings_title_bluetooth" msgid="355855408317564420">"Bluetooth テザリング"</string>
diff --git a/packages/SettingsLib/res/values-ka/strings.xml b/packages/SettingsLib/res/values-ka/strings.xml
index c613a06b..09bea2a0 100644
--- a/packages/SettingsLib/res/values-ka/strings.xml
+++ b/packages/SettingsLib/res/values-ka/strings.xml
@@ -87,8 +87,8 @@
<string name="bluetooth_profile_sap" msgid="5764222021851283125">"SIM წვდომა"</string>
<string name="bluetooth_profile_a2dp_high_quality" msgid="5444517801472820055">"HD აუდიო: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
<string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="8510588052415438887">"HD აუდიო"</string>
- <string name="bluetooth_profile_hearing_aid" msgid="7999237886427812595">"სმენის აპარატი"</string>
- <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="7188282786730266159">"დაკავშირებულია სმენის აპარატთან"</string>
+ <string name="bluetooth_profile_hearing_aid" msgid="6680721080542444257">"სმენის მოწყობილობები"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="3051944447369418317">"დაკავშირებულია სმენის მოწყობილობებთან"</string>
<string name="bluetooth_a2dp_profile_summary_connected" msgid="963376081347721598">"დაკავშირებულია აუდიო მულტიმედიურ სისტემასთან"</string>
<string name="bluetooth_headset_profile_summary_connected" msgid="7661070206715520671">"დაკავშირებულია ტელეფონის აუდიო მოწყობილობასთან"</string>
<string name="bluetooth_opp_profile_summary_connected" msgid="2611913495968309066">"დაკავშირებულია ფაილების გადაცემის სერვერთან"</string>
@@ -105,7 +105,7 @@
<string name="bluetooth_headset_profile_summary_use_for" msgid="8705753622443862627">"გამოიყენეთ ტელეფონის აუდიომოწყობილობაში"</string>
<string name="bluetooth_opp_profile_summary_use_for" msgid="1255674547144769756">"ფაილების ტრანსფერისათვის გამოყენება"</string>
<string name="bluetooth_hid_profile_summary_use_for" msgid="232727040453645139">"შეტანისთვის გამოყენება"</string>
- <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="908775281788309484">"სმენის აპარატის გამოყენება"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="8843499209204010224">"გამოყენება სმენის მოწყობილობებისთვის"</string>
<string name="bluetooth_pairing_accept" msgid="6163520056536604875">"დაწყვილება"</string>
<string name="bluetooth_pairing_accept_all_caps" msgid="6061699265220789149">"დაწყვილება"</string>
<string name="bluetooth_pairing_decline" msgid="4185420413578948140">"გაუქმება"</string>
@@ -136,6 +136,7 @@
<string name="process_kernel_label" msgid="3916858646836739323">"Android OS"</string>
<string name="data_usage_uninstalled_apps" msgid="614263770923231598">"აპების წაშლა"</string>
<string name="data_usage_uninstalled_apps_users" msgid="7986294489899813194">"წაშლილი აპები და მომხმარებლები"</string>
+ <string name="data_usage_ota" msgid="5377889154805560860">"სისტემის განახლებები"</string>
<string name="tether_settings_title_usb" msgid="6688416425801386511">"USB ტეტერინგი"</string>
<string name="tether_settings_title_wifi" msgid="3277144155960302049">"პორტატული უსადენო ქსელი"</string>
<string name="tether_settings_title_bluetooth" msgid="355855408317564420">"Bluetooth ტეტერინგი"</string>
diff --git a/packages/SettingsLib/res/values-kk/strings.xml b/packages/SettingsLib/res/values-kk/strings.xml
index 8d6d76e..8670ec9 100644
--- a/packages/SettingsLib/res/values-kk/strings.xml
+++ b/packages/SettingsLib/res/values-kk/strings.xml
@@ -87,8 +87,8 @@
<string name="bluetooth_profile_sap" msgid="5764222021851283125">"SIM картасына кіру"</string>
<string name="bluetooth_profile_a2dp_high_quality" msgid="5444517801472820055">"HD форматты аудиомазмұн: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
<string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="8510588052415438887">"HD форматты аудиомазмұн"</string>
- <string name="bluetooth_profile_hearing_aid" msgid="7999237886427812595">"Есту аппараты"</string>
- <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="7188282786730266159">"Есту аппаратына жалғанған"</string>
+ <string name="bluetooth_profile_hearing_aid" msgid="6680721080542444257">"Есту аппараттары"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="3051944447369418317">"Есту аппараттарына жалғанған"</string>
<string name="bluetooth_a2dp_profile_summary_connected" msgid="963376081347721598">"Медиа аудиосына жалғанған"</string>
<string name="bluetooth_headset_profile_summary_connected" msgid="7661070206715520671">"Телефон аудиосына қосылған"</string>
<string name="bluetooth_opp_profile_summary_connected" msgid="2611913495968309066">"Файл жіберу серверіне жалғанған"</string>
@@ -105,7 +105,7 @@
<string name="bluetooth_headset_profile_summary_use_for" msgid="8705753622443862627">"Телефон аудиосы үшін қолдану"</string>
<string name="bluetooth_opp_profile_summary_use_for" msgid="1255674547144769756">"Файлды жіберу үшін қолдану"</string>
<string name="bluetooth_hid_profile_summary_use_for" msgid="232727040453645139">"Кіріс үшін қолдану"</string>
- <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="908775281788309484">"Есту аппаратына пайдалану"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="8843499209204010224">"Есту аппараттары үшін пайдалану"</string>
<string name="bluetooth_pairing_accept" msgid="6163520056536604875">"Жұптау"</string>
<string name="bluetooth_pairing_accept_all_caps" msgid="6061699265220789149">"ЖҰПТАУ"</string>
<string name="bluetooth_pairing_decline" msgid="4185420413578948140">"Бас тарту"</string>
@@ -136,6 +136,7 @@
<string name="process_kernel_label" msgid="3916858646836739323">"Android операциялық жүйесі"</string>
<string name="data_usage_uninstalled_apps" msgid="614263770923231598">"Алынған қолданбалар"</string>
<string name="data_usage_uninstalled_apps_users" msgid="7986294489899813194">"Алынған қолданбалар және пайдаланушылар"</string>
+ <string name="data_usage_ota" msgid="5377889154805560860">"Жүйелік жаңарту"</string>
<string name="tether_settings_title_usb" msgid="6688416425801386511">"USB тетеринг"</string>
<string name="tether_settings_title_wifi" msgid="3277144155960302049">"Алынбалы хот-спот"</string>
<string name="tether_settings_title_bluetooth" msgid="355855408317564420">"Bluetooth модем"</string>
diff --git a/packages/SettingsLib/res/values-km/strings.xml b/packages/SettingsLib/res/values-km/strings.xml
index 9903201..6bf8a0f 100644
--- a/packages/SettingsLib/res/values-km/strings.xml
+++ b/packages/SettingsLib/res/values-km/strings.xml
@@ -87,8 +87,8 @@
<string name="bluetooth_profile_sap" msgid="5764222021851283125">"ការចូលដំណើរការស៊ីម"</string>
<string name="bluetooth_profile_a2dp_high_quality" msgid="5444517801472820055">"សំឡេងកម្រិត HD៖ <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
<string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="8510588052415438887">"សំឡេងកម្រិត HD"</string>
- <string name="bluetooth_profile_hearing_aid" msgid="7999237886427812595">"ឧបករណ៍ជំនួយការស្ដាប់"</string>
- <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="7188282786730266159">"បានភ្ជាប់ទៅឧបករណ៍ជំនួយការស្តាប់"</string>
+ <string name="bluetooth_profile_hearing_aid" msgid="6680721080542444257">"ឧបករណ៍ជំនួយការស្ដាប់"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="3051944447369418317">"បានភ្ជាប់ទៅឧបករណ៍ជំនួយការស្ដាប់"</string>
<string name="bluetooth_a2dp_profile_summary_connected" msgid="963376081347721598">"បានភ្ជាប់ទៅអូឌីយ៉ូមេឌៀ"</string>
<string name="bluetooth_headset_profile_summary_connected" msgid="7661070206715520671">"តភ្ជាប់ទៅអូឌីយ៉ូទូរស័ព្ទ"</string>
<string name="bluetooth_opp_profile_summary_connected" msgid="2611913495968309066">"បានតភ្ជាប់ទៅម៉ាស៊ីនមេផ្ទេរឯកសារ"</string>
@@ -105,7 +105,7 @@
<string name="bluetooth_headset_profile_summary_use_for" msgid="8705753622443862627">"ប្រើសម្រាប់អូឌីយ៉ូទូរស័ព្ទ"</string>
<string name="bluetooth_opp_profile_summary_use_for" msgid="1255674547144769756">"ប្រើសម្រាប់ផ្ទេរឯកសារ"</string>
<string name="bluetooth_hid_profile_summary_use_for" msgid="232727040453645139">"ប្រើសម្រាប់បញ្ចូល"</string>
- <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="908775281788309484">"ប្រើសម្រាប់ឧបករណ៍ជំនួយការស្តាប់"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="8843499209204010224">"ប្រើសម្រាប់ឧបករណ៍ជំនួយការស្តាប់"</string>
<string name="bluetooth_pairing_accept" msgid="6163520056536604875">"ផ្គូផ្គង"</string>
<string name="bluetooth_pairing_accept_all_caps" msgid="6061699265220789149">"ផ្គូផ្គង"</string>
<string name="bluetooth_pairing_decline" msgid="4185420413578948140">"បោះបង់"</string>
@@ -136,6 +136,7 @@
<string name="process_kernel_label" msgid="3916858646836739323">"ប្រព័ន្ធប្រតិបត្តិការ Android"</string>
<string name="data_usage_uninstalled_apps" msgid="614263770923231598">"កម្មវិធីដែលបានលុប"</string>
<string name="data_usage_uninstalled_apps_users" msgid="7986294489899813194">"បានលុបកម្មវិធី និងអ្នកប្រើ"</string>
+ <string name="data_usage_ota" msgid="5377889154805560860">"បច្ចុប្បន្នភាពប្រព័ន្ធ"</string>
<string name="tether_settings_title_usb" msgid="6688416425801386511">"ការភ្ជាប់តាម USB"</string>
<string name="tether_settings_title_wifi" msgid="3277144155960302049">"ហតស្ពតចល័ត"</string>
<string name="tether_settings_title_bluetooth" msgid="355855408317564420">"ការភ្ជាប់ប៊្លូធូស"</string>
diff --git a/packages/SettingsLib/res/values-kn/strings.xml b/packages/SettingsLib/res/values-kn/strings.xml
index 888b93f..41b0fbd 100644
--- a/packages/SettingsLib/res/values-kn/strings.xml
+++ b/packages/SettingsLib/res/values-kn/strings.xml
@@ -38,27 +38,20 @@
<string name="connected_via_network_scorer" msgid="5713793306870815341">"%1$s ಮೂಲಕ ಸ್ವಯಂಚಾಲಿತವಾಗಿ ಸಂಪರ್ಕಿಸಲಾಗಿದೆ"</string>
<string name="connected_via_network_scorer_default" msgid="7867260222020343104">"ನೆಟ್ವರ್ಕ್ ರೇಟಿಂಗ್ ಒದಗಿಸುವವರ ಮೂಲಕ ಸ್ವಯಂಚಾಲಿತವಾಗಿ ಸಂಪರ್ಕಿಸಲಾಗಿದೆ"</string>
<string name="connected_via_passpoint" msgid="2826205693803088747">"%1$s ಮೂಲಕ ಸಂಪರ್ಕಗೊಂಡಿದೆ"</string>
- <!-- no translation found for connected_via_app (5571999941988929520) -->
- <skip />
+ <string name="connected_via_app" msgid="5571999941988929520">"<xliff:g id="NAME">%1$s</xliff:g> ಆ್ಯಪ್ ಮೂಲಕ ಸಂಪರ್ಕಿಸಲಾಗಿದೆ"</string>
<string name="available_via_passpoint" msgid="1617440946846329613">"%1$s ಮೂಲಕ ಲಭ್ಯವಿದೆ"</string>
- <!-- no translation found for tap_to_sign_up (6449724763052579434) -->
- <skip />
+ <string name="tap_to_sign_up" msgid="6449724763052579434">"ಸೈನ್ ಅಪ್ ಮಾಡಲು ಟ್ಯಾಪ್ ಮಾಡಿ"</string>
<string name="wifi_connected_no_internet" msgid="8202906332837777829">"ಸಂಪರ್ಕಪಡಿಸಲಾಗಿದೆ, ಇಂಟರ್ನೆಟ್ ಇಲ್ಲ"</string>
<string name="wifi_status_no_internet" msgid="5784710974669608361">"ಇಂಟರ್ನೆಟ್ ಇಲ್ಲ"</string>
<string name="wifi_status_sign_in_required" msgid="123517180404752756">"ಸೈನ್ ಇನ್ ಮಾಡುವ ಅಗತ್ಯವಿದೆ"</string>
<string name="wifi_ap_unable_to_handle_new_sta" msgid="5348824313514404541">"ಪ್ರವೇಶ ಕೇಂದ್ರ ತಾತ್ಕಾಲಿಕವಾಗಿ ಭರ್ತಿಯಾಗಿದೆ"</string>
<string name="connected_via_carrier" msgid="7583780074526041912">"%1$s ಮೂಲಕ ಸಂಪರ್ಕಗೊಂಡಿದೆ"</string>
<string name="available_via_carrier" msgid="1469036129740799053">"%1$s ಮೂಲಕ ಲಭ್ಯವಿದೆ"</string>
- <!-- no translation found for osu_opening_provider (5488997661548640424) -->
- <skip />
- <!-- no translation found for osu_connect_failed (2187750899158158934) -->
- <skip />
- <!-- no translation found for osu_completing_sign_up (9037638564719197082) -->
- <skip />
- <!-- no translation found for osu_sign_up_failed (7296159750352873260) -->
- <skip />
- <!-- no translation found for osu_sign_up_complete (8207626049093289203) -->
- <skip />
+ <string name="osu_opening_provider" msgid="5488997661548640424">"<xliff:g id="PASSPOINTPROVIDER">%1$s</xliff:g> ಅನ್ನು ತೆರೆಯಲಾಗುತ್ತಿದೆ"</string>
+ <string name="osu_connect_failed" msgid="2187750899158158934">"ಸಂಪರ್ಕಿಸಲು ಸಾಧ್ಯವಾಗುತ್ತಿಲ್ಲ"</string>
+ <string name="osu_completing_sign_up" msgid="9037638564719197082">"ಸೈನ್-ಅಪ್ ಅನ್ನು ಪೂರ್ಣಗೊಳಿಸಲಾಗುತ್ತಿದೆ…"</string>
+ <string name="osu_sign_up_failed" msgid="7296159750352873260">"ಸೈನ್-ಅಪ್ ಅನ್ನು ಪೂರ್ಣಗೊಳಿಸಲು ಸಾಧ್ಯವಾಗುತ್ತಿಲ್ಲ. ಮತ್ತೊಮ್ಮೆ ಪ್ರಯತ್ನಿಸಲು ಟ್ಯಾಪ್ ಮಾಡಿ."</string>
+ <string name="osu_sign_up_complete" msgid="8207626049093289203">"ಸೈನ್-ಅಪ್ ಪೂರ್ಣಗೊಂಡಿದೆ. ಸಂಪರ್ಕಿಸಲಾಗುತ್ತಿದೆ…"</string>
<string name="speed_label_very_slow" msgid="1867055264243608530">"ತುಂಬಾ ನಿಧಾನವಾಗಿದೆ"</string>
<string name="speed_label_slow" msgid="813109590815810235">"ನಿಧಾನ"</string>
<string name="speed_label_okay" msgid="2331665440671174858">"ಸರಿ"</string>
@@ -94,8 +87,8 @@
<string name="bluetooth_profile_sap" msgid="5764222021851283125">"ಸಿಮ್ ಪ್ರವೇಶ"</string>
<string name="bluetooth_profile_a2dp_high_quality" msgid="5444517801472820055">"HD ಆಡಿಯೋ: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
<string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="8510588052415438887">"HD ಆಡಿಯೋ"</string>
- <string name="bluetooth_profile_hearing_aid" msgid="7999237886427812595">"ಶ್ರವಣ ಸಾಧನ"</string>
- <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="7188282786730266159">"ಶ್ರವಣ ಸಾಧನಕ್ಕೆ ಸಂಪರ್ಕಪಡಿಸಲಾಗಿದೆ"</string>
+ <string name="bluetooth_profile_hearing_aid" msgid="6680721080542444257">"ಶ್ರವಣ ಸಾಧನಗಳು"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="3051944447369418317">"ಶ್ರವಣ ಸಾಧನಗಳಿಗೆ ಸಂಪರ್ಕಿಸಲಾಗಿದೆ"</string>
<string name="bluetooth_a2dp_profile_summary_connected" msgid="963376081347721598">"ಮಾಧ್ಯಮ ಆಡಿಯೋಗೆ ಸಂಪರ್ಕಗೊಂಡಿದೆ"</string>
<string name="bluetooth_headset_profile_summary_connected" msgid="7661070206715520671">"ಫೋನ್ ಆಡಿಯೋಗೆ ಸಂಪರ್ಕಗೊಂಡಿದೆ"</string>
<string name="bluetooth_opp_profile_summary_connected" msgid="2611913495968309066">"ಫೈಲ್ ವರ್ಗಾವಣೆ ಸರ್ವರ್ಗೆ ಸಂಪರ್ಕಗೊಂಡಿದೆ"</string>
@@ -112,7 +105,7 @@
<string name="bluetooth_headset_profile_summary_use_for" msgid="8705753622443862627">"ಫೋನ್ ಆಡಿಯೋಗಾಗಿ ಬಳಕೆ"</string>
<string name="bluetooth_opp_profile_summary_use_for" msgid="1255674547144769756">"ಫೈಲ್ ವರ್ಗಾವಣೆಗಾಗಿ ಬಳಸು"</string>
<string name="bluetooth_hid_profile_summary_use_for" msgid="232727040453645139">"ಇನ್ಪುಟ್ಗಾಗಿ ಬಳಸು"</string>
- <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="908775281788309484">"ಶ್ರವಣ ಸಾಧನಕ್ಕಾಗಿ ಬಳಸಿ"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="8843499209204010224">"ಶ್ರವಣ ಸಾಧನಗಳಿಗಾಗಿ ಬಳಸಿ"</string>
<string name="bluetooth_pairing_accept" msgid="6163520056536604875">"ಜೋಡಿ"</string>
<string name="bluetooth_pairing_accept_all_caps" msgid="6061699265220789149">"ಜೋಡಿ ಮಾಡು"</string>
<string name="bluetooth_pairing_decline" msgid="4185420413578948140">"ರದ್ದುಮಾಡಿ"</string>
@@ -143,6 +136,8 @@
<string name="process_kernel_label" msgid="3916858646836739323">"Android OS"</string>
<string name="data_usage_uninstalled_apps" msgid="614263770923231598">"ತೆಗೆದುಹಾಕಲಾದ ಅಪ್ಲಿಕೇಶನ್ಗಳು"</string>
<string name="data_usage_uninstalled_apps_users" msgid="7986294489899813194">"ಅಪ್ಲಿಕೇಶನ್ಗಳು ಮತ್ತು ಬಳಕೆದಾರರನ್ನು ತೆಗೆದುಹಾಕಲಾಗಿದೆ"</string>
+ <!-- no translation found for data_usage_ota (5377889154805560860) -->
+ <skip />
<string name="tether_settings_title_usb" msgid="6688416425801386511">"USB ಟೆಥರಿಂಗ್"</string>
<string name="tether_settings_title_wifi" msgid="3277144155960302049">"ಪೋರ್ಟಬಲ್ ಹಾಟ್ಸ್ಪಾಟ್"</string>
<string name="tether_settings_title_bluetooth" msgid="355855408317564420">"ಬ್ಲೂಟೂತ್ ಟೆಥರಿಂಗ್"</string>
diff --git a/packages/SettingsLib/res/values-ko/strings.xml b/packages/SettingsLib/res/values-ko/strings.xml
index d7e9488..877866c 100644
--- a/packages/SettingsLib/res/values-ko/strings.xml
+++ b/packages/SettingsLib/res/values-ko/strings.xml
@@ -87,8 +87,8 @@
<string name="bluetooth_profile_sap" msgid="5764222021851283125">"SIM 액세스"</string>
<string name="bluetooth_profile_a2dp_high_quality" msgid="5444517801472820055">"HD 오디오: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
<string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="8510588052415438887">"HD 오디오"</string>
- <string name="bluetooth_profile_hearing_aid" msgid="7999237886427812595">"보청기"</string>
- <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="7188282786730266159">"보청기에 연결됨"</string>
+ <string name="bluetooth_profile_hearing_aid" msgid="6680721080542444257">"보청기"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="3051944447369418317">"보청기에 연결됨"</string>
<string name="bluetooth_a2dp_profile_summary_connected" msgid="963376081347721598">"미디어 오디오에 연결됨"</string>
<string name="bluetooth_headset_profile_summary_connected" msgid="7661070206715520671">"휴대전화 오디오에 연결됨"</string>
<string name="bluetooth_opp_profile_summary_connected" msgid="2611913495968309066">"파일 전송 서버에 연결됨"</string>
@@ -105,7 +105,7 @@
<string name="bluetooth_headset_profile_summary_use_for" msgid="8705753622443862627">"휴대전화 오디오에 사용"</string>
<string name="bluetooth_opp_profile_summary_use_for" msgid="1255674547144769756">"파일 전송에 사용"</string>
<string name="bluetooth_hid_profile_summary_use_for" msgid="232727040453645139">"입력에 사용"</string>
- <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="908775281788309484">"보청기에 사용"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="8843499209204010224">"보청기로 사용"</string>
<string name="bluetooth_pairing_accept" msgid="6163520056536604875">"페어링"</string>
<string name="bluetooth_pairing_accept_all_caps" msgid="6061699265220789149">"페어링"</string>
<string name="bluetooth_pairing_decline" msgid="4185420413578948140">"취소"</string>
@@ -136,6 +136,7 @@
<string name="process_kernel_label" msgid="3916858646836739323">"Android OS"</string>
<string name="data_usage_uninstalled_apps" msgid="614263770923231598">"삭제된 앱"</string>
<string name="data_usage_uninstalled_apps_users" msgid="7986294489899813194">"삭제된 앱 및 사용자"</string>
+ <string name="data_usage_ota" msgid="5377889154805560860">"시스템 업데이트"</string>
<string name="tether_settings_title_usb" msgid="6688416425801386511">"USB 테더링"</string>
<string name="tether_settings_title_wifi" msgid="3277144155960302049">"휴대용 핫스팟"</string>
<string name="tether_settings_title_bluetooth" msgid="355855408317564420">"블루투스 테더링"</string>
diff --git a/packages/SettingsLib/res/values-ky/strings.xml b/packages/SettingsLib/res/values-ky/strings.xml
index 6898c61..9e4a9a8 100644
--- a/packages/SettingsLib/res/values-ky/strings.xml
+++ b/packages/SettingsLib/res/values-ky/strings.xml
@@ -87,8 +87,8 @@
<string name="bluetooth_profile_sap" msgid="5764222021851283125">"SIM картаны пайдалануу мүмкүнчүлүгү"</string>
<string name="bluetooth_profile_a2dp_high_quality" msgid="5444517801472820055">"HD форматындагы аудио: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
<string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="8510588052415438887">"HD форматындагы аудио"</string>
- <string name="bluetooth_profile_hearing_aid" msgid="7999237886427812595">"Угуу аппараты"</string>
- <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="7188282786730266159">"Угуу аппаратына туташты"</string>
+ <string name="bluetooth_profile_hearing_aid" msgid="6680721080542444257">"Угуу аппараттары"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="3051944447369418317">"Угуу аппараттарына туташып турат"</string>
<string name="bluetooth_a2dp_profile_summary_connected" msgid="963376081347721598">"Медиа аудиого туташты"</string>
<string name="bluetooth_headset_profile_summary_connected" msgid="7661070206715520671">"Телефон аудиосуна туташты"</string>
<string name="bluetooth_opp_profile_summary_connected" msgid="2611913495968309066">"Файл өткөрүү серверине туташты"</string>
@@ -105,7 +105,7 @@
<string name="bluetooth_headset_profile_summary_use_for" msgid="8705753622443862627">"Телефон аудиосу үчүн колдонулсун"</string>
<string name="bluetooth_opp_profile_summary_use_for" msgid="1255674547144769756">"Файл өткөрүү үчүн колдонулсун"</string>
<string name="bluetooth_hid_profile_summary_use_for" msgid="232727040453645139">"Киргизүү үчүн колдонулсун"</string>
- <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="908775281788309484">"Угуу аппараты үчүн колдонуу"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="8843499209204010224">"Угуу аппараттары үчүн колдонуу"</string>
<string name="bluetooth_pairing_accept" msgid="6163520056536604875">"Жупташтыруу"</string>
<string name="bluetooth_pairing_accept_all_caps" msgid="6061699265220789149">"ЖУПТАШТЫРУУ"</string>
<string name="bluetooth_pairing_decline" msgid="4185420413578948140">"Жок"</string>
@@ -136,6 +136,7 @@
<string name="process_kernel_label" msgid="3916858646836739323">"Android OS"</string>
<string name="data_usage_uninstalled_apps" msgid="614263770923231598">"Алынып салынган колдонмолор"</string>
<string name="data_usage_uninstalled_apps_users" msgid="7986294489899813194">"Өчүрүлгөн колдонмолор жана колдонуучулар"</string>
+ <string name="data_usage_ota" msgid="5377889154805560860">"Тутум жаңыртуулары"</string>
<string name="tether_settings_title_usb" msgid="6688416425801386511">"USB модем"</string>
<string name="tether_settings_title_wifi" msgid="3277144155960302049">"Ташыма кошулуу чекити"</string>
<string name="tether_settings_title_bluetooth" msgid="355855408317564420">"Bluetooth модем"</string>
diff --git a/packages/SettingsLib/res/values-lo/strings.xml b/packages/SettingsLib/res/values-lo/strings.xml
index acbaf70..7e6aaac 100644
--- a/packages/SettingsLib/res/values-lo/strings.xml
+++ b/packages/SettingsLib/res/values-lo/strings.xml
@@ -87,8 +87,8 @@
<string name="bluetooth_profile_sap" msgid="5764222021851283125">"ການເຂົ້າເຖິງ SIM"</string>
<string name="bluetooth_profile_a2dp_high_quality" msgid="5444517801472820055">"ສຽງ HD: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
<string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="8510588052415438887">"ສຽງ HD"</string>
- <string name="bluetooth_profile_hearing_aid" msgid="7999237886427812595">"ເຄື່ອງຊ່ວຍຟັງ"</string>
- <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="7188282786730266159">"ເຊື່ອມຕໍ່ຫາເຄື່ອງຊ່ວຍຟັງແລ້ວ"</string>
+ <string name="bluetooth_profile_hearing_aid" msgid="6680721080542444257">"ອຸປະກອນຊ່ວຍຟັງ"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="3051944447369418317">"ເຊື່ອມຕໍ່ຫາອຸປະກອນຊ່ວຍຟັງແລ້ວ"</string>
<string name="bluetooth_a2dp_profile_summary_connected" msgid="963376081347721598">"ເຊື່ອມຕໍ່ກັບສື່ດ້ານສຽງແລ້ວ"</string>
<string name="bluetooth_headset_profile_summary_connected" msgid="7661070206715520671">"ເຊື່ອມຕໍ່ກັບສຽງໂທລະສັບແລ້ວ"</string>
<string name="bluetooth_opp_profile_summary_connected" msgid="2611913495968309066">"ເຊື່ອມຕໍ່ກັບເຊີບເວີໂອນຍ້າຍໄຟລ໌ແລ້ວ"</string>
@@ -105,7 +105,7 @@
<string name="bluetooth_headset_profile_summary_use_for" msgid="8705753622443862627">"ໃຊ້ສຳລັບລະບົບສຽງຂອງໂທລະສັບ"</string>
<string name="bluetooth_opp_profile_summary_use_for" msgid="1255674547144769756">"ໃຊ້ເພື່ອໂອນຍ້າຍໄຟລ໌"</string>
<string name="bluetooth_hid_profile_summary_use_for" msgid="232727040453645139">"ໃຊ້ສຳລັບການປ້ອນຂໍ້ມູນ"</string>
- <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="908775281788309484">"ໃຊ້ກັບເຄື່ອງຊ່ວຍຟັງ"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="8843499209204010224">"ໃຊ້ສຳລັບອຸປະກອນຊ່ວຍຟັງ"</string>
<string name="bluetooth_pairing_accept" msgid="6163520056536604875">"ຈັບຄູ່"</string>
<string name="bluetooth_pairing_accept_all_caps" msgid="6061699265220789149">"ຈັບຄູ່"</string>
<string name="bluetooth_pairing_decline" msgid="4185420413578948140">"ຍົກເລີກ"</string>
@@ -136,6 +136,7 @@
<string name="process_kernel_label" msgid="3916858646836739323">"Android OS"</string>
<string name="data_usage_uninstalled_apps" msgid="614263770923231598">"ແອັບຯທີ່ຖືກລຶບອອກແລ້ວ"</string>
<string name="data_usage_uninstalled_apps_users" msgid="7986294489899813194">"ລຶບແອັບຯ ແລະຜູ່ໃຊ້ແລ້ວ"</string>
+ <string name="data_usage_ota" msgid="5377889154805560860">"ການອັບເດດລະບົບ"</string>
<string name="tether_settings_title_usb" msgid="6688416425801386511">"ການປ່ອຍສັນຍານຜ່ານ USB"</string>
<string name="tether_settings_title_wifi" msgid="3277144155960302049">"ຮັອດສະປອດເຄື່ອນທີ່"</string>
<string name="tether_settings_title_bluetooth" msgid="355855408317564420">"ປ່ອຍສັນຍານຜ່ານ Bluetooth"</string>
diff --git a/packages/SettingsLib/res/values-lt/strings.xml b/packages/SettingsLib/res/values-lt/strings.xml
index 8933451..71b8cf0 100644
--- a/packages/SettingsLib/res/values-lt/strings.xml
+++ b/packages/SettingsLib/res/values-lt/strings.xml
@@ -87,8 +87,8 @@
<string name="bluetooth_profile_sap" msgid="5764222021851283125">"SIM prieiga"</string>
<string name="bluetooth_profile_a2dp_high_quality" msgid="5444517801472820055">"HD garsas: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
<string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="8510588052415438887">"HD garsas"</string>
- <string name="bluetooth_profile_hearing_aid" msgid="7999237886427812595">"Klausos aparatas"</string>
- <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="7188282786730266159">"Prisijungta prie klausos aparato"</string>
+ <string name="bluetooth_profile_hearing_aid" msgid="6680721080542444257">"Klausos aparatai"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="3051944447369418317">"Prisijungta prie klausos aparatų"</string>
<string name="bluetooth_a2dp_profile_summary_connected" msgid="963376081347721598">"Prijungta prie medijos garso įrašo"</string>
<string name="bluetooth_headset_profile_summary_connected" msgid="7661070206715520671">"Prijungta prie telefono garso"</string>
<string name="bluetooth_opp_profile_summary_connected" msgid="2611913495968309066">"Prijungta prie failų perkėlimo serverio"</string>
@@ -105,7 +105,7 @@
<string name="bluetooth_headset_profile_summary_use_for" msgid="8705753622443862627">"Naudoti telefono garso įrašui"</string>
<string name="bluetooth_opp_profile_summary_use_for" msgid="1255674547144769756">"Naudoti failų perkėlimui"</string>
<string name="bluetooth_hid_profile_summary_use_for" msgid="232727040453645139">"Naudoti įvedant"</string>
- <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="908775281788309484">"Klausos aparato naudojimas"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="8843499209204010224">"Naudoti su klausos aparatais"</string>
<string name="bluetooth_pairing_accept" msgid="6163520056536604875">"Susieti"</string>
<string name="bluetooth_pairing_accept_all_caps" msgid="6061699265220789149">"SUSIETI"</string>
<string name="bluetooth_pairing_decline" msgid="4185420413578948140">"Atšaukti"</string>
@@ -136,6 +136,7 @@
<string name="process_kernel_label" msgid="3916858646836739323">"„Android“ OS"</string>
<string name="data_usage_uninstalled_apps" msgid="614263770923231598">"Pašalintos programos"</string>
<string name="data_usage_uninstalled_apps_users" msgid="7986294489899813194">"Pašalintos programos ir naudotojai"</string>
+ <string name="data_usage_ota" msgid="5377889154805560860">"Sistemos naujiniai"</string>
<string name="tether_settings_title_usb" msgid="6688416425801386511">"USB susiejimas"</string>
<string name="tether_settings_title_wifi" msgid="3277144155960302049">"Perkeliama aktyvioji sritis"</string>
<string name="tether_settings_title_bluetooth" msgid="355855408317564420">"„Bluetooth“ susiejimas"</string>
diff --git a/packages/SettingsLib/res/values-lv/strings.xml b/packages/SettingsLib/res/values-lv/strings.xml
index ac41ae0..82ec0ae 100644
--- a/packages/SettingsLib/res/values-lv/strings.xml
+++ b/packages/SettingsLib/res/values-lv/strings.xml
@@ -87,8 +87,8 @@
<string name="bluetooth_profile_sap" msgid="5764222021851283125">"Piekļuve SIM kartei"</string>
<string name="bluetooth_profile_a2dp_high_quality" msgid="5444517801472820055">"HD audio: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
<string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="8510588052415438887">"HD audio"</string>
- <string name="bluetooth_profile_hearing_aid" msgid="7999237886427812595">"Dzirdes aparāts"</string>
- <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="7188282786730266159">"Izveidots savienojums ar dzirdes aparātu"</string>
+ <string name="bluetooth_profile_hearing_aid" msgid="6680721080542444257">"Dzirdes aparāti"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="3051944447369418317">"Izveidots savienojums ar dzirdes aparātiem"</string>
<string name="bluetooth_a2dp_profile_summary_connected" msgid="963376081347721598">"Savienots ar multivides audio"</string>
<string name="bluetooth_headset_profile_summary_connected" msgid="7661070206715520671">"Savienots ar tālruņa audio"</string>
<string name="bluetooth_opp_profile_summary_connected" msgid="2611913495968309066">"Savienots ar failu pārsūtīšanas serveri"</string>
@@ -105,7 +105,7 @@
<string name="bluetooth_headset_profile_summary_use_for" msgid="8705753622443862627">"Izmantot tālruņa skaņai"</string>
<string name="bluetooth_opp_profile_summary_use_for" msgid="1255674547144769756">"Izmantot faila pārsūtīšanai"</string>
<string name="bluetooth_hid_profile_summary_use_for" msgid="232727040453645139">"Izmantot ievadei"</string>
- <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="908775281788309484">"Izmantot dzirdes aparātam"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="8843499209204010224">"Izmantot dzirdes aparātiem"</string>
<string name="bluetooth_pairing_accept" msgid="6163520056536604875">"Izveidot pāri"</string>
<string name="bluetooth_pairing_accept_all_caps" msgid="6061699265220789149">"SAVIENOT PĀRĪ"</string>
<string name="bluetooth_pairing_decline" msgid="4185420413578948140">"Atcelt"</string>
@@ -136,6 +136,7 @@
<string name="process_kernel_label" msgid="3916858646836739323">"Android OS"</string>
<string name="data_usage_uninstalled_apps" msgid="614263770923231598">"Noņemtās lietotnes"</string>
<string name="data_usage_uninstalled_apps_users" msgid="7986294489899813194">"Noņemtās lietotnes un lietotāji"</string>
+ <string name="data_usage_ota" msgid="5377889154805560860">"Sistēmas atjauninājumi"</string>
<string name="tether_settings_title_usb" msgid="6688416425801386511">"USB saistīšana"</string>
<string name="tether_settings_title_wifi" msgid="3277144155960302049">"Pārnēsājams tīklājs"</string>
<string name="tether_settings_title_bluetooth" msgid="355855408317564420">"Bluetooth saistīšana"</string>
diff --git a/packages/SettingsLib/res/values-mk/strings.xml b/packages/SettingsLib/res/values-mk/strings.xml
index 5b45977..c99ef68 100644
--- a/packages/SettingsLib/res/values-mk/strings.xml
+++ b/packages/SettingsLib/res/values-mk/strings.xml
@@ -87,8 +87,8 @@
<string name="bluetooth_profile_sap" msgid="5764222021851283125">"Пристап до SIM"</string>
<string name="bluetooth_profile_a2dp_high_quality" msgid="5444517801472820055">"HD аудио: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
<string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="8510588052415438887">"HD аудио"</string>
- <string name="bluetooth_profile_hearing_aid" msgid="7999237886427812595">"Слушно помагало"</string>
- <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="7188282786730266159">"Поврзано со слушно помагало"</string>
+ <string name="bluetooth_profile_hearing_aid" msgid="6680721080542444257">"Слушни помагала"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="3051944447369418317">"Поврзано со слушни помагала"</string>
<string name="bluetooth_a2dp_profile_summary_connected" msgid="963376081347721598">"Поврзан со аудио на медиуми"</string>
<string name="bluetooth_headset_profile_summary_connected" msgid="7661070206715520671">"Поврзан со аудио на телефон"</string>
<string name="bluetooth_opp_profile_summary_connected" msgid="2611913495968309066">"Поврзан со сервер за пренос на датотеки"</string>
@@ -105,7 +105,7 @@
<string name="bluetooth_headset_profile_summary_use_for" msgid="8705753622443862627">"Користи за аудио на телефон"</string>
<string name="bluetooth_opp_profile_summary_use_for" msgid="1255674547144769756">"Користи за пренос на датотеки"</string>
<string name="bluetooth_hid_profile_summary_use_for" msgid="232727040453645139">"Користи за внес"</string>
- <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="908775281788309484">"Користете како слушно помагало"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="8843499209204010224">"Користи за слушни помагала"</string>
<string name="bluetooth_pairing_accept" msgid="6163520056536604875">"Спари"</string>
<string name="bluetooth_pairing_accept_all_caps" msgid="6061699265220789149">"СПАРИ"</string>
<string name="bluetooth_pairing_decline" msgid="4185420413578948140">"Откажи"</string>
@@ -136,6 +136,7 @@
<string name="process_kernel_label" msgid="3916858646836739323">"Оперативен систем Android"</string>
<string name="data_usage_uninstalled_apps" msgid="614263770923231598">"Отстранети апликации"</string>
<string name="data_usage_uninstalled_apps_users" msgid="7986294489899813194">"Отстранети апликации и корисници"</string>
+ <string name="data_usage_ota" msgid="5377889154805560860">"Ажурирања на системот"</string>
<string name="tether_settings_title_usb" msgid="6688416425801386511">"Поврзување со USB"</string>
<string name="tether_settings_title_wifi" msgid="3277144155960302049">"Преносл. точка на пристап"</string>
<string name="tether_settings_title_bluetooth" msgid="355855408317564420">"Поврзување со Bluetooth"</string>
diff --git a/packages/SettingsLib/res/values-ml/strings.xml b/packages/SettingsLib/res/values-ml/strings.xml
index efe6cd6..0292cab 100644
--- a/packages/SettingsLib/res/values-ml/strings.xml
+++ b/packages/SettingsLib/res/values-ml/strings.xml
@@ -87,8 +87,8 @@
<string name="bluetooth_profile_sap" msgid="5764222021851283125">"SIM ആക്സസ്"</string>
<string name="bluetooth_profile_a2dp_high_quality" msgid="5444517801472820055">"HD ഓഡിയോ: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
<string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="8510588052415438887">"HD ഓഡിയോ"</string>
- <string name="bluetooth_profile_hearing_aid" msgid="7999237886427812595">"ശ്രവണ സഹായി"</string>
- <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="7188282786730266159">"ശ്രവണ സഹായിലേക്ക് കണക്റ്റ് ചെയ്തു"</string>
+ <string name="bluetooth_profile_hearing_aid" msgid="6680721080542444257">"ശ്രവണ സഹായികൾ"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="3051944447369418317">"ശ്രവണ സഹായികളിലേക്ക് കണക്റ്റ് ചെയ്തു"</string>
<string name="bluetooth_a2dp_profile_summary_connected" msgid="963376081347721598">"മീഡിയ ഓഡിയോയിലേക്ക് കണക്റ്റുചെയ്തു"</string>
<string name="bluetooth_headset_profile_summary_connected" msgid="7661070206715520671">"ഫോൺ ഓഡിയോയിൽ കണക്റ്റുചെയ്തു"</string>
<string name="bluetooth_opp_profile_summary_connected" msgid="2611913495968309066">"ഫയൽ കൈമാറ്റ സെർവറിലേക്ക് കണക്റ്റുചെയ്തു"</string>
@@ -105,7 +105,7 @@
<string name="bluetooth_headset_profile_summary_use_for" msgid="8705753622443862627">"ഫോൺ ഓഡിയോയ്ക്കായി ഉപയോഗിക്കുക"</string>
<string name="bluetooth_opp_profile_summary_use_for" msgid="1255674547144769756">"ഫയൽ കൈമാറ്റത്തിനായി ഉപയോഗിക്കുന്നു"</string>
<string name="bluetooth_hid_profile_summary_use_for" msgid="232727040453645139">"ഇൻപുട്ടിനായി ഉപയോഗിക്കുക"</string>
- <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="908775281788309484">"ശ്രവണ സഹായത്തിനായി ഉപയോഗിക്കുക"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="8843499209204010224">"ശ്രവണ സഹായികൾക്കായി ഉപയോഗിക്കുക"</string>
<string name="bluetooth_pairing_accept" msgid="6163520056536604875">"ജോടിയാക്കുക"</string>
<string name="bluetooth_pairing_accept_all_caps" msgid="6061699265220789149">"ജോടിയാക്കുക"</string>
<string name="bluetooth_pairing_decline" msgid="4185420413578948140">"റദ്ദാക്കുക"</string>
@@ -136,6 +136,8 @@
<string name="process_kernel_label" msgid="3916858646836739323">"Android OS"</string>
<string name="data_usage_uninstalled_apps" msgid="614263770923231598">"നീക്കംചെയ്ത അപ്ലിക്കേഷനുകൾ"</string>
<string name="data_usage_uninstalled_apps_users" msgid="7986294489899813194">"നീക്കംചെയ്ത അപ്ലിക്കേഷനുകളും ഉപയോക്താക്കളും"</string>
+ <!-- no translation found for data_usage_ota (5377889154805560860) -->
+ <skip />
<string name="tether_settings_title_usb" msgid="6688416425801386511">"USB ടെതറിംഗ്"</string>
<string name="tether_settings_title_wifi" msgid="3277144155960302049">"പോർട്ടബിൾ ഹോട്ട്സ്പോട്ട്"</string>
<string name="tether_settings_title_bluetooth" msgid="355855408317564420">"ബ്ലൂടൂത്ത് ടെതറിംഗ്"</string>
diff --git a/packages/SettingsLib/res/values-mn/strings.xml b/packages/SettingsLib/res/values-mn/strings.xml
index 9c3db2e..10c1415 100644
--- a/packages/SettingsLib/res/values-mn/strings.xml
+++ b/packages/SettingsLib/res/values-mn/strings.xml
@@ -49,8 +49,8 @@
<string name="available_via_carrier" msgid="1469036129740799053">"%1$s-р боломжтой"</string>
<string name="osu_opening_provider" msgid="5488997661548640424">"<xliff:g id="PASSPOINTPROVIDER">%1$s</xliff:g>-г нээж байна"</string>
<string name="osu_connect_failed" msgid="2187750899158158934">"Холбогдож чадсангүй"</string>
- <string name="osu_completing_sign_up" msgid="9037638564719197082">"Бүртгүүлэлтийг дуусгаж байна…"</string>
- <string name="osu_sign_up_failed" msgid="7296159750352873260">"Бүртгүүлэлтийг дуусгаж чадсангүй. Дахин оролдохын тулд товшино уу."</string>
+ <string name="osu_completing_sign_up" msgid="9037638564719197082">"Бүртгэлийг дуусгаж байна…"</string>
+ <string name="osu_sign_up_failed" msgid="7296159750352873260">"Бүртгэлийг дуусгаж чадсангүй. Дахин оролдохын тулд товшино уу."</string>
<string name="osu_sign_up_complete" msgid="8207626049093289203">"Бүртгүүлж дууслаа. Холбогдож байна…"</string>
<string name="speed_label_very_slow" msgid="1867055264243608530">"Маш удаан"</string>
<string name="speed_label_slow" msgid="813109590815810235">"Удаан"</string>
@@ -87,8 +87,8 @@
<string name="bluetooth_profile_sap" msgid="5764222021851283125">"SIM Хандалт"</string>
<string name="bluetooth_profile_a2dp_high_quality" msgid="5444517801472820055">"HD аудио: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
<string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="8510588052415438887">"HD аудио"</string>
- <string name="bluetooth_profile_hearing_aid" msgid="7999237886427812595">"Сонсголын төхөөрөмж"</string>
- <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="7188282786730266159">"Сонсголын төхөөрөмжид холбогдсон"</string>
+ <string name="bluetooth_profile_hearing_aid" msgid="6680721080542444257">"Сонсголын төхөөрөмж"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="3051944447369418317">"Сонсголын төхөөрөмжтэй холбосон"</string>
<string name="bluetooth_a2dp_profile_summary_connected" msgid="963376081347721598">"Медиа аудиод холбогдсон"</string>
<string name="bluetooth_headset_profile_summary_connected" msgid="7661070206715520671">"Утасны аудид холбогдсон"</string>
<string name="bluetooth_opp_profile_summary_connected" msgid="2611913495968309066">"Файл дамжуулах серверт холбогдсон"</string>
@@ -105,7 +105,7 @@
<string name="bluetooth_headset_profile_summary_use_for" msgid="8705753622443862627">"Утасны аудиод ашиглах"</string>
<string name="bluetooth_opp_profile_summary_use_for" msgid="1255674547144769756">"Файл дамжуулахад ашиглах"</string>
<string name="bluetooth_hid_profile_summary_use_for" msgid="232727040453645139">"Оруулахад ашиглах"</string>
- <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="908775281788309484">"Сонсголын төхөөрөмжид ашиглах"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="8843499209204010224">"Сонсголын төхөөрөмжид ашиглах"</string>
<string name="bluetooth_pairing_accept" msgid="6163520056536604875">"Хослуулах"</string>
<string name="bluetooth_pairing_accept_all_caps" msgid="6061699265220789149">"ХОСЛУУЛАХ"</string>
<string name="bluetooth_pairing_decline" msgid="4185420413578948140">"Цуцлах"</string>
@@ -136,6 +136,7 @@
<string name="process_kernel_label" msgid="3916858646836739323">"Андройд OS"</string>
<string name="data_usage_uninstalled_apps" msgid="614263770923231598">"Арилгасан апп-ууд"</string>
<string name="data_usage_uninstalled_apps_users" msgid="7986294489899813194">"Арилгасан апп-ууд болон хэрэглэгчид"</string>
+ <string name="data_usage_ota" msgid="5377889154805560860">"Системийн шинэчлэлт"</string>
<string name="tether_settings_title_usb" msgid="6688416425801386511">"USB модем болгох"</string>
<string name="tether_settings_title_wifi" msgid="3277144155960302049">"Зөөврийн сүлжээний цэг"</string>
<string name="tether_settings_title_bluetooth" msgid="355855408317564420">"Bluetooth модем болгох"</string>
diff --git a/packages/SettingsLib/res/values-mr/strings.xml b/packages/SettingsLib/res/values-mr/strings.xml
index a792c4f..0c2f0ee 100644
--- a/packages/SettingsLib/res/values-mr/strings.xml
+++ b/packages/SettingsLib/res/values-mr/strings.xml
@@ -87,8 +87,8 @@
<string name="bluetooth_profile_sap" msgid="5764222021851283125">"सिम प्रवेश"</string>
<string name="bluetooth_profile_a2dp_high_quality" msgid="5444517801472820055">"HD ऑडिओ: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
<string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="8510588052415438887">"HD ऑडिओ"</string>
- <string name="bluetooth_profile_hearing_aid" msgid="7999237886427812595">"ऐकण्याची सुविधा"</string>
- <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="7188282786730266159">"ऐकण्याच्या सुविधेशी कनेक्ट केलेले आहे"</string>
+ <string name="bluetooth_profile_hearing_aid" msgid="6680721080542444257">"श्रवण यंत्रे"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="3051944447369418317">"श्रवण यंत्रांशी कनेक्ट केले आहे"</string>
<string name="bluetooth_a2dp_profile_summary_connected" msgid="963376081347721598">"मीडिया ऑडिओवर कनेक्ट केले"</string>
<string name="bluetooth_headset_profile_summary_connected" msgid="7661070206715520671">"फोन ऑडिओ वर कनेक्ट केले"</string>
<string name="bluetooth_opp_profile_summary_connected" msgid="2611913495968309066">"फाईल स्थानांतर सर्व्हरवर कनेक्ट केले"</string>
@@ -105,7 +105,7 @@
<string name="bluetooth_headset_profile_summary_use_for" msgid="8705753622443862627">"फोन ऑडिओसाठी वापरा"</string>
<string name="bluetooth_opp_profile_summary_use_for" msgid="1255674547144769756">"फाईल स्थानांतरणासाठी वापरा"</string>
<string name="bluetooth_hid_profile_summary_use_for" msgid="232727040453645139">"इनपुट साठी वापरा"</string>
- <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="908775281788309484">"ऐकण्याच्या सुविधेसाठी वापरा"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="8843499209204010224">"श्रवण यंत्रांसाठी वापरा"</string>
<string name="bluetooth_pairing_accept" msgid="6163520056536604875">"पेअर करा"</string>
<string name="bluetooth_pairing_accept_all_caps" msgid="6061699265220789149">"पेअर करा"</string>
<string name="bluetooth_pairing_decline" msgid="4185420413578948140">"रद्द करा"</string>
@@ -136,6 +136,8 @@
<string name="process_kernel_label" msgid="3916858646836739323">"Android OS"</string>
<string name="data_usage_uninstalled_apps" msgid="614263770923231598">"काढलेले अॅप्स"</string>
<string name="data_usage_uninstalled_apps_users" msgid="7986294489899813194">"काढलेले अॅप्स आणि वापरकर्ते"</string>
+ <!-- no translation found for data_usage_ota (5377889154805560860) -->
+ <skip />
<string name="tether_settings_title_usb" msgid="6688416425801386511">"USB टेदरिंग"</string>
<string name="tether_settings_title_wifi" msgid="3277144155960302049">"पोर्टेबल हॉटस्पॉट"</string>
<string name="tether_settings_title_bluetooth" msgid="355855408317564420">"ब्लूटूथ टेदरिंग"</string>
diff --git a/packages/SettingsLib/res/values-ms/strings.xml b/packages/SettingsLib/res/values-ms/strings.xml
index 419c6ec..e98418d 100644
--- a/packages/SettingsLib/res/values-ms/strings.xml
+++ b/packages/SettingsLib/res/values-ms/strings.xml
@@ -87,8 +87,8 @@
<string name="bluetooth_profile_sap" msgid="5764222021851283125">"Akses SIM"</string>
<string name="bluetooth_profile_a2dp_high_quality" msgid="5444517801472820055">"Audio HD: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
<string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="8510588052415438887">"Audio HD"</string>
- <string name="bluetooth_profile_hearing_aid" msgid="7999237886427812595">"Alat Bantu Pendengaran"</string>
- <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="7188282786730266159">"Disambungkan ke Alat Bantu Pendengaran"</string>
+ <string name="bluetooth_profile_hearing_aid" msgid="6680721080542444257">"Alat Bantu Dengar"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="3051944447369418317">"Disambungkan pada Alat Bantu Dengar"</string>
<string name="bluetooth_a2dp_profile_summary_connected" msgid="963376081347721598">"Disambungkan ke audio media"</string>
<string name="bluetooth_headset_profile_summary_connected" msgid="7661070206715520671">"Disambungkan ke audio telefon"</string>
<string name="bluetooth_opp_profile_summary_connected" msgid="2611913495968309066">"Bersambung ke pelayan pemindahan fail"</string>
@@ -105,7 +105,7 @@
<string name="bluetooth_headset_profile_summary_use_for" msgid="8705753622443862627">"Gunakan untuk audio telefon"</string>
<string name="bluetooth_opp_profile_summary_use_for" msgid="1255674547144769756">"Gunakan untuk pemindahan fail"</string>
<string name="bluetooth_hid_profile_summary_use_for" msgid="232727040453645139">"Gunakan untuk input"</string>
- <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="908775281788309484">"Gunakan untuk Alat Bantu Pendengaran"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="8843499209204010224">"Gunakan untuk Alat Bantu Dengar"</string>
<string name="bluetooth_pairing_accept" msgid="6163520056536604875">"Jadikan pasangan"</string>
<string name="bluetooth_pairing_accept_all_caps" msgid="6061699265220789149">"JADIKAN PASANGAN"</string>
<string name="bluetooth_pairing_decline" msgid="4185420413578948140">"Batal"</string>
@@ -136,6 +136,7 @@
<string name="process_kernel_label" msgid="3916858646836739323">"OS Android"</string>
<string name="data_usage_uninstalled_apps" msgid="614263770923231598">"Apl dialih keluar"</string>
<string name="data_usage_uninstalled_apps_users" msgid="7986294489899813194">"Apl dan pengguna yang dialih keluar"</string>
+ <string name="data_usage_ota" msgid="5377889154805560860">"Kemas kini sistem"</string>
<string name="tether_settings_title_usb" msgid="6688416425801386511">"Penambatan USB"</string>
<string name="tether_settings_title_wifi" msgid="3277144155960302049">"Titik panas mudah alih"</string>
<string name="tether_settings_title_bluetooth" msgid="355855408317564420">"Penambatan Bluetooth"</string>
diff --git a/packages/SettingsLib/res/values-my/strings.xml b/packages/SettingsLib/res/values-my/strings.xml
index 3e9e181..ed2aae6 100644
--- a/packages/SettingsLib/res/values-my/strings.xml
+++ b/packages/SettingsLib/res/values-my/strings.xml
@@ -87,8 +87,8 @@
<string name="bluetooth_profile_sap" msgid="5764222021851283125">"SIM အသုံးပြုခြင်း"</string>
<string name="bluetooth_profile_a2dp_high_quality" msgid="5444517801472820055">"HD အသံ- <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
<string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="8510588052415438887">"HD အသံ"</string>
- <string name="bluetooth_profile_hearing_aid" msgid="7999237886427812595">"နားကြားကိရိယာ"</string>
- <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="7188282786730266159">"နားကြားကိရိယာသို့ ချိတ်ဆက်ထားသည်"</string>
+ <string name="bluetooth_profile_hearing_aid" msgid="6680721080542444257">"နားကြားကိရိယာ"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="3051944447369418317">"နားကြားကိရိယာနှင့် ချိတ်ဆက်ပြီးပါပြီ"</string>
<string name="bluetooth_a2dp_profile_summary_connected" msgid="963376081347721598">"မီဒီယာအသံအား ချိတ်ဆက်ရန်"</string>
<string name="bluetooth_headset_profile_summary_connected" msgid="7661070206715520671">"ဖုန်းအသံအား ချိတ်ဆက်ရန်"</string>
<string name="bluetooth_opp_profile_summary_connected" msgid="2611913495968309066">"ဖိုင်လွှဲပြောင်းမည့်ဆာဗာနှင့် ချိတ်ဆက်ထားပြီး"</string>
@@ -105,7 +105,7 @@
<string name="bluetooth_headset_profile_summary_use_for" msgid="8705753622443862627">"ဖုန်းအသံအားအသုံးပြုရန်"</string>
<string name="bluetooth_opp_profile_summary_use_for" msgid="1255674547144769756">"ဖိုင်လွဲပြောင်းရန်အတွက်အသုံးပြုရန်"</string>
<string name="bluetooth_hid_profile_summary_use_for" msgid="232727040453645139">"ထည့်သွင်းရန်အသုံးပြုသည်"</string>
- <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="908775281788309484">"နားကြားကိရိယာအတွက် အသုံးပြုရန်"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="8843499209204010224">"နားကြားကိရိယာအတွက် အသုံးပြုသည်"</string>
<string name="bluetooth_pairing_accept" msgid="6163520056536604875">"အတူတွဲပါ"</string>
<string name="bluetooth_pairing_accept_all_caps" msgid="6061699265220789149">"ချိတ်တွဲရန်"</string>
<string name="bluetooth_pairing_decline" msgid="4185420413578948140">"မလုပ်တော့"</string>
@@ -136,6 +136,7 @@
<string name="process_kernel_label" msgid="3916858646836739323">"Android OS"</string>
<string name="data_usage_uninstalled_apps" msgid="614263770923231598">"ဖယ်ရှားထားသော အက်ပ်များ"</string>
<string name="data_usage_uninstalled_apps_users" msgid="7986294489899813194">"ဖယ်ရှားထားသော အပလီကေးရှင်းနှင့် သုံးစွဲသူများ"</string>
+ <string name="data_usage_ota" msgid="5377889154805560860">"စနစ် အပ်ဒိတ်လုပ်ခြင်းများ"</string>
<string name="tether_settings_title_usb" msgid="6688416425801386511">"USB သုံး၍ချိတ်ဆက်ခြင်း"</string>
<string name="tether_settings_title_wifi" msgid="3277144155960302049">"ရွေ့လျားနိုင်သောဟော့စပေါ့"</string>
<string name="tether_settings_title_bluetooth" msgid="355855408317564420">"ဘလူးတုသ်သုံးချိတ်ဆက်ခြင်း"</string>
diff --git a/packages/SettingsLib/res/values-nb/strings.xml b/packages/SettingsLib/res/values-nb/strings.xml
index 65085e8..93e53e5 100644
--- a/packages/SettingsLib/res/values-nb/strings.xml
+++ b/packages/SettingsLib/res/values-nb/strings.xml
@@ -87,8 +87,8 @@
<string name="bluetooth_profile_sap" msgid="5764222021851283125">"Tilgang til SIM-kortet"</string>
<string name="bluetooth_profile_a2dp_high_quality" msgid="5444517801472820055">"HD-lyd: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
<string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="8510588052415438887">"HD-lyd"</string>
- <string name="bluetooth_profile_hearing_aid" msgid="7999237886427812595">"Høreapparat"</string>
- <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="7188282786730266159">"Koblet til høreapparat"</string>
+ <string name="bluetooth_profile_hearing_aid" msgid="6680721080542444257">"Høreapparater"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="3051944447369418317">"Koblet til høreapparater"</string>
<string name="bluetooth_a2dp_profile_summary_connected" msgid="963376081347721598">"Koblet til medielyd"</string>
<string name="bluetooth_headset_profile_summary_connected" msgid="7661070206715520671">"Koblet til telefonlyd"</string>
<string name="bluetooth_opp_profile_summary_connected" msgid="2611913495968309066">"Koblet til tjener for filoverføring"</string>
@@ -105,7 +105,7 @@
<string name="bluetooth_headset_profile_summary_use_for" msgid="8705753622443862627">"Bruk for telefonlyd"</string>
<string name="bluetooth_opp_profile_summary_use_for" msgid="1255674547144769756">"Bruk til filoverføring"</string>
<string name="bluetooth_hid_profile_summary_use_for" msgid="232727040453645139">"Bruk for inndata"</string>
- <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="908775281788309484">"Bruk for høreapparat"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="8843499209204010224">"Bruk for høreapparater"</string>
<string name="bluetooth_pairing_accept" msgid="6163520056536604875">"Sammenkoble"</string>
<string name="bluetooth_pairing_accept_all_caps" msgid="6061699265220789149">"KOBLE TIL"</string>
<string name="bluetooth_pairing_decline" msgid="4185420413578948140">"Avbryt"</string>
@@ -136,6 +136,7 @@
<string name="process_kernel_label" msgid="3916858646836739323">"Android-operativsystem"</string>
<string name="data_usage_uninstalled_apps" msgid="614263770923231598">"Fjernede apper"</string>
<string name="data_usage_uninstalled_apps_users" msgid="7986294489899813194">"Fjernede apper og brukere"</string>
+ <string name="data_usage_ota" msgid="5377889154805560860">"Systemoppdateringer"</string>
<string name="tether_settings_title_usb" msgid="6688416425801386511">"USB-internettdeling"</string>
<string name="tether_settings_title_wifi" msgid="3277144155960302049">"Flyttbar trådløs sone"</string>
<string name="tether_settings_title_bluetooth" msgid="355855408317564420">"Bluetooth-internettdeling"</string>
diff --git a/packages/SettingsLib/res/values-ne/strings.xml b/packages/SettingsLib/res/values-ne/strings.xml
index 16b3b07..7daf956 100644
--- a/packages/SettingsLib/res/values-ne/strings.xml
+++ b/packages/SettingsLib/res/values-ne/strings.xml
@@ -38,27 +38,20 @@
<string name="connected_via_network_scorer" msgid="5713793306870815341">"%1$s मार्फत् स्वतः जडान गरिएको"</string>
<string name="connected_via_network_scorer_default" msgid="7867260222020343104">"नेटवर्कको दर्जा प्रदायक मार्फत स्वत: जडान गरिएको"</string>
<string name="connected_via_passpoint" msgid="2826205693803088747">"%1$s मार्फत जडित"</string>
- <!-- no translation found for connected_via_app (5571999941988929520) -->
- <skip />
+ <string name="connected_via_app" msgid="5571999941988929520">"<xliff:g id="NAME">%1$s</xliff:g> मार्फत जडान गरिएको"</string>
<string name="available_via_passpoint" msgid="1617440946846329613">"%1$s मार्फत उपलब्ध"</string>
- <!-- no translation found for tap_to_sign_up (6449724763052579434) -->
- <skip />
+ <string name="tap_to_sign_up" msgid="6449724763052579434">"साइन अप गर्न ट्याप गर्नुहोस्"</string>
<string name="wifi_connected_no_internet" msgid="8202906332837777829">"जडान गरियो तर इन्टरनेट छैन"</string>
<string name="wifi_status_no_internet" msgid="5784710974669608361">"इन्टरनेटमाथिको पहुँच छैन"</string>
<string name="wifi_status_sign_in_required" msgid="123517180404752756">"साइन इन गर्न आवश्यक छ"</string>
<string name="wifi_ap_unable_to_handle_new_sta" msgid="5348824313514404541">"पहुँचसम्बन्धी स्थान अस्थायी रूपमा भरिएको छ"</string>
<string name="connected_via_carrier" msgid="7583780074526041912">"%1$s मार्फत जडान गरियो"</string>
<string name="available_via_carrier" msgid="1469036129740799053">"%1$s मार्फत उपलब्ध"</string>
- <!-- no translation found for osu_opening_provider (5488997661548640424) -->
- <skip />
- <!-- no translation found for osu_connect_failed (2187750899158158934) -->
- <skip />
- <!-- no translation found for osu_completing_sign_up (9037638564719197082) -->
- <skip />
- <!-- no translation found for osu_sign_up_failed (7296159750352873260) -->
- <skip />
- <!-- no translation found for osu_sign_up_complete (8207626049093289203) -->
- <skip />
+ <string name="osu_opening_provider" msgid="5488997661548640424">"<xliff:g id="PASSPOINTPROVIDER">%1$s</xliff:g> खोल्दै"</string>
+ <string name="osu_connect_failed" msgid="2187750899158158934">"जडान गर्न सकिएन"</string>
+ <string name="osu_completing_sign_up" msgid="9037638564719197082">"साइन अप गर्ने कार्य सम्पन्न गर्दै…"</string>
+ <string name="osu_sign_up_failed" msgid="7296159750352873260">"साइन अप गर्ने कार्य सम्पन्न गर्न सकिएन। फेरि प्रयास गर्न ट्याप गर्नुहोस्।"</string>
+ <string name="osu_sign_up_complete" msgid="8207626049093289203">"साइन अप गर्ने कार्य सम्पन्न भयो। जडान गर्दै…"</string>
<string name="speed_label_very_slow" msgid="1867055264243608530">"धेरै ढिलो"</string>
<string name="speed_label_slow" msgid="813109590815810235">"बिस्तारै"</string>
<string name="speed_label_okay" msgid="2331665440671174858">"ठिक छ"</string>
@@ -94,8 +87,8 @@
<string name="bluetooth_profile_sap" msgid="5764222021851283125">"SIM पहुँच"</string>
<string name="bluetooth_profile_a2dp_high_quality" msgid="5444517801472820055">"HD अडियो: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
<string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="8510588052415438887">"HD अडियो"</string>
- <string name="bluetooth_profile_hearing_aid" msgid="7999237886427812595">"सुन्नमा मद्दत गर्ने यन्त्र"</string>
- <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="7188282786730266159">"सुन्नमा मद्दत गर्ने यन्त्रमा जडान गरियो"</string>
+ <string name="bluetooth_profile_hearing_aid" msgid="6680721080542444257">"श्रवण यन्त्रहरू"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="3051944447369418317">"श्रवण यन्त्रहरूमा जडान गरियो"</string>
<string name="bluetooth_a2dp_profile_summary_connected" msgid="963376081347721598">"मिडिया अडियोसँग जडित"</string>
<string name="bluetooth_headset_profile_summary_connected" msgid="7661070206715520671">"फोन अडियोमा जडान गरियो"</string>
<string name="bluetooth_opp_profile_summary_connected" msgid="2611913495968309066">"फाइल ट्रान्सफर सर्भरमा जडान गरियो"</string>
@@ -112,7 +105,7 @@
<string name="bluetooth_headset_profile_summary_use_for" msgid="8705753622443862627">"फोन अडियोको लागि प्रयोग गर्नुहोस्"</string>
<string name="bluetooth_opp_profile_summary_use_for" msgid="1255674547144769756">"फाइल ट्रान्सफरका लागि प्रयोग गर्नुहोस्"</string>
<string name="bluetooth_hid_profile_summary_use_for" msgid="232727040453645139">"इनपुटको लागि प्रयोग गर्नुहोस्"</string>
- <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="908775281788309484">"सुन्नमा मद्दत गर्ने यन्त्रका लागि प्रयोग गर्नुहोस्"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="8843499209204010224">"श्रवण यन्त्रहरूका लागि प्रयोग गर्नुहोस्"</string>
<string name="bluetooth_pairing_accept" msgid="6163520056536604875">"जोडी"</string>
<string name="bluetooth_pairing_accept_all_caps" msgid="6061699265220789149">"जोडी"</string>
<string name="bluetooth_pairing_decline" msgid="4185420413578948140">"रद्द गर्नुहोस्"</string>
@@ -143,6 +136,8 @@
<string name="process_kernel_label" msgid="3916858646836739323">"एन्ड्रोइड OS"</string>
<string name="data_usage_uninstalled_apps" msgid="614263770923231598">"हटाइएका अनुप्रयोगहरू"</string>
<string name="data_usage_uninstalled_apps_users" msgid="7986294489899813194">"अनुप्रयोगहरू र प्रयोगकर्ताहरू हटाइयो।"</string>
+ <!-- no translation found for data_usage_ota (5377889154805560860) -->
+ <skip />
<string name="tether_settings_title_usb" msgid="6688416425801386511">"USB टेथर गर्दै"</string>
<string name="tether_settings_title_wifi" msgid="3277144155960302049">"पोर्टेबल हटस्पट"</string>
<string name="tether_settings_title_bluetooth" msgid="355855408317564420">"ब्लुटुथ टेथर गर्दै"</string>
diff --git a/packages/SettingsLib/res/values-nl/strings.xml b/packages/SettingsLib/res/values-nl/strings.xml
index 2f8c2c2..959c1ea 100644
--- a/packages/SettingsLib/res/values-nl/strings.xml
+++ b/packages/SettingsLib/res/values-nl/strings.xml
@@ -87,8 +87,8 @@
<string name="bluetooth_profile_sap" msgid="5764222021851283125">"Sim-toegang"</string>
<string name="bluetooth_profile_a2dp_high_quality" msgid="5444517801472820055">"HD-audio: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
<string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="8510588052415438887">"HD-audio"</string>
- <string name="bluetooth_profile_hearing_aid" msgid="7999237886427812595">"Gehoorapparaat"</string>
- <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="7188282786730266159">"Verbonden met gehoorapparaat"</string>
+ <string name="bluetooth_profile_hearing_aid" msgid="6680721080542444257">"Gehoorapparaten"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="3051944447369418317">"Verbonden met gehoorapparaten"</string>
<string name="bluetooth_a2dp_profile_summary_connected" msgid="963376081347721598">"Verbonden met audio van medium"</string>
<string name="bluetooth_headset_profile_summary_connected" msgid="7661070206715520671">"Verbonden met audio van telefoon"</string>
<string name="bluetooth_opp_profile_summary_connected" msgid="2611913495968309066">"Verbonden met server voor bestandsoverdracht"</string>
@@ -105,7 +105,7 @@
<string name="bluetooth_headset_profile_summary_use_for" msgid="8705753622443862627">"Gebruiken voor audio van telefoon"</string>
<string name="bluetooth_opp_profile_summary_use_for" msgid="1255674547144769756">"Gebruiken voor bestandsoverdracht"</string>
<string name="bluetooth_hid_profile_summary_use_for" msgid="232727040453645139">"Gebruiken voor invoer"</string>
- <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="908775281788309484">"Gebruiken voor gehoorapparaat"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="8843499209204010224">"Gebruiken voor gehoorapparaten"</string>
<string name="bluetooth_pairing_accept" msgid="6163520056536604875">"Koppelen"</string>
<string name="bluetooth_pairing_accept_all_caps" msgid="6061699265220789149">"KOPPELEN"</string>
<string name="bluetooth_pairing_decline" msgid="4185420413578948140">"Annuleren"</string>
@@ -136,6 +136,7 @@
<string name="process_kernel_label" msgid="3916858646836739323">"Android-besturingssysteem"</string>
<string name="data_usage_uninstalled_apps" msgid="614263770923231598">"Verwijderde apps"</string>
<string name="data_usage_uninstalled_apps_users" msgid="7986294489899813194">"Verwijderde apps en gebruikers"</string>
+ <string name="data_usage_ota" msgid="5377889154805560860">"Systeemupdates"</string>
<string name="tether_settings_title_usb" msgid="6688416425801386511">"USB-tethering"</string>
<string name="tether_settings_title_wifi" msgid="3277144155960302049">"Draagbare hotspot"</string>
<string name="tether_settings_title_bluetooth" msgid="355855408317564420">"Bluetooth-tethering"</string>
diff --git a/packages/SettingsLib/res/values-or/strings.xml b/packages/SettingsLib/res/values-or/strings.xml
index 95ab7bb..54ddf84 100644
--- a/packages/SettingsLib/res/values-or/strings.xml
+++ b/packages/SettingsLib/res/values-or/strings.xml
@@ -38,27 +38,20 @@
<string name="connected_via_network_scorer" msgid="5713793306870815341">"%1$s ମାଧ୍ୟମରେ ଅଟୋମେଟିକାଲୀ ସଂଯୁକ୍ତ"</string>
<string name="connected_via_network_scorer_default" msgid="7867260222020343104">"ନେଟୱର୍କ ମୂଲ୍ୟାୟନ ପ୍ରଦାତାଙ୍କ ମାଧ୍ୟମରେ ଅଟୋମେଟିକାଲ୍ୟ ସଂଯୁକ୍ତ"</string>
<string name="connected_via_passpoint" msgid="2826205693803088747">"%1$s ମାଧ୍ୟମରେ ସଂଯୁକ୍ତ"</string>
- <!-- no translation found for connected_via_app (5571999941988929520) -->
- <skip />
+ <string name="connected_via_app" msgid="5571999941988929520">"<xliff:g id="NAME">%1$s</xliff:g> ଦ୍ବାରା ସଂଯୋଗ କରାଯାଇଛି"</string>
<string name="available_via_passpoint" msgid="1617440946846329613">"%1$s ମାଧ୍ୟମରେ ଉପଲବ୍ଧ"</string>
- <!-- no translation found for tap_to_sign_up (6449724763052579434) -->
- <skip />
+ <string name="tap_to_sign_up" msgid="6449724763052579434">"ସାଇନ୍ ଅପ୍ ପାଇଁ ଟାପ୍ କରନ୍ତୁ"</string>
<string name="wifi_connected_no_internet" msgid="8202906332837777829">"ସଂଯୁକ୍ତ, ଇଣ୍ଟର୍ନେଟ୍ ନାହିଁ"</string>
<string name="wifi_status_no_internet" msgid="5784710974669608361">"କୌଣସି ଇଣ୍ଟରନେଟ୍ ନାହିଁ"</string>
<string name="wifi_status_sign_in_required" msgid="123517180404752756">"ସାଇନ୍-ଇନ୍ ଆବଶ୍ୟକ"</string>
<string name="wifi_ap_unable_to_handle_new_sta" msgid="5348824313514404541">"ଆକ୍ସେସ୍ ପଏଣ୍ଟ ସାମୟିକ ଭାବେ ପୂର୍ଣ୍ଣ"</string>
<string name="connected_via_carrier" msgid="7583780074526041912">"%1$s ମାଧ୍ୟମରେ ସଂଯୁକ୍ତ"</string>
<string name="available_via_carrier" msgid="1469036129740799053">"%1$s ମାଧ୍ୟମରେ ଉପଲବ୍ଧ"</string>
- <!-- no translation found for osu_opening_provider (5488997661548640424) -->
- <skip />
- <!-- no translation found for osu_connect_failed (2187750899158158934) -->
- <skip />
- <!-- no translation found for osu_completing_sign_up (9037638564719197082) -->
- <skip />
- <!-- no translation found for osu_sign_up_failed (7296159750352873260) -->
- <skip />
- <!-- no translation found for osu_sign_up_complete (8207626049093289203) -->
- <skip />
+ <string name="osu_opening_provider" msgid="5488997661548640424">"<xliff:g id="PASSPOINTPROVIDER">%1$s</xliff:g> ଖୋଲୁଛି"</string>
+ <string name="osu_connect_failed" msgid="2187750899158158934">"ସଂଯୋଗ କରିହେଲା ନାହିଁ"</string>
+ <string name="osu_completing_sign_up" msgid="9037638564719197082">"ସାଇନ୍ ଅପ୍ ଶେଷ ହେଉଛି…"</string>
+ <string name="osu_sign_up_failed" msgid="7296159750352873260">"ସାଇନ୍ ଅପ୍ ଶେଷ ହୋଇପାରିଲା ନାହିଁ। ପୁଣି ଥରେ ଚେଷ୍ଟା କରିବା ପାଇଁ ଟାପ୍ କରନ୍ତୁ।"</string>
+ <string name="osu_sign_up_complete" msgid="8207626049093289203">"ସାଇନ୍ ଅପ୍ ଶେଷ ହୋଇଛି। ସଂଯୋଗ କରୁଛି…"</string>
<string name="speed_label_very_slow" msgid="1867055264243608530">"ବହୁତ ମନ୍ଥର"</string>
<string name="speed_label_slow" msgid="813109590815810235">"କମ୍ ବେଗ"</string>
<string name="speed_label_okay" msgid="2331665440671174858">"ଠିକ୍ ଅଛି"</string>
@@ -94,8 +87,8 @@
<string name="bluetooth_profile_sap" msgid="5764222021851283125">"ସିମ୍ ଆକ୍ସେସ୍"</string>
<string name="bluetooth_profile_a2dp_high_quality" msgid="5444517801472820055">"HD ଅଡିଓ: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
<string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="8510588052415438887">"HD ଅଡିଓ"</string>
- <string name="bluetooth_profile_hearing_aid" msgid="7999237886427812595">"ଶ୍ରବଣ ଯନ୍ତ୍ର"</string>
- <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="7188282786730266159">"ଶ୍ରବଣ ଯନ୍ତ୍ର ସହିତ ସଂଯୁକ୍ତ ହେଲା"</string>
+ <string name="bluetooth_profile_hearing_aid" msgid="6680721080542444257">"ଶ୍ରବଣ ଯନ୍ତ୍ର"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="3051944447369418317">"ଶ୍ରବଣ ଯନ୍ତ୍ରକୁ ସଂଯୋଗ ହୋଇଛି"</string>
<string name="bluetooth_a2dp_profile_summary_connected" msgid="963376081347721598">"ମିଡିଆ ଅଡିଓ ସହ ସଂଯୁକ୍ତ"</string>
<string name="bluetooth_headset_profile_summary_connected" msgid="7661070206715520671">"ଫୋନ୍ ଅଡିଓ ସହିତ ସଂଯୁକ୍ତ"</string>
<string name="bluetooth_opp_profile_summary_connected" msgid="2611913495968309066">"ଫାଇଲ୍ ଟ୍ରାନ୍ସଫର୍ ସର୍ଭର୍ ସହ ସଂଯୁକ୍ତ"</string>
@@ -112,7 +105,7 @@
<string name="bluetooth_headset_profile_summary_use_for" msgid="8705753622443862627">"ଫୋନ୍ ଅଡିଓ ପାଇଁ ବ୍ୟବହାର କର"</string>
<string name="bluetooth_opp_profile_summary_use_for" msgid="1255674547144769756">"ଫାଇଲ୍ ଟ୍ରାନ୍ସଫର୍ ପାଇଁ ବ୍ୟବହାର କରନ୍ତୁ"</string>
<string name="bluetooth_hid_profile_summary_use_for" msgid="232727040453645139">"ଇନ୍ପୁଟ୍ ପାଇଁ ବ୍ୟବହାର କରନ୍ତୁ"</string>
- <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="908775281788309484">"ଶ୍ରବଣ ଯନ୍ତ୍ର ପାଇଁ ବ୍ୟବହାର କରନ୍ତୁ"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="8843499209204010224">"ଶ୍ରବଣ ଯନ୍ତ୍ର ପାଇଁ ବ୍ୟବହାର କରନ୍ତୁ"</string>
<string name="bluetooth_pairing_accept" msgid="6163520056536604875">"ପେୟାର୍"</string>
<string name="bluetooth_pairing_accept_all_caps" msgid="6061699265220789149">"ପେୟାର୍"</string>
<string name="bluetooth_pairing_decline" msgid="4185420413578948140">"କ୍ୟାନ୍ସଲ୍ କରନ୍ତୁ"</string>
@@ -143,6 +136,8 @@
<string name="process_kernel_label" msgid="3916858646836739323">"Android OS"</string>
<string name="data_usage_uninstalled_apps" msgid="614263770923231598">"କଢ଼ାଯାଇଥିବା ଆପ୍ଗୁଡ଼ିକ"</string>
<string name="data_usage_uninstalled_apps_users" msgid="7986294489899813194">"ଆପ୍ ଏବଂ ଉପଯୋଗକର୍ତ୍ତା ବାହାର କରାଗଲା"</string>
+ <!-- no translation found for data_usage_ota (5377889154805560860) -->
+ <skip />
<string name="tether_settings_title_usb" msgid="6688416425801386511">"USB ଟିଥରିଙ୍ଗ"</string>
<string name="tether_settings_title_wifi" msgid="3277144155960302049">"ପୋର୍ଟବଲ୍ ହଟସ୍ପଟ୍"</string>
<string name="tether_settings_title_bluetooth" msgid="355855408317564420">"ବ୍ଲୁଟୂଥ ଟିଥରିଙ୍ଗ"</string>
diff --git a/packages/SettingsLib/res/values-pa/strings.xml b/packages/SettingsLib/res/values-pa/strings.xml
index 1ddd862..dcf3e3c 100644
--- a/packages/SettingsLib/res/values-pa/strings.xml
+++ b/packages/SettingsLib/res/values-pa/strings.xml
@@ -38,27 +38,20 @@
<string name="connected_via_network_scorer" msgid="5713793306870815341">"%1$s ਰਾਹੀਂ ਆਪਣੇ-ਆਪ ਕਨੈਕਟ ਹੋਇਆ"</string>
<string name="connected_via_network_scorer_default" msgid="7867260222020343104">"ਨੈੱਟਵਰਕ ਰੇਟਿੰਗ ਪ੍ਰਦਾਨਕ ਰਾਹੀਂ ਸਵੈਚਲਿਤ ਤੌਰ \'ਤੇ ਕਨੈਕਟ ਹੋਇਆ"</string>
<string name="connected_via_passpoint" msgid="2826205693803088747">"%1$s ਰਾਹੀਂ ਕਨੈਕਟ ਕੀਤਾ"</string>
- <!-- no translation found for connected_via_app (5571999941988929520) -->
- <skip />
+ <string name="connected_via_app" msgid="5571999941988929520">"<xliff:g id="NAME">%1$s</xliff:g> ਰਾਹੀਂ ਕਨੈਕਟ ਕੀਤਾ ਗਿਆ"</string>
<string name="available_via_passpoint" msgid="1617440946846329613">"%1$s ਰਾਹੀਂ ਉਪਲਬਧ"</string>
- <!-- no translation found for tap_to_sign_up (6449724763052579434) -->
- <skip />
+ <string name="tap_to_sign_up" msgid="6449724763052579434">"ਸਾਈਨ-ਅੱਪ ਕਰਨ ਲਈ ਟੈਪ ਕਰੋ"</string>
<string name="wifi_connected_no_internet" msgid="8202906332837777829">"ਕਨੈਕਟ ਕੀਤਾ, ਕੋਈ ਇੰਟਰਨੈੱਟ ਨਹੀਂ"</string>
<string name="wifi_status_no_internet" msgid="5784710974669608361">"ਇੰਟਰਨੈੱਟ ਨਹੀਂ"</string>
<string name="wifi_status_sign_in_required" msgid="123517180404752756">"ਸਾਈਨ-ਇਨ ਲੋੜੀਂਦਾ ਹੈ"</string>
<string name="wifi_ap_unable_to_handle_new_sta" msgid="5348824313514404541">"ਐਕਸੈੱਸ ਪੁਆਇੰਟ ਅਸਥਾਈ ਤੌਰ \'ਤੇ ਸੰਪੂਰਨ ਰੁਝੇਂਵੇਂ ਵਿੱਚ ਹੈ"</string>
<string name="connected_via_carrier" msgid="7583780074526041912">"%1$s ਰਾਹੀਂ ਕਨੈਕਟ ਕੀਤਾ"</string>
<string name="available_via_carrier" msgid="1469036129740799053">"%1$s ਰਾਹੀਂ ਉਪਲਬਧ"</string>
- <!-- no translation found for osu_opening_provider (5488997661548640424) -->
- <skip />
- <!-- no translation found for osu_connect_failed (2187750899158158934) -->
- <skip />
- <!-- no translation found for osu_completing_sign_up (9037638564719197082) -->
- <skip />
- <!-- no translation found for osu_sign_up_failed (7296159750352873260) -->
- <skip />
- <!-- no translation found for osu_sign_up_complete (8207626049093289203) -->
- <skip />
+ <string name="osu_opening_provider" msgid="5488997661548640424">"<xliff:g id="PASSPOINTPROVIDER">%1$s</xliff:g> ਖੋਲ੍ਹਿਆ ਜਾ ਰਿਹਾ ਹੈ"</string>
+ <string name="osu_connect_failed" msgid="2187750899158158934">"ਕਨੈਕਟ ਨਹੀਂ ਕੀਤਾ ਜਾ ਸਕਿਆ"</string>
+ <string name="osu_completing_sign_up" msgid="9037638564719197082">"ਸਾਈਨ-ਅੱਪ ਮੁਕੰਮਲ ਕੀਤਾ ਜਾ ਰਿਹਾ ਹੈ…"</string>
+ <string name="osu_sign_up_failed" msgid="7296159750352873260">"ਸਾਈਨ-ਅੱਪ ਮੁਕੰਮਲ ਨਹੀਂ ਕੀਤਾ ਜਾ ਸਕਿਆ। ਦੁਬਾਰਾ ਕੋਸ਼ਿਸ਼ ਕਰਨ ਲਈ ਟੈਪ ਕਰੋ।"</string>
+ <string name="osu_sign_up_complete" msgid="8207626049093289203">"ਸਾਈਨ-ਅੱਪ ਮੁਕੰਮਲ ਹੋਇਆ ਕਨੈਕਟ ਹੋ ਰਿਹਾ ਹੈ…"</string>
<string name="speed_label_very_slow" msgid="1867055264243608530">"ਬਹੁਤ ਹੌਲੀ"</string>
<string name="speed_label_slow" msgid="813109590815810235">"ਹੌਲੀ"</string>
<string name="speed_label_okay" msgid="2331665440671174858">"ਠੀਕ ਹੈ"</string>
@@ -94,8 +87,8 @@
<string name="bluetooth_profile_sap" msgid="5764222021851283125">"ਸਿਮ ਪਹੁੰਚ"</string>
<string name="bluetooth_profile_a2dp_high_quality" msgid="5444517801472820055">"HD ਆਡੀਓ: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
<string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="8510588052415438887">"HD ਆਡੀਓ"</string>
- <string name="bluetooth_profile_hearing_aid" msgid="7999237886427812595">"ਸੁਣਨ ਦਾ ਸਾਧਨ"</string>
- <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="7188282786730266159">"ਸੁਣਨ ਦੇ ਸਾਧਨ ਨਾਲ ਕਨੈਕਟ ਕੀਤਾ ਗਿਆ"</string>
+ <string name="bluetooth_profile_hearing_aid" msgid="6680721080542444257">"ਸੁਣਨ ਦੇ ਸਾਧਨ"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="3051944447369418317">"ਸੁਣਨ ਦੇ ਸਾਧਨਾਂ ਨਾਲ ਕਨੈਕਟ ਕੀਤਾ ਗਿਆ"</string>
<string name="bluetooth_a2dp_profile_summary_connected" msgid="963376081347721598">"ਮੀਡੀਆ ਆਡੀਓ ਨਾਲ ਕਨੈਕਟ ਕੀਤਾ"</string>
<string name="bluetooth_headset_profile_summary_connected" msgid="7661070206715520671">"ਫ਼ੋਨ ਔਡੀਓ ਨਾਲ ਕਨੈਕਟ ਕੀਤਾ"</string>
<string name="bluetooth_opp_profile_summary_connected" msgid="2611913495968309066">"ਫਾਈਲ ਟ੍ਰਾਂਸਫ਼ਰ ਸਰਵਰ ਨਾਲ ਕਨੈਕਟ ਕੀਤਾ"</string>
@@ -112,7 +105,7 @@
<string name="bluetooth_headset_profile_summary_use_for" msgid="8705753622443862627">"ਫ਼ੋਨ ਔਡੀਓ ਲਈ ਵਰਤੋ"</string>
<string name="bluetooth_opp_profile_summary_use_for" msgid="1255674547144769756">"ਫਾਈਲ ਟ੍ਰਾਂਸਫਰ ਲਈ ਵਰਤੋ"</string>
<string name="bluetooth_hid_profile_summary_use_for" msgid="232727040453645139">"ਇਨਪੁਟ ਲਈ ਵਰਤੋ"</string>
- <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="908775281788309484">"ਸੁਣਨ ਦੇ ਸਾਧਨ ਲਈ ਵਰਤੋ"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="8843499209204010224">"ਸੁਣਨ ਦੇ ਸਾਧਨਾਂ ਲਈ ਵਰਤੋ"</string>
<string name="bluetooth_pairing_accept" msgid="6163520056536604875">"ਪੇਅਰ ਕਰੋ"</string>
<string name="bluetooth_pairing_accept_all_caps" msgid="6061699265220789149">"ਪੇਅਰ ਕਰੋ"</string>
<string name="bluetooth_pairing_decline" msgid="4185420413578948140">"ਰੱਦ ਕਰੋ"</string>
@@ -143,6 +136,8 @@
<string name="process_kernel_label" msgid="3916858646836739323">"Android OS"</string>
<string name="data_usage_uninstalled_apps" msgid="614263770923231598">"ਹਟਾਏ ਗਏ ਐਪਸ"</string>
<string name="data_usage_uninstalled_apps_users" msgid="7986294489899813194">"ਹਟਾਏ ਗਏ ਐਪਸ ਅਤੇ ਉਪਭੋਗਤਾ"</string>
+ <!-- no translation found for data_usage_ota (5377889154805560860) -->
+ <skip />
<string name="tether_settings_title_usb" msgid="6688416425801386511">"USB ਟੈਦਰਿੰਗ"</string>
<string name="tether_settings_title_wifi" msgid="3277144155960302049">"ਪੋਰਟੇਬਲ ਹੌਟਸਪੌਟ"</string>
<string name="tether_settings_title_bluetooth" msgid="355855408317564420">"ਬਲੂਟੁੱਥ ਟੈਦਰਿੰਗ"</string>
diff --git a/packages/SettingsLib/res/values-pl/strings.xml b/packages/SettingsLib/res/values-pl/strings.xml
index e2109c8..505e395 100644
--- a/packages/SettingsLib/res/values-pl/strings.xml
+++ b/packages/SettingsLib/res/values-pl/strings.xml
@@ -87,8 +87,8 @@
<string name="bluetooth_profile_sap" msgid="5764222021851283125">"Dostęp do karty SIM"</string>
<string name="bluetooth_profile_a2dp_high_quality" msgid="5444517801472820055">"Dźwięk HD: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
<string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="8510588052415438887">"Dźwięk HD"</string>
- <string name="bluetooth_profile_hearing_aid" msgid="7999237886427812595">"Aparat słuchowy"</string>
- <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="7188282786730266159">"Po połączeniu z aparatem słuchowym"</string>
+ <string name="bluetooth_profile_hearing_aid" msgid="6680721080542444257">"Aparaty słuchowe"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="3051944447369418317">"Połączono z aparatami słuchowymi"</string>
<string name="bluetooth_a2dp_profile_summary_connected" msgid="963376081347721598">"Połączono z funkcją audio multimediów"</string>
<string name="bluetooth_headset_profile_summary_connected" msgid="7661070206715520671">"Połączono z funkcją audio telefonu"</string>
<string name="bluetooth_opp_profile_summary_connected" msgid="2611913495968309066">"Połączono z serwerem transferu plików"</string>
@@ -105,7 +105,7 @@
<string name="bluetooth_headset_profile_summary_use_for" msgid="8705753622443862627">"Użyj dla funkcji audio telefonu"</string>
<string name="bluetooth_opp_profile_summary_use_for" msgid="1255674547144769756">"Użyj do transferu plików"</string>
<string name="bluetooth_hid_profile_summary_use_for" msgid="232727040453645139">"Użyj do wprowadzania"</string>
- <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="908775281788309484">"Użyj dla funkcji aparatu słuchowego"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="8843499209204010224">"Użyj z aparatami słuchowymi"</string>
<string name="bluetooth_pairing_accept" msgid="6163520056536604875">"Sparuj"</string>
<string name="bluetooth_pairing_accept_all_caps" msgid="6061699265220789149">"SPARUJ"</string>
<string name="bluetooth_pairing_decline" msgid="4185420413578948140">"Anuluj"</string>
@@ -136,6 +136,7 @@
<string name="process_kernel_label" msgid="3916858646836739323">"System operacyjny Android"</string>
<string name="data_usage_uninstalled_apps" msgid="614263770923231598">"Usunięte aplikacje"</string>
<string name="data_usage_uninstalled_apps_users" msgid="7986294489899813194">"Usunięte aplikacje i użytkownicy"</string>
+ <string name="data_usage_ota" msgid="5377889154805560860">"Aktualizacje systemu"</string>
<string name="tether_settings_title_usb" msgid="6688416425801386511">"Tethering przez USB"</string>
<string name="tether_settings_title_wifi" msgid="3277144155960302049">"Przenośny punkt dostępu"</string>
<string name="tether_settings_title_bluetooth" msgid="355855408317564420">"Tethering przez Bluetooth"</string>
diff --git a/packages/SettingsLib/res/values-pt-rBR/strings.xml b/packages/SettingsLib/res/values-pt-rBR/strings.xml
index 19e22e420..c0f31a6 100644
--- a/packages/SettingsLib/res/values-pt-rBR/strings.xml
+++ b/packages/SettingsLib/res/values-pt-rBR/strings.xml
@@ -87,8 +87,8 @@
<string name="bluetooth_profile_sap" msgid="5764222021851283125">"Acesso ao chip"</string>
<string name="bluetooth_profile_a2dp_high_quality" msgid="5444517801472820055">"Áudio HD: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
<string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="8510588052415438887">"Áudio HD"</string>
- <string name="bluetooth_profile_hearing_aid" msgid="7999237886427812595">"Aparelho auditivo"</string>
- <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="7188282786730266159">"Conectado a um aparelho auditivo"</string>
+ <string name="bluetooth_profile_hearing_aid" msgid="6680721080542444257">"Aparelhos auditivos"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="3051944447369418317">"Conectado a aparelhos auditivos"</string>
<string name="bluetooth_a2dp_profile_summary_connected" msgid="963376081347721598">"Conectado ao áudio da mídia"</string>
<string name="bluetooth_headset_profile_summary_connected" msgid="7661070206715520671">"Conectado ao áudio do smartphone"</string>
<string name="bluetooth_opp_profile_summary_connected" msgid="2611913495968309066">"Conectado ao servidor de transferência de arquivo"</string>
@@ -105,7 +105,7 @@
<string name="bluetooth_headset_profile_summary_use_for" msgid="8705753622443862627">"Usar para áudio do smartphone"</string>
<string name="bluetooth_opp_profile_summary_use_for" msgid="1255674547144769756">"Usado para transferência de arquivo"</string>
<string name="bluetooth_hid_profile_summary_use_for" msgid="232727040453645139">"Usar para entrada"</string>
- <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="908775281788309484">"Usar para aparelho auditivo"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="8843499209204010224">"Usar para aparelhos auditivos"</string>
<string name="bluetooth_pairing_accept" msgid="6163520056536604875">"Parear"</string>
<string name="bluetooth_pairing_accept_all_caps" msgid="6061699265220789149">"PAREAR"</string>
<string name="bluetooth_pairing_decline" msgid="4185420413578948140">"Cancelar"</string>
@@ -136,6 +136,7 @@
<string name="process_kernel_label" msgid="3916858646836739323">"Sistema operacional Android"</string>
<string name="data_usage_uninstalled_apps" msgid="614263770923231598">"Apps removidos"</string>
<string name="data_usage_uninstalled_apps_users" msgid="7986294489899813194">"Apps e usuários removidos"</string>
+ <string name="data_usage_ota" msgid="5377889154805560860">"Atualizações do sistema"</string>
<string name="tether_settings_title_usb" msgid="6688416425801386511">"Tethering USB"</string>
<string name="tether_settings_title_wifi" msgid="3277144155960302049">"Ponto de acesso portátil"</string>
<string name="tether_settings_title_bluetooth" msgid="355855408317564420">"Tethering Bluetooth"</string>
diff --git a/packages/SettingsLib/res/values-pt-rPT/strings.xml b/packages/SettingsLib/res/values-pt-rPT/strings.xml
index 1f1072c..08c3cc8 100644
--- a/packages/SettingsLib/res/values-pt-rPT/strings.xml
+++ b/packages/SettingsLib/res/values-pt-rPT/strings.xml
@@ -87,8 +87,8 @@
<string name="bluetooth_profile_sap" msgid="5764222021851283125">"Acesso ao SIM"</string>
<string name="bluetooth_profile_a2dp_high_quality" msgid="5444517801472820055">"Áudio HD: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
<string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="8510588052415438887">"Áudio HD"</string>
- <string name="bluetooth_profile_hearing_aid" msgid="7999237886427812595">"Aparelho auditivo"</string>
- <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="7188282786730266159">"Associar ao aparelho auditivo"</string>
+ <string name="bluetooth_profile_hearing_aid" msgid="6680721080542444257">"Aparelhos auditivos"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="3051944447369418317">"Ligado a aparelhos auditivos"</string>
<string name="bluetooth_a2dp_profile_summary_connected" msgid="963376081347721598">"Ligado ao áudio de multimédia"</string>
<string name="bluetooth_headset_profile_summary_connected" msgid="7661070206715520671">"Ligado ao áudio do telefone"</string>
<string name="bluetooth_opp_profile_summary_connected" msgid="2611913495968309066">"Ligado ao servidor de transferência de ficheiros"</string>
@@ -105,7 +105,7 @@
<string name="bluetooth_headset_profile_summary_use_for" msgid="8705753622443862627">"Utilizar para áudio do telefone"</string>
<string name="bluetooth_opp_profile_summary_use_for" msgid="1255674547144769756">"Utilizar para transferência de ficheiros"</string>
<string name="bluetooth_hid_profile_summary_use_for" msgid="232727040453645139">"Utilizar para entrada"</string>
- <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="908775281788309484">"Utilizar com o aparelho auditivo"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="8843499209204010224">"Utilizar para aparelhos auditivos"</string>
<string name="bluetooth_pairing_accept" msgid="6163520056536604875">"Sincr."</string>
<string name="bluetooth_pairing_accept_all_caps" msgid="6061699265220789149">"SINCRONIZAR"</string>
<string name="bluetooth_pairing_decline" msgid="4185420413578948140">"Cancelar"</string>
@@ -136,6 +136,7 @@
<string name="process_kernel_label" msgid="3916858646836739323">"SO Android"</string>
<string name="data_usage_uninstalled_apps" msgid="614263770923231598">"Aplicações removidas"</string>
<string name="data_usage_uninstalled_apps_users" msgid="7986294489899813194">"Aplicações e utilizadores removidos"</string>
+ <string name="data_usage_ota" msgid="5377889154805560860">"Atualizações do sistema"</string>
<string name="tether_settings_title_usb" msgid="6688416425801386511">"Ligação USB"</string>
<string name="tether_settings_title_wifi" msgid="3277144155960302049">"Hotspot portátil"</string>
<string name="tether_settings_title_bluetooth" msgid="355855408317564420">"Ligação Bluetooth"</string>
diff --git a/packages/SettingsLib/res/values-pt/strings.xml b/packages/SettingsLib/res/values-pt/strings.xml
index 19e22e420..c0f31a6 100644
--- a/packages/SettingsLib/res/values-pt/strings.xml
+++ b/packages/SettingsLib/res/values-pt/strings.xml
@@ -87,8 +87,8 @@
<string name="bluetooth_profile_sap" msgid="5764222021851283125">"Acesso ao chip"</string>
<string name="bluetooth_profile_a2dp_high_quality" msgid="5444517801472820055">"Áudio HD: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
<string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="8510588052415438887">"Áudio HD"</string>
- <string name="bluetooth_profile_hearing_aid" msgid="7999237886427812595">"Aparelho auditivo"</string>
- <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="7188282786730266159">"Conectado a um aparelho auditivo"</string>
+ <string name="bluetooth_profile_hearing_aid" msgid="6680721080542444257">"Aparelhos auditivos"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="3051944447369418317">"Conectado a aparelhos auditivos"</string>
<string name="bluetooth_a2dp_profile_summary_connected" msgid="963376081347721598">"Conectado ao áudio da mídia"</string>
<string name="bluetooth_headset_profile_summary_connected" msgid="7661070206715520671">"Conectado ao áudio do smartphone"</string>
<string name="bluetooth_opp_profile_summary_connected" msgid="2611913495968309066">"Conectado ao servidor de transferência de arquivo"</string>
@@ -105,7 +105,7 @@
<string name="bluetooth_headset_profile_summary_use_for" msgid="8705753622443862627">"Usar para áudio do smartphone"</string>
<string name="bluetooth_opp_profile_summary_use_for" msgid="1255674547144769756">"Usado para transferência de arquivo"</string>
<string name="bluetooth_hid_profile_summary_use_for" msgid="232727040453645139">"Usar para entrada"</string>
- <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="908775281788309484">"Usar para aparelho auditivo"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="8843499209204010224">"Usar para aparelhos auditivos"</string>
<string name="bluetooth_pairing_accept" msgid="6163520056536604875">"Parear"</string>
<string name="bluetooth_pairing_accept_all_caps" msgid="6061699265220789149">"PAREAR"</string>
<string name="bluetooth_pairing_decline" msgid="4185420413578948140">"Cancelar"</string>
@@ -136,6 +136,7 @@
<string name="process_kernel_label" msgid="3916858646836739323">"Sistema operacional Android"</string>
<string name="data_usage_uninstalled_apps" msgid="614263770923231598">"Apps removidos"</string>
<string name="data_usage_uninstalled_apps_users" msgid="7986294489899813194">"Apps e usuários removidos"</string>
+ <string name="data_usage_ota" msgid="5377889154805560860">"Atualizações do sistema"</string>
<string name="tether_settings_title_usb" msgid="6688416425801386511">"Tethering USB"</string>
<string name="tether_settings_title_wifi" msgid="3277144155960302049">"Ponto de acesso portátil"</string>
<string name="tether_settings_title_bluetooth" msgid="355855408317564420">"Tethering Bluetooth"</string>
diff --git a/packages/SettingsLib/res/values-ro/strings.xml b/packages/SettingsLib/res/values-ro/strings.xml
index 7fa75a8..015eb92 100644
--- a/packages/SettingsLib/res/values-ro/strings.xml
+++ b/packages/SettingsLib/res/values-ro/strings.xml
@@ -87,8 +87,8 @@
<string name="bluetooth_profile_sap" msgid="5764222021851283125">"Acces la SIM"</string>
<string name="bluetooth_profile_a2dp_high_quality" msgid="5444517801472820055">"Audio HD: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
<string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="8510588052415438887">"Audio HD"</string>
- <string name="bluetooth_profile_hearing_aid" msgid="7999237886427812595">"Aparat auditiv"</string>
- <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="7188282786730266159">"Conectat la aparatul auditiv"</string>
+ <string name="bluetooth_profile_hearing_aid" msgid="6680721080542444257">"Aparate auditive"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="3051944447369418317">"Conectat la aparatul auditiv"</string>
<string name="bluetooth_a2dp_profile_summary_connected" msgid="963376081347721598">"Conectat la profilul pentru conținut media audio"</string>
<string name="bluetooth_headset_profile_summary_connected" msgid="7661070206715520671">"Conectat la componenta audio a telefonului"</string>
<string name="bluetooth_opp_profile_summary_connected" msgid="2611913495968309066">"Conectat la serverul de transfer de fișiere"</string>
@@ -105,7 +105,7 @@
<string name="bluetooth_headset_profile_summary_use_for" msgid="8705753622443862627">"Utilizați pentru componenta audio a telefonului"</string>
<string name="bluetooth_opp_profile_summary_use_for" msgid="1255674547144769756">"Utilizați pentru transferul de fișiere"</string>
<string name="bluetooth_hid_profile_summary_use_for" msgid="232727040453645139">"Utilizați pentru introducere date"</string>
- <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="908775281788309484">"Utilizați pentru aparatul auditiv"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="8843499209204010224">"Folosiți pentru aparatele auditive"</string>
<string name="bluetooth_pairing_accept" msgid="6163520056536604875">"Asociați"</string>
<string name="bluetooth_pairing_accept_all_caps" msgid="6061699265220789149">"CONECTAȚI"</string>
<string name="bluetooth_pairing_decline" msgid="4185420413578948140">"Anulați"</string>
@@ -136,6 +136,7 @@
<string name="process_kernel_label" msgid="3916858646836739323">"Sistem de operare Android"</string>
<string name="data_usage_uninstalled_apps" msgid="614263770923231598">"Aplicații eliminate"</string>
<string name="data_usage_uninstalled_apps_users" msgid="7986294489899813194">"Aplicații și utilizatori eliminați"</string>
+ <string name="data_usage_ota" msgid="5377889154805560860">"Actualizări de sistem"</string>
<string name="tether_settings_title_usb" msgid="6688416425801386511">"Tethering prin USB"</string>
<string name="tether_settings_title_wifi" msgid="3277144155960302049">"Hotspot portabil"</string>
<string name="tether_settings_title_bluetooth" msgid="355855408317564420">"Tethering prin Bluetooth"</string>
diff --git a/packages/SettingsLib/res/values-ru/strings.xml b/packages/SettingsLib/res/values-ru/strings.xml
index 6cdfd3c..b0b592c 100644
--- a/packages/SettingsLib/res/values-ru/strings.xml
+++ b/packages/SettingsLib/res/values-ru/strings.xml
@@ -87,8 +87,8 @@
<string name="bluetooth_profile_sap" msgid="5764222021851283125">"Доступ к SIM-карте"</string>
<string name="bluetooth_profile_a2dp_high_quality" msgid="5444517801472820055">"HD Audio: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
<string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="8510588052415438887">"HD Audio"</string>
- <string name="bluetooth_profile_hearing_aid" msgid="7999237886427812595">"Слуховой аппарат"</string>
- <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="7188282786730266159">"Подключен к слуховому аппарату"</string>
+ <string name="bluetooth_profile_hearing_aid" msgid="6680721080542444257">"Слуховые аппараты"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="3051944447369418317">"Слуховой аппарат подключен"</string>
<string name="bluetooth_a2dp_profile_summary_connected" msgid="963376081347721598">"Подключено к мультимедийному аудиоустройству"</string>
<string name="bluetooth_headset_profile_summary_connected" msgid="7661070206715520671">"Подключено к аудиоустройству телефона"</string>
<string name="bluetooth_opp_profile_summary_connected" msgid="2611913495968309066">"Установлено подключение к серверу передачи файлов"</string>
@@ -105,7 +105,7 @@
<string name="bluetooth_headset_profile_summary_use_for" msgid="8705753622443862627">"Использовать для аудиоустройства телефона"</string>
<string name="bluetooth_opp_profile_summary_use_for" msgid="1255674547144769756">"Используется для передачи файлов"</string>
<string name="bluetooth_hid_profile_summary_use_for" msgid="232727040453645139">"Использовать для ввода"</string>
- <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="908775281788309484">"Использовать для слухового аппарата"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="8843499209204010224">"Использовать для слухового аппарата"</string>
<string name="bluetooth_pairing_accept" msgid="6163520056536604875">"Добавить"</string>
<string name="bluetooth_pairing_accept_all_caps" msgid="6061699265220789149">"ДОБАВИТЬ"</string>
<string name="bluetooth_pairing_decline" msgid="4185420413578948140">"Отмена"</string>
@@ -136,6 +136,7 @@
<string name="process_kernel_label" msgid="3916858646836739323">"ОС Android"</string>
<string name="data_usage_uninstalled_apps" msgid="614263770923231598">"Удаленные приложения"</string>
<string name="data_usage_uninstalled_apps_users" msgid="7986294489899813194">"Удаленные приложения и пользователи"</string>
+ <string name="data_usage_ota" msgid="5377889154805560860">"Обновления системы"</string>
<string name="tether_settings_title_usb" msgid="6688416425801386511">"USB-модем"</string>
<string name="tether_settings_title_wifi" msgid="3277144155960302049">"Точка доступа Wi-Fi"</string>
<string name="tether_settings_title_bluetooth" msgid="355855408317564420">"Bluetooth-модем"</string>
diff --git a/packages/SettingsLib/res/values-si/strings.xml b/packages/SettingsLib/res/values-si/strings.xml
index f85289c..ca7a962 100644
--- a/packages/SettingsLib/res/values-si/strings.xml
+++ b/packages/SettingsLib/res/values-si/strings.xml
@@ -87,8 +87,8 @@
<string name="bluetooth_profile_sap" msgid="5764222021851283125">"SIM ප්රවේශය"</string>
<string name="bluetooth_profile_a2dp_high_quality" msgid="5444517801472820055">"HD ශ්රව්යය: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
<string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="8510588052415438887">"HD ශ්රව්යය"</string>
- <string name="bluetooth_profile_hearing_aid" msgid="7999237886427812595">"ශ්රවණාධාරකය"</string>
- <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="7188282786730266159">"ශ්රවණාධාරකයට සම්බන්ධයි"</string>
+ <string name="bluetooth_profile_hearing_aid" msgid="6680721080542444257">"ශ්රවණාධාරක"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="3051944447369418317">"ශ්රවණාධාරක වෙත සම්බන්ධ කළා"</string>
<string name="bluetooth_a2dp_profile_summary_connected" msgid="963376081347721598">"මාධ්ය ශ්රව්යට සම්බන්ධ විය"</string>
<string name="bluetooth_headset_profile_summary_connected" msgid="7661070206715520671">"දුරකතනයේ ශ්රව්යට සම්බන්ධ විය"</string>
<string name="bluetooth_opp_profile_summary_connected" msgid="2611913495968309066">"ගොනු හුවමාරු සේවාදායකය සමග සම්බන්ධ විය"</string>
@@ -105,7 +105,7 @@
<string name="bluetooth_headset_profile_summary_use_for" msgid="8705753622443862627">"දුරකථන ශ්රව්ය සඳහා භාවිතා කෙරේ"</string>
<string name="bluetooth_opp_profile_summary_use_for" msgid="1255674547144769756">"ගොනු හුවමාරුව සඳහා භාවිතා කරන්න"</string>
<string name="bluetooth_hid_profile_summary_use_for" msgid="232727040453645139">"ආදානය සඳහා භාවිතා කරන්න"</string>
- <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="908775281788309484">"ශ්රවණාධාරකය සඳහා භාවිත කරන්න"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="8843499209204010224">"ශ්රවණාධාර සඳහා භාවිත කරන්න"</string>
<string name="bluetooth_pairing_accept" msgid="6163520056536604875">"යුගල කරන්න"</string>
<string name="bluetooth_pairing_accept_all_caps" msgid="6061699265220789149">"යුගල කරන්න"</string>
<string name="bluetooth_pairing_decline" msgid="4185420413578948140">"අවලංගු කරන්න"</string>
@@ -136,6 +136,7 @@
<string name="process_kernel_label" msgid="3916858646836739323">"Android OS"</string>
<string name="data_usage_uninstalled_apps" msgid="614263770923231598">"ඉවත් කළ යෙදුම්"</string>
<string name="data_usage_uninstalled_apps_users" msgid="7986294489899813194">"යෙදුම් සහ පරිශීලකයින් ඉවත් කරන ලදි"</string>
+ <string name="data_usage_ota" msgid="5377889154805560860">"පද්ධති යාවත්කාලීන"</string>
<string name="tether_settings_title_usb" msgid="6688416425801386511">"USB ටෙදරින්"</string>
<string name="tether_settings_title_wifi" msgid="3277144155960302049">"ජංගම හොට්ස්පොට්"</string>
<string name="tether_settings_title_bluetooth" msgid="355855408317564420">"බ්ලූටූත් ටෙදරින්"</string>
diff --git a/packages/SettingsLib/res/values-sk/strings.xml b/packages/SettingsLib/res/values-sk/strings.xml
index eae5be7..dd7efdd 100644
--- a/packages/SettingsLib/res/values-sk/strings.xml
+++ b/packages/SettingsLib/res/values-sk/strings.xml
@@ -87,8 +87,8 @@
<string name="bluetooth_profile_sap" msgid="5764222021851283125">"Prístup k SIM karte"</string>
<string name="bluetooth_profile_a2dp_high_quality" msgid="5444517801472820055">"HD zvuk: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
<string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="8510588052415438887">"HD zvuk"</string>
- <string name="bluetooth_profile_hearing_aid" msgid="7999237886427812595">"Načúvacia pomôcka"</string>
- <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="7188282786730266159">"Pripojené k načúvacej pomôcke"</string>
+ <string name="bluetooth_profile_hearing_aid" msgid="6680721080542444257">"Načúvacie pomôcky"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="3051944447369418317">"Pripojené k načúvacím pomôckam"</string>
<string name="bluetooth_a2dp_profile_summary_connected" msgid="963376081347721598">"Pripojené ku zvukovému médiu"</string>
<string name="bluetooth_headset_profile_summary_connected" msgid="7661070206715520671">"Pripojené ku zvuku telefónu"</string>
<string name="bluetooth_opp_profile_summary_connected" msgid="2611913495968309066">"Pripojené na server pre prenos údajov"</string>
@@ -105,7 +105,7 @@
<string name="bluetooth_headset_profile_summary_use_for" msgid="8705753622443862627">"Použiť pre zvuk telefónu"</string>
<string name="bluetooth_opp_profile_summary_use_for" msgid="1255674547144769756">"Použiť na prenos súborov"</string>
<string name="bluetooth_hid_profile_summary_use_for" msgid="232727040453645139">"Použiť pre vstup"</string>
- <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="908775281788309484">"Použitie načúvacej pomôcky"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="8843499209204010224">"Použiť pre načúvacie pomôcky"</string>
<string name="bluetooth_pairing_accept" msgid="6163520056536604875">"Párovať"</string>
<string name="bluetooth_pairing_accept_all_caps" msgid="6061699265220789149">"PÁROVAŤ"</string>
<string name="bluetooth_pairing_decline" msgid="4185420413578948140">"Zrušiť"</string>
@@ -136,6 +136,7 @@
<string name="process_kernel_label" msgid="3916858646836739323">"OS Android"</string>
<string name="data_usage_uninstalled_apps" msgid="614263770923231598">"Odstránené aplikácie"</string>
<string name="data_usage_uninstalled_apps_users" msgid="7986294489899813194">"Odstránené aplikácie a používatelia"</string>
+ <string name="data_usage_ota" msgid="5377889154805560860">"Aktualizácie systému"</string>
<string name="tether_settings_title_usb" msgid="6688416425801386511">"Pripojenie cez USB"</string>
<string name="tether_settings_title_wifi" msgid="3277144155960302049">"Prenosný prístupový bod"</string>
<string name="tether_settings_title_bluetooth" msgid="355855408317564420">"Pripojenie cez Bluetooth"</string>
diff --git a/packages/SettingsLib/res/values-sl/strings.xml b/packages/SettingsLib/res/values-sl/strings.xml
index bef9a3e..fada686 100644
--- a/packages/SettingsLib/res/values-sl/strings.xml
+++ b/packages/SettingsLib/res/values-sl/strings.xml
@@ -87,8 +87,8 @@
<string name="bluetooth_profile_sap" msgid="5764222021851283125">"Dostop do kartice SIM"</string>
<string name="bluetooth_profile_a2dp_high_quality" msgid="5444517801472820055">"Zvok visoke kakovosti: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
<string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="8510588052415438887">"Zvok visoke kakovosti"</string>
- <string name="bluetooth_profile_hearing_aid" msgid="7999237886427812595">"Slušni pripomoček"</string>
- <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="7188282786730266159">"Povezava s slušnim pripomočkom je vzpostavljena"</string>
+ <string name="bluetooth_profile_hearing_aid" msgid="6680721080542444257">"Slušni pripomočki"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="3051944447369418317">"Povezava s slušnimi pripomočki je vzpostavljena"</string>
<string name="bluetooth_a2dp_profile_summary_connected" msgid="963376081347721598">"Povezan s profilom za predstavnostni zvok"</string>
<string name="bluetooth_headset_profile_summary_connected" msgid="7661070206715520671">"Povezava s profilom za zvok telefona vzpostavljena"</string>
<string name="bluetooth_opp_profile_summary_connected" msgid="2611913495968309066">"Povezava s strežnikom za prenos datotek je vzpostavljena"</string>
@@ -105,7 +105,7 @@
<string name="bluetooth_headset_profile_summary_use_for" msgid="8705753622443862627">"Uporabi za zvok telefona"</string>
<string name="bluetooth_opp_profile_summary_use_for" msgid="1255674547144769756">"Uporabi za prenos datotek"</string>
<string name="bluetooth_hid_profile_summary_use_for" msgid="232727040453645139">"Uporabi za vnos"</string>
- <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="908775281788309484">"Uporaba za slušni pripomoček"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="8843499209204010224">"Uporabi za slušne pripomočke"</string>
<string name="bluetooth_pairing_accept" msgid="6163520056536604875">"Seznani"</string>
<string name="bluetooth_pairing_accept_all_caps" msgid="6061699265220789149">"SEZNANI"</string>
<string name="bluetooth_pairing_decline" msgid="4185420413578948140">"Prekliči"</string>
@@ -136,6 +136,7 @@
<string name="process_kernel_label" msgid="3916858646836739323">"OS Android"</string>
<string name="data_usage_uninstalled_apps" msgid="614263770923231598">"Odstranjene aplikacije"</string>
<string name="data_usage_uninstalled_apps_users" msgid="7986294489899813194">"Odstranjene aplikacije in uporabniki"</string>
+ <string name="data_usage_ota" msgid="5377889154805560860">"Posodobitve sistema"</string>
<string name="tether_settings_title_usb" msgid="6688416425801386511">"Internet prek USB-ja"</string>
<string name="tether_settings_title_wifi" msgid="3277144155960302049">"Prenosna dostopna točka"</string>
<string name="tether_settings_title_bluetooth" msgid="355855408317564420">"Internet prek Bluetootha"</string>
diff --git a/packages/SettingsLib/res/values-sq/strings.xml b/packages/SettingsLib/res/values-sq/strings.xml
index 8bb67f9..2132767 100644
--- a/packages/SettingsLib/res/values-sq/strings.xml
+++ b/packages/SettingsLib/res/values-sq/strings.xml
@@ -87,8 +87,8 @@
<string name="bluetooth_profile_sap" msgid="5764222021851283125">"Qasje në kartën SIM"</string>
<string name="bluetooth_profile_a2dp_high_quality" msgid="5444517801472820055">"Audio HD: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
<string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="8510588052415438887">"Audio HD"</string>
- <string name="bluetooth_profile_hearing_aid" msgid="7999237886427812595">"Aparati i dëgjimit"</string>
- <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="7188282786730266159">"Lidhur me aparatin e dëgjimit"</string>
+ <string name="bluetooth_profile_hearing_aid" msgid="6680721080542444257">"Aparatet e dëgjimit"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="3051944447369418317">"Lidhur me aparatet e dëgjimit"</string>
<string name="bluetooth_a2dp_profile_summary_connected" msgid="963376081347721598">"U lidh me audion e medias"</string>
<string name="bluetooth_headset_profile_summary_connected" msgid="7661070206715520671">"U lidh me audion e telefonit"</string>
<string name="bluetooth_opp_profile_summary_connected" msgid="2611913495968309066">"U lidh me serverin e transferimit të skedarëve"</string>
@@ -105,7 +105,7 @@
<string name="bluetooth_headset_profile_summary_use_for" msgid="8705753622443862627">"Përdor për audion e telefonit"</string>
<string name="bluetooth_opp_profile_summary_use_for" msgid="1255674547144769756">"Përdor për transferimin e skedarëve"</string>
<string name="bluetooth_hid_profile_summary_use_for" msgid="232727040453645139">"Përdore për hyrjen"</string>
- <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="908775281788309484">"Përdore për aparatin e dëgjimit"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="8843499209204010224">"Përdore për aparatet e dëgjimit"</string>
<string name="bluetooth_pairing_accept" msgid="6163520056536604875">"Çifto"</string>
<string name="bluetooth_pairing_accept_all_caps" msgid="6061699265220789149">"ÇIFTO"</string>
<string name="bluetooth_pairing_decline" msgid="4185420413578948140">"Anulo"</string>
@@ -136,6 +136,7 @@
<string name="process_kernel_label" msgid="3916858646836739323">"Sistemi operativ Android"</string>
<string name="data_usage_uninstalled_apps" msgid="614263770923231598">"Aplikacionet e hequra"</string>
<string name="data_usage_uninstalled_apps_users" msgid="7986294489899813194">"Aplikacionet dhe përdoruesit e hequr"</string>
+ <string name="data_usage_ota" msgid="5377889154805560860">"Përditësimet e sistemit"</string>
<string name="tether_settings_title_usb" msgid="6688416425801386511">"Ndarje përmes USB-së"</string>
<string name="tether_settings_title_wifi" msgid="3277144155960302049">"Zona e qasjes e lëvizshme"</string>
<string name="tether_settings_title_bluetooth" msgid="355855408317564420">"Ndarje interneti përmes Bluetooth-it"</string>
diff --git a/packages/SettingsLib/res/values-sr/strings.xml b/packages/SettingsLib/res/values-sr/strings.xml
index 4378a46..6cf4b20 100644
--- a/packages/SettingsLib/res/values-sr/strings.xml
+++ b/packages/SettingsLib/res/values-sr/strings.xml
@@ -87,8 +87,8 @@
<string name="bluetooth_profile_sap" msgid="5764222021851283125">"Приступ SIM картици"</string>
<string name="bluetooth_profile_a2dp_high_quality" msgid="5444517801472820055">"HD звук: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
<string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="8510588052415438887">"HD звук"</string>
- <string name="bluetooth_profile_hearing_aid" msgid="7999237886427812595">"Слушни апарат"</string>
- <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="7188282786730266159">"Повезано са слушним апаратом"</string>
+ <string name="bluetooth_profile_hearing_aid" msgid="6680721080542444257">"Слушни апарати"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="3051944447369418317">"Повезано са слушним апаратима"</string>
<string name="bluetooth_a2dp_profile_summary_connected" msgid="963376081347721598">"Повезано са звуком медија"</string>
<string name="bluetooth_headset_profile_summary_connected" msgid="7661070206715520671">"Повезано са звуком телефона"</string>
<string name="bluetooth_opp_profile_summary_connected" msgid="2611913495968309066">"Повезано са сервером за пренос датотека"</string>
@@ -105,7 +105,7 @@
<string name="bluetooth_headset_profile_summary_use_for" msgid="8705753622443862627">"Коришћење за аудио телефона"</string>
<string name="bluetooth_opp_profile_summary_use_for" msgid="1255674547144769756">"Коришћење за пренос датотека"</string>
<string name="bluetooth_hid_profile_summary_use_for" msgid="232727040453645139">"Користи за улаз"</string>
- <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="908775281788309484">"Користи за слушни апарат"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="8843499209204010224">"Користи за слушне апарате"</string>
<string name="bluetooth_pairing_accept" msgid="6163520056536604875">"Упари"</string>
<string name="bluetooth_pairing_accept_all_caps" msgid="6061699265220789149">"УПАРИ"</string>
<string name="bluetooth_pairing_decline" msgid="4185420413578948140">"Откажи"</string>
@@ -136,6 +136,7 @@
<string name="process_kernel_label" msgid="3916858646836739323">"Android ОС"</string>
<string name="data_usage_uninstalled_apps" msgid="614263770923231598">"Уклоњене апликације"</string>
<string name="data_usage_uninstalled_apps_users" msgid="7986294489899813194">"Уклоњене апликације и корисници"</string>
+ <string name="data_usage_ota" msgid="5377889154805560860">"Ажурирања система"</string>
<string name="tether_settings_title_usb" msgid="6688416425801386511">"USB Интернет повезивање"</string>
<string name="tether_settings_title_wifi" msgid="3277144155960302049">"Преносни хотспот"</string>
<string name="tether_settings_title_bluetooth" msgid="355855408317564420">"Bluetooth привезивање"</string>
diff --git a/packages/SettingsLib/res/values-sv/strings.xml b/packages/SettingsLib/res/values-sv/strings.xml
index 3fcb6dc..f2950dc 100644
--- a/packages/SettingsLib/res/values-sv/strings.xml
+++ b/packages/SettingsLib/res/values-sv/strings.xml
@@ -87,8 +87,8 @@
<string name="bluetooth_profile_sap" msgid="5764222021851283125">"SIM-åtkomst"</string>
<string name="bluetooth_profile_a2dp_high_quality" msgid="5444517801472820055">"HD-ljud: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
<string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="8510588052415438887">"HD-ljud"</string>
- <string name="bluetooth_profile_hearing_aid" msgid="7999237886427812595">"Hörapparat"</string>
- <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="7188282786730266159">"Ansluten till hörapparat"</string>
+ <string name="bluetooth_profile_hearing_aid" msgid="6680721080542444257">"Hörapparater"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="3051944447369418317">"Ansluten till hörapparater"</string>
<string name="bluetooth_a2dp_profile_summary_connected" msgid="963376081347721598">"Ansluten till medialjud"</string>
<string name="bluetooth_headset_profile_summary_connected" msgid="7661070206715520671">"Ansluten till telefonens ljud"</string>
<string name="bluetooth_opp_profile_summary_connected" msgid="2611913495968309066">"Ansluten till filöverföringsserver"</string>
@@ -105,7 +105,7 @@
<string name="bluetooth_headset_profile_summary_use_for" msgid="8705753622443862627">"Använd för telefonens ljud"</string>
<string name="bluetooth_opp_profile_summary_use_for" msgid="1255674547144769756">"Använd för filöverföring"</string>
<string name="bluetooth_hid_profile_summary_use_for" msgid="232727040453645139">"Använd för inmatning"</string>
- <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="908775281788309484">"Använd med hörapparat"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="8843499209204010224">"Använd med hörapparater"</string>
<string name="bluetooth_pairing_accept" msgid="6163520056536604875">"Parkoppling"</string>
<string name="bluetooth_pairing_accept_all_caps" msgid="6061699265220789149">"PARKOPPLA"</string>
<string name="bluetooth_pairing_decline" msgid="4185420413578948140">"Avbryt"</string>
@@ -136,6 +136,7 @@
<string name="process_kernel_label" msgid="3916858646836739323">"Operativsystemet Android"</string>
<string name="data_usage_uninstalled_apps" msgid="614263770923231598">"Borttagna appar"</string>
<string name="data_usage_uninstalled_apps_users" msgid="7986294489899813194">"Borttagna appar och användare"</string>
+ <string name="data_usage_ota" msgid="5377889154805560860">"Systemuppdateringar"</string>
<string name="tether_settings_title_usb" msgid="6688416425801386511">"Internetdelning via USB"</string>
<string name="tether_settings_title_wifi" msgid="3277144155960302049">"Mobil surfzon"</string>
<string name="tether_settings_title_bluetooth" msgid="355855408317564420">"Delning via Bluetooth"</string>
diff --git a/packages/SettingsLib/res/values-sw/strings.xml b/packages/SettingsLib/res/values-sw/strings.xml
index 47c7bb2..d8a74a1 100644
--- a/packages/SettingsLib/res/values-sw/strings.xml
+++ b/packages/SettingsLib/res/values-sw/strings.xml
@@ -87,8 +87,8 @@
<string name="bluetooth_profile_sap" msgid="5764222021851283125">"Ufikiaji wa SIM"</string>
<string name="bluetooth_profile_a2dp_high_quality" msgid="5444517801472820055">"Sauti ya HD: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
<string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="8510588052415438887">"Sauti ya HD"</string>
- <string name="bluetooth_profile_hearing_aid" msgid="7999237886427812595">"Visaidizi vya Kusikia"</string>
- <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="7188282786730266159">"Imeunganishwa kwenye Visaidizi vya Kusikia"</string>
+ <string name="bluetooth_profile_hearing_aid" msgid="6680721080542444257">"Vifaa vya Kusaidia Kusikia"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="3051944447369418317">"Imeunganishwa kwenye Vifaa vya Kusaidia Kusikia"</string>
<string name="bluetooth_a2dp_profile_summary_connected" msgid="963376081347721598">"Imeunganishwa kwenye sikika ya njia ya mawasiliano"</string>
<string name="bluetooth_headset_profile_summary_connected" msgid="7661070206715520671">"Imeunganishwa kwenye sauti ya simu"</string>
<string name="bluetooth_opp_profile_summary_connected" msgid="2611913495968309066">"Imeunganishwa kwenye seva ya kuhamisha faili"</string>
@@ -105,7 +105,7 @@
<string name="bluetooth_headset_profile_summary_use_for" msgid="8705753622443862627">"Tumia kwa sauti ya simu"</string>
<string name="bluetooth_opp_profile_summary_use_for" msgid="1255674547144769756">"Tumia kwa hali faili"</string>
<string name="bluetooth_hid_profile_summary_use_for" msgid="232727040453645139">"Tumia kwa kuingiza"</string>
- <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="908775281788309484">"Tumia katika Visaidizi vya Kusikia"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="8843499209204010224">"Tumia kwenye Vifaa vya Kusaidia Kusikia"</string>
<string name="bluetooth_pairing_accept" msgid="6163520056536604875">"Oanisha"</string>
<string name="bluetooth_pairing_accept_all_caps" msgid="6061699265220789149">"OANISHA"</string>
<string name="bluetooth_pairing_decline" msgid="4185420413578948140">"Ghairi"</string>
@@ -136,6 +136,7 @@
<string name="process_kernel_label" msgid="3916858646836739323">"OS ya Android"</string>
<string name="data_usage_uninstalled_apps" msgid="614263770923231598">"Programu zilizoondolewa"</string>
<string name="data_usage_uninstalled_apps_users" msgid="7986294489899813194">"Watumiaji na programu ziilizoondolewa"</string>
+ <string name="data_usage_ota" msgid="5377889154805560860">"Masasisho ya mfumo"</string>
<string name="tether_settings_title_usb" msgid="6688416425801386511">"Shiriki intaneti kwa USB"</string>
<string name="tether_settings_title_wifi" msgid="3277144155960302049">"Intaneti ya kusambazwa"</string>
<string name="tether_settings_title_bluetooth" msgid="355855408317564420">"Shiriki intaneti kwa Bluetooth"</string>
diff --git a/packages/SettingsLib/res/values-ta/strings.xml b/packages/SettingsLib/res/values-ta/strings.xml
index 63c6cd9..71716ce 100644
--- a/packages/SettingsLib/res/values-ta/strings.xml
+++ b/packages/SettingsLib/res/values-ta/strings.xml
@@ -38,27 +38,20 @@
<string name="connected_via_network_scorer" msgid="5713793306870815341">"%1$s மூலம் தானாக இணைக்கப்பட்டது"</string>
<string name="connected_via_network_scorer_default" msgid="7867260222020343104">"நெட்வொர்க் மதிப்பீடு வழங்குநரால் தானாக இணைக்கப்பட்டது"</string>
<string name="connected_via_passpoint" msgid="2826205693803088747">"%1$s வழியாக இணைக்கப்பட்டது"</string>
- <!-- no translation found for connected_via_app (5571999941988929520) -->
- <skip />
+ <string name="connected_via_app" msgid="5571999941988929520">"<xliff:g id="NAME">%1$s</xliff:g> மூலம் இணைக்கப்பட்டது"</string>
<string name="available_via_passpoint" msgid="1617440946846329613">"%1$s வழியாகக் கிடைக்கிறது"</string>
- <!-- no translation found for tap_to_sign_up (6449724763052579434) -->
- <skip />
+ <string name="tap_to_sign_up" msgid="6449724763052579434">"பதிவு செய்யத் தட்டவும்"</string>
<string name="wifi_connected_no_internet" msgid="8202906332837777829">"இணைக்கப்பட்டுள்ளது, ஆனால் இண்டர்நெட் இல்லை"</string>
<string name="wifi_status_no_internet" msgid="5784710974669608361">"இணைய இணைப்பு இல்லை"</string>
<string name="wifi_status_sign_in_required" msgid="123517180404752756">"உள்நுழைய வேண்டும்"</string>
<string name="wifi_ap_unable_to_handle_new_sta" msgid="5348824313514404541">"தற்காலிகமாக அணுகல் புள்ளி நிரம்பியுள்ளது"</string>
<string name="connected_via_carrier" msgid="7583780074526041912">"%1$s வழியாக இணைக்கப்பட்டது"</string>
<string name="available_via_carrier" msgid="1469036129740799053">"%1$s வழியாகக் கிடைக்கிறது"</string>
- <!-- no translation found for osu_opening_provider (5488997661548640424) -->
- <skip />
- <!-- no translation found for osu_connect_failed (2187750899158158934) -->
- <skip />
- <!-- no translation found for osu_completing_sign_up (9037638564719197082) -->
- <skip />
- <!-- no translation found for osu_sign_up_failed (7296159750352873260) -->
- <skip />
- <!-- no translation found for osu_sign_up_complete (8207626049093289203) -->
- <skip />
+ <string name="osu_opening_provider" msgid="5488997661548640424">"<xliff:g id="PASSPOINTPROVIDER">%1$s</xliff:g> திறக்கப்படுகிறது"</string>
+ <string name="osu_connect_failed" msgid="2187750899158158934">"இணைக்க முடியவில்லை"</string>
+ <string name="osu_completing_sign_up" msgid="9037638564719197082">"பதிவு செய்வது நிறைவடைகிறது…"</string>
+ <string name="osu_sign_up_failed" msgid="7296159750352873260">"பதிவு செய்வதை நிறைவுசெய்ய இயலவில்லை மீண்டும் முயற்சிக்கத் தட்டவும்."</string>
+ <string name="osu_sign_up_complete" msgid="8207626049093289203">"பதிவு செய்வது நிறைவடைந்தது. இணைக்கிறது…"</string>
<string name="speed_label_very_slow" msgid="1867055264243608530">"மிகவும் வேகம் குறைவானது"</string>
<string name="speed_label_slow" msgid="813109590815810235">"வேகம் குறைவு"</string>
<string name="speed_label_okay" msgid="2331665440671174858">"சரி"</string>
@@ -94,8 +87,8 @@
<string name="bluetooth_profile_sap" msgid="5764222021851283125">"சிம் அணுகல்"</string>
<string name="bluetooth_profile_a2dp_high_quality" msgid="5444517801472820055">"HD ஆடியோ: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
<string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="8510588052415438887">"HD ஆடியோ"</string>
- <string name="bluetooth_profile_hearing_aid" msgid="7999237886427812595">"செவித்துணைக் கருவி"</string>
- <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="7188282786730266159">"செவித்துணைக் கருவியுடன் இணைக்கப்பட்டிருக்கிறது"</string>
+ <string name="bluetooth_profile_hearing_aid" msgid="6680721080542444257">"செவித்துணை கருவிகள்"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="3051944447369418317">"செவித்துணை கருவிகளுடன் இணைக்கப்பட்டது"</string>
<string name="bluetooth_a2dp_profile_summary_connected" msgid="963376081347721598">"மீடியா ஆடியோவுடன் இணைக்கப்பட்டது"</string>
<string name="bluetooth_headset_profile_summary_connected" msgid="7661070206715520671">"மொபைல் ஆடியோவுடன் இணைக்கப்பட்டது"</string>
<string name="bluetooth_opp_profile_summary_connected" msgid="2611913495968309066">"கோப்பைப் பரிமாற்றும் சேவையகத்துடன் இணைக்கப்பட்டது"</string>
@@ -112,7 +105,7 @@
<string name="bluetooth_headset_profile_summary_use_for" msgid="8705753622443862627">"மொபைல் ஆடியோவைப் பயன்படுத்து"</string>
<string name="bluetooth_opp_profile_summary_use_for" msgid="1255674547144769756">"கோப்பு பரிமாற்றத்திற்காகப் பயன்படுத்து"</string>
<string name="bluetooth_hid_profile_summary_use_for" msgid="232727040453645139">"உள்ளீட்டுக்குப் பயன்படுத்து"</string>
- <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="908775281788309484">"செவித்துணைக் கருவிக்காகப் பயன்படுத்து"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="8843499209204010224">"செவித்துணை கருவிகளுக்குப் பயன்படுத்தவும்"</string>
<string name="bluetooth_pairing_accept" msgid="6163520056536604875">"இணை"</string>
<string name="bluetooth_pairing_accept_all_caps" msgid="6061699265220789149">"இணை"</string>
<string name="bluetooth_pairing_decline" msgid="4185420413578948140">"ரத்துசெய்"</string>
@@ -143,6 +136,8 @@
<string name="process_kernel_label" msgid="3916858646836739323">"Android OS"</string>
<string name="data_usage_uninstalled_apps" msgid="614263770923231598">"அகற்றப்பட்ட பயன்பாடுகள்"</string>
<string name="data_usage_uninstalled_apps_users" msgid="7986294489899813194">"அகற்றப்பட்ட பயன்பாடுகள் மற்றும் பயனர்கள்"</string>
+ <!-- no translation found for data_usage_ota (5377889154805560860) -->
+ <skip />
<string name="tether_settings_title_usb" msgid="6688416425801386511">"USB டெதெரிங்"</string>
<string name="tether_settings_title_wifi" msgid="3277144155960302049">"போர்ட்டபிள் ஹாட்ஸ்பாட்"</string>
<string name="tether_settings_title_bluetooth" msgid="355855408317564420">"புளூடூத் டெதெரிங்"</string>
@@ -203,7 +198,7 @@
<string name="vpn_settings_not_available" msgid="956841430176985598">"இவரால் VPN அமைப்புகளை மாற்ற முடியாது"</string>
<string name="tethering_settings_not_available" msgid="6765770438438291012">"இவரால் இணைப்புமுறை அமைப்புகளை மாற்ற முடியாது"</string>
<string name="apn_settings_not_available" msgid="7873729032165324000">"இவரால் ஆக்சஸ் பாயிண்ட் நேம் அமைப்புகளை மாற்ற முடியாது"</string>
- <string name="enable_adb" msgid="7982306934419797485">"USB பிழைத்திருத்தம்"</string>
+ <string name="enable_adb" msgid="7982306934419797485">"USB பிழைதிருத்தம்"</string>
<string name="enable_adb_summary" msgid="4881186971746056635">"USB இணைக்கப்பட்டிருக்கும்போது பிழைத்திருத்தப் பயன்முறையை அமை"</string>
<string name="clear_adb_keys" msgid="4038889221503122743">"USB பிழைத்திருத்த அங்கீகரிப்புகளை நிராகரி"</string>
<string name="bugreport_in_power" msgid="7923901846375587241">"பிழைப் புகாருக்கான ஷார்ட்கட்"</string>
@@ -263,8 +258,8 @@
<string name="debug_view_attributes" msgid="6485448367803310384">"காட்சி பண்புக்கூறு சோதனையை இயக்கு"</string>
<string name="mobile_data_always_on_summary" msgid="8149773901431697910">"வைஃபை இயங்கும் போதும் (வேகமான நெட்வொர்க் மாற்றத்திற்கு), மொபைல் டேட்டாவை எப்போதும் இயக்கத்தில் வைக்கும்."</string>
<string name="tethering_hardware_offload_summary" msgid="7726082075333346982">"வன்பொருள் விரைவுப்படுத்துதல் இணைப்பு முறை கிடைக்கும் போது, அதைப் பயன்படுத்தும்"</string>
- <string name="adb_warning_title" msgid="6234463310896563253">"USB பிழைத்திருத்தத்தை அனுமதிக்கவா?"</string>
- <string name="adb_warning_message" msgid="7316799925425402244">"USB பிழைத்திருத்தம் மேம்படுத்தல் நோக்கங்களுக்காக மட்டுமே. அதை உங்கள் கணினி மற்றும் சாதனத்திற்கு இடையில் தரவை நகலெடுக்கவும், அறிவிப்பு இல்லாமல் உங்கள் சாதனத்தில் பயன்பாடுகளை நிறுவவும், பதிவு தரவைப் படிக்கவும் பயன்படுத்தவும்."</string>
+ <string name="adb_warning_title" msgid="6234463310896563253">"USB பிழைதிருத்தத்தை அனுமதிக்கவா?"</string>
+ <string name="adb_warning_message" msgid="7316799925425402244">"USB பிழைதிருத்தம் மேம்படுத்தல் நோக்கங்களுக்காக மட்டுமே. அதை உங்கள் கணினி மற்றும் சாதனத்திற்கு இடையில் தரவை நகலெடுக்கவும், அறிவிப்பு இல்லாமல் உங்கள் சாதனத்தில் பயன்பாடுகளை நிறுவவும், பதிவு தரவைப் படிக்கவும் பயன்படுத்தவும்."</string>
<string name="adb_keys_warning_message" msgid="5659849457135841625">"நீங்கள் ஏற்கனவே அனுமதித்த எல்லா கணினிகளிலிருந்தும் USB பிழைத்திருத்தத்திற்கான அணுகலைத் திரும்பப்பெற வேண்டுமா?"</string>
<string name="dev_settings_warning_title" msgid="7244607768088540165">"மேம்பட்ட அமைப்புகளை அனுமதிக்கவா?"</string>
<string name="dev_settings_warning_message" msgid="2298337781139097964">"இந்த அமைப்பு மேம்பட்டப் பயன்பாட்டிற்காக மட்டுமே. உங்கள் சாதனம் மற்றும் அதில் உள்ள பயன்பாடுகளைச் சிதைக்கும் அல்லது தவறாகச் செயல்படும் வகையில் பாதிப்பை ஏற்படுத்தும்."</string>
@@ -276,10 +271,10 @@
<string name="enable_terminal_summary" msgid="67667852659359206">"அக ஷெல் அணுகலை வழங்கும் இறுதிப் பயன்பாட்டை இயக்கு"</string>
<string name="hdcp_checking_title" msgid="8605478913544273282">"HDCP சரிபார்ப்பு"</string>
<string name="hdcp_checking_dialog_title" msgid="5141305530923283">"HDCP சரிபார்க்கும் செயல்பாடுகளை அமை"</string>
- <string name="debug_debugging_category" msgid="6781250159513471316">"பிழைத்திருத்தம்"</string>
+ <string name="debug_debugging_category" msgid="6781250159513471316">"பிழைதிருத்தம்"</string>
<string name="debug_app" msgid="8349591734751384446">"பிழைத்திருத்தப் பயன்பாட்டைத் தேர்ந்தெடுக்கவும்"</string>
<string name="debug_app_not_set" msgid="718752499586403499">"பிழைத்திருத்தப் பயன்பாடு அமைக்கப்படவில்லை"</string>
- <string name="debug_app_set" msgid="2063077997870280017">"பிழைத்திருத்தும் பயன்பாடு: <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+ <string name="debug_app_set" msgid="2063077997870280017">"பிழைதிருத்தும் பயன்பாடு: <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
<string name="select_application" msgid="5156029161289091703">"பயன்பாட்டைத் தேர்ந்தெடுக்கவும்"</string>
<string name="no_application" msgid="2813387563129153880">"ஒன்றுமில்லை"</string>
<string name="wait_for_debugger" msgid="1202370874528893091">"பிழைதிருத்திக்குக் காத்திருக்கவும்"</string>
diff --git a/packages/SettingsLib/res/values-te/strings.xml b/packages/SettingsLib/res/values-te/strings.xml
index d8ec167..e4dd85f 100644
--- a/packages/SettingsLib/res/values-te/strings.xml
+++ b/packages/SettingsLib/res/values-te/strings.xml
@@ -87,8 +87,8 @@
<string name="bluetooth_profile_sap" msgid="5764222021851283125">"SIM యాక్సెస్"</string>
<string name="bluetooth_profile_a2dp_high_quality" msgid="5444517801472820055">"HD ఆడియో: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
<string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="8510588052415438887">"HD ఆడియో"</string>
- <string name="bluetooth_profile_hearing_aid" msgid="7999237886427812595">"వినికిడి పరికరం"</string>
- <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="7188282786730266159">"వినికిడి పరికరానికి కనెక్ట్ చేస్తోంది"</string>
+ <string name="bluetooth_profile_hearing_aid" msgid="6680721080542444257">"వినికిడి మద్దతు ఉపకరణాలు"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="3051944447369418317">"వినికిడి మద్దతు ఉపకరణాలకు కనెక్ట్ చేయబడింది"</string>
<string name="bluetooth_a2dp_profile_summary_connected" msgid="963376081347721598">"మీడియా ఆడియోకు కనెక్ట్ చేయబడింది"</string>
<string name="bluetooth_headset_profile_summary_connected" msgid="7661070206715520671">"ఫోన్ ఆడియోకు కనెక్ట్ చేయబడింది"</string>
<string name="bluetooth_opp_profile_summary_connected" msgid="2611913495968309066">"ఫైల్ బదిలీ సర్వర్కు కనెక్ట్ చేయబడింది"</string>
@@ -105,7 +105,7 @@
<string name="bluetooth_headset_profile_summary_use_for" msgid="8705753622443862627">"ఫోన్ ఆడియో కోసం ఉపయోగించు"</string>
<string name="bluetooth_opp_profile_summary_use_for" msgid="1255674547144769756">"ఫైల్ బదిలీ కోసం ఉపయోగించు"</string>
<string name="bluetooth_hid_profile_summary_use_for" msgid="232727040453645139">"ఇన్పుట్ కోసం ఉపయోగించు"</string>
- <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="908775281788309484">"వినికిడి పరికరం కోసం ఉపయోగించు"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="8843499209204010224">"వినికిడి మద్దతు ఉపకరణాలకు ఉపయోగించండి"</string>
<string name="bluetooth_pairing_accept" msgid="6163520056536604875">"జత చేయి"</string>
<string name="bluetooth_pairing_accept_all_caps" msgid="6061699265220789149">"జత చేయి"</string>
<string name="bluetooth_pairing_decline" msgid="4185420413578948140">"రద్దు చేయి"</string>
@@ -136,6 +136,7 @@
<string name="process_kernel_label" msgid="3916858646836739323">"Android OS"</string>
<string name="data_usage_uninstalled_apps" msgid="614263770923231598">"తీసివేయబడిన అనువర్తనాలు"</string>
<string name="data_usage_uninstalled_apps_users" msgid="7986294489899813194">"తీసివేయబడిన అనువర్తనాలు మరియు వినియోగదారులు"</string>
+ <string name="data_usage_ota" msgid="5377889154805560860">"సిస్టమ్ అప్డేట్లు"</string>
<string name="tether_settings_title_usb" msgid="6688416425801386511">"USB టీథరింగ్"</string>
<string name="tether_settings_title_wifi" msgid="3277144155960302049">"పోర్టబుల్ హాట్స్పాట్"</string>
<string name="tether_settings_title_bluetooth" msgid="355855408317564420">"బ్లూటూత్ టీథరింగ్"</string>
diff --git a/packages/SettingsLib/res/values-th/strings.xml b/packages/SettingsLib/res/values-th/strings.xml
index 1f4c727..cf8362f 100644
--- a/packages/SettingsLib/res/values-th/strings.xml
+++ b/packages/SettingsLib/res/values-th/strings.xml
@@ -87,8 +87,8 @@
<string name="bluetooth_profile_sap" msgid="5764222021851283125">"การเข้าถึงซิม"</string>
<string name="bluetooth_profile_a2dp_high_quality" msgid="5444517801472820055">"เสียง HD: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
<string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="8510588052415438887">"เสียง HD"</string>
- <string name="bluetooth_profile_hearing_aid" msgid="7999237886427812595">"เครื่องช่วยการได้ยิน"</string>
- <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="7188282786730266159">"เชื่อมต่อเครื่องช่วยการได้ยินแล้ว"</string>
+ <string name="bluetooth_profile_hearing_aid" msgid="6680721080542444257">"เครื่องช่วยการได้ยิน"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="3051944447369418317">"เชื่อมต่อกับเครื่องช่วยการได้ยินแล้ว"</string>
<string name="bluetooth_a2dp_profile_summary_connected" msgid="963376081347721598">"เชื่อมต่อกับระบบเสียงของสื่อแล้ว"</string>
<string name="bluetooth_headset_profile_summary_connected" msgid="7661070206715520671">"เชื่อมต่อกับระบบเสียงของโทรศัพท์แล้ว"</string>
<string name="bluetooth_opp_profile_summary_connected" msgid="2611913495968309066">"เชื่อมต่อกับเซิร์ฟเวอร์สำหรับโอนไฟล์แล้ว"</string>
@@ -105,7 +105,7 @@
<string name="bluetooth_headset_profile_summary_use_for" msgid="8705753622443862627">"ใช้สำหรับระบบเสียงของโทรศัพท์"</string>
<string name="bluetooth_opp_profile_summary_use_for" msgid="1255674547144769756">"ใช้สำหรับการโอนไฟล์"</string>
<string name="bluetooth_hid_profile_summary_use_for" msgid="232727040453645139">"ใช้สำหรับการป้อนข้อมูล"</string>
- <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="908775281788309484">"ใช้สำหรับเครื่องช่วยการได้ยิน"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="8843499209204010224">"ใช้สำหรับเครื่องช่วยการได้ยิน"</string>
<string name="bluetooth_pairing_accept" msgid="6163520056536604875">"จับคู่อุปกรณ์"</string>
<string name="bluetooth_pairing_accept_all_caps" msgid="6061699265220789149">"จับคู่อุปกรณ์"</string>
<string name="bluetooth_pairing_decline" msgid="4185420413578948140">"ยกเลิก"</string>
@@ -136,6 +136,7 @@
<string name="process_kernel_label" msgid="3916858646836739323">"ระบบปฏิบัติการของ Android"</string>
<string name="data_usage_uninstalled_apps" msgid="614263770923231598">"แอปพลิเคชันที่นำออก"</string>
<string name="data_usage_uninstalled_apps_users" msgid="7986294489899813194">"แอปพลิเคชันและผู้ใช้ที่นำออก"</string>
+ <string name="data_usage_ota" msgid="5377889154805560860">"การอัปเดตระบบ"</string>
<string name="tether_settings_title_usb" msgid="6688416425801386511">"ปล่อยสัญญาณผ่าน USB"</string>
<string name="tether_settings_title_wifi" msgid="3277144155960302049">"ฮอตสปอตแบบพกพาได้"</string>
<string name="tether_settings_title_bluetooth" msgid="355855408317564420">"ปล่อยสัญญาณบลูทูธ"</string>
diff --git a/packages/SettingsLib/res/values-tl/strings.xml b/packages/SettingsLib/res/values-tl/strings.xml
index 7a31cc9e..e690800 100644
--- a/packages/SettingsLib/res/values-tl/strings.xml
+++ b/packages/SettingsLib/res/values-tl/strings.xml
@@ -87,8 +87,8 @@
<string name="bluetooth_profile_sap" msgid="5764222021851283125">"Access sa SIM"</string>
<string name="bluetooth_profile_a2dp_high_quality" msgid="5444517801472820055">"HD audio: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
<string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="8510588052415438887">"HD audio"</string>
- <string name="bluetooth_profile_hearing_aid" msgid="7999237886427812595">"Hearing Aid"</string>
- <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="7188282786730266159">"Nakakonekta sa Hearing Aid"</string>
+ <string name="bluetooth_profile_hearing_aid" msgid="6680721080542444257">"Mga Hearing Aid"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="3051944447369418317">"Nakakonekta sa Mga Hearing Aid"</string>
<string name="bluetooth_a2dp_profile_summary_connected" msgid="963376081347721598">"Konektado sa media audio"</string>
<string name="bluetooth_headset_profile_summary_connected" msgid="7661070206715520671">"Nakakonekta sa audio ng telepono"</string>
<string name="bluetooth_opp_profile_summary_connected" msgid="2611913495968309066">"Nakakonekta sa server sa paglilipat ng file"</string>
@@ -105,7 +105,7 @@
<string name="bluetooth_headset_profile_summary_use_for" msgid="8705753622443862627">"Ginagamit para sa audio ng telepono"</string>
<string name="bluetooth_opp_profile_summary_use_for" msgid="1255674547144769756">"Ginagamit para sa paglilipat ng file"</string>
<string name="bluetooth_hid_profile_summary_use_for" msgid="232727040453645139">"Gamitin para sa input"</string>
- <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="908775281788309484">"Gamitin para sa Hearing Aid"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="8843499209204010224">"Gamitin para sa Mga Hearing Aid"</string>
<string name="bluetooth_pairing_accept" msgid="6163520056536604875">"Pares"</string>
<string name="bluetooth_pairing_accept_all_caps" msgid="6061699265220789149">"IPARES"</string>
<string name="bluetooth_pairing_decline" msgid="4185420413578948140">"Kanselahin"</string>
@@ -136,6 +136,7 @@
<string name="process_kernel_label" msgid="3916858646836739323">"Android OS"</string>
<string name="data_usage_uninstalled_apps" msgid="614263770923231598">"Mga inalis na app"</string>
<string name="data_usage_uninstalled_apps_users" msgid="7986294489899813194">"Mga inalis na apps at user"</string>
+ <string name="data_usage_ota" msgid="5377889154805560860">"Mga pag-update ng system"</string>
<string name="tether_settings_title_usb" msgid="6688416425801386511">"Pag-tether sa USB"</string>
<string name="tether_settings_title_wifi" msgid="3277144155960302049">"Portable na hotspot"</string>
<string name="tether_settings_title_bluetooth" msgid="355855408317564420">"Pag-tether ng Bluetooth"</string>
diff --git a/packages/SettingsLib/res/values-tr/strings.xml b/packages/SettingsLib/res/values-tr/strings.xml
index 28fc38f..ea340e8 100644
--- a/packages/SettingsLib/res/values-tr/strings.xml
+++ b/packages/SettingsLib/res/values-tr/strings.xml
@@ -87,8 +87,8 @@
<string name="bluetooth_profile_sap" msgid="5764222021851283125">"SIM Erişimi"</string>
<string name="bluetooth_profile_a2dp_high_quality" msgid="5444517801472820055">"HD ses: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
<string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="8510588052415438887">"HD ses"</string>
- <string name="bluetooth_profile_hearing_aid" msgid="7999237886427812595">"İşitme Cihazı"</string>
- <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="7188282786730266159">"İşitme Cihazına bağlandı"</string>
+ <string name="bluetooth_profile_hearing_aid" msgid="6680721080542444257">"İşitme Cihazları"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="3051944447369418317">"İşitme Cihazlarına Bağlandı"</string>
<string name="bluetooth_a2dp_profile_summary_connected" msgid="963376081347721598">"Medya sesine bağlanıldı"</string>
<string name="bluetooth_headset_profile_summary_connected" msgid="7661070206715520671">"Telefon sesine bağlandı"</string>
<string name="bluetooth_opp_profile_summary_connected" msgid="2611913495968309066">"Dosya aktarım sunucusuna bağlandı"</string>
@@ -105,7 +105,7 @@
<string name="bluetooth_headset_profile_summary_use_for" msgid="8705753622443862627">"Telefon sesi için kullan"</string>
<string name="bluetooth_opp_profile_summary_use_for" msgid="1255674547144769756">"Dosya aktarımı için kullan"</string>
<string name="bluetooth_hid_profile_summary_use_for" msgid="232727040453645139">"Giriş için kullan"</string>
- <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="908775281788309484">"İşitme Cihazı için kullan"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="8843499209204010224">"İşitme Cihazları için kullan"</string>
<string name="bluetooth_pairing_accept" msgid="6163520056536604875">"Eşle"</string>
<string name="bluetooth_pairing_accept_all_caps" msgid="6061699265220789149">"EŞLE"</string>
<string name="bluetooth_pairing_decline" msgid="4185420413578948140">"İptal"</string>
@@ -136,6 +136,7 @@
<string name="process_kernel_label" msgid="3916858646836739323">"Android OS"</string>
<string name="data_usage_uninstalled_apps" msgid="614263770923231598">"Kaldırılan uygulamalar"</string>
<string name="data_usage_uninstalled_apps_users" msgid="7986294489899813194">"Kaldırılmış kullanıcılar ve uygulamalar"</string>
+ <string name="data_usage_ota" msgid="5377889154805560860">"Sistem güncellemeleri"</string>
<string name="tether_settings_title_usb" msgid="6688416425801386511">"USB tethering"</string>
<string name="tether_settings_title_wifi" msgid="3277144155960302049">"Taşınabilir hotspot"</string>
<string name="tether_settings_title_bluetooth" msgid="355855408317564420">"Bluetooth tethering"</string>
diff --git a/packages/SettingsLib/res/values-uk/strings.xml b/packages/SettingsLib/res/values-uk/strings.xml
index c63f7e0..cf90ed1 100644
--- a/packages/SettingsLib/res/values-uk/strings.xml
+++ b/packages/SettingsLib/res/values-uk/strings.xml
@@ -87,8 +87,8 @@
<string name="bluetooth_profile_sap" msgid="5764222021851283125">"Доступ до SIM-карти"</string>
<string name="bluetooth_profile_a2dp_high_quality" msgid="5444517801472820055">"HD-аудіо: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
<string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="8510588052415438887">"HD-аудіо"</string>
- <string name="bluetooth_profile_hearing_aid" msgid="7999237886427812595">"Слуховий апарат"</string>
- <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="7188282786730266159">"Під’єднано до слухового апарата"</string>
+ <string name="bluetooth_profile_hearing_aid" msgid="6680721080542444257">"Слухові апарати"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="3051944447369418317">"Підключено до слухових апаратів"</string>
<string name="bluetooth_a2dp_profile_summary_connected" msgid="963376081347721598">"Підключено до аудіоджерела"</string>
<string name="bluetooth_headset_profile_summary_connected" msgid="7661070206715520671">"Підключено до звуку телеф."</string>
<string name="bluetooth_opp_profile_summary_connected" msgid="2611913495968309066">"Підключ. до сервера передачі файлів"</string>
@@ -105,7 +105,7 @@
<string name="bluetooth_headset_profile_summary_use_for" msgid="8705753622443862627">"Викор. для звуку тел."</string>
<string name="bluetooth_opp_profile_summary_use_for" msgid="1255674547144769756">"Викор. для перед. файлів"</string>
<string name="bluetooth_hid_profile_summary_use_for" msgid="232727040453645139">"Викор. для введ."</string>
- <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="908775281788309484">"Використовувати для слухового апарата"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="8843499209204010224">"Використовувати для слухових апаратів"</string>
<string name="bluetooth_pairing_accept" msgid="6163520056536604875">"Підключити"</string>
<string name="bluetooth_pairing_accept_all_caps" msgid="6061699265220789149">"ПІДКЛЮЧИТИСЯ"</string>
<string name="bluetooth_pairing_decline" msgid="4185420413578948140">"Скасувати"</string>
@@ -136,6 +136,7 @@
<string name="process_kernel_label" msgid="3916858646836739323">"ОС Android"</string>
<string name="data_usage_uninstalled_apps" msgid="614263770923231598">"Видалені програми"</string>
<string name="data_usage_uninstalled_apps_users" msgid="7986294489899813194">"Видалені програми та користувачі"</string>
+ <string name="data_usage_ota" msgid="5377889154805560860">"Оновлення системи"</string>
<string name="tether_settings_title_usb" msgid="6688416425801386511">"USB-модем"</string>
<string name="tether_settings_title_wifi" msgid="3277144155960302049">"Порт. точка дост."</string>
<string name="tether_settings_title_bluetooth" msgid="355855408317564420">"Bluetooth-модем"</string>
diff --git a/packages/SettingsLib/res/values-ur/strings.xml b/packages/SettingsLib/res/values-ur/strings.xml
index 27aa730..65ed110 100644
--- a/packages/SettingsLib/res/values-ur/strings.xml
+++ b/packages/SettingsLib/res/values-ur/strings.xml
@@ -38,27 +38,20 @@
<string name="connected_via_network_scorer" msgid="5713793306870815341">"%1$s کے ذریعے از خود منسلک کردہ"</string>
<string name="connected_via_network_scorer_default" msgid="7867260222020343104">"نیٹ ورک درجہ بندی کے فراہم کنندہ کے ذریعے از خود منسلک"</string>
<string name="connected_via_passpoint" msgid="2826205693803088747">"منسلک بذریعہ %1$s"</string>
- <!-- no translation found for connected_via_app (5571999941988929520) -->
- <skip />
+ <string name="connected_via_app" msgid="5571999941988929520">"<xliff:g id="NAME">%1$s</xliff:g> کے ذریعے منسلک"</string>
<string name="available_via_passpoint" msgid="1617440946846329613">"دستیاب بذریعہ %1$s"</string>
- <!-- no translation found for tap_to_sign_up (6449724763052579434) -->
- <skip />
+ <string name="tap_to_sign_up" msgid="6449724763052579434">"سائن اپ کے لیے تھپتھپائیں"</string>
<string name="wifi_connected_no_internet" msgid="8202906332837777829">"منسلک، انٹرنیٹ نہیں ہے"</string>
<string name="wifi_status_no_internet" msgid="5784710974669608361">"انٹرنیٹ نہیں ہے"</string>
<string name="wifi_status_sign_in_required" msgid="123517180404752756">"سائن ان درکار ہے"</string>
<string name="wifi_ap_unable_to_handle_new_sta" msgid="5348824313514404541">"رسائی پوائنٹ عارضی طور پر فُل ہے"</string>
<string name="connected_via_carrier" msgid="7583780074526041912">"منسلک بذریعہ %1$s"</string>
<string name="available_via_carrier" msgid="1469036129740799053">"دستیاب بذریعہ %1$s"</string>
- <!-- no translation found for osu_opening_provider (5488997661548640424) -->
- <skip />
- <!-- no translation found for osu_connect_failed (2187750899158158934) -->
- <skip />
- <!-- no translation found for osu_completing_sign_up (9037638564719197082) -->
- <skip />
- <!-- no translation found for osu_sign_up_failed (7296159750352873260) -->
- <skip />
- <!-- no translation found for osu_sign_up_complete (8207626049093289203) -->
- <skip />
+ <string name="osu_opening_provider" msgid="5488997661548640424">"<xliff:g id="PASSPOINTPROVIDER">%1$s</xliff:g> کھل رہا ہے"</string>
+ <string name="osu_connect_failed" msgid="2187750899158158934">"منسلک نہیں کیا جا سکا"</string>
+ <string name="osu_completing_sign_up" msgid="9037638564719197082">"سائن اپ مکمل ہو رہا ہے…"</string>
+ <string name="osu_sign_up_failed" msgid="7296159750352873260">"سائن اپ مکمل نہیں ہو سکا۔ دوبارہ کوشش کرنے کے لیے تھپتھپائیں۔"</string>
+ <string name="osu_sign_up_complete" msgid="8207626049093289203">"سائن اپ مکمل ہو گیا۔ منسلک ہو رہا ہے…"</string>
<string name="speed_label_very_slow" msgid="1867055264243608530">"بہت سست"</string>
<string name="speed_label_slow" msgid="813109590815810235">"سست"</string>
<string name="speed_label_okay" msgid="2331665440671174858">"ٹھیک ہے"</string>
@@ -94,8 +87,8 @@
<string name="bluetooth_profile_sap" msgid="5764222021851283125">"SIM رسائی"</string>
<string name="bluetooth_profile_a2dp_high_quality" msgid="5444517801472820055">"HD آڈیو: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
<string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="8510588052415438887">"HD آڈیو"</string>
- <string name="bluetooth_profile_hearing_aid" msgid="7999237886427812595">"سماعتی آلہ"</string>
- <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="7188282786730266159">"سماعتی آلے سے منسلک"</string>
+ <string name="bluetooth_profile_hearing_aid" msgid="6680721080542444257">"سماعتی آلات"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="3051944447369418317">"سماعتی آلات سے منسلک ہے"</string>
<string name="bluetooth_a2dp_profile_summary_connected" msgid="963376081347721598">"میڈیا آڈیو سے مربوط"</string>
<string name="bluetooth_headset_profile_summary_connected" msgid="7661070206715520671">"فون آڈیو سے مربوط"</string>
<string name="bluetooth_opp_profile_summary_connected" msgid="2611913495968309066">"فائل منتقلی سرور سے مربوط ہو گیا ہے"</string>
@@ -112,7 +105,7 @@
<string name="bluetooth_headset_profile_summary_use_for" msgid="8705753622443862627">"فون آڈیو کیلئے استعمال کریں"</string>
<string name="bluetooth_opp_profile_summary_use_for" msgid="1255674547144769756">"فائل منتقل کرنے کیلئے استعمال کریں"</string>
<string name="bluetooth_hid_profile_summary_use_for" msgid="232727040453645139">"ان پٹ کیلئے استعمال"</string>
- <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="908775281788309484">"سماعتی آلے کیلئے استعمال کریں"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="8843499209204010224">"سماعتی آلات کے لیے استعمال کریں"</string>
<string name="bluetooth_pairing_accept" msgid="6163520056536604875">"جوڑا بنائیں"</string>
<string name="bluetooth_pairing_accept_all_caps" msgid="6061699265220789149">"جوڑا بنائیں"</string>
<string name="bluetooth_pairing_decline" msgid="4185420413578948140">"منسوخ کریں"</string>
@@ -143,6 +136,8 @@
<string name="process_kernel_label" msgid="3916858646836739323">"Android OS"</string>
<string name="data_usage_uninstalled_apps" msgid="614263770923231598">"ہٹائی گئی ایپس"</string>
<string name="data_usage_uninstalled_apps_users" msgid="7986294489899813194">"ہٹائی گئی ایپس اور صارفین"</string>
+ <!-- no translation found for data_usage_ota (5377889154805560860) -->
+ <skip />
<string name="tether_settings_title_usb" msgid="6688416425801386511">"USB ٹیدرنگ"</string>
<string name="tether_settings_title_wifi" msgid="3277144155960302049">"پورٹیبل ہاٹ اسپاٹ"</string>
<string name="tether_settings_title_bluetooth" msgid="355855408317564420">"بلوٹوتھ ٹیدرنگ"</string>
diff --git a/packages/SettingsLib/res/values-uz/strings.xml b/packages/SettingsLib/res/values-uz/strings.xml
index bcb4d27..2851baf 100644
--- a/packages/SettingsLib/res/values-uz/strings.xml
+++ b/packages/SettingsLib/res/values-uz/strings.xml
@@ -87,8 +87,8 @@
<string name="bluetooth_profile_sap" msgid="5764222021851283125">"SIM-kartaga kirish"</string>
<string name="bluetooth_profile_a2dp_high_quality" msgid="5444517801472820055">"HD audio: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
<string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="8510588052415438887">"HD audio"</string>
- <string name="bluetooth_profile_hearing_aid" msgid="7999237886427812595">"Eshitish apparati"</string>
- <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="7188282786730266159">"Eshitish apparatiga ulangan"</string>
+ <string name="bluetooth_profile_hearing_aid" msgid="6680721080542444257">"Eshitish apparatlari"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="3051944447369418317">"Eshitish apparatlariga ulangan"</string>
<string name="bluetooth_a2dp_profile_summary_connected" msgid="963376081347721598">"Audio qurilmasiga ulangan"</string>
<string name="bluetooth_headset_profile_summary_connected" msgid="7661070206715520671">"Telefon karnayiga ulanildi"</string>
<string name="bluetooth_opp_profile_summary_connected" msgid="2611913495968309066">"Fayl almashinish serveriga ulanildi"</string>
@@ -105,7 +105,7 @@
<string name="bluetooth_headset_profile_summary_use_for" msgid="8705753622443862627">"Dok’dan karnay sifatida foydalanish"</string>
<string name="bluetooth_opp_profile_summary_use_for" msgid="1255674547144769756">"Fayl almashinish uchun foydalanish"</string>
<string name="bluetooth_hid_profile_summary_use_for" msgid="232727040453645139">"Kiritish qurilmasi sifatida foydalanish"</string>
- <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="908775281788309484">"Eshitish apparati uchun foydalanish"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="8843499209204010224">"Eshitish apparatlari uchun foydalanish"</string>
<string name="bluetooth_pairing_accept" msgid="6163520056536604875">"Biriktirish"</string>
<string name="bluetooth_pairing_accept_all_caps" msgid="6061699265220789149">"ULANISH"</string>
<string name="bluetooth_pairing_decline" msgid="4185420413578948140">"Bekor qilish"</string>
@@ -136,6 +136,7 @@
<string name="process_kernel_label" msgid="3916858646836739323">"Android OS"</string>
<string name="data_usage_uninstalled_apps" msgid="614263770923231598">"O‘chirilgan ilovalar"</string>
<string name="data_usage_uninstalled_apps_users" msgid="7986294489899813194">"O‘chirib tashlangan ilova va foydalanuvchilar"</string>
+ <string name="data_usage_ota" msgid="5377889154805560860">"Tizimni yangilash"</string>
<string name="tether_settings_title_usb" msgid="6688416425801386511">"USB modem"</string>
<string name="tether_settings_title_wifi" msgid="3277144155960302049">"Ixcham hotspot"</string>
<string name="tether_settings_title_bluetooth" msgid="355855408317564420">"Bluetooth modem"</string>
diff --git a/packages/SettingsLib/res/values-vi/strings.xml b/packages/SettingsLib/res/values-vi/strings.xml
index d03b2f1..3fb101e 100644
--- a/packages/SettingsLib/res/values-vi/strings.xml
+++ b/packages/SettingsLib/res/values-vi/strings.xml
@@ -87,8 +87,8 @@
<string name="bluetooth_profile_sap" msgid="5764222021851283125">"Quyền truy cập SIM"</string>
<string name="bluetooth_profile_a2dp_high_quality" msgid="5444517801472820055">"Âm thanh HD: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
<string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="8510588052415438887">"Âm thanh HD"</string>
- <string name="bluetooth_profile_hearing_aid" msgid="7999237886427812595">"Trợ thính"</string>
- <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="7188282786730266159">"Đã kết nối với thiết bị trợ thính"</string>
+ <string name="bluetooth_profile_hearing_aid" msgid="6680721080542444257">"Thiết bị trợ thính"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="3051944447369418317">"Đã kết nối với Thiết bị trợ thính"</string>
<string name="bluetooth_a2dp_profile_summary_connected" msgid="963376081347721598">"Đã kết nối với âm thanh phương tiện"</string>
<string name="bluetooth_headset_profile_summary_connected" msgid="7661070206715520671">"Đã kết nối với âm thanh điện thoại"</string>
<string name="bluetooth_opp_profile_summary_connected" msgid="2611913495968309066">"Đã kết nối với máy chủ chuyển tệp"</string>
@@ -105,7 +105,7 @@
<string name="bluetooth_headset_profile_summary_use_for" msgid="8705753622443862627">"Sử dụng cho âm thanh điện thoại"</string>
<string name="bluetooth_opp_profile_summary_use_for" msgid="1255674547144769756">"Sử dụng để chuyển tệp"</string>
<string name="bluetooth_hid_profile_summary_use_for" msgid="232727040453645139">"Sử dụng để nhập"</string>
- <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="908775281788309484">"Sử dụng cho thiết bị trợ thính"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="8843499209204010224">"Dùng cho Thiết bị trợ thính"</string>
<string name="bluetooth_pairing_accept" msgid="6163520056536604875">"Ghép nối"</string>
<string name="bluetooth_pairing_accept_all_caps" msgid="6061699265220789149">"GHÉP NỐI"</string>
<string name="bluetooth_pairing_decline" msgid="4185420413578948140">"Hủy"</string>
@@ -136,6 +136,7 @@
<string name="process_kernel_label" msgid="3916858646836739323">"Hệ điều hành Android"</string>
<string name="data_usage_uninstalled_apps" msgid="614263770923231598">"Ứng dụng đã xóa"</string>
<string name="data_usage_uninstalled_apps_users" msgid="7986294489899813194">"Ứng dụng và người dùng bị xóa"</string>
+ <string name="data_usage_ota" msgid="5377889154805560860">"Bản cập nhật hệ thống"</string>
<string name="tether_settings_title_usb" msgid="6688416425801386511">"Chia sẻ kết nối Internet qua USB"</string>
<string name="tether_settings_title_wifi" msgid="3277144155960302049">"Điểm phát sóng di động"</string>
<string name="tether_settings_title_bluetooth" msgid="355855408317564420">"Chia sẻ kết nối Internet qua Bluetooth"</string>
diff --git a/packages/SettingsLib/res/values-zh-rCN/strings.xml b/packages/SettingsLib/res/values-zh-rCN/strings.xml
index 6967447..0a318d7 100644
--- a/packages/SettingsLib/res/values-zh-rCN/strings.xml
+++ b/packages/SettingsLib/res/values-zh-rCN/strings.xml
@@ -87,8 +87,8 @@
<string name="bluetooth_profile_sap" msgid="5764222021851283125">"SIM 卡存取权限"</string>
<string name="bluetooth_profile_a2dp_high_quality" msgid="5444517801472820055">"HD 音频:<xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
<string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="8510588052415438887">"HD 音频"</string>
- <string name="bluetooth_profile_hearing_aid" msgid="7999237886427812595">"助听器"</string>
- <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="7188282786730266159">"已连接到助听器"</string>
+ <string name="bluetooth_profile_hearing_aid" msgid="6680721080542444257">"助听器"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="3051944447369418317">"已连接到助听器"</string>
<string name="bluetooth_a2dp_profile_summary_connected" msgid="963376081347721598">"已连接到媒体音频"</string>
<string name="bluetooth_headset_profile_summary_connected" msgid="7661070206715520671">"已连接到手机音频"</string>
<string name="bluetooth_opp_profile_summary_connected" msgid="2611913495968309066">"已连接到文件传输服务器"</string>
@@ -105,7 +105,7 @@
<string name="bluetooth_headset_profile_summary_use_for" msgid="8705753622443862627">"用于手机音频"</string>
<string name="bluetooth_opp_profile_summary_use_for" msgid="1255674547144769756">"用于文件传输"</string>
<string name="bluetooth_hid_profile_summary_use_for" msgid="232727040453645139">"用于输入"</string>
- <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="908775281788309484">"用于助听器"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="8843499209204010224">"用于助听器"</string>
<string name="bluetooth_pairing_accept" msgid="6163520056536604875">"配对"</string>
<string name="bluetooth_pairing_accept_all_caps" msgid="6061699265220789149">"配对"</string>
<string name="bluetooth_pairing_decline" msgid="4185420413578948140">"取消"</string>
@@ -136,6 +136,7 @@
<string name="process_kernel_label" msgid="3916858646836739323">"Android 操作系统"</string>
<string name="data_usage_uninstalled_apps" msgid="614263770923231598">"已删除的应用"</string>
<string name="data_usage_uninstalled_apps_users" msgid="7986294489899813194">"已删除的应用和用户"</string>
+ <string name="data_usage_ota" msgid="5377889154805560860">"系统更新"</string>
<string name="tether_settings_title_usb" msgid="6688416425801386511">"USB 网络共享"</string>
<string name="tether_settings_title_wifi" msgid="3277144155960302049">"便携式热点"</string>
<string name="tether_settings_title_bluetooth" msgid="355855408317564420">"蓝牙网络共享"</string>
diff --git a/packages/SettingsLib/res/values-zh-rHK/strings.xml b/packages/SettingsLib/res/values-zh-rHK/strings.xml
index 5394afc..06bee94 100644
--- a/packages/SettingsLib/res/values-zh-rHK/strings.xml
+++ b/packages/SettingsLib/res/values-zh-rHK/strings.xml
@@ -38,9 +38,9 @@
<string name="connected_via_network_scorer" msgid="5713793306870815341">"已透過 %1$s 自動連線"</string>
<string name="connected_via_network_scorer_default" msgid="7867260222020343104">"已透過網絡評分供應商自動連線"</string>
<string name="connected_via_passpoint" msgid="2826205693803088747">"已透過 %1$s 連線"</string>
- <string name="connected_via_app" msgid="5571999941988929520">"透過「<xliff:g id="NAME">%1$s</xliff:g>」連線"</string>
+ <string name="connected_via_app" msgid="5571999941988929520">"已透過「<xliff:g id="NAME">%1$s</xliff:g>」連線"</string>
<string name="available_via_passpoint" msgid="1617440946846329613">"可透過 %1$s 連線"</string>
- <string name="tap_to_sign_up" msgid="6449724763052579434">"輕觸即可註冊"</string>
+ <string name="tap_to_sign_up" msgid="6449724763052579434">"輕按即可登入"</string>
<string name="wifi_connected_no_internet" msgid="8202906332837777829">"已連線,但沒有互聯網"</string>
<string name="wifi_status_no_internet" msgid="5784710974669608361">"沒有互聯網連線"</string>
<string name="wifi_status_sign_in_required" msgid="123517180404752756">"必須登入"</string>
@@ -48,10 +48,10 @@
<string name="connected_via_carrier" msgid="7583780074526041912">"已透過 %1$s 連線"</string>
<string name="available_via_carrier" msgid="1469036129740799053">"可透過 %1$s 連線"</string>
<string name="osu_opening_provider" msgid="5488997661548640424">"正在開啟 <xliff:g id="PASSPOINTPROVIDER">%1$s</xliff:g>"</string>
- <string name="osu_connect_failed" msgid="2187750899158158934">"無法連線"</string>
- <string name="osu_completing_sign_up" msgid="9037638564719197082">"正在完成註冊程序…"</string>
- <string name="osu_sign_up_failed" msgid="7296159750352873260">"無法完成註冊程序。輕觸即可重試。"</string>
- <string name="osu_sign_up_complete" msgid="8207626049093289203">"註冊完成。連線中…"</string>
+ <string name="osu_connect_failed" msgid="2187750899158158934">"無法連接"</string>
+ <string name="osu_completing_sign_up" msgid="9037638564719197082">"正在完成申請…"</string>
+ <string name="osu_sign_up_failed" msgid="7296159750352873260">"無法完成申請。輕按即可重試。"</string>
+ <string name="osu_sign_up_complete" msgid="8207626049093289203">"已完成申請。連接中…"</string>
<string name="speed_label_very_slow" msgid="1867055264243608530">"非常慢"</string>
<string name="speed_label_slow" msgid="813109590815810235">"慢"</string>
<string name="speed_label_okay" msgid="2331665440671174858">"良好"</string>
@@ -87,8 +87,8 @@
<string name="bluetooth_profile_sap" msgid="5764222021851283125">"SIM 卡存取"</string>
<string name="bluetooth_profile_a2dp_high_quality" msgid="5444517801472820055">"高清音訊:<xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
<string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="8510588052415438887">"高清音訊"</string>
- <string name="bluetooth_profile_hearing_aid" msgid="7999237886427812595">"助聽器"</string>
- <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="7188282786730266159">"已連線至助聽器"</string>
+ <string name="bluetooth_profile_hearing_aid" msgid="6680721080542444257">"助聽器"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="3051944447369418317">"已連接助聽器"</string>
<string name="bluetooth_a2dp_profile_summary_connected" msgid="963376081347721598">"已連接媒體音頻裝置"</string>
<string name="bluetooth_headset_profile_summary_connected" msgid="7661070206715520671">"已連接手機耳機"</string>
<string name="bluetooth_opp_profile_summary_connected" msgid="2611913495968309066">"已連線至檔案傳輸伺服器"</string>
@@ -105,7 +105,7 @@
<string name="bluetooth_headset_profile_summary_use_for" msgid="8705753622443862627">"用於手機音效"</string>
<string name="bluetooth_opp_profile_summary_use_for" msgid="1255674547144769756">"用於傳輸檔案"</string>
<string name="bluetooth_hid_profile_summary_use_for" msgid="232727040453645139">"用於輸入"</string>
- <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="908775281788309484">"用於助聽器"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="8843499209204010224">"用於助聽器"</string>
<string name="bluetooth_pairing_accept" msgid="6163520056536604875">"配對"</string>
<string name="bluetooth_pairing_accept_all_caps" msgid="6061699265220789149">"配對"</string>
<string name="bluetooth_pairing_decline" msgid="4185420413578948140">"取消"</string>
@@ -136,6 +136,7 @@
<string name="process_kernel_label" msgid="3916858646836739323">"Android 作業系統"</string>
<string name="data_usage_uninstalled_apps" msgid="614263770923231598">"已移除的應用程式"</string>
<string name="data_usage_uninstalled_apps_users" msgid="7986294489899813194">"已移除的應用程式和使用者"</string>
+ <string name="data_usage_ota" msgid="5377889154805560860">"系統更新"</string>
<string name="tether_settings_title_usb" msgid="6688416425801386511">"USB 網絡共享"</string>
<string name="tether_settings_title_wifi" msgid="3277144155960302049">"可攜式熱點"</string>
<string name="tether_settings_title_bluetooth" msgid="355855408317564420">"藍牙網絡共享"</string>
diff --git a/packages/SettingsLib/res/values-zh-rTW/strings.xml b/packages/SettingsLib/res/values-zh-rTW/strings.xml
index 107eb6d..a5074d9 100644
--- a/packages/SettingsLib/res/values-zh-rTW/strings.xml
+++ b/packages/SettingsLib/res/values-zh-rTW/strings.xml
@@ -87,8 +87,8 @@
<string name="bluetooth_profile_sap" msgid="5764222021851283125">"SIM 卡存取權"</string>
<string name="bluetooth_profile_a2dp_high_quality" msgid="5444517801472820055">"HD 高解析音訊:<xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
<string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="8510588052415438887">"HD 高解析音訊"</string>
- <string name="bluetooth_profile_hearing_aid" msgid="7999237886427812595">"助聽器"</string>
- <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="7188282786730266159">"已連接到助聽器"</string>
+ <string name="bluetooth_profile_hearing_aid" msgid="6680721080542444257">"助聽器"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="3051944447369418317">"已連接到助聽器"</string>
<string name="bluetooth_a2dp_profile_summary_connected" msgid="963376081347721598">"連接至媒體音訊"</string>
<string name="bluetooth_headset_profile_summary_connected" msgid="7661070206715520671">"連接至電話音訊"</string>
<string name="bluetooth_opp_profile_summary_connected" msgid="2611913495968309066">"已連線到檔案傳輸伺服器"</string>
@@ -105,7 +105,7 @@
<string name="bluetooth_headset_profile_summary_use_for" msgid="8705753622443862627">"用於電話音訊"</string>
<string name="bluetooth_opp_profile_summary_use_for" msgid="1255674547144769756">"用於傳輸檔案"</string>
<string name="bluetooth_hid_profile_summary_use_for" msgid="232727040453645139">"用於輸入"</string>
- <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="908775281788309484">"用於助聽器"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="8843499209204010224">"用於助聽器"</string>
<string name="bluetooth_pairing_accept" msgid="6163520056536604875">"配對"</string>
<string name="bluetooth_pairing_accept_all_caps" msgid="6061699265220789149">"配對"</string>
<string name="bluetooth_pairing_decline" msgid="4185420413578948140">"取消"</string>
@@ -136,6 +136,7 @@
<string name="process_kernel_label" msgid="3916858646836739323">"Android 作業系統"</string>
<string name="data_usage_uninstalled_apps" msgid="614263770923231598">"移除的應用程式"</string>
<string name="data_usage_uninstalled_apps_users" msgid="7986294489899813194">"已移除的應用程式和使用者"</string>
+ <string name="data_usage_ota" msgid="5377889154805560860">"系統更新"</string>
<string name="tether_settings_title_usb" msgid="6688416425801386511">"USB 網路共用"</string>
<string name="tether_settings_title_wifi" msgid="3277144155960302049">"可攜式無線基地台"</string>
<string name="tether_settings_title_bluetooth" msgid="355855408317564420">"藍牙網路共用"</string>
diff --git a/packages/SettingsLib/res/values-zu/strings.xml b/packages/SettingsLib/res/values-zu/strings.xml
index 920df4b..5892093 100644
--- a/packages/SettingsLib/res/values-zu/strings.xml
+++ b/packages/SettingsLib/res/values-zu/strings.xml
@@ -87,8 +87,8 @@
<string name="bluetooth_profile_sap" msgid="5764222021851283125">"Ukufinyelela kwe-SIM"</string>
<string name="bluetooth_profile_a2dp_high_quality" msgid="5444517801472820055">"Umsindo we-HD: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
<string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="8510588052415438887">"Umsindo we-HD"</string>
- <string name="bluetooth_profile_hearing_aid" msgid="7999237886427812595">"Usizo lokuzwa"</string>
- <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="7188282786730266159">"Ixhunywe kokokusiza ukuzwa"</string>
+ <string name="bluetooth_profile_hearing_aid" msgid="6680721080542444257">"Izinsiza zokuzwa"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="3051944447369418317">"Kuxhumeke kwizinsiza zokuzwa"</string>
<string name="bluetooth_a2dp_profile_summary_connected" msgid="963376081347721598">"Ixhume emsindweni wemidiya"</string>
<string name="bluetooth_headset_profile_summary_connected" msgid="7661070206715520671">"Ixhunywe kumsindo wefoni"</string>
<string name="bluetooth_opp_profile_summary_connected" msgid="2611913495968309066">"Ixhunywe kwiseva yokudlulisa ifayela"</string>
@@ -105,7 +105,7 @@
<string name="bluetooth_headset_profile_summary_use_for" msgid="8705753622443862627">"Sebenziselwa umsindo wefoni"</string>
<string name="bluetooth_opp_profile_summary_use_for" msgid="1255674547144769756">"Sebenziselwa ukudlulisa ifayela"</string>
<string name="bluetooth_hid_profile_summary_use_for" msgid="232727040453645139">"Isetshenziselwa okufakwayo"</string>
- <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="908775281788309484">"Sebenzisela usizo lokuzwa"</string>
+ <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="8843499209204010224">"Sebenzisa izinsiza zokuzwa"</string>
<string name="bluetooth_pairing_accept" msgid="6163520056536604875">"Bhangqa"</string>
<string name="bluetooth_pairing_accept_all_caps" msgid="6061699265220789149">"BHANQA"</string>
<string name="bluetooth_pairing_decline" msgid="4185420413578948140">"Khansela"</string>
@@ -136,6 +136,7 @@
<string name="process_kernel_label" msgid="3916858646836739323">"I-Android OS"</string>
<string name="data_usage_uninstalled_apps" msgid="614263770923231598">"Izinhlelo zokusebenza zisusiwe"</string>
<string name="data_usage_uninstalled_apps_users" msgid="7986294489899813194">"Izinhelo zokusebenza nabasebenzisi abasusiwe"</string>
+ <string name="data_usage_ota" msgid="5377889154805560860">"Izibuyekezo zesistimu"</string>
<string name="tether_settings_title_usb" msgid="6688416425801386511">"Imodemu nge-USB"</string>
<string name="tether_settings_title_wifi" msgid="3277144155960302049">"I-hotspot ephathekayo"</string>
<string name="tether_settings_title_bluetooth" msgid="355855408317564420">"Imodemu nge-Bluetooth"</string>
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/widget/BarChartPreferenceTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/widget/BarChartPreferenceTest.java
index c3ea336..1080cf4 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/widget/BarChartPreferenceTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/widget/BarChartPreferenceTest.java
@@ -20,6 +20,7 @@
import android.content.Context;
import android.graphics.drawable.Drawable;
+import android.text.TextUtils;
import android.view.View;
import android.widget.TextView;
@@ -46,6 +47,7 @@
private BarView mBarView2;
private BarView mBarView3;
private BarView mBarView4;
+ private TextView mTitleView;
private TextView mDetailsView;
private PreferenceViewHolder mHolder;
private BarChartPreference mPreference;
@@ -63,6 +65,7 @@
mBarView2 = mBarChartView.findViewById(R.id.bar_view2);
mBarView3 = mBarChartView.findViewById(R.id.bar_view3);
mBarView4 = mBarChartView.findViewById(R.id.bar_view4);
+ mTitleView = mBarChartView.findViewById(R.id.bar_chart_title);
mDetailsView = mBarChartView.findViewById(R.id.bar_chart_details);
mBarChartInfo = new BarChartInfo.Builder()
@@ -76,7 +79,6 @@
@Test
public void initializeBarChart_titleSet_shouldSetTitleInChartView() {
- final TextView titleView = mBarChartView.findViewById(R.id.bar_chart_title);
final BarChartInfo barChartInfo = new BarChartInfo.Builder()
.setTitle(R.string.debug_app)
.build();
@@ -84,8 +86,8 @@
mPreference.initializeBarChart(barChartInfo);
mPreference.onBindViewHolder(mHolder);
- assertThat(titleView.getVisibility()).isEqualTo(View.VISIBLE);
- assertThat(titleView.getText()).isEqualTo(mContext.getText(R.string.debug_app));
+ assertThat(mTitleView.getVisibility()).isEqualTo(View.VISIBLE);
+ assertThat(mTitleView.getText()).isEqualTo(mContext.getText(R.string.debug_app));
}
@Test
@@ -99,8 +101,7 @@
// We don't add any bar view yet.
mPreference.onBindViewHolder(mHolder);
- assertThat(mBarChartView.findViewById(R.id.bar_chart_title).getVisibility())
- .isEqualTo(View.VISIBLE);
+ assertThat(mTitleView.getVisibility()).isEqualTo(View.VISIBLE);
assertThat(mBarChartView.findViewById(R.id.empty_view).getVisibility())
.isEqualTo(View.VISIBLE);
assertThat(mBarChartView.findViewById(R.id.bar_views_container).getVisibility())
@@ -302,4 +303,38 @@
assertThat(mBarView1.getVisibility()).isEqualTo(View.VISIBLE);
assertThat(mBarView1.hasOnClickListeners()).isTrue();
}
+
+ @Test
+ public void onBindViewHolder_loadingStateIsTrue_shouldNotInitAnyView() {
+ final BarViewInfo viewInfo = new BarViewInfo(mIcon, 30 /* barNumber */, R.string.debug_app);
+ viewInfo.setClickListener(v -> {
+ });
+ final BarViewInfo[] barViewsInfo = new BarViewInfo[]{viewInfo};
+
+ mPreference.initializeBarChart(mBarChartInfo);
+ mPreference.setBarViewInfos(barViewsInfo);
+ mPreference.updateLoadingState(true /* isLoading */);
+
+ mPreference.onBindViewHolder(mHolder);
+
+ assertThat(TextUtils.isEmpty(mTitleView.getText())).isTrue();
+ assertThat(TextUtils.isEmpty(mDetailsView.getText())).isTrue();
+ }
+
+ @Test
+ public void onBindViewHolder_loadingStateIsFalse_shouldInitAnyView() {
+ final BarViewInfo viewInfo = new BarViewInfo(mIcon, 30 /* barNumber */, R.string.debug_app);
+ viewInfo.setClickListener(v -> {
+ });
+ final BarViewInfo[] barViewsInfo = new BarViewInfo[]{viewInfo};
+
+ mPreference.initializeBarChart(mBarChartInfo);
+ mPreference.setBarViewInfos(barViewsInfo);
+ mPreference.updateLoadingState(false /* isLoading */);
+
+ mPreference.onBindViewHolder(mHolder);
+
+ assertThat(TextUtils.isEmpty(mTitleView.getText())).isFalse();
+ assertThat(TextUtils.isEmpty(mDetailsView.getText())).isFalse();
+ }
}
diff --git a/packages/SettingsProvider/Android.bp b/packages/SettingsProvider/Android.bp
new file mode 100644
index 0000000..1c97fc3
--- /dev/null
+++ b/packages/SettingsProvider/Android.bp
@@ -0,0 +1,40 @@
+android_app {
+ name: "SettingsProvider",
+ resource_dirs: ["res"],
+ srcs: [
+ "src/**/*.java",
+ "src/com/android/providers/settings/EventLogTags.logtags",
+ ],
+ libs: [
+ "telephony-common",
+ "ims-common",
+ ],
+ static_libs: ["junit"],
+ platform_apis: true,
+ certificate: "platform",
+ privileged: true,
+}
+
+android_test {
+ name: "SettingsProviderTest",
+ // Note we statically link several classes to do some unit tests. It's not accessible otherwise
+ // because this test is not an instrumentation test. (because the target runs in the system process.)
+ srcs: [
+ "test/**/*.java",
+ "src/com/android/providers/settings/SettingsState.java",
+ "src/com/android/providers/settings/SettingsHelper.java",
+ ],
+ static_libs: ["androidx.test.rules"],
+ libs: ["android.test.base"],
+ resource_dirs: ["res"],
+ aaptflags: [
+ "--auto-add-overlay",
+ "--extra-packages",
+ "com.android.providers.settings",
+ ],
+ platform_apis: true,
+ certificate: "platform",
+ test_suites: ["device-tests"],
+ manifest: "test/AndroidManifest.xml",
+ test_config: "test/AndroidTest.xml",
+}
diff --git a/packages/SettingsProvider/Android.mk b/packages/SettingsProvider/Android.mk
deleted file mode 100644
index ccde571..0000000
--- a/packages/SettingsProvider/Android.mk
+++ /dev/null
@@ -1,22 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_TAGS := optional
-
-LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res
-
-LOCAL_SRC_FILES := $(call all-java-files-under, src) \
- src/com/android/providers/settings/EventLogTags.logtags
-
-LOCAL_JAVA_LIBRARIES := telephony-common ims-common
-LOCAL_STATIC_JAVA_LIBRARIES := junit
-
-LOCAL_PACKAGE_NAME := SettingsProvider
-LOCAL_PRIVATE_PLATFORM_APIS := true
-LOCAL_CERTIFICATE := platform
-LOCAL_PRIVILEGED_MODULE := true
-
-include $(BUILD_PACKAGE)
-
-########################
-include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
index db4b131..81b304d 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
@@ -724,6 +724,9 @@
dumpSetting(s, p,
Settings.Global.GAME_DRIVER_BLACKLISTS,
GlobalSettingsProto.Gpu.GAME_DRIVER_BLACKLISTS);
+ dumpSetting(s, p,
+ Settings.Global.GAME_DRIVER_SPHAL_LIBRARIES,
+ GlobalSettingsProto.Gpu.GAME_DRIVER_SPHAL_LIBRARIES);
p.end(gpuToken);
final long hdmiToken = p.start(GlobalSettingsProto.HDMI);
diff --git a/packages/SettingsProvider/test/Android.mk b/packages/SettingsProvider/test/Android.mk
deleted file mode 100644
index ac97adb..0000000
--- a/packages/SettingsProvider/test/Android.mk
+++ /dev/null
@@ -1,30 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_TAGS := tests
-
-# Note we statically link several classes to do some unit tests. It's not accessible otherwise
-# because this test is not an instrumentation test. (because the target runs in the system process.)
-LOCAL_SRC_FILES := $(call all-subdir-java-files) \
- ../src/com/android/providers/settings/SettingsState.java \
- ../src/com/android/providers/settings/SettingsHelper.java
-
-LOCAL_STATIC_JAVA_LIBRARIES := androidx.test.rules
-
-LOCAL_JAVA_LIBRARIES := android.test.base
-
-LOCAL_RESOURCE_DIR := frameworks/base/packages/SettingsProvider/res
-
-LOCAL_AAPT_FLAGS += --auto-add-overlay --extra-packages com.android.providers.settings
-
-LOCAL_PACKAGE_NAME := SettingsProviderTest
-LOCAL_PRIVATE_PLATFORM_APIS := true
-
-LOCAL_MODULE_TAGS := tests
-
-LOCAL_CERTIFICATE := platform
-
-LOCAL_COMPATIBILITY_SUITE := device-tests
-
-include $(BUILD_PACKAGE)
diff --git a/packages/SharedStorageBackup/Android.bp b/packages/SharedStorageBackup/Android.bp
new file mode 100644
index 0000000..5380832
--- /dev/null
+++ b/packages/SharedStorageBackup/Android.bp
@@ -0,0 +1,26 @@
+//
+// Copyright (C) 2011 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT 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_app {
+ name: "SharedStorageBackup",
+ srcs: ["src/**/*.java"],
+ optimize: {
+ proguard_flags_files: ["proguard.flags"],
+ },
+ platform_apis: true,
+ certificate: "platform",
+ privileged: true,
+}
diff --git a/packages/SharedStorageBackup/Android.mk b/packages/SharedStorageBackup/Android.mk
deleted file mode 100644
index 2e07ab1..0000000
--- a/packages/SharedStorageBackup/Android.mk
+++ /dev/null
@@ -1,35 +0,0 @@
-#
-# Copyright (C) 2011 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-LOCAL_PATH := $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_TAGS := optional
-
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-
-LOCAL_PROGUARD_FLAG_FILES := proguard.flags
-
-LOCAL_PACKAGE_NAME := SharedStorageBackup
-LOCAL_PRIVATE_PLATFORM_APIS := true
-LOCAL_CERTIFICATE := platform
-LOCAL_PRIVILEGED_MODULE := true
-
-include $(BUILD_PACKAGE)
-
-########################
-include $(call all-makefiles-under,$(LOCAL_PATH))
-
diff --git a/packages/StatementService/Android.bp b/packages/StatementService/Android.bp
new file mode 100644
index 0000000..586292e
--- /dev/null
+++ b/packages/StatementService/Android.bp
@@ -0,0 +1,27 @@
+// Copyright (C) 2015 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+android_app {
+ name: "StatementService",
+ srcs: ["src/**/*.java"],
+ optimize: {
+ proguard_flags_files: ["proguard.flags"],
+ },
+ platform_apis: true,
+ privileged: true,
+ libs: ["org.apache.http.legacy"],
+ static_libs: [
+ "libprotobuf-java-nano",
+ "volley",
+ ],
+}
diff --git a/packages/StatementService/Android.mk b/packages/StatementService/Android.mk
deleted file mode 100644
index b9b29e7..0000000
--- a/packages/StatementService/Android.mk
+++ /dev/null
@@ -1,36 +0,0 @@
-# Copyright (C) 2015 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_TAGS := optional
-
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-
-LOCAL_PROGUARD_FLAG_FILES := proguard.flags
-
-LOCAL_PACKAGE_NAME := StatementService
-LOCAL_PRIVATE_PLATFORM_APIS := true
-LOCAL_PRIVILEGED_MODULE := true
-
-LOCAL_JAVA_LIBRARIES += org.apache.http.legacy
-
-LOCAL_STATIC_JAVA_LIBRARIES := \
- libprotobuf-java-nano \
- volley
-
-include $(BUILD_PACKAGE)
-
-include $(call all-makefiles-under,$(LOCAL_PATH)/src)
diff --git a/packages/SystemUI/Android.bp b/packages/SystemUI/Android.bp
index e0d178f..29ae1b2 100644
--- a/packages/SystemUI/Android.bp
+++ b/packages/SystemUI/Android.bp
@@ -137,6 +137,7 @@
static_libs: [
"SystemUI-core",
],
+ resource_dirs: [],
platform_apis: true,
product_specific: true,
diff --git a/packages/SystemUI/AndroidManifest.xml b/packages/SystemUI/AndroidManifest.xml
index 4a5388b..265d464 100644
--- a/packages/SystemUI/AndroidManifest.xml
+++ b/packages/SystemUI/AndroidManifest.xml
@@ -22,6 +22,11 @@
android:sharedUserId="android.uid.systemui"
coreApp="true">
+ <!-- Using OpenGL ES 2.0 -->
+ <uses-feature
+ android:glEsVersion="0x00020000"
+ android:required="true" />
+
<!-- SysUI must be the one to define this permission; its name is
referenced by the core OS. -->
<permission android:name="android.permission.systemui.IDENTITY"
diff --git a/packages/SystemUI/res-keyguard/drawable-xxxhdpi/bubble_preview.png b/packages/SystemUI/res-keyguard/drawable-xxxhdpi/bubble_preview.png
deleted file mode 100644
index 67f072f..0000000
--- a/packages/SystemUI/res-keyguard/drawable-xxxhdpi/bubble_preview.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res-keyguard/drawable-xxxhdpi/stretch_preview.png b/packages/SystemUI/res-keyguard/drawable-xxxhdpi/stretch_preview.png
deleted file mode 100644
index 63927bc..0000000
--- a/packages/SystemUI/res-keyguard/drawable-xxxhdpi/stretch_preview.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res-keyguard/drawable-xxxhdpi/type_preview.png b/packages/SystemUI/res-keyguard/drawable-xxxhdpi/type_preview.png
deleted file mode 100644
index a538149..0000000
--- a/packages/SystemUI/res-keyguard/drawable-xxxhdpi/type_preview.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/layout-land/global_actions_grid.xml b/packages/SystemUI/res/layout-land/global_actions_grid.xml
index 911b661..480f523 100644
--- a/packages/SystemUI/res/layout-land/global_actions_grid.xml
+++ b/packages/SystemUI/res/layout-land/global_actions_grid.xml
@@ -29,10 +29,10 @@
android:layoutDirection="ltr"
android:layout_marginTop="@dimen/global_actions_grid_side_margin"
android:translationZ="@dimen/global_actions_translate"
- android:paddingLeft="@dimen/global_actions_grid_top_padding"
- android:paddingRight="@dimen/global_actions_grid_bottom_padding"
- android:paddingTop="@dimen/global_actions_grid_left_padding"
- android:paddingBottom="@dimen/global_actions_grid_right_padding"
+ android:paddingLeft="@dimen/global_actions_grid_horizontal_padding"
+ android:paddingRight="@dimen/global_actions_grid_horizontal_padding"
+ android:paddingTop="@dimen/global_actions_grid_vertical_padding"
+ android:paddingBottom="@dimen/global_actions_grid_vertical_padding"
android:background="?android:attr/colorBackgroundFloating"
>
<LinearLayout
@@ -61,17 +61,18 @@
<!-- For separated items-->
<LinearLayout
android:id="@+id/separated_button"
- android:layout_width="wrap_content"
+ android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/global_actions_grid_side_margin"
android:layout_marginBottom="@dimen/global_actions_grid_side_margin"
- android:paddingTop="@dimen/global_actions_grid_left_padding"
- android:paddingLeft="@dimen/global_actions_grid_top_padding"
- android:paddingBottom="@dimen/global_actions_grid_right_padding"
- android:paddingRight="@dimen/global_actions_grid_bottom_padding"
+ android:paddingLeft="@dimen/global_actions_grid_horizontal_padding"
+ android:paddingRight="@dimen/global_actions_grid_horizontal_padding"
+ android:paddingTop="@dimen/global_actions_grid_vertical_padding"
+ android:paddingBottom="@dimen/global_actions_grid_vertical_padding"
android:orientation="horizontal"
android:layoutDirection="ltr"
android:background="?android:attr/colorBackgroundFloating"
+ android:gravity="center"
android:translationZ="@dimen/global_actions_translate"
/>
diff --git a/packages/SystemUI/res/layout-land/global_actions_grid_seascape.xml b/packages/SystemUI/res/layout-land/global_actions_grid_seascape.xml
index 669be1b..4f86826 100644
--- a/packages/SystemUI/res/layout-land/global_actions_grid_seascape.xml
+++ b/packages/SystemUI/res/layout-land/global_actions_grid_seascape.xml
@@ -23,17 +23,18 @@
<LinearLayout
android:id="@+id/separated_button"
android:layout_gravity="top|left"
- android:layout_width="wrap_content"
+ android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/global_actions_grid_side_margin"
android:layout_marginBottom="@dimen/global_actions_grid_side_margin"
- android:paddingTop="@dimen/global_actions_grid_left_padding"
- android:paddingLeft="@dimen/global_actions_grid_top_padding"
- android:paddingBottom="@dimen/global_actions_grid_right_padding"
- android:paddingRight="@dimen/global_actions_grid_bottom_padding"
+ android:paddingLeft="@dimen/global_actions_grid_horizontal_padding"
+ android:paddingRight="@dimen/global_actions_grid_horizontal_padding"
+ android:paddingTop="@dimen/global_actions_grid_vertical_padding"
+ android:paddingBottom="@dimen/global_actions_grid_vertical_padding"
android:orientation="horizontal"
android:layoutDirection="rtl"
android:background="?android:attr/colorBackgroundFloating"
+ android:gravity="center"
android:translationZ="@dimen/global_actions_translate"
/>
@@ -44,12 +45,12 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
- android:layout_marginTop="@dimen/global_actions_grid_side_margin"
+ android:layout_marginBottom="@dimen/global_actions_grid_side_margin"
android:translationZ="@dimen/global_actions_translate"
- android:paddingLeft="@dimen/global_actions_grid_top_padding"
- android:paddingRight="@dimen/global_actions_grid_bottom_padding"
- android:paddingTop="@dimen/global_actions_grid_left_padding"
- android:paddingBottom="@dimen/global_actions_grid_right_padding"
+ android:paddingLeft="@dimen/global_actions_grid_horizontal_padding"
+ android:paddingRight="@dimen/global_actions_grid_horizontal_padding"
+ android:paddingTop="@dimen/global_actions_grid_vertical_padding"
+ android:paddingBottom="@dimen/global_actions_grid_vertical_padding"
android:background="?android:attr/colorBackgroundFloating"
>
<LinearLayout
diff --git a/packages/SystemUI/res/layout/global_actions_grid.xml b/packages/SystemUI/res/layout/global_actions_grid.xml
index 1b56fa0..729e96e 100644
--- a/packages/SystemUI/res/layout/global_actions_grid.xml
+++ b/packages/SystemUI/res/layout/global_actions_grid.xml
@@ -23,15 +23,16 @@
<LinearLayout
android:id="@+id/separated_button"
android:layout_width="wrap_content"
- android:layout_height="wrap_content"
+ android:layout_height="match_parent"
android:layout_marginLeft="@dimen/global_actions_grid_side_margin"
android:layout_marginRight="@dimen/global_actions_grid_side_margin"
- android:paddingTop="@dimen/global_actions_grid_top_padding"
- android:paddingLeft="@dimen/global_actions_grid_left_padding"
- android:paddingBottom="@dimen/global_actions_grid_bottom_padding"
- android:paddingRight="@dimen/global_actions_grid_right_padding"
+ android:paddingLeft="@dimen/global_actions_grid_horizontal_padding"
+ android:paddingRight="@dimen/global_actions_grid_horizontal_padding"
+ android:paddingTop="@dimen/global_actions_grid_vertical_padding"
+ android:paddingBottom="@dimen/global_actions_grid_vertical_padding"
android:orientation="vertical"
android:background="?android:attr/colorBackgroundFloating"
+ android:gravity="center"
android:translationZ="@dimen/global_actions_translate"
/>
@@ -44,10 +45,10 @@
android:layoutDirection="rtl"
android:layout_marginRight="@dimen/global_actions_grid_side_margin"
android:translationZ="@dimen/global_actions_translate"
- android:paddingLeft="@dimen/global_actions_grid_left_padding"
- android:paddingRight="@dimen/global_actions_grid_right_padding"
- android:paddingTop="@dimen/global_actions_grid_top_padding"
- android:paddingBottom="@dimen/global_actions_grid_bottom_padding"
+ android:paddingLeft="@dimen/global_actions_grid_horizontal_padding"
+ android:paddingRight="@dimen/global_actions_grid_horizontal_padding"
+ android:paddingTop="@dimen/global_actions_grid_vertical_padding"
+ android:paddingBottom="@dimen/global_actions_grid_vertical_padding"
android:background="?android:attr/colorBackgroundFloating"
>
<LinearLayout
diff --git a/packages/SystemUI/res/layout/global_actions_grid_item.xml b/packages/SystemUI/res/layout/global_actions_grid_item.xml
index a893839..5dee09d 100644
--- a/packages/SystemUI/res/layout/global_actions_grid_item.xml
+++ b/packages/SystemUI/res/layout/global_actions_grid_item.xml
@@ -18,46 +18,43 @@
work around this for now with LinearLayouts. -->
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="72dp"
- android:layout_height="72dp"
- android:gravity="center"
+ android:layout_width="@dimen/global_actions_grid_item_width"
+ android:layout_height="@dimen/global_actions_grid_item_height"
+ android:gravity="top|center_horizontal"
android:orientation="vertical"
android:layout_marginTop="@dimen/global_actions_grid_item_vertical_margin"
android:layout_marginBottom="@dimen/global_actions_grid_item_vertical_margin"
android:layout_marginLeft="@dimen/global_actions_grid_item_side_margin"
android:layout_marginRight="@dimen/global_actions_grid_item_side_margin"
- android:paddingEnd="4dip"
- android:paddingStart="4dip">
-
+>
<ImageView
android:id="@*android:id/icon"
- android:layout_width="24dp"
- android:layout_height="24dp"
- android:layout_gravity="center"
+ android:layout_width="@dimen/global_actions_grid_item_icon_width"
+ android:layout_height="@dimen/global_actions_grid_item_icon_height"
+ android:layout_marginTop="@dimen/global_actions_grid_item_icon_top_margin"
+ android:layout_marginBottom="@dimen/global_actions_grid_item_icon_bottom_margin"
+ android:layout_marginLeft="@dimen/global_actions_grid_item_icon_side_margin"
+ android:layout_marginRight="@dimen/global_actions_grid_item_icon_side_margin"
android:scaleType="center"
android:alpha="?android:attr/primaryContentAlpha"
/>
<TextView
android:id="@*android:id/message"
- android:layout_width="wrap_content"
+ android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:layout_gravity="top|center_horizontal"
- android:paddingTop="10dp"
android:gravity="center"
- android:textSize="12sp"
+ android:textSize="12dp"
android:textAppearance="?android:attr/textAppearanceSmall"
- android:singleLine="true"
/>
<TextView
+ android:visibility="gone"
android:id="@*android:id/status"
- android:layout_width="wrap_content"
+ android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:layout_gravity="top|center_horizontal"
android:gravity="center"
android:textColor="?android:attr/textColorTertiary"
android:textAppearance="?android:attr/textAppearanceSmall"
- android:singleLine="true"
/>
</LinearLayout>
diff --git a/packages/SystemUI/res/layout/home_handle.xml b/packages/SystemUI/res/layout/home_handle.xml
new file mode 100644
index 0000000..48ea5c4
--- /dev/null
+++ b/packages/SystemUI/res/layout/home_handle.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ 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.
+ -->
+
+<com.android.systemui.statusbar.phone.NavigationHandle
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/home_handle"
+ android:layout_width="@dimen/navigation_handle_width"
+ android:layout_height="match_parent"
+ android:layout_weight="0"
+ />
+
diff --git a/packages/SystemUI/res/raw/image_wallpaper_fragment_shader.glsl b/packages/SystemUI/res/raw/image_wallpaper_fragment_shader.glsl
new file mode 100644
index 0000000..586cdf3
--- /dev/null
+++ b/packages/SystemUI/res/raw/image_wallpaper_fragment_shader.glsl
@@ -0,0 +1,27 @@
+precision mediump float;
+
+uniform sampler2D uTexture;
+uniform float uCenterReveal;
+uniform float uReveal;
+uniform float uAod2Opacity;
+varying vec2 vTextureCoordinates;
+
+vec3 luminosity(vec3 color) {
+ float lum = 0.2126 * color.r + 0.7152 * color.g + 0.0722 * color.b;
+ return vec3(lum);
+}
+
+vec4 transform(vec3 diffuse) {
+ // TODO: Add well comments here, tracking on b/123615467.
+ vec3 lum = luminosity(diffuse);
+ diffuse = mix(diffuse, lum, smoothstep(0., uCenterReveal, uReveal));
+ float val = mix(uReveal, uCenterReveal, step(uCenterReveal, uReveal));
+ diffuse = smoothstep(val, 1.0, diffuse);
+ diffuse *= uAod2Opacity * (1. - smoothstep(uCenterReveal, 1., uReveal));
+ return vec4(diffuse.r, diffuse.g, diffuse.b, 1.);
+}
+
+void main() {
+ vec4 fragColor = texture2D(uTexture, vTextureCoordinates);
+ gl_FragColor = transform(fragColor.rgb);
+}
\ No newline at end of file
diff --git a/packages/SystemUI/res/raw/image_wallpaper_vertex_shader.glsl b/packages/SystemUI/res/raw/image_wallpaper_vertex_shader.glsl
new file mode 100644
index 0000000..4393e2b
--- /dev/null
+++ b/packages/SystemUI/res/raw/image_wallpaper_vertex_shader.glsl
@@ -0,0 +1,8 @@
+attribute vec4 aPosition;
+attribute vec2 aTextureCoordinates;
+varying vec2 vTextureCoordinates;
+
+void main() {
+ vTextureCoordinates = aTextureCoordinates;
+ gl_Position = aPosition;
+}
\ No newline at end of file
diff --git a/packages/SystemUI/res/values-sw320dp-land/dimens.xml b/packages/SystemUI/res/values-sw320dp-land/dimens.xml
new file mode 100644
index 0000000..2ec5abd
--- /dev/null
+++ b/packages/SystemUI/res/values-sw320dp-land/dimens.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ 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
+ -->
+<resources>
+
+ <!-- Global actions grid -->
+ <dimen name="global_actions_grid_vertical_padding">3dp</dimen>
+ <dimen name="global_actions_grid_horizontal_padding">0dp</dimen>
+
+ <dimen name="global_actions_grid_item_side_margin">4dp</dimen>
+ <dimen name="global_actions_grid_item_vertical_margin">5dp</dimen>
+
+</resources>
+
diff --git a/packages/SystemUI/res/values-sw320dp/dimens.xml b/packages/SystemUI/res/values-sw320dp/dimens.xml
new file mode 100644
index 0000000..0c2b1cc
--- /dev/null
+++ b/packages/SystemUI/res/values-sw320dp/dimens.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ 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
+ -->
+<resources>
+
+ <!-- Global actions grid -->
+ <dimen name="global_actions_grid_container_bottom_margin">16dp</dimen>
+
+ <dimen name="global_actions_grid_vertical_padding">0dp</dimen>
+ <dimen name="global_actions_grid_horizontal_padding">3dp</dimen>
+
+ <dimen name="global_actions_grid_item_side_margin">5dp</dimen>
+ <dimen name="global_actions_grid_item_vertical_margin">4dp</dimen>
+ <dimen name="global_actions_grid_item_width">64dp</dimen>
+ <dimen name="global_actions_grid_item_height">64dp</dimen>
+
+ <dimen name="global_actions_grid_item_icon_width">18dp</dimen>
+ <dimen name="global_actions_grid_item_icon_height">18dp</dimen>
+ <dimen name="global_actions_grid_item_icon_top_margin">12dp</dimen>
+ <dimen name="global_actions_grid_item_icon_side_margin">22dp</dimen>
+ <dimen name="global_actions_grid_item_icon_bottom_margin">4dp</dimen>
+
+</resources>
+
diff --git a/packages/SystemUI/res/values-sw410dp-land/dimens.xml b/packages/SystemUI/res/values-sw410dp-land/dimens.xml
new file mode 100644
index 0000000..61ba2d0
--- /dev/null
+++ b/packages/SystemUI/res/values-sw410dp-land/dimens.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ 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
+ -->
+<resources>
+
+ <!-- Global actions grid -->
+ <dimen name="global_actions_grid_vertical_padding">4dp</dimen>
+ <dimen name="global_actions_grid_horizontal_padding">8dp</dimen>
+
+ <dimen name="global_actions_grid_item_side_margin">8dp</dimen>
+ <dimen name="global_actions_grid_item_vertical_margin">12dp</dimen>
+
+</resources>
+
diff --git a/packages/SystemUI/res/values-sw410dp/dimens.xml b/packages/SystemUI/res/values-sw410dp/dimens.xml
index 5ce6524..4197eb2 100644
--- a/packages/SystemUI/res/values-sw410dp/dimens.xml
+++ b/packages/SystemUI/res/values-sw410dp/dimens.xml
@@ -21,4 +21,22 @@
for different hardware and product builds. -->
<resources>
<dimen name="qs_detail_items_padding_top">16dp</dimen>
+
+ <!-- Global actions grid -->
+ <dimen name="global_actions_grid_container_bottom_margin">16dp</dimen>
+
+ <dimen name="global_actions_grid_vertical_padding">8dp</dimen>
+ <dimen name="global_actions_grid_horizontal_padding">4dp</dimen>
+
+ <dimen name="global_actions_grid_item_side_margin">12dp</dimen>
+ <dimen name="global_actions_grid_item_vertical_margin">8dp</dimen>
+ <dimen name="global_actions_grid_item_width">72dp</dimen>
+ <dimen name="global_actions_grid_item_height">72dp</dimen>
+
+ <dimen name="global_actions_grid_item_icon_width">24dp</dimen>
+ <dimen name="global_actions_grid_item_icon_height">24dp</dimen>
+ <dimen name="global_actions_grid_item_icon_top_margin">16dp</dimen>
+ <dimen name="global_actions_grid_item_icon_side_margin">24dp</dimen>
+ <dimen name="global_actions_grid_item_icon_bottom_margin">4dp</dimen>
+
</resources>
diff --git a/packages/SystemUI/res/values/config.xml b/packages/SystemUI/res/values/config.xml
index 76eb85e..4396a42 100644
--- a/packages/SystemUI/res/values/config.xml
+++ b/packages/SystemUI/res/values/config.xml
@@ -325,6 +325,7 @@
<!-- Nav bar button default ordering/layout -->
<string name="config_navBarLayout" translatable="false">left[.5W],back[1WC];home;recent[1WC],right[.5W]</string>
<string name="config_navBarLayoutQuickstep" translatable="false">back[1.7WC];home;contextual[1.7WC]</string>
+ <string name="config_navBarLayoutHandle" translatable="false">";home_handle;"</string>
<bool name="quick_settings_show_full_alarm">false</bool>
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index 1c7ee36..371a060 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -33,6 +33,11 @@
<!-- size of the dead zone when touches have recently occurred elsewhere on screen -->
<dimen name="navigation_bar_deadzone_size_max">32dp</dimen>
+ <!-- dimensions for the navigation bar handle -->
+ <dimen name="navigation_handle_width">180dp</dimen>
+ <dimen name="navigation_handle_radius">2dp</dimen>
+ <dimen name="navigation_handle_bottom">8dp</dimen>
+
<!-- Height of notification icons in the status bar -->
<dimen name="status_bar_icon_size">@*android:dimen/status_bar_icon_size</dimen>
@@ -841,26 +846,15 @@
<dimen name="default_gear_space">18dp</dimen>
<dimen name="cell_overlay_padding">18dp</dimen>
+ <!-- Global actions power menu -->
<dimen name="global_actions_panel_width">120dp</dimen>
-
- <dimen name="global_actions_grid_container_bottom_margin">16dp</dimen>
-
- <dimen name="global_actions_grid_side_margin">4dp</dimen>
- <dimen name="global_actions_grid_separated_panel_width">104dp</dimen>
- <dimen name="global_actions_grid_top_padding">8dp</dimen>
- <dimen name="global_actions_grid_bottom_padding">8dp</dimen>
- <dimen name="global_actions_grid_left_padding">4dp</dimen>
- <dimen name="global_actions_grid_right_padding">4dp</dimen>
-
- <dimen name="global_actions_grid_item_side_margin">12dp</dimen>
- <dimen name="global_actions_grid_item_vertical_margin">8dp</dimen>
-
<dimen name="global_actions_top_padding">120dp</dimen>
-
<dimen name="global_actions_padding">12dp</dimen>
-
<dimen name="global_actions_translate">9dp</dimen>
+ <!-- Global actions grid layout -->
+ <dimen name="global_actions_grid_side_margin">4dp</dimen>
+
<!-- The maximum offset in either direction that elements are moved horizontally to prevent
burn-in on AOD. -->
<dimen name="burn_in_prevention_offset_x">8dp</dimen>
@@ -1019,8 +1013,8 @@
<dimen name="bubble_icon_inset">16dp</dimen>
<!-- Padding around the view displayed when the bubble is expanded -->
<dimen name="bubble_expanded_view_padding">8dp</dimen>
- <!-- Default height of the expanded view shown when the bubble is expanded -->
- <dimen name="bubble_expanded_default_height">400dp</dimen>
+ <!-- Default (and minimum) height of the expanded view shown when the bubble is expanded -->
+ <dimen name="bubble_expanded_default_height">180dp</dimen>
<!-- Height of the triangle that points to the expanded bubble -->
<dimen name="bubble_pointer_height">4dp</dimen>
<!-- Width of the triangle that points to the expanded bubble -->
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index 01595f0..0fde2de 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -1069,7 +1069,10 @@
<string name="battery_saver_notification_action_text">Turn off Battery Saver</string>
<!-- Media projection permission dialog warning text. [CHAR LIMIT=NONE] -->
- <string name="media_projection_dialog_text"><xliff:g id="app_seeking_permission" example="Hangouts">%s</xliff:g> will start capturing everything that\'s displayed on your screen.</string>
+ <string name="media_projection_dialog_text"><xliff:g id="app_seeking_permission" example="Hangouts">%s</xliff:g> will start capturing everything on your screen including notifications, passwords, photos, messages and payment information.</string>
+
+ <!-- Media projection permission dialog warning title. [CHAR LIMIT=NONE] -->
+ <string name="media_projection_dialog_title">Allow <xliff:g id="app_seeking_permission" example="Hangouts">%s</xliff:g> to record or cast your screen?</string>
<!-- Media projection permission dialog permanent grant check box. [CHAR LIMIT=NONE] -->
<string name="media_projection_remember_text">Don\'t show again</string>
diff --git a/packages/SystemUI/src/com/android/keyguard/clock/ClockManager.java b/packages/SystemUI/src/com/android/keyguard/clock/ClockManager.java
index 078108d..c5dc324 100644
--- a/packages/SystemUI/src/com/android/keyguard/clock/ClockManager.java
+++ b/packages/SystemUI/src/com/android/keyguard/clock/ClockManager.java
@@ -16,42 +16,59 @@
package com.android.keyguard.clock;
import android.annotation.Nullable;
+import android.app.WallpaperManager;
import android.content.ContentResolver;
import android.content.Context;
import android.content.res.Resources;
import android.database.ContentObserver;
+import android.graphics.Bitmap;
+import android.graphics.Bitmap.Config;
import android.graphics.BitmapFactory;
+import android.graphics.Canvas;
+import android.graphics.Color;
import android.os.Handler;
import android.os.Looper;
import android.provider.Settings;
+import android.util.ArrayMap;
+import android.util.DisplayMetrics;
import android.view.LayoutInflater;
+import android.view.View;
+import android.view.View.MeasureSpec;
import androidx.annotation.VisibleForTesting;
+import com.android.internal.colorextraction.ColorExtractor;
import com.android.keyguard.R;
+import com.android.systemui.colorextraction.SysuiColorExtractor;
import com.android.systemui.dock.DockManager;
import com.android.systemui.dock.DockManager.DockEventListener;
import com.android.systemui.plugins.ClockPlugin;
-import com.android.systemui.statusbar.policy.ExtensionController;
-import com.android.systemui.statusbar.policy.ExtensionController.Extension;
+import com.android.systemui.util.InjectionInflationController;
import java.util.ArrayList;
import java.util.List;
-import java.util.function.Consumer;
+import java.util.Map;
+import java.util.function.Supplier;
import javax.inject.Inject;
import javax.inject.Singleton;
/**
- * Manages custom clock faces.
+ * Manages custom clock faces for AOD and lock screen.
*/
@Singleton
public final class ClockManager {
- private final ContentResolver mContentResolver;
-
private final List<ClockInfo> mClockInfos = new ArrayList<>();
/**
+ * Map from expected value stored in settings to supplier of custom clock face.
+ */
+ private final Map<String, Supplier<ClockPlugin>> mClocks = new ArrayMap<>();
+ @Nullable private ClockPlugin mCurrentClock;
+
+ private final ContentResolver mContentResolver;
+ private final SettingsWrapper mSettingsWrapper;
+ /**
* Observe settings changes to know when to switch the clock face.
*/
private final ContentObserver mContentObserver =
@@ -59,24 +76,9 @@
@Override
public void onChange(boolean selfChange) {
super.onChange(selfChange);
- if (mClockExtension != null) {
- mClockExtension.reload();
- }
+ reload();
}
};
- private final ExtensionController mExtensionController;
- /**
- * Used to select between plugin or default implementations of ClockPlugin interface.
- */
- private Extension<ClockPlugin> mClockExtension;
- /**
- * Consumer that accepts the a new ClockPlugin implementation when the Extension reloads.
- */
- private final Consumer<ClockPlugin> mClockPluginConsumer = this::setClockPlugin;
- /**
- * Supplier of default ClockPlugin implementation.
- */
- private final DefaultClockSupplier mDefaultClockSupplier;
/**
* Observe changes to dock state to know when to switch the clock face.
*/
@@ -84,25 +86,38 @@
new DockEventListener() {
@Override
public void onEvent(int event) {
- final boolean isDocked = (event == DockManager.STATE_DOCKED
+ mIsDocked = (event == DockManager.STATE_DOCKED
|| event == DockManager.STATE_DOCKED_HIDE);
- mDefaultClockSupplier.setDocked(isDocked);
- if (mClockExtension != null) {
- mClockExtension.reload();
- }
+ reload();
}
};
- @Nullable
- private final DockManager mDockManager;
+ @Nullable private final DockManager mDockManager;
+ /**
+ * When docked, the DOCKED_CLOCK_FACE setting will be checked for the custom clock face
+ * to show.
+ */
+ private boolean mIsDocked;
private final List<ClockChangedListener> mListeners = new ArrayList<>();
+ private final SysuiColorExtractor mColorExtractor;
+ private final int mWidth;
+ private final int mHeight;
+
@Inject
- public ClockManager(Context context, ExtensionController extensionController,
- @Nullable DockManager dockManager) {
- mExtensionController = extensionController;
+ public ClockManager(Context context, InjectionInflationController injectionInflater,
+ @Nullable DockManager dockManager, SysuiColorExtractor colorExtractor) {
+ this(context, injectionInflater, dockManager, colorExtractor, context.getContentResolver(),
+ new SettingsWrapper(context.getContentResolver()));
+ }
+
+ ClockManager(Context context, InjectionInflationController injectionInflater,
+ @Nullable DockManager dockManager, SysuiColorExtractor colorExtractor,
+ ContentResolver contentResolver, SettingsWrapper settingsWrapper) {
mDockManager = dockManager;
- mContentResolver = context.getContentResolver();
+ mColorExtractor = colorExtractor;
+ mContentResolver = contentResolver;
+ mSettingsWrapper = settingsWrapper;
Resources res = context.getResources();
mClockInfos.add(ClockInfo.builder()
@@ -117,25 +132,35 @@
.setTitle(res.getString(R.string.clock_title_bubble))
.setId(BubbleClockController.class.getName())
.setThumbnail(() -> BitmapFactory.decodeResource(res, R.drawable.bubble_thumbnail))
- .setPreview(() -> BitmapFactory.decodeResource(res, R.drawable.bubble_preview))
+ .setPreview(() -> getClockPreview(BubbleClockController.class.getName()))
.build());
mClockInfos.add(ClockInfo.builder()
.setName("stretch")
.setTitle(res.getString(R.string.clock_title_stretch))
.setId(StretchAnalogClockController.class.getName())
.setThumbnail(() -> BitmapFactory.decodeResource(res, R.drawable.stretch_thumbnail))
- .setPreview(() -> BitmapFactory.decodeResource(res, R.drawable.stretch_preview))
+ .setPreview(() -> getClockPreview(StretchAnalogClockController.class.getName()))
.build());
mClockInfos.add(ClockInfo.builder()
.setName("type")
.setTitle(res.getString(R.string.clock_title_type))
.setId(TypeClockController.class.getName())
.setThumbnail(() -> BitmapFactory.decodeResource(res, R.drawable.type_thumbnail))
- .setPreview(() -> BitmapFactory.decodeResource(res, R.drawable.type_preview))
+ .setPreview(() -> getClockPreview(TypeClockController.class.getName()))
.build());
- mDefaultClockSupplier = new DefaultClockSupplier(new SettingsWrapper(mContentResolver),
- LayoutInflater.from(context));
+ LayoutInflater layoutInflater = injectionInflater.injectable(LayoutInflater.from(context));
+ mClocks.put(BubbleClockController.class.getName(),
+ () -> BubbleClockController.build(layoutInflater));
+ mClocks.put(StretchAnalogClockController.class.getName(),
+ () -> StretchAnalogClockController.build(layoutInflater));
+ mClocks.put(TypeClockController.class.getName(),
+ () -> TypeClockController.build(layoutInflater));
+
+ // Store the size of the display for generation of clock preview.
+ DisplayMetrics dm = res.getDisplayMetrics();
+ mWidth = dm.widthPixels;
+ mHeight = dm.heightPixels;
}
/**
@@ -146,9 +171,7 @@
register();
}
mListeners.add(listener);
- if (mClockExtension != null) {
- mClockExtension.reload();
- }
+ reload();
}
/**
@@ -168,7 +191,66 @@
return mClockInfos;
}
- private void setClockPlugin(ClockPlugin plugin) {
+ /**
+ * Get the current clock.
+ * @returns current custom clock or null for default.
+ */
+ @Nullable
+ ClockPlugin getCurrentClock() {
+ return mCurrentClock;
+ }
+
+ @VisibleForTesting
+ boolean isDocked() {
+ return mIsDocked;
+ }
+
+ @VisibleForTesting
+ ContentObserver getContentObserver() {
+ return mContentObserver;
+ }
+
+ /**
+ * Generate a realistic preview of a clock face.
+ * @param clockId ID of clock to use for preview, should be obtained from {@link getClockInfos}.
+ * Returns null if clockId is not found.
+ */
+ @Nullable
+ private Bitmap getClockPreview(String clockId) {
+ Supplier<ClockPlugin> supplier = mClocks.get(clockId);
+ if (supplier == null) {
+ return null;
+ }
+ ClockPlugin plugin = supplier.get();
+
+ // Use the big clock view for the preview
+ View clockView = plugin.getBigClockView();
+ if (clockView == null) {
+ return null;
+ }
+
+ // Initialize state of plugin before generating preview.
+ plugin.setDarkAmount(1f);
+ plugin.setTextColor(Color.WHITE);
+
+ ColorExtractor.GradientColors colors = mColorExtractor.getColors(WallpaperManager.FLAG_LOCK,
+ true);
+ plugin.setColorPalette(colors.supportsDarkText(), colors.getColorPalette());
+ plugin.dozeTimeTick();
+
+ // Draw clock view hierarchy to canvas.
+ Bitmap bitmap = Bitmap.createBitmap(mWidth, mHeight, Config.ARGB_8888);
+ Canvas canvas = new Canvas(bitmap);
+ clockView.measure(MeasureSpec.makeMeasureSpec(mWidth, MeasureSpec.EXACTLY),
+ MeasureSpec.makeMeasureSpec(mHeight, MeasureSpec.EXACTLY));
+ clockView.layout(0, 0, mWidth, mHeight);
+ canvas.drawColor(Color.BLACK);
+ clockView.draw(canvas);
+
+ return bitmap;
+ }
+
+ private void notifyClockChanged(ClockPlugin plugin) {
for (int i = 0; i < mListeners.size(); i++) {
// It probably doesn't make sense to supply the same plugin instances to multiple
// listeners. This should be fine for now since there is only a single listener.
@@ -186,11 +268,6 @@
if (mDockManager != null) {
mDockManager.addListener(mDockEventListener);
}
- mClockExtension = mExtensionController.newExtension(ClockPlugin.class)
- .withPlugin(ClockPlugin.class)
- .withCallback(mClockPluginConsumer)
- .withDefault(mDefaultClockSupplier)
- .build();
}
private void unregister() {
@@ -198,12 +275,35 @@
if (mDockManager != null) {
mDockManager.removeListener(mDockEventListener);
}
- mClockExtension.destroy();
}
- @VisibleForTesting
- boolean isDocked() {
- return mDefaultClockSupplier.isDocked();
+ private void reload() {
+ mCurrentClock = getClockPlugin();
+ notifyClockChanged(mCurrentClock);
+ }
+
+ private ClockPlugin getClockPlugin() {
+ ClockPlugin plugin = null;
+ if (mIsDocked) {
+ final String name = mSettingsWrapper.getDockedClockFace();
+ if (name != null) {
+ Supplier<ClockPlugin> supplier = mClocks.get(name);
+ if (supplier != null) {
+ plugin = supplier.get();
+ if (plugin != null) {
+ return plugin;
+ }
+ }
+ }
+ }
+ final String name = mSettingsWrapper.getLockScreenCustomClockFace();
+ if (name != null) {
+ Supplier<ClockPlugin> supplier = mClocks.get(name);
+ if (supplier != null) {
+ plugin = supplier.get();
+ }
+ }
+ return plugin;
}
/**
diff --git a/packages/SystemUI/src/com/android/keyguard/clock/DefaultClockSupplier.java b/packages/SystemUI/src/com/android/keyguard/clock/DefaultClockSupplier.java
deleted file mode 100644
index 7fdd235..0000000
--- a/packages/SystemUI/src/com/android/keyguard/clock/DefaultClockSupplier.java
+++ /dev/null
@@ -1,101 +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.
- */
-package com.android.keyguard.clock;
-
-import android.util.ArrayMap;
-import android.view.LayoutInflater;
-
-import com.android.systemui.plugins.ClockPlugin;
-
-import java.util.Map;
-import java.util.function.Supplier;
-
-/**
- * Supplier that only gets an instance when a settings value matches expected value.
- */
-public class DefaultClockSupplier implements Supplier<ClockPlugin> {
-
- private final SettingsWrapper mSettingsWrapper;
- /**
- * Map from expected value stored in settings to supplier of custom clock face.
- */
- private final Map<String, Supplier<ClockPlugin>> mClocks = new ArrayMap<>();
- /**
- * When docked, the DOCKED_CLOCK_FACE setting will be checked for the custom clock face
- * to show.
- */
- private boolean mIsDocked;
-
- /**
- * Constructs a supplier that changes secure setting key against value.
- *
- * @param settingsWrapper Wrapper around settings used to look up the custom clock face.
- * @param layoutInflater Provided to clocks as dependency to inflate clock views.
- */
- public DefaultClockSupplier(SettingsWrapper settingsWrapper, LayoutInflater layoutInflater) {
- mSettingsWrapper = settingsWrapper;
-
- mClocks.put(BubbleClockController.class.getName(),
- () -> BubbleClockController.build(layoutInflater));
- mClocks.put(StretchAnalogClockController.class.getName(),
- () -> StretchAnalogClockController.build(layoutInflater));
- mClocks.put(TypeClockController.class.getName(),
- () -> TypeClockController.build(layoutInflater));
- }
-
- /**
- * Sets the dock state.
- *
- * @param isDocked True when docked, false otherwise.
- */
- public void setDocked(boolean isDocked) {
- mIsDocked = isDocked;
- }
-
- boolean isDocked() {
- return mIsDocked;
- }
-
- /**
- * Get the custom clock face based on values in settings.
- *
- * @return Custom clock face, null if the settings value doesn't match a custom clock.
- */
- @Override
- public ClockPlugin get() {
- ClockPlugin plugin = null;
- if (mIsDocked) {
- final String name = mSettingsWrapper.getDockedClockFace();
- if (name != null) {
- Supplier<ClockPlugin> supplier = mClocks.get(name);
- if (supplier != null) {
- plugin = supplier.get();
- if (plugin != null) {
- return plugin;
- }
- }
- }
- }
- final String name = mSettingsWrapper.getLockScreenCustomClockFace();
- if (name != null) {
- Supplier<ClockPlugin> supplier = mClocks.get(name);
- if (supplier != null) {
- plugin = supplier.get();
- }
- }
- return plugin;
- }
-}
diff --git a/packages/SystemUI/src/com/android/keyguard/clock/ImageClock.java b/packages/SystemUI/src/com/android/keyguard/clock/ImageClock.java
index e35cf11..2275380 100644
--- a/packages/SystemUI/src/com/android/keyguard/clock/ImageClock.java
+++ b/packages/SystemUI/src/com/android/keyguard/clock/ImageClock.java
@@ -37,7 +37,7 @@
private ImageView mHourHand;
private ImageView mMinuteHand;
- private Calendar mTime;
+ private final Calendar mTime = Calendar.getInstance(TimeZone.getDefault());
private String mDescFormat;
private TimeZone mTimeZone;
@@ -51,7 +51,6 @@
public ImageClock(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
- mTime = Calendar.getInstance();
mDescFormat = ((SimpleDateFormat) DateFormat.getTimeFormat(context)).toLocalizedPattern();
}
@@ -98,7 +97,7 @@
@Override
protected void onAttachedToWindow() {
super.onAttachedToWindow();
- mTime = Calendar.getInstance(mTimeZone != null ? mTimeZone : TimeZone.getDefault());
+ mTime.setTimeZone(mTimeZone != null ? mTimeZone : TimeZone.getDefault());
onTimeChanged();
}
}
diff --git a/packages/SystemUI/src/com/android/keyguard/clock/StretchAnalogClock.java b/packages/SystemUI/src/com/android/keyguard/clock/StretchAnalogClock.java
index 3c9a4f8..34c855b 100644
--- a/packages/SystemUI/src/com/android/keyguard/clock/StretchAnalogClock.java
+++ b/packages/SystemUI/src/com/android/keyguard/clock/StretchAnalogClock.java
@@ -37,7 +37,7 @@
private final Paint mHourPaint = new Paint();
private final Paint mMinutePaint = new Paint();
- private Calendar mTime;
+ private Calendar mTime = Calendar.getInstance(TimeZone.getDefault());
private TimeZone mTimeZone;
public StretchAnalogClock(Context context) {
@@ -138,7 +138,7 @@
@Override
protected void onAttachedToWindow() {
super.onAttachedToWindow();
- mTime = Calendar.getInstance(mTimeZone != null ? mTimeZone : TimeZone.getDefault());
+ mTime.setTimeZone(mTimeZone != null ? mTimeZone : TimeZone.getDefault());
onTimeChanged();
}
}
diff --git a/packages/SystemUI/src/com/android/keyguard/clock/TypographicClock.java b/packages/SystemUI/src/com/android/keyguard/clock/TypographicClock.java
index 6f1b59c..7bce3c5 100644
--- a/packages/SystemUI/src/com/android/keyguard/clock/TypographicClock.java
+++ b/packages/SystemUI/src/com/android/keyguard/clock/TypographicClock.java
@@ -44,7 +44,7 @@
private final String[] mHours;
private final String[] mMinutes;
private int mAccentColor;
- private Calendar mTime;
+ private final Calendar mTime = Calendar.getInstance(TimeZone.getDefault());
private String mDescFormat;
private TimeZone mTimeZone;
@@ -58,7 +58,6 @@
public TypographicClock(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
- mTime = Calendar.getInstance();
mDescFormat = ((SimpleDateFormat) DateFormat.getTimeFormat(context)).toLocalizedPattern();
mResources = context.getResources();
mHours = mResources.getStringArray(R.array.type_clock_hours);
@@ -111,12 +110,13 @@
*/
public void setClockColor(int color) {
mAccentColor = color;
+ onTimeChanged();
}
@Override
protected void onAttachedToWindow() {
super.onAttachedToWindow();
- mTime = Calendar.getInstance(mTimeZone != null ? mTimeZone : TimeZone.getDefault());
+ mTime.setTimeZone(mTimeZone != null ? mTimeZone : TimeZone.getDefault());
onTimeChanged();
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java b/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java
index 2aecc24..7e645ab 100644
--- a/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java
+++ b/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java
@@ -28,7 +28,9 @@
import android.graphics.RectF;
import android.graphics.Region.Op;
import android.hardware.display.DisplayManager;
+import android.opengl.GLSurfaceView;
import android.os.AsyncTask;
+import android.os.Build;
import android.os.Handler;
import android.os.Trace;
import android.service.wallpaper.WallpaperService;
@@ -39,6 +41,7 @@
import android.view.SurfaceHolder;
import com.android.internal.annotations.VisibleForTesting;
+import com.android.systemui.glwallpaper.ImageWallpaperRenderer;
import java.io.FileDescriptor;
import java.io.IOException;
@@ -73,10 +76,78 @@
@Override
public Engine onCreateEngine() {
- mEngine = new DrawableEngine();
- return mEngine;
+ if (Build.IS_DEBUGGABLE) {
+ Log.v(TAG, "We are using GLEngine");
+ }
+ return new GLEngine(this);
}
+ class GLEngine extends Engine {
+ private GLWallpaperSurfaceView mWallpaperSurfaceView;
+
+ GLEngine(Context context) {
+ mWallpaperSurfaceView = new GLWallpaperSurfaceView(context);
+ mWallpaperSurfaceView.setRenderer(
+ new ImageWallpaperRenderer(context, mWallpaperSurfaceView));
+ mWallpaperSurfaceView.setRenderMode(GLSurfaceView.RENDERMODE_WHEN_DIRTY);
+ setOffsetNotificationsEnabled(true);
+ }
+
+ @Override
+ public void onAmbientModeChanged(boolean inAmbientMode, long animationDuration) {
+ if (mWallpaperSurfaceView != null) {
+ mWallpaperSurfaceView.notifyAmbientModeChanged(inAmbientMode, animationDuration);
+ }
+ }
+
+ @Override
+ public void onOffsetsChanged(float xOffset, float yOffset, float xOffsetStep,
+ float yOffsetStep, int xPixelOffset, int yPixelOffset) {
+ if (mWallpaperSurfaceView != null) {
+ mWallpaperSurfaceView.notifyOffsetsChanged(xOffset, yOffset);
+ }
+ }
+
+ private class GLWallpaperSurfaceView extends GLSurfaceView implements ImageGLView {
+ private WallpaperStatusListener mWallpaperChangedListener;
+
+ GLWallpaperSurfaceView(Context context) {
+ super(context);
+ setEGLContextClientVersion(2);
+ }
+
+ @Override
+ public SurfaceHolder getHolder() {
+ return getSurfaceHolder();
+ }
+
+ @Override
+ public void setRenderer(Renderer renderer) {
+ super.setRenderer(renderer);
+ mWallpaperChangedListener = (WallpaperStatusListener) renderer;
+ }
+
+ private void notifyAmbientModeChanged(boolean inAmbient, long duration) {
+ if (mWallpaperChangedListener != null) {
+ mWallpaperChangedListener.onAmbientModeChanged(inAmbient, duration);
+ }
+ }
+
+ private void notifyOffsetsChanged(float xOffset, float yOffset) {
+ if (mWallpaperChangedListener != null) {
+ mWallpaperChangedListener.onOffsetsChanged(
+ xOffset, yOffset, getHolder().getSurfaceFrame());
+ }
+ }
+
+ @Override
+ public void render() {
+ requestRender();
+ }
+ }
+ }
+
+ // TODO: Remove this engine, tracking on b/123617158.
class DrawableEngine extends Engine {
private final Runnable mUnloadWallpaperCallback = () -> {
unloadWallpaper(false /* forgetSize */);
@@ -564,4 +635,35 @@
}
}
}
+
+ /**
+ * A listener to trace status of image wallpaper.
+ */
+ public interface WallpaperStatusListener {
+
+ /**
+ * Called back while ambient mode changes.
+ * @param inAmbientMode true if is in ambient mode, false otherwise.
+ * @param duration the duration of animation.
+ */
+ void onAmbientModeChanged(boolean inAmbientMode, long duration);
+
+ /**
+ * Called back while wallpaper offsets.
+ * @param xOffset The offset portion along x.
+ * @param yOffset The offset portion along y.
+ */
+ void onOffsetsChanged(float xOffset, float yOffset, Rect frame);
+ }
+
+ /**
+ * An abstraction for view of GLRenderer.
+ */
+ public interface ImageGLView {
+
+ /**
+ * Ask the view to render.
+ */
+ void render();
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/MultiListLayout.java b/packages/SystemUI/src/com/android/systemui/MultiListLayout.java
index 00ff518..8c49d56 100644
--- a/packages/SystemUI/src/com/android/systemui/MultiListLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/MultiListLayout.java
@@ -151,7 +151,10 @@
return null;
}
- interface RotationListener {
+ /**
+ * Interface to provide callbacks which trigger when this list detects a rotation.
+ */
+ public interface RotationListener {
void onRotate(int from, int to);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/Bubble.java b/packages/SystemUI/src/com/android/systemui/bubbles/Bubble.java
index 4778434..4fe09a9 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/Bubble.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/Bubble.java
@@ -50,6 +50,6 @@
public void setEntry(NotificationEntry entry) {
key = entry.key;
iconView.update(entry);
- // TODO: should also update the expanded view here (e.g. height change)
+ expandedView.update(entry);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java
index e62c77de..0832296 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java
@@ -243,6 +243,16 @@
}
/**
+ * Directs a back gesture at the bubble stack. When opened, the current expanded bubble
+ * is forwarded a back key down/up pair.
+ */
+ public void performBackPressIfNeeded() {
+ if (mStackView != null) {
+ mStackView.performBackPressIfNeeded();
+ }
+ }
+
+ /**
* Adds or updates a bubble associated with the provided notification entry.
*
* @param notif the notification associated with this bubble.
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleExpandedView.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleExpandedView.java
index 492eadd..c2327ad 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleExpandedView.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleExpandedView.java
@@ -89,8 +89,8 @@
private boolean mActivityViewReady = false;
private PendingIntent mBubbleIntent;
- private int mBubbleHeight;
- private int mDefaultHeight;
+ private int mMinHeight;
+ private int mHeaderHeight;
private NotificationEntry mEntry;
private PackageManager mPm;
@@ -149,7 +149,7 @@
int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
mPm = context.getPackageManager();
- mDefaultHeight = getResources().getDimensionPixelSize(
+ mMinHeight = getResources().getDimensionPixelSize(
R.dimen.bubble_expanded_default_height);
try {
mNotificationManagerService = INotificationManager.Stub.asInterface(
@@ -194,6 +194,8 @@
viewWrapper.setLayoutTransition(transition);
viewWrapper.getLayoutTransition().enableTransitionType(LayoutTransition.CHANGING);
+ mHeaderHeight = getContext().getResources().getDimensionPixelSize(
+ R.dimen.bubble_expanded_header_height);
mHeaderView = findViewById(R.id.header_layout);
mHeaderTextView = findViewById(R.id.header_text);
mDeepLinkIcon = findViewById(R.id.deep_link_button);
@@ -273,6 +275,21 @@
mActivityView.setCallback(mStateCallback);
}
+ /**
+ * Updates the entry backing this view. This will not re-populate ActivityView, it will
+ * only update the deep-links in the header, the title, and the height of the view.
+ */
+ public void update(NotificationEntry entry) {
+ if (entry.key.equals(mEntry.key)) {
+ mEntry = entry;
+ updateHeaderView();
+ updateHeight();
+ } else {
+ Log.w(TAG, "Trying to update entry with different key, new entry: "
+ + entry.key + " old entry: " + mEntry.key);
+ }
+ }
+
private void updateHeaderView() {
mSettingsIcon.setContentDescription(getResources().getString(
R.string.bubbles_settings_button_description, mAppName));
@@ -315,14 +332,6 @@
removeView(mNotifRow);
mNotifRow = null;
}
- Notification.BubbleMetadata data = mEntry.getBubbleMetadata();
- mBubbleHeight = data != null && data.getDesiredHeight() > 0
- ? data.getDesiredHeight()
- : mDefaultHeight;
- // XXX: enforce max / min height
- LayoutParams lp = (LayoutParams) mActivityView.getLayoutParams();
- lp.height = mBubbleHeight;
- mActivityView.setLayoutParams(lp);
mActivityView.setVisibility(VISIBLE);
} else {
// Hide activity view if we had it previously
@@ -335,6 +344,36 @@
updateView();
}
+ boolean performBackPressIfNeeded() {
+ if (mActivityView == null || !usingActivityView()) {
+ return false;
+ }
+ mActivityView.performBackPress();
+ return true;
+ }
+
+ void updateHeight() {
+ if (usingActivityView()) {
+ Notification.BubbleMetadata data = mEntry.getBubbleMetadata();
+ int desiredHeight;
+ if (data == null) {
+ // This is a contentIntent based bubble, lets allow it to be the max height
+ // as it was forced into this mode and not prepared to be small
+ desiredHeight = mStackView.getMaxExpandedHeight();
+ } else {
+ desiredHeight = data.getDesiredHeight() > 0
+ ? data.getDesiredHeight()
+ : mMinHeight;
+ }
+ int max = mStackView.getMaxExpandedHeight() - mHeaderHeight;
+ int height = Math.min(desiredHeight, max);
+ height = Math.max(height, mMinHeight);
+ LayoutParams lp = (LayoutParams) mActivityView.getLayoutParams();
+ lp.height = height;
+ mActivityView.setLayoutParams(lp);
+ }
+ }
+
@Override
public void onClick(View view) {
if (mEntry == null) {
@@ -399,6 +438,7 @@
} else if (mNotifRow != null) {
applyRowState(mNotifRow);
}
+ updateHeight();
}
/**
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java
index ed9b38b..5546e4c 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java
@@ -99,6 +99,7 @@
private int mExpandedAnimateXDistance;
private int mExpandedAnimateYDistance;
private int mStatusBarHeight;
+ private int mPipDismissHeight;
private Bubble mExpandedBubble;
private boolean mIsExpanded;
@@ -159,6 +160,8 @@
res.getDimensionPixelSize(R.dimen.bubble_expanded_animate_y_distance);
mStatusBarHeight =
res.getDimensionPixelSize(com.android.internal.R.dimen.status_bar_height);
+ mPipDismissHeight = mContext.getResources().getDimensionPixelSize(
+ R.dimen.pip_dismiss_gradient_height);
mDisplaySize = new Point();
WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
@@ -390,8 +393,7 @@
*/
public void updateBubble(NotificationEntry entry, boolean updatePosition) {
Bubble b = mBubbleData.getBubble(entry.key);
- b.iconView.update(entry);
- // TODO: should also update the expanded view here (e.g. height change)
+ mBubbleData.updateBubble(entry.key, entry);
if (updatePosition && !mIsExpanded) {
// If alerting it gets promoted to top of the stack.
@@ -653,6 +655,20 @@
}
/**
+ * Calculates how large the expanded view of the bubble can be. This takes into account the
+ * y position when the bubbles are expanded as well as the bounds of the dismiss target.
+ */
+ int getMaxExpandedHeight() {
+ int expandedY = (int) mExpandedAnimationController.getExpandedY();
+ int bubbleContainerHeight = mBubbleContainer.getChildAt(0) != null
+ ? mBubbleContainer.getChildAt(0).getHeight()
+ : 0;
+ // PIP dismiss view uses FLAG_LAYOUT_IN_SCREEN so we need to subtract the bottom inset
+ int pipDismissHeight = mPipDismissHeight - getBottomInset();
+ return mDisplaySize.y - expandedY - mBubbleSize - pipDismissHeight;
+ }
+
+ /**
* Minimum velocity, in pixels/second, required to get from x to destX while being slowed by a
* given frictional force.
*
@@ -688,6 +704,14 @@
return 0;
}
+ private int getBottomInset() {
+ if (getRootWindowInsets() != null) {
+ WindowInsets insets = getRootWindowInsets();
+ return insets.getSystemWindowInsetBottom();
+ }
+ return 0;
+ }
+
private boolean isIntersecting(View view, float x, float y) {
mTempLoc = view.getLocationOnScreen();
mTempRect.set(mTempLoc[0], mTempLoc[1], mTempLoc[0] + view.getWidth(),
@@ -815,4 +839,15 @@
getNormalizedYPosition());
}
}
+
+ /**
+ * Called when a back gesture should be directed to the Bubbles stack. When expanded,
+ * a back key down/up event pair is forwarded to the bubble Activity.
+ */
+ boolean performBackPressIfNeeded() {
+ if (!isExpanded()) {
+ return false;
+ }
+ return mExpandedBubble.expandedView.performBackPressIfNeeded();
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/animation/ExpandedAnimationController.java b/packages/SystemUI/src/com/android/systemui/bubbles/animation/ExpandedAnimationController.java
index 9fd26b8..f0d9be1 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/animation/ExpandedAnimationController.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/animation/ExpandedAnimationController.java
@@ -203,8 +203,8 @@
}
/** The Y value of the row of expanded bubbles. */
- private float getExpandedY() {
- final WindowInsets insets = mLayout.getRootWindowInsets();
+ public float getExpandedY() {
+ final WindowInsets insets = mLayout != null ? mLayout.getRootWindowInsets() : null;
if (insets != null) {
return mBubblePaddingPx + Math.max(
mStatusBarHeight,
diff --git a/packages/SystemUI/src/com/android/systemui/colorextraction/SysuiColorExtractor.java b/packages/SystemUI/src/com/android/systemui/colorextraction/SysuiColorExtractor.java
index 900ea72..a74c328 100644
--- a/packages/SystemUI/src/com/android/systemui/colorextraction/SysuiColorExtractor.java
+++ b/packages/SystemUI/src/com/android/systemui/colorextraction/SysuiColorExtractor.java
@@ -61,7 +61,7 @@
@VisibleForTesting
public SysuiColorExtractor(Context context, ExtractionType type, boolean registerVisibility) {
- super(context, type);
+ super(context, type, false /* immediately */);
mTonal = type instanceof Tonal ? (Tonal) type : new Tonal(context);
mWpHiddenColors = new GradientColors();
diff --git a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java
index 7c9b286..3fa6035 100644
--- a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java
+++ b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java
@@ -33,7 +33,6 @@
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.UserInfo;
-import android.content.res.Configuration;
import android.database.ContentObserver;
import android.graphics.Point;
import android.graphics.drawable.Drawable;
@@ -161,8 +160,6 @@
private final ScreenshotHelper mScreenshotHelper;
private final ScreenRecordHelper mScreenRecordHelper;
- private int mLastRotation;
-
/**
* @param context everything needs a context :(
*/
@@ -205,8 +202,6 @@
mScreenshotHelper = new ScreenshotHelper(context);
mScreenRecordHelper = new ScreenRecordHelper(context);
- mLastRotation = RotationUtils.getRotation(mContext);
-
Dependency.get(ConfigurationController.class).addCallback(this);
}
@@ -432,15 +427,6 @@
mContext.getTheme().applyStyle(mContext.getThemeResId(), true);
}
- @Override
- public void onConfigChanged(Configuration newConfig) {
- int rotation = RotationUtils.getRotation(mContext);
- if (rotation != mLastRotation) {
- mDialog.onRotate();
- }
- mLastRotation = rotation;
- }
-
public void destroy() {
Dependency.get(ConfigurationController.class).removeCallback(this);
}
@@ -1540,13 +1526,7 @@
return true;
}
});
- }
-
- public void onRotate() {
- if (mShowing && isGridEnabled(mContext)) {
- initializeLayout();
- updateList();
- }
+ mGlobalActionsLayout.setRotationListener(this::onRotate);
}
private int getGlobalActionsLayoutId(Context context) {
@@ -1703,6 +1683,13 @@
public void setKeyguardShowing(boolean keyguardShowing) {
mKeyguardShowing = keyguardShowing;
}
+
+ public void onRotate(int from, int to) {
+ if (mShowing && isGridEnabled(mContext)) {
+ initializeLayout();
+ updateList();
+ }
+ }
}
/**
diff --git a/packages/SystemUI/src/com/android/systemui/glwallpaper/ImageGLProgram.java b/packages/SystemUI/src/com/android/systemui/glwallpaper/ImageGLProgram.java
new file mode 100644
index 0000000..d03b00b
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/glwallpaper/ImageGLProgram.java
@@ -0,0 +1,115 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.glwallpaper;
+
+import static android.opengl.GLES20.GL_FRAGMENT_SHADER;
+import static android.opengl.GLES20.GL_VERTEX_SHADER;
+import static android.opengl.GLES20.glAttachShader;
+import static android.opengl.GLES20.glCompileShader;
+import static android.opengl.GLES20.glCreateProgram;
+import static android.opengl.GLES20.glCreateShader;
+import static android.opengl.GLES20.glGetAttribLocation;
+import static android.opengl.GLES20.glGetUniformLocation;
+import static android.opengl.GLES20.glLinkProgram;
+import static android.opengl.GLES20.glShaderSource;
+import static android.opengl.GLES20.glUseProgram;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.util.Log;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStreamReader;
+
+/**
+ * This class takes charge of linking shader codes and then return a handle for OpenGL ES program.
+ */
+class ImageGLProgram {
+ private static final String TAG = ImageGLProgram.class.getSimpleName();
+
+ private Context mContext;
+ private int mProgramHandle;
+
+ ImageGLProgram(Context context) {
+ mContext = context.getApplicationContext();
+ }
+
+ private int loadShaderProgram(int vertexId, int fragmentId) {
+ final String vertexSrc = getShaderResource(vertexId);
+ final String fragmentSrc = getShaderResource(fragmentId);
+ final int vertexHandle = getShaderHandle(GL_VERTEX_SHADER, vertexSrc);
+ final int fragmentHandle = getShaderHandle(GL_FRAGMENT_SHADER, fragmentSrc);
+ return getProgramHandle(vertexHandle, fragmentHandle);
+ }
+
+ private String getShaderResource(int shaderId) {
+ Resources res = mContext.getResources();
+ StringBuilder code = new StringBuilder();
+
+ try (BufferedReader reader = new BufferedReader(
+ new InputStreamReader(res.openRawResource(shaderId)))) {
+ String nextLine;
+ while ((nextLine = reader.readLine()) != null) {
+ code.append(nextLine).append("\n");
+ }
+ } catch (IOException | Resources.NotFoundException ex) {
+ Log.d(TAG, "Can not read the shader source", ex);
+ code = null;
+ }
+
+ return code == null ? "" : code.toString();
+ }
+
+ private int getShaderHandle(int type, String src) {
+ final int shader = glCreateShader(type);
+ if (shader == 0) {
+ Log.d(TAG, "Create shader failed, type=" + type);
+ return 0;
+ }
+ glShaderSource(shader, src);
+ glCompileShader(shader);
+ return shader;
+ }
+
+ private int getProgramHandle(int vertexHandle, int fragmentHandle) {
+ final int program = glCreateProgram();
+ if (program == 0) {
+ Log.d(TAG, "Can not create OpenGL ES program");
+ return 0;
+ }
+
+ glAttachShader(program, vertexHandle);
+ glAttachShader(program, fragmentHandle);
+ glLinkProgram(program);
+ return program;
+ }
+
+ boolean useGLProgram(int vertexResId, int fragmentResId) {
+ mProgramHandle = loadShaderProgram(vertexResId, fragmentResId);
+ glUseProgram(mProgramHandle);
+ return true;
+ }
+
+ int getAttributeHandle(String name) {
+ return glGetAttribLocation(mProgramHandle, name);
+ }
+
+ int getUniformHandle(String name) {
+ return glGetUniformLocation(mProgramHandle, name);
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/glwallpaper/ImageGLWallpaper.java b/packages/SystemUI/src/com/android/systemui/glwallpaper/ImageGLWallpaper.java
new file mode 100644
index 0000000..19d85b1
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/glwallpaper/ImageGLWallpaper.java
@@ -0,0 +1,259 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.glwallpaper;
+
+import static android.opengl.GLES20.GL_FLOAT;
+import static android.opengl.GLES20.GL_LINEAR;
+import static android.opengl.GLES20.GL_TEXTURE0;
+import static android.opengl.GLES20.GL_TEXTURE_2D;
+import static android.opengl.GLES20.GL_TEXTURE_MAG_FILTER;
+import static android.opengl.GLES20.GL_TEXTURE_MIN_FILTER;
+import static android.opengl.GLES20.GL_TRIANGLES;
+import static android.opengl.GLES20.glActiveTexture;
+import static android.opengl.GLES20.glBindTexture;
+import static android.opengl.GLES20.glDrawArrays;
+import static android.opengl.GLES20.glEnableVertexAttribArray;
+import static android.opengl.GLES20.glGenTextures;
+import static android.opengl.GLES20.glTexParameteri;
+import static android.opengl.GLES20.glUniform1i;
+import static android.opengl.GLES20.glVertexAttribPointer;
+
+import android.graphics.Bitmap;
+import android.opengl.GLUtils;
+import android.os.Build;
+import android.util.Log;
+
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import java.nio.FloatBuffer;
+
+/**
+ * This class takes charge of the geometry data like vertices and texture coordinates.
+ * It delivers these data to opengl runtime and triggers draw calls if necessary.
+ */
+class ImageGLWallpaper {
+ private static final String TAG = ImageGLWallpaper.class.getSimpleName();
+
+ static final String A_POSITION = "aPosition";
+ static final String A_TEXTURE_COORDINATES = "aTextureCoordinates";
+ static final String U_CENTER_REVEAL = "uCenterReveal";
+ static final String U_REVEAL = "uReveal";
+ static final String U_AOD2OPACITY = "uAod2Opacity";
+ static final String U_TEXTURE = "uTexture";
+
+ private static final int HANDLE_UNDEFINED = -1;
+ private static final int POSITION_COMPONENT_COUNT = 2;
+ private static final int TEXTURE_COMPONENT_COUNT = 2;
+ private static final int BYTES_PER_FLOAT = 4;
+
+ // Vertices to define the square with 2 triangles.
+ private static final float[] VERTICES = {
+ -1.0f, -1.0f,
+ +1.0f, -1.0f,
+ +1.0f, +1.0f,
+ +1.0f, +1.0f,
+ -1.0f, +1.0f,
+ -1.0f, -1.0f
+ };
+
+ // Texture coordinates that maps to vertices.
+ private static final float[] TEXTURES = {
+ 0f, 1f,
+ 1f, 1f,
+ 1f, 0f,
+ 1f, 0f,
+ 0f, 0f,
+ 0f, 1f
+ };
+
+ private final FloatBuffer mVertexBuffer;
+ private final FloatBuffer mTextureBuffer;
+ private final ImageGLProgram mProgram;
+
+ private int mAttrPosition;
+ private int mAttrTextureCoordinates;
+ private int mUniAod2Opacity;
+ private int mUniCenterReveal;
+ private int mUniReveal;
+ private int mUniTexture;
+ private int mTextureId;
+
+ ImageGLWallpaper(ImageGLProgram program) {
+ mProgram = program;
+
+ // Create an float array in opengles runtime (native) and put vertex data.
+ mVertexBuffer = ByteBuffer.allocateDirect(VERTICES.length * BYTES_PER_FLOAT)
+ .order(ByteOrder.nativeOrder())
+ .asFloatBuffer();
+ mVertexBuffer.put(VERTICES);
+ mVertexBuffer.position(0);
+
+ // Create an float array in opengles runtime (native) and put texture data.
+ mTextureBuffer = ByteBuffer.allocateDirect(TEXTURES.length * BYTES_PER_FLOAT)
+ .order(ByteOrder.nativeOrder())
+ .asFloatBuffer();
+ mTextureBuffer.put(TEXTURES);
+ mTextureBuffer.position(0);
+ }
+
+ void setup() {
+ setupAttributes();
+ setupUniforms();
+ }
+
+ private void setupAttributes() {
+ mAttrPosition = mProgram.getAttributeHandle(A_POSITION);
+ mVertexBuffer.position(0);
+ glVertexAttribPointer(mAttrPosition, POSITION_COMPONENT_COUNT, GL_FLOAT,
+ false, 0, mVertexBuffer);
+ glEnableVertexAttribArray(mAttrPosition);
+
+ mAttrTextureCoordinates = mProgram.getAttributeHandle(A_TEXTURE_COORDINATES);
+ mTextureBuffer.position(0);
+ glVertexAttribPointer(mAttrTextureCoordinates, TEXTURE_COMPONENT_COUNT, GL_FLOAT,
+ false, 0, mTextureBuffer);
+ glEnableVertexAttribArray(mAttrTextureCoordinates);
+ }
+
+ private void setupUniforms() {
+ mUniAod2Opacity = mProgram.getUniformHandle(U_AOD2OPACITY);
+ mUniCenterReveal = mProgram.getUniformHandle(U_CENTER_REVEAL);
+ mUniReveal = mProgram.getUniformHandle(U_REVEAL);
+ mUniTexture = mProgram.getUniformHandle(U_TEXTURE);
+ }
+
+ int getHandle(String name) {
+ switch (name) {
+ case A_POSITION:
+ return mAttrPosition;
+ case A_TEXTURE_COORDINATES:
+ return mAttrTextureCoordinates;
+ case U_AOD2OPACITY:
+ return mUniAod2Opacity;
+ case U_CENTER_REVEAL:
+ return mUniCenterReveal;
+ case U_REVEAL:
+ return mUniReveal;
+ case U_TEXTURE:
+ return mUniTexture;
+ default:
+ return HANDLE_UNDEFINED;
+ }
+ }
+
+ void draw() {
+ glDrawArrays(GL_TRIANGLES, 0, VERTICES.length / 2);
+ }
+
+ void setupTexture(Bitmap bitmap) {
+ final int[] tids = new int[1];
+
+ if (bitmap == null) {
+ Log.w(TAG, "setupTexture: invalid bitmap");
+ return;
+ }
+
+ // Generate one texture object and store the id in tids[0].
+ glGenTextures(1, tids, 0);
+ if (tids[0] == 0) {
+ Log.w(TAG, "setupTexture: glGenTextures() failed");
+ return;
+ }
+
+ // Bind a named texture to a texturing target.
+ glBindTexture(GL_TEXTURE_2D, tids[0]);
+ // Load the bitmap data and copy it over into the texture object that is currently bound.
+ GLUtils.texImage2D(GL_TEXTURE_2D, 0, bitmap, 0);
+ // Use bilinear texture filtering when minification.
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ // Use bilinear texture filtering when magnification.
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+
+ mTextureId = tids[0];
+ }
+
+ void useTexture() {
+ // Set the active texture unit to texture unit 0.
+ glActiveTexture(GL_TEXTURE0);
+ // Bind the texture to this unit.
+ glBindTexture(GL_TEXTURE_2D, mTextureId);
+ // Let the texture sampler in fragment shader to read form this texture unit.
+ glUniform1i(mUniTexture, 0);
+ }
+
+ void adjustTextureCoordinates(Bitmap bitmap, int surfaceWidth, int surfaceHeight,
+ float xOffset, float yOffset) {
+ if (bitmap == null) {
+ Log.d(TAG, "adjustTextureCoordinates: invalid bitmap");
+ return;
+ }
+
+ int bitmapWidth = bitmap.getWidth();
+ int bitmapHeight = bitmap.getHeight();
+ float ratioW = 1f;
+ float ratioH = 1f;
+ float rX = 0f;
+ float rY = 0f;
+ float[] coordinates = null;
+
+ final boolean adjustWidth = bitmapWidth > surfaceWidth;
+ final boolean adjustHeight = bitmapHeight > surfaceHeight;
+
+ if (adjustWidth || adjustHeight) {
+ coordinates = TEXTURES.clone();
+ }
+
+ if (adjustWidth) {
+ float x = (float) Math.round((bitmapWidth - surfaceWidth) * xOffset) / bitmapWidth;
+ ratioW = (float) surfaceWidth / bitmapWidth;
+ float referenceX = x + ratioW > 1f ? 1f - ratioW : x;
+ for (int i = 0; i < coordinates.length; i += 2) {
+ if (i == 2 || i == 4 || i == 6) {
+ coordinates[i] = Math.min(1f, referenceX + ratioW);
+ } else {
+ coordinates[i] = referenceX;
+ }
+ }
+ rX = referenceX;
+ }
+
+
+ if (adjustHeight) {
+ float y = (float) Math.round((bitmapHeight - surfaceHeight) * yOffset) / bitmapHeight;
+ ratioH = (float) surfaceHeight / bitmapHeight;
+ float referenceY = y + ratioH > 1f ? 1f - ratioH : y;
+ for (int i = 1; i < coordinates.length; i += 2) {
+ if (i == 1 || i == 3 || i == 11) {
+ coordinates[i] = Math.min(1f, referenceY + ratioH);
+ } else {
+ coordinates[i] = referenceY;
+ }
+ }
+ rY = referenceY;
+ }
+
+ if (adjustWidth || adjustHeight) {
+ if (Build.IS_DEBUGGABLE) {
+ Log.d(TAG, "adjustTextureCoordinates: sW=" + surfaceWidth + ", sH=" + surfaceHeight
+ + ", bW=" + bitmapWidth + ", bH=" + bitmapHeight
+ + ", rW=" + ratioW + ", rH=" + ratioH + ", rX=" + rX + ", rY=" + rY);
+ }
+ mTextureBuffer.put(coordinates);
+ mTextureBuffer.position(0);
+ }
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/glwallpaper/ImageProcessHelper.java b/packages/SystemUI/src/com/android/systemui/glwallpaper/ImageProcessHelper.java
new file mode 100644
index 0000000..477e7d7e
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/glwallpaper/ImageProcessHelper.java
@@ -0,0 +1,144 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.glwallpaper;
+
+import android.graphics.Bitmap;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.ColorMatrix;
+import android.graphics.ColorMatrixColorFilter;
+import android.graphics.Matrix;
+import android.graphics.Paint;
+import android.os.AsyncTask;
+import android.os.Handler;
+import android.os.Handler.Callback;
+import android.os.Message;
+import android.util.Log;
+
+/**
+ * A helper class that computes histogram and percentile 85 from a bitmap.
+ * Percentile 85 will be computed each time the user picks a new image wallpaper.
+ */
+class ImageProcessHelper {
+ private static final String TAG = ImageProcessHelper.class.getSimpleName();
+ private static final float DEFAULT_PER85 = 0.8f;
+ private static final int MSG_UPDATE_PER85 = 1;
+
+ /**
+ * This color matrix will be applied to each pixel to get luminance from rgb by below formula:
+ * Luminance = .2126f * r + .7152f * g + .0722f * b.
+ */
+ private static final float[] LUMINOSITY_MATRIX = new float[] {
+ .2126f, .0000f, .0000f, .0000f, .0000f,
+ .0000f, .7152f, .0000f, .0000f, .0000f,
+ .0000f, .0000f, .0722f, .0000f, .0000f,
+ .0000f, .0000f, .0000f, 1.000f, .0000f
+ };
+
+ private final Handler mHandler = new Handler(new Callback() {
+ @Override
+ public boolean handleMessage(Message msg) {
+ switch (msg.what) {
+ case MSG_UPDATE_PER85:
+ mPer85 = (float) msg.obj;
+ return true;
+ default:
+ return false;
+ }
+ }
+ });
+
+ private float mPer85 = DEFAULT_PER85;
+
+ void startComputingPercentile85(Bitmap bitmap) {
+ new Per85ComputeTask(mHandler).execute(bitmap);
+ }
+
+ float getPercentile85() {
+ return mPer85;
+ }
+
+ private static class Per85ComputeTask extends AsyncTask<Bitmap, Void, Float> {
+ private Handler mUpdateHandler;
+
+ Per85ComputeTask(Handler handler) {
+ super(handler);
+ mUpdateHandler = handler;
+ }
+
+ @Override
+ protected Float doInBackground(Bitmap... bitmaps) {
+ Bitmap bitmap = bitmaps[0];
+ if (bitmap != null) {
+ int[] histogram = processHistogram(bitmap);
+ return computePercentile85(bitmap, histogram);
+ }
+ Log.e(TAG, "Per85ComputeTask: Can't get bitmap");
+ return DEFAULT_PER85;
+ }
+
+ @Override
+ protected void onPostExecute(Float result) {
+ Message msg = mUpdateHandler.obtainMessage(MSG_UPDATE_PER85, result);
+ mUpdateHandler.sendMessage(msg);
+ }
+
+ private int[] processHistogram(Bitmap bitmap) {
+ int width = bitmap.getWidth();
+ int height = bitmap.getHeight();
+
+ Bitmap target = Bitmap.createBitmap(width, height, bitmap.getConfig());
+ Canvas canvas = new Canvas(target);
+ ColorMatrix cm = new ColorMatrix(LUMINOSITY_MATRIX);
+ Paint paint = new Paint();
+ paint.setColorFilter(new ColorMatrixColorFilter(cm));
+ canvas.drawBitmap(bitmap, new Matrix(), paint);
+
+ // TODO: Fine tune the performance here, tracking on b/123615079.
+ int[] histogram = new int[256];
+ for (int row = 0; row < height; row++) {
+ for (int col = 0; col < width; col++) {
+ int pixel = target.getPixel(col, row);
+ int y = Color.red(pixel) + Color.green(pixel) + Color.blue(pixel);
+ histogram[y]++;
+ }
+ }
+
+ return histogram;
+ }
+
+ private float computePercentile85(Bitmap bitmap, int[] histogram) {
+ float per85 = DEFAULT_PER85;
+ int pixelCount = bitmap.getWidth() * bitmap.getHeight();
+ float[] acc = new float[256];
+ for (int i = 0; i < acc.length; i++) {
+ acc[i] = (float) histogram[i] / pixelCount;
+ float prev = i == 0 ? 0f : acc[i - 1];
+ float next = acc[i];
+ float idx = (float) (i + 1) / 255;
+ float sum = prev + next;
+ if (prev < 0.85f && sum >= 0.85f) {
+ per85 = idx;
+ }
+ if (i > 0) {
+ acc[i] += acc[i - 1];
+ }
+ }
+ return per85;
+ }
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/glwallpaper/ImageRevealHelper.java b/packages/SystemUI/src/com/android/systemui/glwallpaper/ImageRevealHelper.java
new file mode 100644
index 0000000..5914236
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/glwallpaper/ImageRevealHelper.java
@@ -0,0 +1,97 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.glwallpaper;
+
+import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
+import android.animation.ValueAnimator;
+
+import com.android.systemui.Interpolators;
+
+/**
+ * Use ValueAnimator and appropriate interpolator to control the progress of reveal transition.
+ * The transition will happen while getting awake and quit events.
+ */
+class ImageRevealHelper {
+ private static final String TAG = ImageRevealHelper.class.getSimpleName();
+ private static final float MAX_REVEAL = 0f;
+ private static final float MIN_REVEAL = 1f;
+
+ private final ValueAnimator mAnimator;
+ private final RevealStateListener mRevealListener;
+ private float mReveal = MAX_REVEAL;
+ private boolean mAwake = false;
+
+ ImageRevealHelper(RevealStateListener listener) {
+ mRevealListener = listener;
+ mAnimator = ValueAnimator.ofFloat();
+ mAnimator.setInterpolator(Interpolators.FAST_OUT_SLOW_IN);
+ mAnimator.addUpdateListener(animator -> {
+ mReveal = (float) animator.getAnimatedValue();
+ if (mRevealListener != null) {
+ mRevealListener.onRevealStateChanged();
+ }
+ });
+ mAnimator.addListener(new AnimatorListenerAdapter() {
+ private boolean mIsCanceled;
+
+ @Override
+ public void onAnimationCancel(Animator animation) {
+ mIsCanceled = true;
+ }
+
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ if (!mIsCanceled) {
+ mAwake = !mAwake;
+ }
+ mIsCanceled = false;
+ }
+ });
+ }
+
+ private void animate() {
+ mAnimator.cancel();
+ mAnimator.setFloatValues(mReveal, !mAwake ? MIN_REVEAL : MAX_REVEAL);
+ mAnimator.start();
+ }
+
+ public float getReveal() {
+ return mReveal;
+ }
+
+ public boolean isAwake() {
+ return mAwake;
+ }
+
+ void updateAwake(boolean awake, long duration) {
+ mAwake = awake;
+ mAnimator.setDuration(duration);
+ animate();
+ }
+
+ /**
+ * A listener to trace value changes of reveal.
+ */
+ public interface RevealStateListener {
+
+ /**
+ * Called back while reveal status changes.
+ */
+ void onRevealStateChanged();
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/glwallpaper/ImageWallpaperRenderer.java b/packages/SystemUI/src/com/android/systemui/glwallpaper/ImageWallpaperRenderer.java
new file mode 100644
index 0000000..991b116
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/glwallpaper/ImageWallpaperRenderer.java
@@ -0,0 +1,150 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.glwallpaper;
+
+import static android.opengl.GLES20.GL_COLOR_BUFFER_BIT;
+import static android.opengl.GLES20.glClear;
+import static android.opengl.GLES20.glClearColor;
+import static android.opengl.GLES20.glUniform1f;
+import static android.opengl.GLES20.glViewport;
+
+import android.app.WallpaperManager;
+import android.content.Context;
+import android.graphics.Bitmap;
+import android.graphics.Rect;
+import android.opengl.GLSurfaceView;
+import android.os.Build;
+import android.util.Log;
+
+import com.android.systemui.ImageWallpaper;
+import com.android.systemui.ImageWallpaper.ImageGLView;
+import com.android.systemui.R;
+
+import javax.microedition.khronos.egl.EGLConfig;
+import javax.microedition.khronos.opengles.GL10;
+
+/**
+ * A GL renderer for image wallpaper.
+ */
+public class ImageWallpaperRenderer implements GLSurfaceView.Renderer,
+ ImageWallpaper.WallpaperStatusListener, ImageRevealHelper.RevealStateListener {
+ private static final String TAG = ImageWallpaperRenderer.class.getSimpleName();
+
+ private final WallpaperManager mWallpaperManager;
+ private final ImageGLProgram mProgram;
+ private final ImageGLWallpaper mWallpaper;
+ private final ImageProcessHelper mImageProcessHelper;
+ private final ImageRevealHelper mImageRevealHelper;
+ private final ImageGLView mGLView;
+ private float mXOffset = 0f;
+ private float mYOffset = 0f;
+
+ public ImageWallpaperRenderer(Context context, ImageGLView glView) {
+ mWallpaperManager = context.getSystemService(WallpaperManager.class);
+ if (mWallpaperManager == null) {
+ Log.w(TAG, "WallpaperManager not available");
+ }
+
+ mProgram = new ImageGLProgram(context);
+ mWallpaper = new ImageGLWallpaper(mProgram);
+ mImageProcessHelper = new ImageProcessHelper();
+ mImageRevealHelper = new ImageRevealHelper(this);
+ mGLView = glView;
+
+ if (mWallpaperManager != null) {
+ // Compute per85 as transition threshold, this is an async work.
+ mImageProcessHelper.startComputingPercentile85(mWallpaperManager.getBitmap());
+ }
+ }
+
+ @Override
+ public void onSurfaceCreated(GL10 gl, EGLConfig config) {
+ glClearColor(0f, 0f, 0f, 1.0f);
+ mProgram.useGLProgram(
+ R.raw.image_wallpaper_vertex_shader, R.raw.image_wallpaper_fragment_shader);
+ mWallpaper.setup();
+ mWallpaper.setupTexture(mWallpaperManager.getBitmap());
+ }
+
+ @Override
+ public void onSurfaceChanged(GL10 gl, int width, int height) {
+ glViewport(0, 0, width, height);
+ if (Build.IS_DEBUGGABLE) {
+ Log.d(TAG, "onSurfaceChanged: width=" + width + ", height=" + height
+ + ", xOffset=" + mXOffset + ", yOffset=" + mYOffset);
+ }
+ mWallpaper.adjustTextureCoordinates(mWallpaperManager.getBitmap(),
+ width, height, mXOffset, mYOffset);
+ }
+
+ @Override
+ public void onDrawFrame(GL10 gl) {
+ float threshold = mImageProcessHelper.getPercentile85();
+ float reveal = mImageRevealHelper.getReveal();
+
+ glClear(GL_COLOR_BUFFER_BIT);
+
+ glUniform1f(mWallpaper.getHandle(ImageGLWallpaper.U_AOD2OPACITY), 1);
+ glUniform1f(mWallpaper.getHandle(ImageGLWallpaper.U_CENTER_REVEAL), threshold);
+ glUniform1f(mWallpaper.getHandle(ImageGLWallpaper.U_REVEAL), reveal);
+
+ mWallpaper.useTexture();
+ mWallpaper.draw();
+ }
+
+ @Override
+ public void onAmbientModeChanged(boolean inAmbientMode, long duration) {
+ mImageRevealHelper.updateAwake(!inAmbientMode, duration);
+ requestRender();
+ }
+
+ @Override
+ public void onOffsetsChanged(float xOffset, float yOffset, Rect frame) {
+ if (frame == null || mWallpaperManager == null
+ || (xOffset == mXOffset && yOffset == mYOffset)) {
+ return;
+ }
+
+ Bitmap bitmap = mWallpaperManager.getBitmap();
+ if (bitmap == null) {
+ return;
+ }
+
+ int width = frame.width();
+ int height = frame.height();
+ mXOffset = xOffset;
+ mYOffset = yOffset;
+
+ if (Build.IS_DEBUGGABLE) {
+ Log.d(TAG, "onOffsetsChanged: width=" + width + ", height=" + height
+ + ", xOffset=" + mXOffset + ", yOffset=" + mYOffset);
+ }
+ mWallpaper.adjustTextureCoordinates(bitmap, width, height, mXOffset, mYOffset);
+ requestRender();
+ }
+
+ @Override
+ public void onRevealStateChanged() {
+ requestRender();
+ }
+
+ private void requestRender() {
+ if (mGLView != null) {
+ mGLView.render();
+ }
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaProjectionPermissionActivity.java b/packages/SystemUI/src/com/android/systemui/media/MediaProjectionPermissionActivity.java
index df76315..9bca2cc 100644
--- a/packages/SystemUI/src/com/android/systemui/media/MediaProjectionPermissionActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/media/MediaProjectionPermissionActivity.java
@@ -40,19 +40,15 @@
import android.util.Log;
import android.view.Window;
import android.view.WindowManager;
-import android.widget.CheckBox;
-import android.widget.CompoundButton;
import com.android.systemui.R;
public class MediaProjectionPermissionActivity extends Activity
- implements DialogInterface.OnClickListener, CheckBox.OnCheckedChangeListener,
- DialogInterface.OnCancelListener {
+ implements DialogInterface.OnClickListener, DialogInterface.OnCancelListener {
private static final String TAG = "MediaProjectionPermissionActivity";
private static final float MAX_APP_NAME_SIZE_PX = 500f;
private static final String ELLIPSIS = "\u2026";
- private boolean mPermanentGrant;
private String mPackageName;
private int mUid;
private IMediaProjectionManager mService;
@@ -85,8 +81,7 @@
try {
if (mService.hasProjectionPermission(mUid, mPackageName)) {
- setResult(RESULT_OK, getMediaProjectionIntent(mUid, mPackageName,
- false /*permanentGrant*/));
+ setResult(RESULT_OK, getMediaProjectionIntent(mUid, mPackageName));
finish();
return;
}
@@ -136,19 +131,20 @@
appNameIndex, appNameIndex + appName.length(), 0);
}
+ String dialogTitle = getString(R.string.media_projection_dialog_title, appName);
+
mDialog = new AlertDialog.Builder(this)
+ .setTitle(dialogTitle)
.setIcon(aInfo.loadIcon(packageManager))
.setMessage(message)
.setPositiveButton(R.string.media_projection_action_text, this)
.setNegativeButton(android.R.string.cancel, this)
- .setView(R.layout.remember_permission_checkbox)
.setOnCancelListener(this)
.create();
mDialog.create();
mDialog.getButton(DialogInterface.BUTTON_POSITIVE).setFilterTouchesWhenObscured(true);
- ((CheckBox) mDialog.findViewById(R.id.remember)).setOnCheckedChangeListener(this);
final Window w = mDialog.getWindow();
w.setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
w.addSystemFlags(SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS);
@@ -168,8 +164,7 @@
public void onClick(DialogInterface dialog, int which) {
try {
if (which == AlertDialog.BUTTON_POSITIVE) {
- setResult(RESULT_OK, getMediaProjectionIntent(
- mUid, mPackageName, mPermanentGrant));
+ setResult(RESULT_OK, getMediaProjectionIntent(mUid, mPackageName));
}
} catch (RemoteException e) {
Log.e(TAG, "Error granting projection permission", e);
@@ -182,15 +177,10 @@
}
}
- @Override
- public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
- mPermanentGrant = isChecked;
- }
-
- private Intent getMediaProjectionIntent(int uid, String packageName, boolean permanentGrant)
+ private Intent getMediaProjectionIntent(int uid, String packageName)
throws RemoteException {
IMediaProjection projection = mService.createProjection(uid, packageName,
- MediaProjectionManager.TYPE_SCREEN_CAPTURE, permanentGrant);
+ MediaProjectionManager.TYPE_SCREEN_CAPTURE, false /* permanentGrant */);
Intent intent = new Intent();
intent.putExtra(MediaProjectionManager.EXTRA_MEDIA_PROJECTION, projection.asBinder());
return intent;
diff --git a/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java b/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java
index 7a7d1f6..bb34a87 100644
--- a/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java
+++ b/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java
@@ -461,6 +461,9 @@
if (mSnapAlgorithm == null) {
mSnapAlgorithm = new DividerSnapAlgorithm(getContext().getResources(), mDisplayWidth,
mDisplayHeight, mDividerSize, isHorizontalDivision(), mStableInsets, mDockSide);
+ if (mSnapTargetBeforeMinimized != null && mSnapTargetBeforeMinimized.isMiddleTarget) {
+ mSnapTargetBeforeMinimized = mSnapAlgorithm.getMiddleTarget();
+ }
}
if (mMinimizedSnapAlgorithm == null) {
mMinimizedSnapAlgorithm = new DividerSnapAlgorithm(getContext().getResources(),
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentInflater.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentInflater.java
index b34907d..b65c4a5 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentInflater.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentInflater.java
@@ -125,6 +125,7 @@
private boolean mIsChildInGroup;
private InflationCallback mCallback;
private boolean mRedactAmbient;
+ private boolean mInflateSynchronously = false;
private final ArrayMap<Integer, RemoteViews> mCachedContentViews = new ArrayMap<>();
public NotificationContentInflater(ExpandableNotificationRow row) {
@@ -248,10 +249,20 @@
// To check if the notification has inline image and preload inline image if necessary.
mRow.getImageResolver().preloadImages(sbn.getNotification());
- AsyncInflationTask task = new AsyncInflationTask(sbn, reInflateFlags, mCachedContentViews,
- mRow, mIsLowPriority, mIsChildInGroup, mUsesIncreasedHeight,
- mUsesIncreasedHeadsUpHeight, mRedactAmbient, mCallback, mRemoteViewClickHandler);
- if (mCallback != null && mCallback.doInflateSynchronous()) {
+ AsyncInflationTask task = new AsyncInflationTask(
+ sbn,
+ mInflateSynchronously,
+ reInflateFlags,
+ mCachedContentViews,
+ mRow,
+ mIsLowPriority,
+ mIsChildInGroup,
+ mUsesIncreasedHeight,
+ mUsesIncreasedHeadsUpHeight,
+ mRedactAmbient,
+ mCallback,
+ mRemoteViewClickHandler);
+ if (mInflateSynchronously) {
task.onPostExecute(task.doInBackground());
} else {
task.execute();
@@ -259,13 +270,23 @@
}
@VisibleForTesting
- InflationProgress inflateNotificationViews(@InflationFlag int reInflateFlags,
- Notification.Builder builder, Context packageContext) {
+ InflationProgress inflateNotificationViews(
+ boolean inflateSynchronously,
+ @InflationFlag int reInflateFlags,
+ Notification.Builder builder,
+ Context packageContext) {
InflationProgress result = createRemoteViews(reInflateFlags, builder, mIsLowPriority,
mIsChildInGroup, mUsesIncreasedHeight, mUsesIncreasedHeadsUpHeight,
mRedactAmbient, packageContext);
- apply(result, reInflateFlags, mCachedContentViews, mRow, mRedactAmbient,
- mRemoteViewClickHandler, null);
+ apply(
+ inflateSynchronously,
+ result,
+ reInflateFlags,
+ mCachedContentViews,
+ mRow,
+ mRedactAmbient,
+ mRemoteViewClickHandler,
+ null);
return result;
}
@@ -348,9 +369,13 @@
return result;
}
- public static CancellationSignal apply(InflationProgress result,
- @InflationFlag int reInflateFlags, ArrayMap<Integer, RemoteViews> cachedContentViews,
- ExpandableNotificationRow row, boolean redactAmbient,
+ public static CancellationSignal apply(
+ boolean inflateSynchronously,
+ InflationProgress result,
+ @InflationFlag int reInflateFlags,
+ ArrayMap<Integer, RemoteViews> cachedContentViews,
+ ExpandableNotificationRow row,
+ boolean redactAmbient,
RemoteViews.OnClickHandler remoteViewClickHandler,
@Nullable InflationCallback callback) {
NotificationContentView privateLayout = row.getPrivateLayout();
@@ -373,8 +398,8 @@
return result.newContentView;
}
};
- applyRemoteView(result, reInflateFlags, flag, cachedContentViews, row, redactAmbient,
- isNewView, remoteViewClickHandler, callback, privateLayout,
+ applyRemoteView(inflateSynchronously, result, reInflateFlags, flag, cachedContentViews,
+ row, redactAmbient, isNewView, remoteViewClickHandler, callback, privateLayout,
privateLayout.getContractedChild(), privateLayout.getVisibleWrapper(
NotificationContentView.VISIBLE_TYPE_CONTRACTED),
runningInflations, applyCallback);
@@ -397,9 +422,9 @@
return result.newExpandedView;
}
};
- applyRemoteView(result, reInflateFlags, flag, cachedContentViews, row,
- redactAmbient, isNewView, remoteViewClickHandler, callback,
- privateLayout, privateLayout.getExpandedChild(),
+ applyRemoteView(inflateSynchronously, result, reInflateFlags, flag,
+ cachedContentViews, row, redactAmbient, isNewView, remoteViewClickHandler,
+ callback, privateLayout, privateLayout.getExpandedChild(),
privateLayout.getVisibleWrapper(
NotificationContentView.VISIBLE_TYPE_EXPANDED), runningInflations,
applyCallback);
@@ -423,9 +448,9 @@
return result.newHeadsUpView;
}
};
- applyRemoteView(result, reInflateFlags, flag, cachedContentViews, row,
- redactAmbient, isNewView, remoteViewClickHandler, callback,
- privateLayout, privateLayout.getHeadsUpChild(),
+ applyRemoteView(inflateSynchronously, result, reInflateFlags, flag,
+ cachedContentViews, row, redactAmbient, isNewView, remoteViewClickHandler,
+ callback, privateLayout, privateLayout.getHeadsUpChild(),
privateLayout.getVisibleWrapper(
VISIBLE_TYPE_HEADSUP), runningInflations,
applyCallback);
@@ -448,8 +473,8 @@
return result.newPublicView;
}
};
- applyRemoteView(result, reInflateFlags, flag, cachedContentViews, row,
- redactAmbient, isNewView, remoteViewClickHandler, callback,
+ applyRemoteView(inflateSynchronously, result, reInflateFlags, flag, cachedContentViews,
+ row, redactAmbient, isNewView, remoteViewClickHandler, callback,
publicLayout, publicLayout.getContractedChild(),
publicLayout.getVisibleWrapper(NotificationContentView.VISIBLE_TYPE_CONTRACTED),
runningInflations, applyCallback);
@@ -472,8 +497,8 @@
return result.newAmbientView;
}
};
- applyRemoteView(result, reInflateFlags, flag, cachedContentViews, row,
- redactAmbient, isNewView, remoteViewClickHandler, callback,
+ applyRemoteView(inflateSynchronously, result, reInflateFlags, flag, cachedContentViews,
+ row, redactAmbient, isNewView, remoteViewClickHandler, callback,
newParent, newParent.getAmbientChild(), newParent.getVisibleWrapper(
NotificationContentView.VISIBLE_TYPE_AMBIENT), runningInflations,
applyCallback);
@@ -489,18 +514,24 @@
}
@VisibleForTesting
- static void applyRemoteView(final InflationProgress result,
- final @InflationFlag int reInflateFlags, @InflationFlag int inflationId,
+ static void applyRemoteView(
+ boolean inflateSynchronously,
+ final InflationProgress result,
+ final @InflationFlag int reInflateFlags,
+ @InflationFlag int inflationId,
final ArrayMap<Integer, RemoteViews> cachedContentViews,
- final ExpandableNotificationRow row, final boolean redactAmbient, boolean isNewView,
+ final ExpandableNotificationRow row,
+ final boolean redactAmbient,
+ boolean isNewView,
RemoteViews.OnClickHandler remoteViewClickHandler,
@Nullable final InflationCallback callback,
- NotificationContentView parentLayout, View existingView,
+ NotificationContentView parentLayout,
+ View existingView,
NotificationViewWrapper existingWrapper,
final HashMap<Integer, CancellationSignal> runningInflations,
ApplyCallback applyCallback) {
RemoteViews newContentView = applyCallback.getRemoteView();
- if (callback != null && callback.doInflateSynchronous()) {
+ if (inflateSynchronously) {
try {
if (isNewView) {
View v = newContentView.apply(
@@ -723,15 +754,7 @@
* @param entry the entry with the content views set
* @param inflatedFlags the flags associated with the content views that were inflated
*/
- void onAsyncInflationFinished(NotificationEntry entry,
- @InflationFlag int inflatedFlags);
-
- /**
- * Used to disable async-ness for tests. Should only be used for tests.
- */
- default boolean doInflateSynchronous() {
- return false;
- }
+ void onAsyncInflationFinished(NotificationEntry entry, @InflationFlag int inflatedFlags);
}
public void clearCachesAndReInflate() {
@@ -739,6 +762,15 @@
inflateNotificationViews();
}
+ /**
+ * Sets whether to perform inflation on the same thread as the caller. This method should only
+ * be used in tests, not in production.
+ */
+ @VisibleForTesting
+ void setInflateSynchronously(boolean inflateSynchronously) {
+ mInflateSynchronously = inflateSynchronously;
+ }
+
private static boolean canReapplyAmbient(ExpandableNotificationRow row, boolean redactAmbient) {
NotificationContentView ambientView = redactAmbient ? row.getPublicLayout()
: row.getPrivateLayout();
@@ -750,6 +782,7 @@
private final StatusBarNotification mSbn;
private final Context mContext;
+ private final boolean mInflateSynchronously;
private final boolean mIsLowPriority;
private final boolean mIsChildInGroup;
private final boolean mUsesIncreasedHeight;
@@ -763,14 +796,22 @@
private RemoteViews.OnClickHandler mRemoteViewClickHandler;
private CancellationSignal mCancellationSignal;
- private AsyncInflationTask(StatusBarNotification notification,
+ private AsyncInflationTask(
+ StatusBarNotification notification,
+ boolean inflateSynchronously,
@InflationFlag int reInflateFlags,
- ArrayMap<Integer, RemoteViews> cachedContentViews, ExpandableNotificationRow row,
- boolean isLowPriority, boolean isChildInGroup, boolean usesIncreasedHeight,
- boolean usesIncreasedHeadsUpHeight, boolean redactAmbient,
- InflationCallback callback, RemoteViews.OnClickHandler remoteViewClickHandler) {
+ ArrayMap<Integer, RemoteViews> cachedContentViews,
+ ExpandableNotificationRow row,
+ boolean isLowPriority,
+ boolean isChildInGroup,
+ boolean usesIncreasedHeight,
+ boolean usesIncreasedHeadsUpHeight,
+ boolean redactAmbient,
+ InflationCallback callback,
+ RemoteViews.OnClickHandler remoteViewClickHandler) {
mRow = row;
mSbn = notification;
+ mInflateSynchronously = inflateSynchronously;
mReInflateFlags = reInflateFlags;
mCachedContentViews = cachedContentViews;
mContext = mRow.getContext();
@@ -817,8 +858,8 @@
@Override
protected void onPostExecute(InflationProgress result) {
if (mError == null) {
- mCancellationSignal = apply(result, mReInflateFlags, mCachedContentViews, mRow,
- mRedactAmbient, mRemoteViewClickHandler, this);
+ mCancellationSignal = apply(mInflateSynchronously, result, mReInflateFlags,
+ mCachedContentViews, mRow, mRedactAmbient, mRemoteViewClickHandler, this);
} else {
handleError(mError);
}
@@ -866,11 +907,6 @@
// try to purge unnecessary cached entries.
mRow.getImageResolver().purgeCache();
}
-
- @Override
- public boolean doInflateSynchronous() {
- return mCallback != null && mCallback.doInflateSynchronous();
- }
}
@VisibleForTesting
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ContextualButtonGroup.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ContextualButtonGroup.java
index cc8adde..38df17a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ContextualButtonGroup.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ContextualButtonGroup.java
@@ -112,6 +112,9 @@
* their icons for their buttons.
*/
public void updateIcons() {
+ if (getCurrentView() == null || !getCurrentView().isAttachedToWindow()) {
+ return;
+ }
for (ButtonData data : mButtonData) {
data.button.updateIcon();
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LightBarTransitionsController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LightBarTransitionsController.java
index 5ccb9b2..b622688 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LightBarTransitionsController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LightBarTransitionsController.java
@@ -18,14 +18,12 @@
import static com.android.systemui.statusbar.phone.NavBarTintController.DEFAULT_COLOR_ADAPT_TRANSITION_TIME;
import static com.android.systemui.statusbar.phone.NavBarTintController.MIN_COLOR_ADAPT_TRANSITION_TIME;
-import static com.android.systemui.statusbar.phone.NavBarTintController.NAV_COLOR_TRANSITION_TIME_SETTING;
import android.animation.ValueAnimator;
import android.content.Context;
import android.os.Bundle;
import android.os.Handler;
import android.os.SystemClock;
-import android.provider.Settings;
import android.util.MathUtils;
import android.util.TimeUtils;
@@ -167,9 +165,7 @@
public long getTintAnimationDuration() {
if (NavBarTintController.isEnabled(mContext)) {
- return Math.max(Settings.Global.getInt(mContext.getContentResolver(),
- NAV_COLOR_TRANSITION_TIME_SETTING, DEFAULT_COLOR_ADAPT_TRANSITION_TIME),
- MIN_COLOR_ADAPT_TRANSITION_TIME);
+ return Math.max(DEFAULT_COLOR_ADAPT_TRANSITION_TIME, MIN_COLOR_ADAPT_TRANSITION_TIME);
}
return DEFAULT_TINT_ANIMATION_DURATION;
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavBarTintController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavBarTintController.java
index b4f850b..cf3f89e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavBarTintController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavBarTintController.java
@@ -17,6 +17,7 @@
package com.android.systemui.statusbar.phone;
import android.content.Context;
+import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.Bitmap.Config;
import android.graphics.Color;
@@ -27,11 +28,13 @@
import android.provider.Settings;
import android.util.DisplayMetrics;
import android.view.SurfaceControl;
+import android.view.View;
+
+import com.android.systemui.R;
public class NavBarTintController {
- public static final String NAV_COLOR_TRANSITION_TIME_SETTING = "navbar_color_adapt_transition";
public static final int MIN_COLOR_ADAPT_TRANSITION_TIME = 400;
- public static final int DEFAULT_COLOR_ADAPT_TRANSITION_TIME = 1500;
+ public static final int DEFAULT_COLOR_ADAPT_TRANSITION_TIME = 1700;
private final HandlerThread mColorAdaptHandlerThread = new HandlerThread("ColorExtractThread");
private Handler mColorAdaptionHandler;
@@ -42,23 +45,25 @@
// Passing the threshold of this luminance value will make the button black otherwise white
private static final float LUMINANCE_THRESHOLD = 0.3f;
- // The home button's icon is actually smaller than the button's size, the percentage will
- // cut into the button's size to determine the icon size
- private static final float PERCENTAGE_BUTTON_PADDING = 0.3f;
-
- // The distance from the home button to color sample around
- private static final int COLOR_SAMPLE_MARGIN = 20;
+ // The margin from the bounds of the view to color sample around
+ private static final int COLOR_SAMPLE_MARGIN = 10;
private boolean mRunning;
private final NavigationBarView mNavigationBarView;
private final LightBarTransitionsController mLightBarController;
private final Handler mMainHandler = new Handler(Looper.getMainLooper());
+ private final int mBarRadius;
+ private final int mBarBottom;
public NavBarTintController(NavigationBarView navigationBarView,
LightBarTransitionsController lightBarController) {
mNavigationBarView = navigationBarView;
mLightBarController = lightBarController;
+
+ final Resources res = navigationBarView.getResources();
+ mBarRadius = res.getDimensionPixelSize(R.dimen.navigation_handle_radius);
+ mBarBottom = res.getDimensionPixelSize(R.dimen.navigation_handle_bottom);
}
public void start() {
@@ -91,27 +96,28 @@
private void updateTint() {
int[] navPos = new int[2];
int[] butPos = new int[2];
- if (mNavigationBarView.getHomeButton().getCurrentView() == null) {
+ View view = mNavigationBarView.getHomeHandle().getCurrentView();
+ if (view == null) {
return;
}
- // Determine the area of the home icon in the larger home button
- mNavigationBarView.getHomeButton().getCurrentView().getLocationInSurface(butPos);
- final int navWidth = mNavigationBarView.getHomeButton().getCurrentView().getWidth();
- final int navHeight = mNavigationBarView.getHomeButton().getCurrentView().getHeight();
- final int xPadding = (int) (PERCENTAGE_BUTTON_PADDING * navWidth);
- final int yPadding = (int) (PERCENTAGE_BUTTON_PADDING * navHeight);
- final Rect homeButtonRect = new Rect(butPos[0] + xPadding, butPos[1] + yPadding,
- navWidth + butPos[0] - xPadding, navHeight + butPos[1] - yPadding);
- if (mNavigationBarView.getCurrentView() == null || homeButtonRect.isEmpty()) {
+ // Determine the area of the icon within its view bounds
+ view.getLocationInSurface(butPos);
+ final int navWidth = view.getWidth();
+ final int navHeight = view.getHeight();
+ int viewBottom = butPos[1] + navHeight - mBarBottom;
+ final Rect viewIconRect = new Rect(butPos[0], viewBottom - mBarRadius * 2,
+ butPos[0] + navWidth, viewBottom);
+
+ if (mNavigationBarView.getCurrentView() == null || viewIconRect.isEmpty()) {
scheduleColorAdaption();
return;
}
mNavigationBarView.getCurrentView().getLocationOnScreen(navPos);
- homeButtonRect.offset(navPos[0], navPos[1]);
+ viewIconRect.offset(navPos[0], navPos[1]);
// Apply a margin area around the button region to sample the colors, crop from screenshot
- final Rect cropRect = new Rect(homeButtonRect);
+ final Rect cropRect = new Rect(viewIconRect);
cropRect.inset(-COLOR_SAMPLE_MARGIN, -COLOR_SAMPLE_MARGIN);
if (cropRect.isEmpty()) {
scheduleColorAdaption();
@@ -120,8 +126,8 @@
// Determine the size of the home area
Rect homeArea = new Rect(COLOR_SAMPLE_MARGIN, COLOR_SAMPLE_MARGIN,
- homeButtonRect.width() + COLOR_SAMPLE_MARGIN,
- homeButtonRect.height() + COLOR_SAMPLE_MARGIN);
+ viewIconRect.width() + COLOR_SAMPLE_MARGIN,
+ viewIconRect.height() + COLOR_SAMPLE_MARGIN);
// Get the screenshot around the home button icon to determine the color
DisplayMetrics mDisplayMetrics = new DisplayMetrics();
@@ -129,7 +135,8 @@
final Bitmap hardBitmap = SurfaceControl
.screenshot(new Rect(), mDisplayMetrics.widthPixels, mDisplayMetrics.heightPixels,
mNavigationBarView.getContext().getDisplay().getRotation());
- if (hardBitmap != null && cropRect.bottom <= hardBitmap.getHeight()) {
+ if (cropRect.bottom <= hardBitmap.getHeight()
+ && cropRect.left + cropRect.width() <= hardBitmap.getWidth()) {
final Bitmap cropBitmap = Bitmap.createBitmap(hardBitmap, cropRect.left, cropRect.top,
cropRect.width(), cropRect.height());
final Bitmap softBitmap = cropBitmap.copy(Config.ARGB_8888, false);
@@ -204,6 +211,8 @@
public static boolean isEnabled(Context context) {
return Settings.Global.getInt(context.getContentResolver(),
- NavigationPrototypeController.NAV_COLOR_ADAPT_ENABLE_SETTING, 0) == 1;
+ NavigationPrototypeController.NAV_COLOR_ADAPT_ENABLE_SETTING, 0) == 1
+ && Settings.Global.getInt(context.getContentResolver(),
+ NavigationPrototypeController.SHOW_HOME_HANDLE_SETTING, 0) == 1;
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java
index 538d797..1eb4990 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java
@@ -445,8 +445,11 @@
// Respect the disabled flag, no need for action as flag change callback will handle hiding
if (rotateSuggestionsDisabled) return;
- mNavigationBarView.getRotateSuggestionButton()
- .onRotationProposal(rotation, winRotation, isValid);
+ View rotationButton = mNavigationBarView.getRotateSuggestionButton().getCurrentView();
+ if (rotationButton != null && rotationButton.isAttachedToWindow()) {
+ mNavigationBarView.getRotateSuggestionButton()
+ .onRotationProposal(rotation, winRotation, isValid);
+ }
}
/**
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarInflaterView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarInflaterView.java
index 7c31dae..c9fa89e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarInflaterView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarInflaterView.java
@@ -65,6 +65,7 @@
public static final String RECENT = "recent";
public static final String NAVSPACE = "space";
public static final String CLIPBOARD = "clipboard";
+ public static final String HOME_HANDLE = "home_handle";
public static final String KEY = "key";
public static final String LEFT = "left";
public static final String RIGHT = "right";
@@ -393,6 +394,8 @@
v = inflater.inflate(R.layout.clipboard, parent, false);
} else if (CONTEXTUAL.equals(button)) {
v = inflater.inflate(R.layout.contextual, parent, false);
+ } else if (HOME_HANDLE.equals(button)) {
+ v = inflater.inflate(R.layout.home_handle, parent, false);
} else if (button.startsWith(KEY)) {
String uri = extractImage(button);
int code = extractKeycode(button);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
index 8152206..d6d3d08 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
@@ -29,6 +29,7 @@
import static com.android.systemui.shared.system.NavigationBarCompat.HIT_TARGET_NONE;
import static com.android.systemui.shared.system.NavigationBarCompat.HIT_TARGET_OVERVIEW;
import static com.android.systemui.shared.system.NavigationBarCompat.HIT_TARGET_ROTATION;
+import static com.android.systemui.statusbar.phone.NavigationBarInflaterView.NAV_BAR_VIEWS;
import android.animation.LayoutTransition;
import android.animation.LayoutTransition.TransitionListener;
@@ -339,6 +340,11 @@
mRightEdgePanel.setDimensions(width, height);
}
}
+
+ @Override
+ public void onHomeHandleVisiblilityChanged(boolean visible) {
+ showHomeHandle(visible);
+ }
};
public NavigationBarView(Context context, AttributeSet attrs) {
@@ -376,6 +382,7 @@
mButtonDispatchers.put(R.id.back, new ButtonDispatcher(R.id.back));
mButtonDispatchers.put(R.id.home, new ButtonDispatcher(R.id.home));
+ mButtonDispatchers.put(R.id.home_handle, new ButtonDispatcher(R.id.home_handle));
mButtonDispatchers.put(R.id.recent_apps, new ButtonDispatcher(R.id.recent_apps));
mButtonDispatchers.put(R.id.menu, menuButton);
mButtonDispatchers.put(R.id.ime_switcher, imeSwitcherButton);
@@ -573,6 +580,10 @@
.getContextButton(R.id.rotate_suggestion);
}
+ public ButtonDispatcher getHomeHandle() {
+ return mButtonDispatchers.get(R.id.home_handle);
+ }
+
public SparseArray<ButtonDispatcher> getButtonDispatchers() {
return mButtonDispatchers;
}
@@ -855,6 +866,10 @@
final boolean showSwipeUpUI = mOverviewProxyService.shouldShowSwipeUpUI();
if (mNavigationInflaterView != null) {
+ if (mPrototypeController.showHomeHandle()) {
+ showHomeHandle(true /* visible */);
+ }
+
// Reinflate the navbar if needed, no-op unless the swipe up state changes
mNavigationInflaterView.onLikelyDefaultLayoutChange();
}
@@ -899,6 +914,9 @@
private void setWindowFlag(int flags, boolean enable) {
final ViewGroup navbarView = ((ViewGroup) getParent());
+ if (navbarView == null) {
+ return;
+ }
WindowManager.LayoutParams lp = (WindowManager.LayoutParams) navbarView.getLayoutParams();
if (lp == null || enable == ((lp.flags & flags) != 0)) {
return;
@@ -912,6 +930,18 @@
wm.updateViewLayout(navbarView, lp);
}
+ private void showHomeHandle(boolean visible) {
+ mNavigationInflaterView.onTuningChanged(NAV_BAR_VIEWS,
+ visible ? getContext().getString(R.string.config_navBarLayoutHandle) : null);
+
+ // Color adaption is tied with showing home handle, only avaliable if visible
+ if (visible) {
+ mColorAdaptionController.start();
+ } else {
+ mColorAdaptionController.end();
+ }
+ }
+
public void setMenuVisibility(final boolean show) {
mContextualButtonGroup.setButtonVisiblity(R.id.menu, show);
}
@@ -1136,6 +1166,12 @@
// If car mode or density changes, we need to reset the icons.
updateNavButtonIcons();
}
+
+ if (newConfig.orientation == Configuration.ORIENTATION_PORTRAIT) {
+ mColorAdaptionController.start();
+ } else {
+ mColorAdaptionController.end();
+ }
}
/**
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationHandle.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationHandle.java
new file mode 100644
index 0000000..968074c
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationHandle.java
@@ -0,0 +1,99 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.phone;
+
+import android.animation.ArgbEvaluator;
+import android.annotation.ColorInt;
+import android.content.Context;
+import android.content.res.Resources;
+import android.graphics.Canvas;
+import android.graphics.Paint;
+import android.graphics.drawable.Drawable;
+import android.util.AttributeSet;
+import android.view.ContextThemeWrapper;
+import android.view.View;
+
+import com.android.settingslib.Utils;
+import com.android.systemui.R;
+import com.android.systemui.plugins.statusbar.phone.NavBarButtonProvider.ButtonInterface;
+
+public class NavigationHandle extends View implements ButtonInterface {
+ private float mDarkIntensity = -1;
+
+ private final Paint mPaint = new Paint();
+ private @ColorInt final int mLightColor;
+ private @ColorInt final int mDarkColor;
+ private final int mRadius;
+ private final int mBottom;
+
+ public NavigationHandle(Context context) {
+ this(context, null);
+ }
+
+ public NavigationHandle(Context context, AttributeSet attr) {
+ super(context, attr);
+ final Resources res = context.getResources();
+ mRadius = res.getDimensionPixelSize(R.dimen.navigation_handle_radius);
+ mBottom = res.getDimensionPixelSize(R.dimen.navigation_handle_bottom);
+
+ final int dualToneDarkTheme = Utils.getThemeAttr(context, R.attr.darkIconTheme);
+ final int dualToneLightTheme = Utils.getThemeAttr(context, R.attr.lightIconTheme);
+ Context lightContext = new ContextThemeWrapper(context, dualToneLightTheme);
+ Context darkContext = new ContextThemeWrapper(context, dualToneDarkTheme);
+ mLightColor = Utils.getColorAttrDefaultColor(lightContext, R.attr.singleToneColor);
+ mDarkColor = Utils.getColorAttrDefaultColor(darkContext, R.attr.singleToneColor);
+ mPaint.setAntiAlias(true);
+ }
+
+ @Override
+ protected void onDraw(Canvas canvas) {
+ super.onDraw(canvas);
+
+ // Draw that bar
+ int navHeight = getHeight();
+ int height = mRadius * 2;
+ int width = getWidth();
+ int y = (navHeight - mBottom - height);
+ canvas.drawRoundRect(mRadius, y, width - mRadius, y + height, mRadius, mRadius, mPaint);
+ }
+
+ @Override
+ public void setImageDrawable(Drawable drawable) {
+ }
+
+ @Override
+ public void abortCurrentGesture() {
+ }
+
+ @Override
+ public void setVertical(boolean vertical) {
+ }
+
+ @Override
+ public void setDarkIntensity(float intensity) {
+ if (mDarkIntensity != intensity) {
+ mPaint.setColor((int) ArgbEvaluator.getInstance().evaluate(intensity, mLightColor,
+ mDarkColor));
+ mDarkIntensity = intensity;
+ invalidate();
+ }
+ }
+
+ @Override
+ public void setDelayTouchFeedback(boolean shouldDelay) {
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationPrototypeController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationPrototypeController.java
index 8421e23..2c31e2c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationPrototypeController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationPrototypeController.java
@@ -20,6 +20,7 @@
import android.content.Context;
import android.content.res.Resources;
import android.database.ContentObserver;
+import android.graphics.Point;
import android.net.Uri;
import android.os.Handler;
import android.provider.Settings;
@@ -37,12 +38,11 @@
private static final String HIDE_HOME_BUTTON_SETTING = "quickstepcontroller_hidehome";
private static final String PROTOTYPE_ENABLED = "prototype_enabled";
- private static final String EDGE_SENSITIVITY_HEIGHT_SETTING =
- "quickstepcontroller_edge_height_sensitivity";
public static final String EDGE_SENSITIVITY_WIDTH_SETTING =
"quickstepcontroller_edge_width_sensitivity";
private final String GESTURE_MATCH_SETTING = "quickstepcontroller_gesture_match_map";
public static final String NAV_COLOR_ADAPT_ENABLE_SETTING = "navbar_color_adapt_enable";
+ public static final String SHOW_HOME_HANDLE_SETTING = "quickstepcontroller_showhandle";
@Retention(RetentionPolicy.SOURCE)
@IntDef({ACTION_DEFAULT, ACTION_QUICKSTEP, ACTION_QUICKSCRUB, ACTION_BACK,
@@ -86,7 +86,7 @@
registerObserver(GESTURE_MATCH_SETTING);
registerObserver(NAV_COLOR_ADAPT_ENABLE_SETTING);
registerObserver(EDGE_SENSITIVITY_WIDTH_SETTING);
- registerObserver(EDGE_SENSITIVITY_HEIGHT_SETTING);
+ registerObserver(SHOW_HOME_HANDLE_SETTING);
}
/**
@@ -114,20 +114,29 @@
} else if (path.endsWith(NAV_COLOR_ADAPT_ENABLE_SETTING)) {
mListener.onColorAdaptChanged(
NavBarTintController.isEnabled(mContext));
- } else if (path.endsWith(EDGE_SENSITIVITY_WIDTH_SETTING)
- || path.endsWith(EDGE_SENSITIVITY_HEIGHT_SETTING)) {
+ } else if (path.endsWith(EDGE_SENSITIVITY_WIDTH_SETTING)) {
mListener.onEdgeSensitivityChanged(getEdgeSensitivityWidth(),
getEdgeSensitivityHeight());
+ } else if (path.endsWith(SHOW_HOME_HANDLE_SETTING)) {
+ mListener.onHomeHandleVisiblilityChanged(showHomeHandle());
}
}
}
+ /**
+ * @return the width for edge swipe
+ */
public int getEdgeSensitivityWidth() {
return convertDpToPixel(getGlobalInt(EDGE_SENSITIVITY_WIDTH_SETTING, 0));
}
+ /**
+ * @return full screen height
+ */
public int getEdgeSensitivityHeight() {
- return convertDpToPixel(getGlobalInt(EDGE_SENSITIVITY_HEIGHT_SETTING, 0));
+ final Point size = new Point();
+ mContext.getDisplay().getRealSize(size);
+ return size.y;
}
public boolean isEnabled() {
@@ -149,6 +158,10 @@
return getGlobalBool(HIDE_HOME_BUTTON_SETTING, false /* default */);
}
+ boolean showHomeHandle() {
+ return getGlobalBool(SHOW_HOME_HANDLE_SETTING, false /* default */);
+ }
+
/**
* Since Settings.Global cannot pass arrays, use a string to represent each character as a
* gesture map to actions corresponding to {@see GestureAction}. The number is represented as:
@@ -185,6 +198,7 @@
void onGestureRemap(@GestureAction int[] actions);
void onBackButtonVisibilityChanged(boolean visible);
void onHomeButtonVisibilityChanged(boolean visible);
+ void onHomeHandleVisiblilityChanged(boolean visible);
void onColorAdaptChanged(boolean enabled);
void onEdgeSensitivityChanged(int width, int height);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
index 30d5b65..51ffc1d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
@@ -479,8 +479,7 @@
updateAodMaskVisibility(deviceSupportsAodWallpaper && aodImageWallpaperEnabled);
// If WallpaperInfo is null, it must be ImageWallpaper.
final boolean supportsAmbientMode = deviceSupportsAodWallpaper
- && (info == null && aodImageWallpaperEnabled
- || info != null && info.supportsAmbientMode());
+ && (info == null || info.supportsAmbientMode());
mStatusBarWindowController.setWallpaperSupportsAmbientMode(supportsAmbientMode);
mScrimController.setWallpaperSupportsAmbientMode(supportsAmbientMode);
@@ -3262,7 +3261,11 @@
return true;
}
if (mState != StatusBarState.KEYGUARD && mState != StatusBarState.SHADE_LOCKED) {
- animateCollapsePanels();
+ if (mNotificationPanel.canPanelBeCollapsed()) {
+ animateCollapsePanels();
+ } else {
+ mBubbleController.performBackPressIfNeeded();
+ }
return true;
}
if (mKeyguardUserSwitcher != null && mKeyguardUserSwitcher.hideIfNotSimple(true)) {
diff --git a/packages/SystemUI/src/com/android/systemui/wallpaper/AodMaskView.java b/packages/SystemUI/src/com/android/systemui/wallpaper/AodMaskView.java
index 6ee341d..f446cef 100644
--- a/packages/SystemUI/src/com/android/systemui/wallpaper/AodMaskView.java
+++ b/packages/SystemUI/src/com/android/systemui/wallpaper/AodMaskView.java
@@ -156,6 +156,8 @@
private boolean checkIfNeedMask() {
// We need mask for ImageWallpaper / LockScreen Wallpaper (Music album art).
+ // Because of conflicting with another wallpaper feature,
+ // we only support LockScreen wallpaper currently.
return mWallpaperManager.getWallpaperInfo() == null || ScrimState.AOD.hasBackdrop();
}
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/clock/ClockManagerTest.java b/packages/SystemUI/tests/src/com/android/keyguard/clock/ClockManagerTest.java
index f813ac6..58701e7 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/clock/ClockManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/keyguard/clock/ClockManagerTest.java
@@ -17,15 +17,21 @@
import static com.google.common.truth.Truth.assertThat;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.when;
+
+import android.content.ContentResolver;
+import android.database.ContentObserver;
import android.test.suitebuilder.annotation.SmallTest;
import android.testing.AndroidTestingRunner;
-import android.testing.LeakCheck;
import android.testing.TestableLooper.RunWithLooper;
+import android.view.LayoutInflater;
import com.android.systemui.SysuiTestCase;
+import com.android.systemui.colorextraction.SysuiColorExtractor;
import com.android.systemui.dock.DockManager;
import com.android.systemui.dock.DockManagerFake;
-import com.android.systemui.utils.leaks.FakeExtensionController;
+import com.android.systemui.util.InjectionInflationController;
import org.junit.After;
import org.junit.Before;
@@ -39,21 +45,31 @@
@RunWithLooper
public final class ClockManagerTest extends SysuiTestCase {
+ private static final String BUBBLE_CLOCK = BubbleClockController.class.getName();
+ private static final Class<?> BUBBLE_CLOCK_CLASS = BubbleClockController.class;
+
private ClockManager mClockManager;
- private LeakCheck mLeakCheck;
- private FakeExtensionController mFakeExtensionController;
+ private ContentObserver mContentObserver;
private DockManagerFake mFakeDockManager;
+ @Mock InjectionInflationController mMockInjectionInflationController;
+ @Mock SysuiColorExtractor mMockColorExtractor;
+ @Mock ContentResolver mMockContentResolver;
+ @Mock SettingsWrapper mMockSettingsWrapper;
@Mock ClockManager.ClockChangedListener mMockListener;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
- mLeakCheck = new LeakCheck();
- mFakeExtensionController = new FakeExtensionController(mLeakCheck);
+
+ LayoutInflater inflater = LayoutInflater.from(getContext());
+ when(mMockInjectionInflationController.injectable(any())).thenReturn(inflater);
+
mFakeDockManager = new DockManagerFake();
- mClockManager = new ClockManager(getContext(), mFakeExtensionController,
- mFakeDockManager);
+ mClockManager = new ClockManager(getContext(), mMockInjectionInflationController,
+ mFakeDockManager, mMockColorExtractor, mMockContentResolver, mMockSettingsWrapper);
+
mClockManager.addOnClockChangedListener(mMockListener);
+ mContentObserver = mClockManager.getContentObserver();
}
@After
@@ -72,4 +88,76 @@
mFakeDockManager.setDockEvent(DockManager.STATE_NONE);
assertThat(mClockManager.isDocked()).isFalse();
}
+
+ @Test
+ public void getCurrentClock_default() {
+ // GIVEN that settings doesn't contain any values
+ when(mMockSettingsWrapper.getLockScreenCustomClockFace()).thenReturn(null);
+ when(mMockSettingsWrapper.getDockedClockFace()).thenReturn(null);
+ // WHEN settings change event is fired
+ mContentObserver.onChange(false);
+ // THEN the result is null, indicated the default clock face should be used.
+ assertThat(mClockManager.getCurrentClock()).isNull();
+ }
+
+ @Test
+ public void getCurrentClock_customClock() {
+ // GIVEN that settings is set to the bubble clock face
+ when(mMockSettingsWrapper.getLockScreenCustomClockFace()).thenReturn(BUBBLE_CLOCK);
+ // WHEN settings change event is fired
+ mContentObserver.onChange(false);
+ // THEN the plugin is the bubble clock face.
+ assertThat(mClockManager.getCurrentClock()).isInstanceOf(BUBBLE_CLOCK_CLASS);
+ }
+
+ @Test
+ public void getCurrentClock_badSettingsValue() {
+ // GIVEN that settings contains a value that doesn't correspond to a
+ // custom clock face.
+ when(mMockSettingsWrapper.getLockScreenCustomClockFace()).thenReturn("bad value");
+ // WHEN settings change event is fired
+ mContentObserver.onChange(false);
+ // THEN the result is null.
+ assertThat(mClockManager.getCurrentClock()).isNull();
+ }
+
+ @Test
+ public void getCurrentClock_dockedDefault() {
+ // WHEN dock event is fired
+ mFakeDockManager.setDockEvent(DockManager.STATE_DOCKED);
+ // THEN the result is null, indicating the default clock face.
+ assertThat(mClockManager.getCurrentClock()).isNull();
+ }
+
+ @Test
+ public void getCurrentClock_dockedCustomClock() {
+ // GIVEN settings is set to the bubble clock face
+ when(mMockSettingsWrapper.getDockedClockFace()).thenReturn(BUBBLE_CLOCK);
+ // WHEN dock event fires
+ mFakeDockManager.setDockEvent(DockManager.STATE_DOCKED);
+ // THEN the plugin is the bubble clock face.
+ assertThat(mClockManager.getCurrentClock()).isInstanceOf(BUBBLE_CLOCK_CLASS);
+ }
+
+ @Test
+ public void getCurrentClock_badDockedSettingsValue() {
+ // GIVEN settings contains a value that doesn't correspond to an available clock face.
+ when(mMockSettingsWrapper.getDockedClockFace()).thenReturn("bad value");
+ // WHEN dock event fires
+ mFakeDockManager.setDockEvent(DockManager.STATE_DOCKED);
+ // THEN the result is null.
+ assertThat(mClockManager.getCurrentClock()).isNull();
+ }
+
+ @Test
+ public void getCurrentClock_badDockedSettingsFallback() {
+ // GIVEN settings contains a value that doesn't correspond to an available clock face, but
+ // locked screen settings is set to bubble clock.
+ when(mMockSettingsWrapper.getDockedClockFace()).thenReturn("bad value");
+ when(mMockSettingsWrapper.getLockScreenCustomClockFace()).thenReturn(BUBBLE_CLOCK);
+ // WHEN dock event is fired
+ mFakeDockManager.setDockEvent(DockManager.STATE_DOCKED);
+ // THEN the plugin is the bubble clock face.
+ assertThat(mClockManager.getCurrentClock()).isInstanceOf(BUBBLE_CLOCK_CLASS);
+ }
}
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/clock/DefaultClockSupplierTest.java b/packages/SystemUI/tests/src/com/android/keyguard/clock/DefaultClockSupplierTest.java
deleted file mode 100644
index 1a3b198..0000000
--- a/packages/SystemUI/tests/src/com/android/keyguard/clock/DefaultClockSupplierTest.java
+++ /dev/null
@@ -1,132 +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.
- */
-package com.android.keyguard.clock;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import static org.mockito.Mockito.when;
-
-import android.test.suitebuilder.annotation.SmallTest;
-import android.testing.AndroidTestingRunner;
-import android.testing.TestableLooper.RunWithLooper;
-import android.view.LayoutInflater;
-
-import com.android.systemui.SysuiTestCase;
-import com.android.systemui.plugins.ClockPlugin;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
-
-@SmallTest
-@RunWith(AndroidTestingRunner.class)
-@RunWithLooper
-public final class DefaultClockSupplierTest extends SysuiTestCase {
-
- private static final String BUBBLE_CLOCK = BubbleClockController.class.getName();
- private static final Class<?> BUBBLE_CLOCK_CLASS = BubbleClockController.class;
-
- private DefaultClockSupplier mDefaultClockSupplier;
- @Mock SettingsWrapper mMockSettingsWrapper;
-
- @Before
- public void setUp() {
- MockitoAnnotations.initMocks(this);
- mDefaultClockSupplier = new DefaultClockSupplier(mMockSettingsWrapper,
- LayoutInflater.from(getContext()));
- }
-
- @Test
- public void get_default() {
- // GIVEN that settings doesn't contain any values
- when(mMockSettingsWrapper.getLockScreenCustomClockFace()).thenReturn(null);
- when(mMockSettingsWrapper.getDockedClockFace()).thenReturn(null);
- // WHEN get is called
- ClockPlugin plugin = mDefaultClockSupplier.get();
- // THEN the result is null, indicated the default clock face should be used.
- assertThat(plugin).isNull();
- }
-
- @Test
- public void get_customClock() {
- // GIVEN that settings is set to the bubble clock face
- when(mMockSettingsWrapper.getLockScreenCustomClockFace()).thenReturn(BUBBLE_CLOCK);
- // WHEN get is called
- ClockPlugin plugin = mDefaultClockSupplier.get();
- // THEN the plugin is the bubble clock face.
- assertThat(plugin).isInstanceOf(BUBBLE_CLOCK_CLASS);
- }
-
- @Test
- public void get_badSettingsValue() {
- // GIVEN that settings contains a value that doesn't correspond to a
- // custom clock face.
- when(mMockSettingsWrapper.getLockScreenCustomClockFace()).thenReturn("bad value");
- // WHEN get is called
- ClockPlugin plugin = mDefaultClockSupplier.get();
- // THEN the result is null.
- assertThat(plugin).isNull();
- }
-
- @Test
- public void get_dockedDefault() {
- // GIVEN docked
- mDefaultClockSupplier.setDocked(true);
- // WHEN get is called
- ClockPlugin plugin = mDefaultClockSupplier.get();
- // THEN the result is null, indicating the default clock face.
- assertThat(plugin).isNull();
- }
-
- @Test
- public void get_dockedCustomClock() {
- // GIVEN docked and settings is set to the bubble clock face
- mDefaultClockSupplier.setDocked(true);
- when(mMockSettingsWrapper.getDockedClockFace()).thenReturn(BUBBLE_CLOCK);
- // WHEN get is called
- ClockPlugin plugin = mDefaultClockSupplier.get();
- // THEN the plugin is the bubble clock face.
- assertThat(plugin).isInstanceOf(BUBBLE_CLOCK_CLASS);
- }
-
- @Test
- public void get_badDockedSettingsValue() {
- // GIVEN docked and settings contains a value that doesn't correspond to
- // an available clock face.
- mDefaultClockSupplier.setDocked(true);
- when(mMockSettingsWrapper.getDockedClockFace()).thenReturn("bad value");
- // WHEN get is called
- ClockPlugin plugin = mDefaultClockSupplier.get();
- // THEN the result is null.
- assertThat(plugin).isNull();
- }
-
- @Test
- public void get_badDockedSettingsFallback() {
- // GIVEN docked and settings contains a value that doesn't correspond to
- // an available clock face, but locked screen settings is set to bubble
- // clock.
- mDefaultClockSupplier.setDocked(true);
- when(mMockSettingsWrapper.getDockedClockFace()).thenReturn("bad value");
- when(mMockSettingsWrapper.getLockScreenCustomClockFace()).thenReturn(BUBBLE_CLOCK);
- // WHEN get is called
- ClockPlugin plugin = mDefaultClockSupplier.get();
- // THEN the plugin is the bubble clock face.
- assertThat(plugin).isInstanceOf(BUBBLE_CLOCK_CLASS);
- }
-}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationContentInflaterTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationContentInflaterTest.java
index dfaa76a..99dc9f8 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationContentInflaterTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationContentInflaterTest.java
@@ -99,7 +99,11 @@
public void testIncreasedHeadsUpBeingUsed() {
mNotificationInflater.setUsesIncreasedHeadsUpHeight(true);
Notification.Builder builder = spy(mBuilder);
- mNotificationInflater.inflateNotificationViews(FLAG_CONTENT_VIEW_ALL, builder, mContext);
+ mNotificationInflater.inflateNotificationViews(
+ false /* inflateSynchronously */,
+ FLAG_CONTENT_VIEW_ALL,
+ builder,
+ mContext);
verify(builder).createHeadsUpContentView(true);
}
@@ -107,7 +111,11 @@
public void testIncreasedHeightBeingUsed() {
mNotificationInflater.setUsesIncreasedHeight(true);
Notification.Builder builder = spy(mBuilder);
- mNotificationInflater.inflateNotificationViews(FLAG_CONTENT_VIEW_ALL, builder, mContext);
+ mNotificationInflater.inflateNotificationViews(
+ false /* inflateSynchronously */,
+ FLAG_CONTENT_VIEW_ALL,
+ builder,
+ mContext);
verify(builder).createContentView(true);
}
@@ -163,7 +171,11 @@
new NotificationContentInflater.InflationProgress();
result.packageContext = mContext;
CountDownLatch countDownLatch = new CountDownLatch(1);
- NotificationContentInflater.applyRemoteView(result, FLAG_CONTENT_VIEW_EXPANDED, 0,
+ NotificationContentInflater.applyRemoteView(
+ false /* inflateSynchronously */,
+ result,
+ FLAG_CONTENT_VIEW_EXPANDED,
+ 0,
new ArrayMap() /* cachedContentViews */, mRow, false /* redactAmbient */,
true /* isNewView */, (v, p, r) -> true,
new InflationCallback() {
@@ -246,6 +258,7 @@
NotificationContentInflater inflater) throws Exception {
CountDownLatch countDownLatch = new CountDownLatch(1);
final ExceptionHolder exceptionHolder = new ExceptionHolder();
+ inflater.setInflateSynchronously(true);
inflater.setInflationCallback(new InflationCallback() {
@Override
public void handleInflationException(StatusBarNotification notification,
@@ -265,11 +278,6 @@
}
countDownLatch.countDown();
}
-
- @Override
- public boolean doInflateSynchronous() {
- return true;
- }
});
block.run();
assertTrue(countDownLatch.await(500, TimeUnit.MILLISECONDS));
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NavigationBarButtonTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NavigationBarButtonTest.java
index 6177344..5c80718 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NavigationBarButtonTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NavigationBarButtonTest.java
@@ -24,9 +24,11 @@
import android.hardware.display.DisplayManager;
import android.hardware.display.VirtualDisplay;
import android.media.ImageReader;
+import android.os.SystemClock;
import android.support.test.filters.SmallTest;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper.RunWithLooper;
+import android.util.Log;
import android.view.Display;
import android.view.DisplayInfo;
@@ -39,12 +41,15 @@
import org.junit.Test;
import org.junit.runner.RunWith;
+import java.util.function.Predicate;
+
/** atest NavigationBarButtonTest */
@RunWith(AndroidTestingRunner.class)
@RunWithLooper
@SmallTest
public class NavigationBarButtonTest extends SysuiTestCase {
+ private static final String TAG = "NavigationBarButtonTest";
private ImageReader mReader;
private NavigationBarView mNavBar;
private VirtualDisplay mVirtualDisplay;
@@ -78,9 +83,31 @@
assertNotNull("virtual display must not be null", mVirtualDisplay);
+ waitForDisplayReady(mVirtualDisplay.getDisplay().getDisplayId());
+
return mVirtualDisplay.getDisplay();
}
+ private void waitForDisplayReady(int displayId) {
+ waitForDisplayCondition(displayId, state -> state);
+ }
+
+ private void waitForDisplayCondition(int displayId, Predicate<Boolean> condition) {
+ for (int retry = 1; retry <= 10; retry++) {
+ if (condition.test(isDisplayOn(displayId))) {
+ return;
+ }
+ Log.i(TAG, "Waiting for virtual display ready ... retry = " + retry);
+ SystemClock.sleep(500);
+ }
+ }
+
+ private boolean isDisplayOn(int displayId) {
+ DisplayManager displayManager = mContext.getSystemService(DisplayManager.class);
+ Display display = displayManager.getDisplay(displayId);
+ return display != null && display.getState() == Display.STATE_ON;
+ }
+
@After
public void tearDown() {
releaseDisplay();
diff --git a/packages/VpnDialogs/Android.bp b/packages/VpnDialogs/Android.bp
new file mode 100644
index 0000000..6f2f50c
--- /dev/null
+++ b/packages/VpnDialogs/Android.bp
@@ -0,0 +1,23 @@
+//
+// Copyright (C) 2011 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT 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_app {
+ name: "VpnDialogs",
+ certificate: "platform",
+ privileged: true,
+ srcs: ["src/**/*.java"],
+ platform_apis: true,
+}
diff --git a/packages/VpnDialogs/Android.mk b/packages/VpnDialogs/Android.mk
deleted file mode 100644
index 8507646..0000000
--- a/packages/VpnDialogs/Android.mk
+++ /dev/null
@@ -1,32 +0,0 @@
-#
-# Copyright (C) 2011 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-LOCAL_PATH := $(call my-dir)
-
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_TAGS := optional
-
-LOCAL_CERTIFICATE := platform
-
-LOCAL_PRIVILEGED_MODULE := true
-
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-
-LOCAL_PACKAGE_NAME := VpnDialogs
-LOCAL_PRIVATE_PLATFORM_APIS := true
-
-include $(BUILD_PACKAGE)
diff --git a/packages/WAPPushManager/Android.bp b/packages/WAPPushManager/Android.bp
new file mode 100644
index 0000000..1bec492
--- /dev/null
+++ b/packages/WAPPushManager/Android.bp
@@ -0,0 +1,12 @@
+// Copyright 2007-2008 The Android Open Source Project
+
+android_app {
+ name: "WAPPushManager",
+ srcs: ["src/**/*.java"],
+ platform_apis: true,
+ libs: ["telephony-common"],
+ static_libs: ["android-common"],
+ optimize: {
+ proguard_flags_files: ["proguard.flags"],
+ },
+}
diff --git a/packages/WAPPushManager/Android.mk b/packages/WAPPushManager/Android.mk
deleted file mode 100644
index 91526dd..0000000
--- a/packages/WAPPushManager/Android.mk
+++ /dev/null
@@ -1,22 +0,0 @@
-# Copyright 2007-2008 The Android Open Source Project
-
-
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_TAGS := optional
-
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-
-LOCAL_PACKAGE_NAME := WAPPushManager
-LOCAL_PRIVATE_PLATFORM_APIS := true
-
-LOCAL_JAVA_LIBRARIES += telephony-common
-LOCAL_STATIC_JAVA_LIBRARIES += android-common
-
-LOCAL_PROGUARD_FLAG_FILES := proguard.flags
-
-include $(BUILD_PACKAGE)
-
-# This finds and builds the test apk as well, so a single make does both.
-include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/packages/WAPPushManager/tests/Android.bp b/packages/WAPPushManager/tests/Android.bp
new file mode 100644
index 0000000..25c6121
--- /dev/null
+++ b/packages/WAPPushManager/tests/Android.bp
@@ -0,0 +1,34 @@
+// Copyright 2008, The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT 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 {
+ name: "WAPPushManagerTests",
+ libs: [
+ "android.test.runner",
+ "telephony-common",
+ "android.test.base",
+ ],
+ static_libs: ["junit"],
+ // Include all test java files.
+ srcs: [
+ "src/**/*.java",
+ "src/com/android/smspush/unitTests/IDataVerify.aidl",
+ ],
+ // Notice that we don't have to include the src files of Email
+ // because running the tests using an instrumentation targeting
+ // Email, we automatically get all of its classes loaded into
+ // our environment.
+ platform_apis: true,
+ instrumentation_for: "WAPPushManager",
+}
diff --git a/packages/WAPPushManager/tests/Android.mk b/packages/WAPPushManager/tests/Android.mk
deleted file mode 100644
index c4c2240f..0000000
--- a/packages/WAPPushManager/tests/Android.mk
+++ /dev/null
@@ -1,40 +0,0 @@
-# Copyright 2008, The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-# We only want this apk build for tests.
-LOCAL_MODULE_TAGS := tests
-
-LOCAL_JAVA_LIBRARIES := android.test.runner telephony-common android.test.base
-LOCAL_STATIC_JAVA_LIBRARIES := junit
-
-# Include all test java files.
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-LOCAL_SRC_FILES += \
- src/com/android/smspush/unitTests/IDataVerify.aidl
-
-
-# Notice that we don't have to include the src files of Email because, by
-# running the tests using an instrumentation targeting Eamil, we
-# automatically get all of its classes loaded into our environment.
-
-LOCAL_PACKAGE_NAME := WAPPushManagerTests
-LOCAL_PRIVATE_PLATFORM_APIS := true
-
-LOCAL_INSTRUMENTATION_FOR := WAPPushManager
-
-include $(BUILD_PACKAGE)
-
diff --git a/packages/WallpaperBackup/Android.bp b/packages/WallpaperBackup/Android.bp
new file mode 100644
index 0000000..56020cd
--- /dev/null
+++ b/packages/WallpaperBackup/Android.bp
@@ -0,0 +1,26 @@
+//
+// Copyright (C) 2016 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+android_app {
+ name: "WallpaperBackup",
+ srcs: ["src/**/*.java"],
+ optimize: {
+ proguard_flags_files: ["proguard.flags"],
+ },
+ platform_apis: true,
+ certificate: "platform",
+ privileged: false,
+}
diff --git a/packages/WallpaperBackup/Android.mk b/packages/WallpaperBackup/Android.mk
deleted file mode 100644
index a6426a6..0000000
--- a/packages/WallpaperBackup/Android.mk
+++ /dev/null
@@ -1,35 +0,0 @@
-#
-# Copyright (C) 2016 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-LOCAL_PATH := $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_TAGS := optional
-
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-
-LOCAL_PROGUARD_FLAG_FILES := proguard.flags
-
-LOCAL_PACKAGE_NAME := WallpaperBackup
-LOCAL_PRIVATE_PLATFORM_APIS := true
-LOCAL_CERTIFICATE := platform
-LOCAL_PRIVILEGED_MODULE := false
-
-include $(BUILD_PACKAGE)
-
-########################
-include $(call all-makefiles-under,$(LOCAL_PATH))
-
diff --git a/packages/WallpaperBackup/src/com/android/wallpaperbackup/WallpaperBackupAgent.java b/packages/WallpaperBackup/src/com/android/wallpaperbackup/WallpaperBackupAgent.java
index 4254a0b..2e40c1a 100644
--- a/packages/WallpaperBackup/src/com/android/wallpaperbackup/WallpaperBackupAgent.java
+++ b/packages/WallpaperBackup/src/com/android/wallpaperbackup/WallpaperBackupAgent.java
@@ -115,8 +115,10 @@
// We always back up this 'empty' file to ensure that the absence of
// storable wallpaper imagery still produces a non-empty backup data
// stream, otherwise it'd simply be ignored in preflight.
- FileOutputStream touch = new FileOutputStream(empty);
- touch.close();
+ if (!empty.exists()) {
+ FileOutputStream touch = new FileOutputStream(empty);
+ touch.close();
+ }
fullBackupFile(empty, data);
SharedPreferences prefs = getSharedPreferences(PREFS_NAME, Context.MODE_PRIVATE);
diff --git a/packages/WallpaperCropper/Android.bp b/packages/WallpaperCropper/Android.bp
new file mode 100644
index 0000000..40c4235
--- /dev/null
+++ b/packages/WallpaperCropper/Android.bp
@@ -0,0 +1,11 @@
+android_app {
+ name: "WallpaperCropper",
+ srcs: ["src/**/*.java"],
+ platform_apis: true,
+ certificate: "platform",
+ product_specific: true,
+ privileged: true,
+ optimize: {
+ proguard_flags_files: ["proguard.flags"],
+ },
+}
diff --git a/packages/WallpaperCropper/Android.mk b/packages/WallpaperCropper/Android.mk
deleted file mode 100644
index 2fa1dde..0000000
--- a/packages/WallpaperCropper/Android.mk
+++ /dev/null
@@ -1,18 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_TAGS := optional
-
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-
-LOCAL_PACKAGE_NAME := WallpaperCropper
-LOCAL_PRIVATE_PLATFORM_APIS := true
-LOCAL_CERTIFICATE := platform
-LOCAL_PRODUCT_MODULE := true
-LOCAL_PRIVILEGED_MODULE := true
-
-LOCAL_PROGUARD_FLAG_FILES := proguard.flags
-
-include $(BUILD_PACKAGE)
-
-include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/packages/overlays/Android.mk b/packages/overlays/Android.mk
index 1294dbb..7ce13c2 100644
--- a/packages/overlays/Android.mk
+++ b/packages/overlays/Android.mk
@@ -44,6 +44,7 @@
LOCAL_MODULE := frameworks-base-overlays-debug
LOCAL_REQUIRED_MODULES := \
ExperimentNavigationBarFloatingOverlay \
+ ExperimentNavigationBarVisualInsetOverlay \
ExperimentNavigationBarDefaultOverlay \
ExperimentNavigationBarSlimOverlay32 \
ExperimentNavigationBarSlimOverlay40 \
diff --git a/packages/FusedLocation/Android.mk b/packages/overlays/ExperimentNavigationBarVisualInsetOverlay/Android.mk
similarity index 66%
rename from packages/FusedLocation/Android.mk
rename to packages/overlays/ExperimentNavigationBarVisualInsetOverlay/Android.mk
index d795870..56bf516 100644
--- a/packages/FusedLocation/Android.mk
+++ b/packages/overlays/ExperimentNavigationBarVisualInsetOverlay/Android.mk
@@ -1,29 +1,30 @@
-# Copyright (C) 2012 The Android Open Source Project
+#
+# Copyright 2018, The Android Open Source Project
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
-# http://www.apache.org/licenses/LICENSE-2.0
+# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
+#
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
-LOCAL_MODULE_TAGS := optional
+LOCAL_RRO_THEME := ExperimentNavigationBarVisualInset
+LOCAL_CERTIFICATE := platform
LOCAL_SRC_FILES := $(call all-subdir-java-files)
-LOCAL_JAVA_LIBRARIES := com.android.location.provider
+LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res
-LOCAL_PACKAGE_NAME := FusedLocation
-LOCAL_PRIVATE_PLATFORM_APIS := true
-LOCAL_CERTIFICATE := platform
-LOCAL_PRIVILEGED_MODULE := true
+LOCAL_PACKAGE_NAME := ExperimentNavigationBarVisualInsetOverlay
+LOCAL_SDK_VERSION := current
-include $(BUILD_PACKAGE)
+include $(BUILD_RRO_PACKAGE)
\ No newline at end of file
diff --git a/packages/overlays/ExperimentNavigationBarVisualInsetOverlay/AndroidManifest.xml b/packages/overlays/ExperimentNavigationBarVisualInsetOverlay/AndroidManifest.xml
new file mode 100644
index 0000000..3ea5dc4
--- /dev/null
+++ b/packages/overlays/ExperimentNavigationBarVisualInsetOverlay/AndroidManifest.xml
@@ -0,0 +1,27 @@
+<!--
+/**
+ * Copyright (c) 2018, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+-->
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.android.internal.experiment.navbar.type.inset"
+ android:versionCode="1"
+ android:versionName="1.0">
+ <overlay android:targetPackage="android"
+ android:category="com.android.internal.experiment_navbar_visual_inset"
+ android:priority="1"/>
+
+ <application android:label="@string/experiment_navigationbar_overlay" android:hasCode="false"/>
+</manifest>
\ No newline at end of file
diff --git a/packages/overlays/ExperimentNavigationBarVisualInsetOverlay/res/values/config.xml b/packages/overlays/ExperimentNavigationBarVisualInsetOverlay/res/values/config.xml
new file mode 100644
index 0000000..d35a744
--- /dev/null
+++ b/packages/overlays/ExperimentNavigationBarVisualInsetOverlay/res/values/config.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/**
+ * Copyright (c) 2018, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+-->
+<resources>
+ <!-- Height of the bottom navigation / system bar. -->
+ <dimen name="navigation_bar_height">16dp</dimen>
+ <!-- Width of the navigation bar when it is placed vertically on the screen -->
+ <dimen name="navigation_bar_width">16dp</dimen>
+</resources>
\ No newline at end of file
diff --git a/packages/overlays/ExperimentNavigationBarVisualInsetOverlay/res/values/strings.xml b/packages/overlays/ExperimentNavigationBarVisualInsetOverlay/res/values/strings.xml
new file mode 100644
index 0000000..84dfcb7
--- /dev/null
+++ b/packages/overlays/ExperimentNavigationBarVisualInsetOverlay/res/values/strings.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/**
+ * Copyright (c) 2018, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <!-- Name of overlay [CHAR LIMIT=64] -->
+ <string name="experiment_navigationbar_overlay" translatable="false">Visual Inset Navigation Bar</string>
+</resources>
\ No newline at end of file
diff --git a/packages/services/PacProcessor/Android.bp b/packages/services/PacProcessor/Android.bp
new file mode 100644
index 0000000..93b2d95
--- /dev/null
+++ b/packages/services/PacProcessor/Android.bp
@@ -0,0 +1,23 @@
+//
+// Copyright (C) 2010 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT 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_app {
+ name: "PacProcessor",
+ srcs: ["src/**/*.java"],
+ platform_apis: true,
+ certificate: "platform",
+ jni_libs: ["libjni_pacprocessor"],
+}
diff --git a/packages/services/PacProcessor/Android.mk b/packages/services/PacProcessor/Android.mk
deleted file mode 100644
index be9ba43..0000000
--- a/packages/services/PacProcessor/Android.mk
+++ /dev/null
@@ -1,31 +0,0 @@
-#
-# Copyright (C) 2010 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-LOCAL_PATH := $(call my-dir)
-
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_TAGS := optional
-
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-
-LOCAL_PACKAGE_NAME := PacProcessor
-LOCAL_PRIVATE_PLATFORM_APIS := true
-LOCAL_CERTIFICATE := platform
-
-LOCAL_JNI_SHARED_LIBRARIES := libjni_pacprocessor
-
-include $(BUILD_PACKAGE)
diff --git a/packages/services/Proxy/Android.bp b/packages/services/Proxy/Android.bp
new file mode 100644
index 0000000..87aa763
--- /dev/null
+++ b/packages/services/Proxy/Android.bp
@@ -0,0 +1,7 @@
+android_app {
+ name: "ProxyHandler",
+ srcs: ["src/**/*.java"],
+ platform_apis: true,
+ certificate: "platform",
+ privileged: true,
+}
diff --git a/packages/services/Proxy/Android.mk b/packages/services/Proxy/Android.mk
deleted file mode 100644
index ce1715f..0000000
--- a/packages/services/Proxy/Android.mk
+++ /dev/null
@@ -1,15 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_TAGS := optional
-
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-
-LOCAL_PACKAGE_NAME := ProxyHandler
-LOCAL_PRIVATE_PLATFORM_APIS := true
-LOCAL_CERTIFICATE := platform
-LOCAL_PRIVILEGED_MODULE := true
-
-include $(BUILD_PACKAGE)
-
-include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/services/backup/java/com/android/server/backup/UserBackupManagerService.java b/services/backup/java/com/android/server/backup/UserBackupManagerService.java
index d4ac731..32e2cac 100644
--- a/services/backup/java/com/android/server/backup/UserBackupManagerService.java
+++ b/services/backup/java/com/android/server/backup/UserBackupManagerService.java
@@ -70,6 +70,7 @@
import android.database.ContentObserver;
import android.net.Uri;
import android.os.Binder;
+import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.os.HandlerThread;
@@ -1484,19 +1485,50 @@
}
/**
- * Clear an application's data, blocking until the operation completes or times out. If {@code
- * keepSystemState} is {@code true}, we intentionally do not clear system state that would
- * ordinarily also be cleared, because we aren't actually wiping the app back to empty; we're
- * bringing it into the actual expected state related to the already-restored notification state
- * etc.
+ * Clear an application's data after a failed restore, blocking until the operation completes or
+ * times out.
*/
- public void clearApplicationDataSynchronous(String packageName, boolean keepSystemState) {
- // Don't wipe packages marked allowClearUserData=false
+ public void clearApplicationDataAfterRestoreFailure(String packageName) {
+ clearApplicationDataSynchronous(packageName, true, false);
+ }
+
+ /**
+ * Clear an application's data before restore, blocking until the operation completes or times
+ * out.
+ */
+ public void clearApplicationDataBeforeRestore(String packageName) {
+ clearApplicationDataSynchronous(packageName, false, true);
+ }
+
+ /**
+ * Clear an application's data, blocking until the operation completes or times out.
+ *
+ * @param checkFlagAllowClearUserDataOnFailedRestore if {@code true} uses
+ * {@link ApplicationInfo#PRIVATE_FLAG_ALLOW_CLEAR_USER_DATA_ON_FAILED_RESTORE} to decide if
+ * clearing data is allowed after a failed restore.
+ *
+ * @param keepSystemState if {@code true}, we don't clear system state such as already restored
+ * notification settings, permission grants, etc.
+ */
+ private void clearApplicationDataSynchronous(String packageName,
+ boolean checkFlagAllowClearUserDataOnFailedRestore, boolean keepSystemState) {
try {
- PackageInfo info = mPackageManager.getPackageInfoAsUser(packageName, 0, mUserId);
- if ((info.applicationInfo.flags & ApplicationInfo.FLAG_ALLOW_CLEAR_USER_DATA) == 0) {
+ ApplicationInfo applicationInfo = mPackageManager.getPackageInfoAsUser(
+ packageName, 0, mUserId).applicationInfo;
+
+ boolean shouldClearData;
+ if (checkFlagAllowClearUserDataOnFailedRestore
+ && applicationInfo.targetSdkVersion >= Build.VERSION_CODES.Q) {
+ shouldClearData = (applicationInfo.privateFlags
+ & ApplicationInfo.PRIVATE_FLAG_ALLOW_CLEAR_USER_DATA_ON_FAILED_RESTORE) != 0;
+ } else {
+ shouldClearData =
+ (applicationInfo.flags & ApplicationInfo.FLAG_ALLOW_CLEAR_USER_DATA) != 0;
+ }
+
+ if (!shouldClearData) {
if (MORE_DEBUG) {
- Slog.i(TAG, "allowClearUserData=false so not wiping "
+ Slog.i(TAG, "Clearing app data is not allowed so not wiping "
+ packageName);
}
return;
@@ -1511,8 +1543,8 @@
synchronized (mClearDataLock) {
mClearingData = true;
try {
- mActivityManager.clearApplicationUserData(
- packageName, keepSystemState, observer, mUserId);
+ mActivityManager.clearApplicationUserData(packageName, keepSystemState, observer,
+ mUserId);
} catch (RemoteException e) {
// can't happen because the activity manager is in this process
}
diff --git a/services/backup/java/com/android/server/backup/restore/FullRestoreEngine.java b/services/backup/java/com/android/server/backup/restore/FullRestoreEngine.java
index c5389fa..836a5e8 100644
--- a/services/backup/java/com/android/server/backup/restore/FullRestoreEngine.java
+++ b/services/backup/java/com/android/server/backup/restore/FullRestoreEngine.java
@@ -352,7 +352,7 @@
Slog.d(TAG,
"Clearing app data preparatory to full restore");
}
- mBackupManagerService.clearApplicationDataSynchronous(pkg, true);
+ mBackupManagerService.clearApplicationDataBeforeRestore(pkg);
} else {
if (MORE_DEBUG) {
Slog.d(TAG, "backup agent ("
diff --git a/services/backup/java/com/android/server/backup/restore/PerformUnifiedRestoreTask.java b/services/backup/java/com/android/server/backup/restore/PerformUnifiedRestoreTask.java
index 324c2d9..6714b0a 100644
--- a/services/backup/java/com/android/server/backup/restore/PerformUnifiedRestoreTask.java
+++ b/services/backup/java/com/android/server/backup/restore/PerformUnifiedRestoreTask.java
@@ -660,7 +660,7 @@
++mCount;
} catch (Exception e) {
Slog.e(TAG, "Error when attempting restore: " + e.toString());
- keyValueAgentErrorCleanup();
+ keyValueAgentErrorCleanup(false);
executeNextState(UnifiedRestoreState.RUNNING_QUEUE);
}
}
@@ -686,6 +686,7 @@
boolean staging = !packageName.equals("android");
ParcelFileDescriptor stage;
File downloadFile = (staging) ? mStageName : mBackupDataName;
+ boolean startedAgentRestore = false;
try {
IBackupTransport transport =
@@ -766,13 +767,15 @@
long restoreAgentTimeoutMillis = mAgentTimeoutParameters.getRestoreAgentTimeoutMillis();
backupManagerService.prepareOperationTimeout(
mEphemeralOpToken, restoreAgentTimeoutMillis, this, OP_TYPE_RESTORE_WAIT);
+ startedAgentRestore = true;
mAgent.doRestore(mBackupData, appVersionCode, mNewState,
mEphemeralOpToken, backupManagerService.getBackupManagerBinder());
} catch (Exception e) {
Slog.e(TAG, "Unable to call app for restore: " + packageName, e);
EventLog.writeEvent(EventLogTags.RESTORE_AGENT_FAILURE,
packageName, e.toString());
- keyValueAgentErrorCleanup(); // clears any pending timeout messages as well
+ // Clears any pending timeout messages as well.
+ keyValueAgentErrorCleanup(startedAgentRestore);
// After a restore failure we go back to running the queue. If there
// are no more packages to be restored that will be handled by the
@@ -832,7 +835,7 @@
Slog.e(TAG, "Unable to finalize restore of " + packageName);
EventLog.writeEvent(EventLogTags.RESTORE_AGENT_FAILURE,
packageName, e.toString());
- keyValueAgentErrorCleanup();
+ keyValueAgentErrorCleanup(true);
executeNextState(UnifiedRestoreState.RUNNING_QUEUE);
}
}
@@ -988,8 +991,8 @@
// We also need to wipe the current target's data, as it's probably
// in an incoherent state.
- backupManagerService.clearApplicationDataSynchronous(
- mCurrentPackage.packageName, false);
+ backupManagerService.clearApplicationDataAfterRestoreFailure(
+ mCurrentPackage.packageName);
// Schedule the next state based on the nature of our failure
if (status == BackupTransport.TRANSPORT_ERROR) {
@@ -1110,11 +1113,18 @@
mListener.onFinished(callerLogString);
}
- void keyValueAgentErrorCleanup() {
- // If the agent fails restore, it might have put the app's data
- // into an incoherent state. For consistency we wipe its data
- // again in this case before continuing with normal teardown
- backupManagerService.clearApplicationDataSynchronous(mCurrentPackage.packageName, false);
+ /**
+ * @param clearAppData - set to {@code true} if the backup agent had already been invoked when
+ * restore faied. So the app data may be in corrupted state and has to be cleared.
+ */
+ void keyValueAgentErrorCleanup(boolean clearAppData) {
+ if (clearAppData) {
+ // If the agent fails restore, it might have put the app's data
+ // into an incoherent state. For consistency we wipe its data
+ // again in this case before continuing with normal teardown
+ backupManagerService.clearApplicationDataAfterRestoreFailure(
+ mCurrentPackage.packageName);
+ }
keyValueAgentCleanup();
}
@@ -1251,7 +1261,7 @@
// Some kind of horrible semantic error; we're in an unexpected state.
// Back off hard and wind up.
Slog.e(TAG, "Unexpected restore callback into state " + mState);
- keyValueAgentErrorCleanup();
+ keyValueAgentErrorCleanup(true);
nextState = UnifiedRestoreState.FINAL;
break;
}
@@ -1271,7 +1281,7 @@
EventLog.writeEvent(EventLogTags.RESTORE_AGENT_FAILURE,
mCurrentPackage.packageName, "restore timeout");
// Handle like an agent that threw on invocation: wipe it and go on to the next
- keyValueAgentErrorCleanup();
+ keyValueAgentErrorCleanup(true);
executeNextState(UnifiedRestoreState.RUNNING_QUEUE);
}
diff --git a/services/contentcapture/java/com/android/server/contentcapture/ContentCaptureManagerService.java b/services/contentcapture/java/com/android/server/contentcapture/ContentCaptureManagerService.java
index 4bd50ec..45ceeda 100644
--- a/services/contentcapture/java/com/android/server/contentcapture/ContentCaptureManagerService.java
+++ b/services/contentcapture/java/com/android/server/contentcapture/ContentCaptureManagerService.java
@@ -505,31 +505,6 @@
}
@Override
- public void setContentCaptureFeatureEnabled(boolean enabled,
- @NonNull IResultReceiver result) {
- final int userId = UserHandle.getCallingUserId();
- final boolean isService;
- synchronized (mLock) {
- isService = assertCalledByServiceLocked("setContentCaptureFeatureEnabled()", userId,
- Binder.getCallingUid(), result);
- }
- if (!isService) return;
-
- final long token = Binder.clearCallingIdentity();
- try {
- Settings.Secure.putStringForUser(getContext().getContentResolver(),
- Settings.Secure.CONTENT_CAPTURE_ENABLED, Boolean.toString(enabled), userId);
- } finally {
- Binder.restoreCallingIdentity(token);
- }
- try {
- result.send(ContentCaptureManager.RESULT_CODE_TRUE, /* resultData= */null);
- } catch (RemoteException e) {
- Slog.w(mTag, "Unable to send setContentCaptureFeatureEnabled(): " + e);
- }
- }
-
- @Override
public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
if (!DumpUtils.checkDumpPermission(getContext(), mTag, pw)) return;
diff --git a/services/contentcapture/java/com/android/server/contentcapture/ContentCapturePerUserService.java b/services/contentcapture/java/com/android/server/contentcapture/ContentCapturePerUserService.java
index 7150264..9e15960 100644
--- a/services/contentcapture/java/com/android/server/contentcapture/ContentCapturePerUserService.java
+++ b/services/contentcapture/java/com/android/server/contentcapture/ContentCapturePerUserService.java
@@ -21,6 +21,7 @@
import static android.view.contentcapture.ContentCaptureSession.STATE_DUPLICATED_ID;
import static android.view.contentcapture.ContentCaptureSession.STATE_INTERNAL_ERROR;
import static android.view.contentcapture.ContentCaptureSession.STATE_NO_SERVICE;
+import static android.view.contentcapture.ContentCaptureSession.STATE_PACKAGE_NOT_WHITELISTED;
import static com.android.server.wm.ActivityTaskManagerInternal.ASSIST_KEY_CONTENT;
import static com.android.server.wm.ActivityTaskManagerInternal.ASSIST_KEY_DATA;
@@ -43,11 +44,12 @@
import android.os.IBinder;
import android.os.RemoteException;
import android.os.UserHandle;
+import android.provider.Settings;
import android.service.contentcapture.ContentCaptureService;
import android.service.contentcapture.IContentCaptureServiceCallback;
import android.service.contentcapture.SnapshotData;
import android.util.ArrayMap;
-import android.util.Log;
+import android.util.ArraySet;
import android.util.Slog;
import android.view.contentcapture.UserDataRemovalRequest;
@@ -87,6 +89,12 @@
private final ContentCaptureServiceRemoteCallback mRemoteServiceCallback =
new ContentCaptureServiceRemoteCallback();
+ /**
+ * List of packages that are whitelisted to be content captured.
+ */
+ @GuardedBy("mLock")
+ private final ArraySet<String> mWhitelistedPackages = new ArraySet<>();
+
// TODO(b/111276913): add mechanism to prune stale sessions, similar to Autofill's
ContentCapturePerUserService(@NonNull ContentCaptureManagerService master,
@@ -185,6 +193,7 @@
final int taskId = activityPresentationInfo.taskId;
final int displayId = activityPresentationInfo.displayId;
final ComponentName componentName = activityPresentationInfo.componentName;
+ final boolean whitelisted = isWhitelistedLocked(componentName);
final ComponentName serviceComponentName = getServiceComponentName();
final boolean enabled = isEnabledLocked();
if (mMaster.mRequestsHistory != null) {
@@ -193,7 +202,8 @@
+ " a=" + ComponentName.flattenToShortString(componentName)
+ " t=" + taskId + " d=" + displayId
+ " s=" + ComponentName.flattenToShortString(serviceComponentName)
- + " u=" + mUserId + " f=" + flags + (enabled ? "" : " (disabled)");
+ + " u=" + mUserId + " f=" + flags + (enabled ? "" : " (disabled)")
+ + " w=" + whitelisted;
mMaster.mRequestsHistory.log(historyItem);
}
@@ -214,6 +224,16 @@
return;
}
+ if (!whitelisted) {
+ if (mMaster.debug) {
+ Slog.d(TAG, "startSession(" + componentName + "): not whitelisted");
+ }
+ // TODO(b/122595322): need to return STATE_ACTIVITY_NOT_WHITELISTED as well
+ setClientState(clientReceiver, STATE_DISABLED | STATE_PACKAGE_NOT_WHITELISTED,
+ /* binder= */ null);
+ return;
+ }
+
final ContentCaptureServerSession existingSession = mSessions.get(sessionId);
if (existingSession != null) {
Slog.w(TAG, "startSession(id=" + existingSession + ", token=" + activityToken
@@ -247,6 +267,26 @@
newSession.notifySessionStartedLocked(clientReceiver);
}
+ @GuardedBy("mLock")
+ private boolean isWhitelistedLocked(@NonNull ComponentName componentName) {
+ // TODO(b/122595322): need to check whitelisted activities as well.
+ final String packageName = componentName.getPackageName();
+ return mWhitelistedPackages.contains(packageName);
+ }
+
+ private void whitelistPackages(@NonNull List<String> packages) {
+ // TODO(b/122595322): add CTS test for when it's null
+ synchronized (mLock) {
+ if (packages == null) {
+ if (mMaster.verbose) Slog.v(TAG, "clearing all whitelisted packages");
+ mWhitelistedPackages.clear();
+ } else {
+ if (mMaster.verbose) Slog.v(TAG, "whitelisting packages: " + packages);
+ mWhitelistedPackages.addAll(packages);
+ }
+ }
+ }
+
// TODO(b/119613670): log metrics
@GuardedBy("mLock")
public void finishSessionLocked(@NonNull String sessionId) {
@@ -378,15 +418,23 @@
mRemoteService.dump(prefix2, pw);
}
+ final int whitelistSize = mWhitelistedPackages.size();
+ pw.print(prefix); pw.print("Whitelisted packages: "); pw.println(whitelistSize);
+ for (int i = 0; i < whitelistSize; i++) {
+ final String whitelistedPkg = mWhitelistedPackages.valueAt(i);
+ pw.print(prefix2); pw.print(i + 1); pw.print(": "); pw.println(whitelistedPkg);
+ }
+
if (mSessions.isEmpty()) {
pw.print(prefix); pw.println("no sessions");
} else {
- final int size = mSessions.size();
- pw.print(prefix); pw.print("number sessions: "); pw.println(size);
- for (int i = 0; i < size; i++) {
- pw.print(prefix); pw.print("session@"); pw.println(i);
+ final int sessionsSize = mSessions.size();
+ pw.print(prefix); pw.print("number sessions: "); pw.println(sessionsSize);
+ for (int i = 0; i < sessionsSize; i++) {
+ pw.print(prefix); pw.print("#"); pw.println(i);
final ContentCaptureServerSession session = mSessions.valueAt(i);
session.dumpLocked(prefix2, pw);
+ pw.println();
}
}
}
@@ -412,11 +460,26 @@
public void setContentCaptureWhitelist(List<String> packages,
List<ComponentName> activities) {
if (mMaster.verbose) {
- Log.v(TAG, "setContentCaptureWhitelist(packages=" + packages + ", activities="
+ Slog.v(TAG, "setContentCaptureWhitelist(packages=" + packages + ", activities="
+ activities + ")");
}
- // TODO(b/122595322): implement
+ whitelistPackages(packages);
+
+ // TODO(b/122595322): whitelist activities as well
// TODO(b/119613670): log metrics
}
+
+ @Override
+ public void disableSelf() {
+ if (mMaster.verbose) Slog.v(TAG, "disableSelf()");
+
+ final long token = Binder.clearCallingIdentity();
+ try {
+ Settings.Secure.putStringForUser(getContext().getContentResolver(),
+ Settings.Secure.CONTENT_CAPTURE_ENABLED, "false", mUserId);
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
}
}
diff --git a/services/core/java/com/android/server/RescueParty.java b/services/core/java/com/android/server/RescueParty.java
index 62da3f8..6e5d316 100644
--- a/services/core/java/com/android/server/RescueParty.java
+++ b/services/core/java/com/android/server/RescueParty.java
@@ -37,6 +37,7 @@
import android.util.StatsLog;
import com.android.internal.util.ArrayUtils;
+import com.android.server.utils.FlagNamespaceUtils;
import java.io.File;
@@ -194,6 +195,8 @@
RecoverySystem.rebootPromptAndWipeUserData(context, TAG);
break;
}
+ FlagNamespaceUtils.addToKnownResetNamespaces(
+ FlagNamespaceUtils.NAMESPACE_NO_PACKAGE);
}
private static void resetAllSettings(Context context, int mode) throws Exception {
@@ -203,14 +206,19 @@
final ContentResolver resolver = context.getContentResolver();
try {
Settings.Global.resetToDefaultsAsUser(resolver, null, mode, UserHandle.USER_SYSTEM);
- } catch (Throwable t) {
- res = new RuntimeException("Failed to reset global settings", t);
+ } catch (Exception e) {
+ res = new RuntimeException("Failed to reset global settings", e);
+ }
+ try {
+ FlagNamespaceUtils.resetDeviceConfig(mode);
+ } catch (Exception e) {
+ res = new RuntimeException("Failed to reset config settings", e);
}
for (int userId : getAllUserIds()) {
try {
Settings.Secure.resetToDefaultsAsUser(resolver, null, mode, userId);
- } catch (Throwable t) {
- res = new RuntimeException("Failed to reset secure settings for " + userId, t);
+ } catch (Exception e) {
+ res = new RuntimeException("Failed to reset secure settings for " + userId, e);
}
}
if (res != null) {
diff --git a/services/core/java/com/android/server/TelephonyRegistry.java b/services/core/java/com/android/server/TelephonyRegistry.java
index 8120976..fd946cd 100644
--- a/services/core/java/com/android/server/TelephonyRegistry.java
+++ b/services/core/java/com/android/server/TelephonyRegistry.java
@@ -237,7 +237,7 @@
private PhoneCapability mPhoneCapability = null;
- private int mPreferredDataSubId = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
+ private int mActiveDataSubId = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
@TelephonyManager.RadioPowerState
private int mRadioPowerState = TelephonyManager.RADIO_POWER_UNAVAILABLE;
@@ -257,7 +257,8 @@
static final int ENFORCE_PHONE_STATE_PERMISSION_MASK =
PhoneStateListener.LISTEN_CALL_FORWARDING_INDICATOR
| PhoneStateListener.LISTEN_MESSAGE_WAITING_INDICATOR
- | PhoneStateListener.LISTEN_EMERGENCY_NUMBER_LIST;
+ | PhoneStateListener.LISTEN_EMERGENCY_NUMBER_LIST
+ | PhoneStateListener.LISTEN_ACTIVE_DATA_SUBID_CHANGE;
static final int PRECISE_PHONE_STATE_PERMISSION_MASK =
PhoneStateListener.LISTEN_PRECISE_CALL_STATE |
@@ -819,9 +820,9 @@
remove(r.binder);
}
}
- if ((events & PhoneStateListener.LISTEN_PREFERRED_DATA_SUBID_CHANGE) != 0) {
+ if ((events & PhoneStateListener.LISTEN_ACTIVE_DATA_SUBID_CHANGE) != 0) {
try {
- r.callback.onPreferredDataSubIdChanged(mPreferredDataSubId);
+ r.callback.onActiveDataSubIdChanged(mActiveDataSubId);
} catch (RemoteException ex) {
remove(r.binder);
}
@@ -1757,23 +1758,23 @@
}
}
- public void notifyPreferredDataSubIdChanged(int preferredSubId) {
- if (!checkNotifyPermission("notifyPreferredDataSubIdChanged()")) {
+ public void notifyActiveDataSubIdChanged(int activeDataSubId) {
+ if (!checkNotifyPermission("notifyActiveDataSubIdChanged()")) {
return;
}
if (VDBG) {
- log("notifyPreferredDataSubIdChanged: preferredSubId=" + preferredSubId);
+ log("notifyActiveDataSubIdChanged: activeDataSubId=" + activeDataSubId);
}
synchronized (mRecords) {
- mPreferredDataSubId = preferredSubId;
+ mActiveDataSubId = activeDataSubId;
for (Record r : mRecords) {
if (r.matchPhoneStateListenerEvent(
- PhoneStateListener.LISTEN_PREFERRED_DATA_SUBID_CHANGE)) {
+ PhoneStateListener.LISTEN_ACTIVE_DATA_SUBID_CHANGE)) {
try {
- r.callback.onPreferredDataSubIdChanged(preferredSubId);
+ r.callback.onActiveDataSubIdChanged(activeDataSubId);
} catch (RemoteException ex) {
mRemoveList.add(r.binder);
}
@@ -1909,7 +1910,7 @@
pw.println("mBackgroundCallState=" + mBackgroundCallState);
pw.println("mSrvccState=" + mSrvccState);
pw.println("mPhoneCapability=" + mPhoneCapability);
- pw.println("mPreferredDataSubId=" + mPreferredDataSubId);
+ pw.println("mActiveDataSubId=" + mActiveDataSubId);
pw.println("mRadioPowerState=" + mRadioPowerState);
pw.println("mEmergencyNumberList=" + mEmergencyNumberList);
pw.println("mCallQuality=" + mCallQuality);
@@ -2181,14 +2182,6 @@
android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, null);
}
- if ((events & PhoneStateListener.LISTEN_PREFERRED_DATA_SUBID_CHANGE) != 0) {
- // It can have either READ_PHONE_STATE or READ_PRIVILEGED_PHONE_STATE.
- TelephonyPermissions.checkReadPhoneState(mContext,
- SubscriptionManager.INVALID_SUBSCRIPTION_ID, Binder.getCallingPid(),
- Binder.getCallingUid(), callingPackage, "listen to "
- + "LISTEN_PREFERRED_DATA_SUBID_CHANGE");
- }
-
if ((events & PhoneStateListener.LISTEN_CALL_DISCONNECT_CAUSES) != 0) {
mContext.enforceCallingOrSelfPermission(
android.Manifest.permission.READ_PRECISE_PHONE_STATE, null);
diff --git a/services/core/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java
index 026430b..aebe2b7 100644
--- a/services/core/java/com/android/server/am/ActiveServices.java
+++ b/services/core/java/com/android/server/am/ActiveServices.java
@@ -319,10 +319,6 @@
ServiceRecord r = mDelayedStartList.remove(0);
if (DEBUG_DELAYED_STARTS) Slog.v(TAG_SERVICE,
"REM FR DELAY LIST (exec next): " + r);
- if (r.pendingStarts.size() <= 0) {
- Slog.w(TAG, "**** NO PENDING STARTS! " + r + " startReq=" + r.startRequested
- + " delayedStop=" + r.delayedStop);
- }
if (DEBUG_DELAYED_SERVICE) {
if (mDelayedStartList.size() > 0) {
Slog.v(TAG_SERVICE, "Remaining delayed list:");
@@ -332,11 +328,16 @@
}
}
r.delayed = false;
- try {
- startServiceInnerLocked(this, r.pendingStarts.get(0).intent, r, false, true,
- false);
- } catch (TransactionTooLargeException e) {
- // Ignore, nobody upstack cares.
+ if (r.pendingStarts.size() <= 0) {
+ Slog.wtf(TAG, "**** NO PENDING STARTS! " + r + " startReq=" + r.startRequested
+ + " delayedStop=" + r.delayedStop);
+ } else {
+ try {
+ startServiceInnerLocked(this, r.pendingStarts.get(0).intent, r, false, true,
+ false);
+ } catch (TransactionTooLargeException e) {
+ // Ignore, nobody upstack cares.
+ }
}
}
if (mStartingBackground.size() > 0) {
@@ -2978,6 +2979,7 @@
// Clear start entries.
r.clearDeliveredStartsLocked();
r.pendingStarts.clear();
+ smap.mDelayedStartList.remove(r);
if (r.app != null) {
synchronized (r.stats.getBatteryStats()) {
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 2f20572..bfe1f6a 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -2704,8 +2704,8 @@
public void batterySendBroadcast(Intent intent) {
synchronized (this) {
broadcastIntentLocked(null, null, intent, null, null, 0, null, null, null,
- OP_NONE, null, false, false,
- -1, SYSTEM_UID, UserHandle.USER_ALL);
+ OP_NONE, null, false, false, -1, SYSTEM_UID, Binder.getCallingUid(),
+ Binder.getCallingPid(), UserHandle.USER_ALL);
}
}
@@ -3823,12 +3823,13 @@
intent.putExtra(Intent.EXTRA_USER_HANDLE, resolvedUserId);
if (isInstantApp) {
intent.putExtra(Intent.EXTRA_PACKAGE_NAME, packageName);
- broadcastIntentInPackage("android", SYSTEM_UID, intent, null, null, 0,
- null, null, permission.ACCESS_INSTANT_APPS, null, false, false,
- resolvedUserId, false);
+ broadcastIntentInPackage("android", SYSTEM_UID, uid, pid, intent, null,
+ null, 0, null, null, permission.ACCESS_INSTANT_APPS, null, false,
+ false, resolvedUserId, false);
} else {
- broadcastIntentInPackage("android", SYSTEM_UID, intent, null, null, 0,
- null, null, null, null, false, false, resolvedUserId, false);
+ broadcastIntentInPackage("android", SYSTEM_UID, uid, pid, intent, null,
+ null, 0, null, null, null, null, false, false, resolvedUserId,
+ false);
}
if (observer != null) {
@@ -4263,7 +4264,8 @@
intent.putExtra(Intent.EXTRA_USER_HANDLE, UserHandle.getUserId(uid));
broadcastIntentLocked(null, null, intent,
null, null, 0, null, null, null, OP_NONE,
- null, false, false, MY_PID, SYSTEM_UID, UserHandle.getUserId(uid));
+ null, false, false, MY_PID, SYSTEM_UID, Binder.getCallingUid(),
+ Binder.getCallingPid(), UserHandle.getUserId(uid));
}
private void cleanupDisabledPackageComponentsLocked(
@@ -8709,6 +8711,8 @@
mAtmInternal.showSystemReadyErrorDialogsIfNeeded();
+ final int callingUid = Binder.getCallingUid();
+ final int callingPid = Binder.getCallingPid();
long ident = Binder.clearCallingIdentity();
try {
Intent intent = new Intent(Intent.ACTION_USER_STARTED);
@@ -8717,7 +8721,7 @@
intent.putExtra(Intent.EXTRA_USER_HANDLE, currentUserId);
broadcastIntentLocked(null, null, intent,
null, null, 0, null, null, null, OP_NONE,
- null, false, false, MY_PID, SYSTEM_UID,
+ null, false, false, MY_PID, SYSTEM_UID, callingUid, callingPid,
currentUserId);
intent = new Intent(Intent.ACTION_USER_STARTING);
intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
@@ -8731,7 +8735,8 @@
}
}, 0, null, null,
new String[] {INTERACT_ACROSS_USERS}, OP_NONE,
- null, true, false, MY_PID, SYSTEM_UID, UserHandle.USER_ALL);
+ null, true, false, MY_PID, SYSTEM_UID, callingUid, callingPid,
+ UserHandle.USER_ALL);
} catch (Throwable t) {
Slog.wtf(TAG, "Failed sending first user broadcasts", t);
} finally {
@@ -14369,10 +14374,12 @@
String callerPackage, Intent intent, String resolvedType,
IIntentReceiver resultTo, int resultCode, String resultData,
Bundle resultExtras, String[] requiredPermissions, int appOp, Bundle bOptions,
- boolean ordered, boolean sticky, int callingPid, int callingUid, int userId) {
+ boolean ordered, boolean sticky, int callingPid, int callingUid, int realCallingUid,
+ int realCallingPid, int userId) {
return broadcastIntentLocked(callerApp, callerPackage, intent, resolvedType, resultTo,
resultCode, resultData, resultExtras, requiredPermissions, appOp, bOptions, ordered,
- sticky, callingPid, callingUid, userId, false /* allowBackgroundActivityStarts */);
+ sticky, callingPid, callingUid, realCallingUid, realCallingPid, userId,
+ false /* allowBackgroundActivityStarts */);
}
@GuardedBy("this")
@@ -14380,8 +14387,8 @@
String callerPackage, Intent intent, String resolvedType,
IIntentReceiver resultTo, int resultCode, String resultData,
Bundle resultExtras, String[] requiredPermissions, int appOp, Bundle bOptions,
- boolean ordered, boolean sticky, int callingPid, int callingUid, int userId,
- boolean allowBackgroundActivityStarts) {
+ boolean ordered, boolean sticky, int callingPid, int callingUid, int realCallingUid,
+ int realCallingPid, int userId, boolean allowBackgroundActivityStarts) {
intent = new Intent(intent);
final boolean callerInstantApp = isInstantApp(callerApp, callerPackage, callingUid);
@@ -14430,7 +14437,7 @@
// PendingIntent), because that who is actually supplied the arguments.
if (checkComponentPermission(
android.Manifest.permission.CHANGE_DEVICE_IDLE_TEMP_WHITELIST,
- Binder.getCallingPid(), Binder.getCallingUid(), -1, true)
+ realCallingPid, realCallingUid, -1, true)
!= PackageManager.PERMISSION_GRANTED) {
String msg = "Permission Denial: " + intent.getAction()
+ " broadcast from " + callerPackage + " (pid=" + callingPid
@@ -14448,6 +14455,25 @@
+ " has background restrictions");
return ActivityManager.START_CANCELED;
}
+ if (brOptions.allowsBackgroundActivityStarts()) {
+ // See if the caller is allowed to do this. Note we are checking against
+ // the actual real caller (not whoever provided the operation as say a
+ // PendingIntent), because that who is actually supplied the arguments.
+ if (checkComponentPermission(
+ android.Manifest.permission.START_ACTIVITIES_FROM_BACKGROUND,
+ realCallingPid, realCallingUid, -1, true)
+ != PackageManager.PERMISSION_GRANTED) {
+ String msg = "Permission Denial: " + intent.getAction()
+ + " broadcast from " + callerPackage + " (pid=" + callingPid
+ + ", uid=" + callingUid + ")"
+ + " requires "
+ + android.Manifest.permission.START_ACTIVITIES_FROM_BACKGROUND;
+ Slog.w(TAG, msg);
+ throw new SecurityException(msg);
+ } else {
+ allowBackgroundActivityStarts = true;
+ }
+ }
}
// Verify that protected broadcasts are only being sent by system code,
@@ -15118,15 +15144,15 @@
callerApp != null ? callerApp.info.packageName : null,
intent, resolvedType, resultTo, resultCode, resultData, resultExtras,
requiredPermissions, appOp, bOptions, serialized, sticky,
- callingPid, callingUid, userId);
+ callingPid, callingUid, callingUid, callingPid, userId);
Binder.restoreCallingIdentity(origId);
return res;
}
}
- int broadcastIntentInPackage(String packageName, int uid,
- Intent intent, String resolvedType, IIntentReceiver resultTo,
+ int broadcastIntentInPackage(String packageName, int uid, int realCallingUid,
+ int realCallingPid, Intent intent, String resolvedType, IIntentReceiver resultTo,
int resultCode, String resultData, Bundle resultExtras,
String requiredPermission, Bundle bOptions, boolean serialized, boolean sticky,
int userId, boolean allowBackgroundActivityStarts) {
@@ -15139,7 +15165,8 @@
int res = broadcastIntentLocked(null, packageName, intent, resolvedType,
resultTo, resultCode, resultData, resultExtras,
requiredPermissions, OP_NONE, bOptions, serialized,
- sticky, -1, uid, userId, allowBackgroundActivityStarts);
+ sticky, -1, uid, realCallingUid, realCallingPid, userId,
+ allowBackgroundActivityStarts);
Binder.restoreCallingIdentity(origId);
return res;
}
@@ -17721,15 +17748,16 @@
}
@Override
- public int broadcastIntentInPackage(String packageName, int uid, Intent intent,
- String resolvedType, IIntentReceiver resultTo, int resultCode, String resultData,
- Bundle resultExtras, String requiredPermission, Bundle bOptions, boolean serialized,
- boolean sticky, int userId, boolean allowBackgroundActivityStarts) {
+ public int broadcastIntentInPackage(String packageName, int uid, int realCallingUid,
+ int realCallingPid, Intent intent, String resolvedType, IIntentReceiver resultTo,
+ int resultCode, String resultData, Bundle resultExtras, String requiredPermission,
+ Bundle bOptions, boolean serialized, boolean sticky, int userId,
+ boolean allowBackgroundActivityStarts) {
synchronized (ActivityManagerService.this) {
return ActivityManagerService.this.broadcastIntentInPackage(packageName, uid,
- intent, resolvedType, resultTo, resultCode, resultData, resultExtras,
- requiredPermission, bOptions, serialized, sticky, userId,
- allowBackgroundActivityStarts);
+ realCallingUid, realCallingPid, intent, resolvedType, resultTo, resultCode,
+ resultData, resultExtras, requiredPermission, bOptions, serialized, sticky,
+ userId, allowBackgroundActivityStarts);
}
}
@@ -17830,8 +17858,8 @@
| Intent.FLAG_RECEIVER_FOREGROUND
| Intent.FLAG_RECEIVER_VISIBLE_TO_INSTANT_APPS);
broadcastIntentLocked(null, null, intent, null, null, 0, null, null, null,
- OP_NONE, null, false, false, MY_PID, SYSTEM_UID,
- UserHandle.USER_ALL);
+ OP_NONE, null, false, false, MY_PID, SYSTEM_UID, Binder.getCallingUid(),
+ Binder.getCallingPid(), UserHandle.USER_ALL);
if ((changes & ActivityInfo.CONFIG_LOCALE) != 0) {
intent = new Intent(Intent.ACTION_LOCALE_CHANGED);
intent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND
@@ -17841,8 +17869,8 @@
intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
}
broadcastIntentLocked(null, null, intent, null, null, 0, null, null, null,
- OP_NONE, null, false, false, MY_PID, SYSTEM_UID,
- UserHandle.USER_ALL);
+ OP_NONE, null, false, false, MY_PID, SYSTEM_UID, Binder.getCallingUid(),
+ Binder.getCallingPid(), UserHandle.USER_ALL);
}
// Send a broadcast to PackageInstallers if the configuration change is interesting
@@ -17857,7 +17885,7 @@
new String[] { android.Manifest.permission.INSTALL_PACKAGES };
broadcastIntentLocked(null, null, intent, null, null, 0, null, null,
permissions, OP_NONE, null, false, false, MY_PID, SYSTEM_UID,
- UserHandle.USER_ALL);
+ Binder.getCallingUid(), Binder.getCallingPid(), UserHandle.USER_ALL);
}
}
}
@@ -17881,7 +17909,8 @@
}
broadcastIntentLocked(null, null, intent, null, null, 0, null, null, null,
- OP_NONE, null, false, false, -1, SYSTEM_UID, UserHandle.USER_ALL);
+ OP_NONE, null, false, false, -1, SYSTEM_UID, Binder.getCallingUid(),
+ Binder.getCallingPid(), UserHandle.USER_ALL);
}
}
@@ -17896,10 +17925,18 @@
@Override
public void startProcess(String processName, ApplicationInfo info,
boolean knownToBeDead, String hostingType, ComponentName hostingName) {
- synchronized (ActivityManagerService.this) {
- startProcessLocked(processName, info, knownToBeDead, 0 /* intentFlags */,
- hostingType, hostingName, false /* allowWhileBooting */,
- false /* isolated */, true /* keepIfLarge */);
+ try {
+ if (Trace.isTagEnabled(Trace.TRACE_TAG_ACTIVITY_MANAGER)) {
+ Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "startProcess:"
+ + processName);
+ }
+ synchronized (ActivityManagerService.this) {
+ startProcessLocked(processName, info, knownToBeDead, 0 /* intentFlags */,
+ hostingType, hostingName, false /* allowWhileBooting */,
+ false /* isolated */, true /* keepIfLarge */);
+ }
+ } finally {
+ Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
}
}
diff --git a/services/core/java/com/android/server/am/AppCompactor.java b/services/core/java/com/android/server/am/AppCompactor.java
index c7e4fc7..17ffd9c 100644
--- a/services/core/java/com/android/server/am/AppCompactor.java
+++ b/services/core/java/com/android/server/am/AppCompactor.java
@@ -28,6 +28,7 @@
import android.app.ActivityManager;
import android.app.ActivityThread;
+import android.os.Debug;
import android.os.Handler;
import android.os.Message;
import android.os.Process;
@@ -410,6 +411,7 @@
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "Compact "
+ ((pendingAction == COMPACT_PROCESS_SOME) ? "some" : "full")
+ ": " + name);
+ long zramFreeKbBefore = Debug.getZramFreeKb();
long[] rssBefore = Process.getRss(pid);
FileOutputStream fos = new FileOutputStream("/proc/" + pid + "/reclaim");
fos.write(action.getBytes());
@@ -417,10 +419,12 @@
long[] rssAfter = Process.getRss(pid);
long end = SystemClock.uptimeMillis();
long time = end - start;
+ long zramFreeKbAfter = Debug.getZramFreeKb();
EventLog.writeEvent(EventLogTags.AM_COMPACT, pid, name, action,
rssBefore[0], rssBefore[1], rssBefore[2], rssBefore[3],
rssAfter[0], rssAfter[1], rssAfter[2], rssAfter[3], time,
- lastCompactAction, lastCompactTime, msg.arg1, msg.arg2);
+ lastCompactAction, lastCompactTime, msg.arg1, msg.arg2,
+ zramFreeKbBefore, zramFreeKbAfter);
// Note that as above not taking mPhenoTypeFlagLock here to avoid locking
// on every single compaction for a flag that will seldom change and the
// impact of reading the wrong value here is low.
@@ -429,7 +433,8 @@
rssBefore[0], rssBefore[1], rssBefore[2], rssBefore[3],
rssAfter[0], rssAfter[1], rssAfter[2], rssAfter[3], time,
lastCompactAction, lastCompactTime, msg.arg1,
- ActivityManager.processStateAmToProto(msg.arg2));
+ ActivityManager.processStateAmToProto(msg.arg2),
+ zramFreeKbBefore, zramFreeKbAfter);
}
synchronized (mAm) {
proc.lastCompactTime = end;
diff --git a/services/core/java/com/android/server/am/CoreSettingsObserver.java b/services/core/java/com/android/server/am/CoreSettingsObserver.java
index 8ffb67a..06d0152 100644
--- a/services/core/java/com/android/server/am/CoreSettingsObserver.java
+++ b/services/core/java/com/android/server/am/CoreSettingsObserver.java
@@ -79,6 +79,7 @@
sGlobalSettingToTypeMap.put(Settings.Global.GAME_DRIVER_BLACKLIST, String.class);
sGlobalSettingToTypeMap.put(Settings.Global.GAME_DRIVER_WHITELIST, String.class);
sGlobalSettingToTypeMap.put(Settings.Global.GAME_DRIVER_BLACKLISTS, String.class);
+ sGlobalSettingToTypeMap.put(Settings.Global.GAME_DRIVER_SPHAL_LIBRARIES, String.class);
// add other global settings here...
}
diff --git a/services/core/java/com/android/server/am/EventLogTags.logtags b/services/core/java/com/android/server/am/EventLogTags.logtags
index a71f6af..4b12e43 100644
--- a/services/core/java/com/android/server/am/EventLogTags.logtags
+++ b/services/core/java/com/android/server/am/EventLogTags.logtags
@@ -138,4 +138,4 @@
30061 am_remove_task (Task ID|1|5), (Stack ID|1|5)
# The task is being compacted
-30063 am_compact (Pid|1|5),(Process Name|3),(Action|3),(BeforeRssTotal|2|2),(BeforeRssFile|2|2),(BeforeRssAnon|2|2),(BeforeRssSwap|2|2),(AfterRssTotal|2|2),(AfterRssFile|2|2),(AfterRssAnon|2|2),(AfterRssSwap|2|2),(Time|2|3),(LastAction|1|2),(LastActionTimestamp|2|3),(setAdj|1|2),(procState|1|2)
+30063 am_compact (Pid|1|5),(Process Name|3),(Action|3),(BeforeRssTotal|2|2),(BeforeRssFile|2|2),(BeforeRssAnon|2|2),(BeforeRssSwap|2|2),(AfterRssTotal|2|2),(AfterRssFile|2|2),(AfterRssAnon|2|2),(AfterRssSwap|2|2),(Time|2|3),(LastAction|1|2),(LastActionTimestamp|2|3),(setAdj|1|2),(procState|1|2),(BeforeZRAMFree|2|2),(AfterZRAMFree|2|2)
diff --git a/services/core/java/com/android/server/am/PendingIntentRecord.java b/services/core/java/com/android/server/am/PendingIntentRecord.java
index af56352..a08c829 100644
--- a/services/core/java/com/android/server/am/PendingIntentRecord.java
+++ b/services/core/java/com/android/server/am/PendingIntentRecord.java
@@ -423,9 +423,9 @@
// If a completion callback has been requested, require
// that the broadcast be delivered synchronously
int sent = controller.mAmInternal.broadcastIntentInPackage(key.packageName,
- uid, finalIntent, resolvedType, finishedReceiver, code, null, null,
- requiredPermission, options, (finishedReceiver != null),
- false, userId,
+ uid, callingUid, callingPid, finalIntent, resolvedType,
+ finishedReceiver, code, null, null, requiredPermission, options,
+ (finishedReceiver != null), false, userId,
mAllowBgActivityStartsForBroadcastSender.contains(whitelistToken)
|| allowTrampoline);
if (sent == ActivityManager.BROADCAST_SUCCESS) {
diff --git a/services/core/java/com/android/server/am/PreBootBroadcaster.java b/services/core/java/com/android/server/am/PreBootBroadcaster.java
index 3ea1147..376999d 100644
--- a/services/core/java/com/android/server/am/PreBootBroadcaster.java
+++ b/services/core/java/com/android/server/am/PreBootBroadcaster.java
@@ -27,6 +27,7 @@
import android.content.IIntentReceiver;
import android.content.Intent;
import android.content.pm.ResolveInfo;
+import android.os.Binder;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
@@ -108,7 +109,7 @@
mIntent.setComponent(componentName);
mService.broadcastIntentLocked(null, null, mIntent, null, this, 0, null, null, null,
AppOpsManager.OP_NONE, null, true, false, ActivityManagerService.MY_PID,
- Process.SYSTEM_UID, mUserId);
+ Process.SYSTEM_UID, Binder.getCallingUid(), Binder.getCallingPid(), mUserId);
}
@Override
diff --git a/services/core/java/com/android/server/am/ProcessList.java b/services/core/java/com/android/server/am/ProcessList.java
index 0d49e4c..3a61dd9 100644
--- a/services/core/java/com/android/server/am/ProcessList.java
+++ b/services/core/java/com/android/server/am/ProcessList.java
@@ -1498,6 +1498,13 @@
// Also turn on CheckJNI for debuggable apps. It's quite
// awkward to turn on otherwise.
runtimeFlags |= Zygote.DEBUG_ENABLE_CHECKJNI;
+
+ // Check if the developer does not want ART verification
+ if (android.provider.Settings.Global.getInt(mService.mContext.getContentResolver(),
+ android.provider.Settings.Global.ART_VERIFIER_VERIFY_DEBUGGABLE, 1) == 0) {
+ runtimeFlags |= Zygote.DISABLE_VERIFIER;
+ Slog.w(TAG_PROCESSES, app + ": ART verification disabled");
+ }
}
// Run the app in safe mode if its manifest requests so or the
// system is booted in safe mode.
@@ -1705,9 +1712,15 @@
zygoteProcesses.remove(app);
if (zygoteProcesses.size() == 0) {
mService.mHandler.removeMessages(KILL_APP_ZYGOTE_MSG);
- Message msg = mService.mHandler.obtainMessage(KILL_APP_ZYGOTE_MSG);
- msg.obj = appZygote;
- mService.mHandler.sendMessageDelayed(msg, KILL_APP_ZYGOTE_DELAY_MS);
+ if (app.removed) {
+ // If we stopped this process because the package hosting it was removed,
+ // there's no point in delaying the app zygote kill.
+ killAppZygoteIfNeededLocked(appZygote);
+ } else {
+ Message msg = mService.mHandler.obtainMessage(KILL_APP_ZYGOTE_MSG);
+ msg.obj = appZygote;
+ mService.mHandler.sendMessageDelayed(msg, KILL_APP_ZYGOTE_DELAY_MS);
+ }
}
}
}
@@ -2162,6 +2175,29 @@
for (int i=0; i<N; i++) {
removeProcessLocked(procs.get(i), callerWillRestart, allowRestart, reason);
}
+ // See if there are any app zygotes running for this packageName / UID combination,
+ // and kill it if so.
+ final ArrayList<AppZygote> zygotesToKill = new ArrayList<>();
+ for (SparseArray<AppZygote> appZygotes : mAppZygotes.getMap().values()) {
+ for (int i = 0; i < appZygotes.size(); ++i) {
+ final int appZygoteUid = appZygotes.keyAt(i);
+ if (userId != UserHandle.USER_ALL && UserHandle.getUserId(appZygoteUid) != userId) {
+ continue;
+ }
+ if (appId >= 0 && UserHandle.getAppId(appZygoteUid) != appId) {
+ continue;
+ }
+ final AppZygote appZygote = appZygotes.valueAt(i);
+ if (packageName != null
+ && !packageName.equals(appZygote.getAppInfo().packageName)) {
+ continue;
+ }
+ zygotesToKill.add(appZygote);
+ }
+ }
+ for (AppZygote appZygote : zygotesToKill) {
+ killAppZygoteIfNeededLocked(appZygote);
+ }
mService.updateOomAdjLocked();
return N > 0;
}
diff --git a/services/core/java/com/android/server/am/UserController.java b/services/core/java/com/android/server/am/UserController.java
index 7f6648a..ac20f6c7 100644
--- a/services/core/java/com/android/server/am/UserController.java
+++ b/services/core/java/com/android/server/am/UserController.java
@@ -371,7 +371,8 @@
| Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND);
mInjector.broadcastIntent(intent, null, resultTo, 0, null, null,
new String[]{android.Manifest.permission.RECEIVE_BOOT_COMPLETED},
- AppOpsManager.OP_NONE, null, true, false, MY_PID, SYSTEM_UID, userId);
+ AppOpsManager.OP_NONE, null, true, false, MY_PID, SYSTEM_UID,
+ Binder.getCallingUid(), Binder.getCallingPid(), userId);
}
// We need to delay unlocking managed profiles until the parent user
@@ -471,7 +472,7 @@
Intent.FLAG_RECEIVER_REGISTERED_ONLY | Intent.FLAG_RECEIVER_FOREGROUND);
mInjector.broadcastIntent(unlockedIntent, null, null, 0, null,
null, null, AppOpsManager.OP_NONE, null, false, false, MY_PID, SYSTEM_UID,
- userId);
+ Binder.getCallingUid(), Binder.getCallingPid(), userId);
if (getUserInfo(userId).isManagedProfile()) {
UserInfo parent = mInjector.getUserManager().getProfileParent(userId);
@@ -484,8 +485,8 @@
| Intent.FLAG_RECEIVER_FOREGROUND);
mInjector.broadcastIntent(profileUnlockedIntent,
null, null, 0, null, null, null, AppOpsManager.OP_NONE,
- null, false, false, MY_PID, SYSTEM_UID,
- parent.id);
+ null, false, false, MY_PID, SYSTEM_UID, Binder.getCallingUid(),
+ Binder.getCallingPid(), parent.id);
}
}
@@ -543,7 +544,8 @@
mInjector.getUserManager().makeInitialized(userInfo.id);
}
}, 0, null, null, null, AppOpsManager.OP_NONE,
- null, true, false, MY_PID, SYSTEM_UID, userId);
+ null, true, false, MY_PID, SYSTEM_UID, Binder.getCallingUid(),
+ Binder.getCallingPid(), userId);
}
}
@@ -573,7 +575,8 @@
}
}, 0, null, null,
new String[]{android.Manifest.permission.RECEIVE_BOOT_COMPLETED},
- AppOpsManager.OP_NONE, null, true, false, MY_PID, SYSTEM_UID, userId);
+ AppOpsManager.OP_NONE, null, true, false, MY_PID, SYSTEM_UID,
+ Binder.getCallingUid(), Binder.getCallingPid(), userId);
}
int restartUser(final int userId, final boolean foreground) {
@@ -696,7 +699,8 @@
mInjector.broadcastIntent(stoppingIntent,
null, stoppingReceiver, 0, null, null,
new String[]{INTERACT_ACROSS_USERS}, AppOpsManager.OP_NONE,
- null, true, false, MY_PID, SYSTEM_UID, UserHandle.USER_ALL);
+ null, true, false, MY_PID, SYSTEM_UID, Binder.getCallingUid(),
+ Binder.getCallingPid(), UserHandle.USER_ALL);
});
}
}
@@ -735,7 +739,8 @@
mInjector.broadcastIntent(shutdownIntent,
null, shutdownReceiver, 0, null, null, null,
AppOpsManager.OP_NONE,
- null, true, false, MY_PID, SYSTEM_UID, userId);
+ null, true, false, MY_PID, SYSTEM_UID, Binder.getCallingUid(),
+ Binder.getCallingPid(), userId);
}
void finishUserStopped(UserState uss) {
@@ -834,7 +839,8 @@
intent.putExtra(Intent.EXTRA_USER_HANDLE, userId);
mInjector.broadcastIntent(intent,
null, null, 0, null, null, null, AppOpsManager.OP_NONE,
- null, false, false, MY_PID, SYSTEM_UID, UserHandle.USER_ALL);
+ null, false, false, MY_PID, SYSTEM_UID, Binder.getCallingUid(),
+ Binder.getCallingPid(), UserHandle.USER_ALL);
}
/**
@@ -950,6 +956,8 @@
Slog.i(TAG, "Starting userid:" + userId + " fg:" + foreground);
+ final int callingUid = Binder.getCallingUid();
+ final int callingPid = Binder.getCallingPid();
final long ident = Binder.clearCallingIdentity();
try {
final int oldUserId = getCurrentUserId();
@@ -1088,7 +1096,7 @@
intent.putExtra(Intent.EXTRA_USER_HANDLE, userId);
mInjector.broadcastIntent(intent,
null, null, 0, null, null, null, AppOpsManager.OP_NONE,
- null, false, false, MY_PID, SYSTEM_UID, userId);
+ null, false, false, MY_PID, SYSTEM_UID, callingUid, callingPid, userId);
}
if (foreground) {
@@ -1111,7 +1119,8 @@
}
}, 0, null, null,
new String[]{INTERACT_ACROSS_USERS}, AppOpsManager.OP_NONE,
- null, true, false, MY_PID, SYSTEM_UID, UserHandle.USER_ALL);
+ null, true, false, MY_PID, SYSTEM_UID, callingUid, callingPid,
+ UserHandle.USER_ALL);
}
} finally {
Binder.restoreCallingIdentity(ident);
@@ -1427,6 +1436,8 @@
}
void sendUserSwitchBroadcasts(int oldUserId, int newUserId) {
+ final int callingUid = Binder.getCallingUid();
+ final int callingPid = Binder.getCallingPid();
long ident = Binder.clearCallingIdentity();
try {
Intent intent;
@@ -1442,7 +1453,8 @@
intent.putExtra(Intent.EXTRA_USER_HANDLE, profileUserId);
mInjector.broadcastIntent(intent,
null, null, 0, null, null, null, AppOpsManager.OP_NONE,
- null, false, false, MY_PID, SYSTEM_UID, profileUserId);
+ null, false, false, MY_PID, SYSTEM_UID, callingUid, callingPid,
+ profileUserId);
}
}
if (newUserId >= 0) {
@@ -1457,7 +1469,8 @@
intent.putExtra(Intent.EXTRA_USER_HANDLE, profileUserId);
mInjector.broadcastIntent(intent,
null, null, 0, null, null, null, AppOpsManager.OP_NONE,
- null, false, false, MY_PID, SYSTEM_UID, profileUserId);
+ null, false, false, MY_PID, SYSTEM_UID, callingUid, callingPid,
+ profileUserId);
}
intent = new Intent(Intent.ACTION_USER_SWITCHED);
intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY
@@ -1466,8 +1479,8 @@
mInjector.broadcastIntent(intent,
null, null, 0, null, null,
new String[] {android.Manifest.permission.MANAGE_USERS},
- AppOpsManager.OP_NONE, null, false, false, MY_PID, SYSTEM_UID,
- UserHandle.USER_ALL);
+ AppOpsManager.OP_NONE, null, false, false, MY_PID, SYSTEM_UID, callingUid,
+ callingPid, UserHandle.USER_ALL);
}
} finally {
Binder.restoreCallingIdentity(ident);
@@ -2107,12 +2120,14 @@
protected int broadcastIntent(Intent intent, String resolvedType,
IIntentReceiver resultTo, int resultCode, String resultData,
Bundle resultExtras, String[] requiredPermissions, int appOp, Bundle bOptions,
- boolean ordered, boolean sticky, int callingPid, int callingUid, int userId) {
+ boolean ordered, boolean sticky, int callingPid, int callingUid, int realCallingUid,
+ int realCallingPid, int userId) {
// TODO b/64165549 Verify that mLock is not held before calling AMS methods
synchronized (mService) {
return mService.broadcastIntentLocked(null, null, intent, resolvedType, resultTo,
resultCode, resultData, resultExtras, requiredPermissions, appOp, bOptions,
- ordered, sticky, callingPid, callingUid, userId);
+ ordered, sticky, callingPid, callingUid, realCallingUid, realCallingPid,
+ userId);
}
}
diff --git a/services/core/java/com/android/server/appop/AppOpsService.java b/services/core/java/com/android/server/appop/AppOpsService.java
index 0e33090..70c28a8 100644
--- a/services/core/java/com/android/server/appop/AppOpsService.java
+++ b/services/core/java/com/android/server/appop/AppOpsService.java
@@ -38,6 +38,7 @@
import android.app.AppGlobals;
import android.app.AppOpsManager;
import android.app.AppOpsManager.HistoricalOps;
+import android.app.AppOpsManager.HistoricalOpsRequest;
import android.app.AppOpsManagerInternal;
import android.app.AppOpsManagerInternal.CheckOpsDelegate;
import android.content.BroadcastReceiver;
@@ -1024,25 +1025,29 @@
@Override
public void getHistoricalOps(int uid, @NonNull String packageName,
- @Nullable String[] opNames, long beginTimeMillis, long endTimeMillis,
+ @Nullable List<String> opNames, long beginTimeMillis, long endTimeMillis,
@NonNull RemoteCallback callback) {
- Preconditions.checkArgument(uid == Process.INVALID_UID || uid >= 0,
- "uid must be " + Process.INVALID_UID + " or non negative");
- Preconditions.checkArgument(beginTimeMillis >= 0 && beginTimeMillis < endTimeMillis,
- "beginTimeMillis must be non negative and lesser than endTimeMillis");
+ // Use the builder to validate arguments.
+ final HistoricalOpsRequest request = new HistoricalOpsRequest.Builder(
+ beginTimeMillis, endTimeMillis)
+ .setUid(uid)
+ .setPackageName(packageName)
+ .setOpNames(opNames)
+ .build();
Preconditions.checkNotNull(callback, "callback cannot be null");
- checkValidOpsOrNull(opNames);
mContext.enforcePermission(android.Manifest.permission.GET_APP_OPS_STATS,
Binder.getCallingPid(), Binder.getCallingUid(), "getHistoricalOps");
+ final String[] opNamesArray = (opNames != null)
+ ? opNames.toArray(new String[opNames.size()]) : null;
if (mHistoricalRegistry.getMode() == AppOpsManager.HISTORICAL_MODE_DISABLED) {
// TODO (bug:122218838): Remove once the feature fully enabled.
- getHistoricalPackagesOpsCompat(uid, packageName, opNames, beginTimeMillis,
+ getHistoricalPackagesOpsCompat(uid, packageName, opNamesArray, beginTimeMillis,
endTimeMillis, callback);
} else {
// Must not hold the appops lock
- mHistoricalRegistry.getHistoricalOps(uid, packageName, opNames,
+ mHistoricalRegistry.getHistoricalOps(uid, packageName, opNamesArray,
beginTimeMillis, endTimeMillis, callback);
}
}
@@ -1101,20 +1106,25 @@
@Override
public void getHistoricalOpsFromDiskRaw(int uid, @NonNull String packageName,
- @Nullable String[] opNames, long beginTimeMillis, long endTimeMillis,
+ @Nullable List<String> opNames, long beginTimeMillis, long endTimeMillis,
@NonNull RemoteCallback callback) {
- Preconditions.checkArgument(uid == Process.INVALID_UID || uid >= 0,
- "uid must be " + Process.INVALID_UID + " or non negative");
- Preconditions.checkArgument(beginTimeMillis >= 0 && beginTimeMillis < endTimeMillis,
- "beginTimeMillis must be non negative and lesser than endTimeMillis");
+ // Use the builder to validate arguments.
+ final HistoricalOpsRequest request = new HistoricalOpsRequest.Builder(
+ beginTimeMillis, endTimeMillis)
+ .setUid(uid)
+ .setPackageName(packageName)
+ .setOpNames(opNames)
+ .build();
Preconditions.checkNotNull(callback, "callback cannot be null");
- checkValidOpsOrNull(opNames);
mContext.enforcePermission(android.Manifest.permission.GET_APP_OPS_STATS,
Binder.getCallingPid(), Binder.getCallingUid(), "getHistoricalOps");
+ final String[] opNamesArray = (opNames != null)
+ ? opNames.toArray(new String[opNames.size()]) : null;
+
// Must not hold the appops lock
- mHistoricalRegistry.getHistoricalOpsFromDiskRaw(uid, packageName, opNames,
+ mHistoricalRegistry.getHistoricalOpsFromDiskRaw(uid, packageName, opNamesArray,
beginTimeMillis, endTimeMillis, callback);
}
@@ -4266,16 +4276,6 @@
return packageNames;
}
- private static void checkValidOpsOrNull(String[] opNames) {
- if (opNames != null) {
- for (String opName : opNames) {
- if (AppOpsManager.strOpToOp(opName) == AppOpsManager.OP_NONE) {
- throw new IllegalArgumentException("Unknown op: " + opName);
- }
- }
- }
- }
-
private final class ClientRestrictionState implements DeathRecipient {
private final IBinder token;
SparseArray<boolean[]> perUserRestrictions;
diff --git a/services/core/java/com/android/server/connectivity/Vpn.java b/services/core/java/com/android/server/connectivity/Vpn.java
index da547ea..59fffb4 100644
--- a/services/core/java/com/android/server/connectivity/Vpn.java
+++ b/services/core/java/com/android/server/connectivity/Vpn.java
@@ -918,6 +918,7 @@
TreeSet<IpPrefix> ipv4Prefixes = new TreeSet<>(prefixLengthComparator);
TreeSet<IpPrefix> ipv6Prefixes = new TreeSet<>(prefixLengthComparator);
for (final RouteInfo route : routes) {
+ if (route.getType() == RouteInfo.RTN_UNREACHABLE) continue;
IpPrefix destination = route.getDestination();
if (destination.isIPv4()) {
ipv4Prefixes.add(destination);
diff --git a/services/core/java/com/android/server/display/OverlayDisplayAdapter.java b/services/core/java/com/android/server/display/OverlayDisplayAdapter.java
index e65637f..2f507d1 100644
--- a/services/core/java/com/android/server/display/OverlayDisplayAdapter.java
+++ b/services/core/java/com/android/server/display/OverlayDisplayAdapter.java
@@ -308,7 +308,7 @@
mInfo.flags |= DisplayDeviceInfo.FLAG_SECURE;
}
mInfo.type = Display.TYPE_OVERLAY;
- mInfo.touch = DisplayDeviceInfo.TOUCH_NONE;
+ mInfo.touch = DisplayDeviceInfo.TOUCH_VIRTUAL;
mInfo.state = mState;
}
return mInfo;
diff --git a/services/core/java/com/android/server/input/InputForwarder.java b/services/core/java/com/android/server/input/InputForwarder.java
deleted file mode 100644
index 00af839..0000000
--- a/services/core/java/com/android/server/input/InputForwarder.java
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License
- */
-
-package com.android.server.input;
-
-import android.app.IInputForwarder;
-import android.hardware.input.InputManagerInternal;
-import android.view.InputEvent;
-
-import com.android.server.LocalServices;
-
-import static android.hardware.input.InputManager.INJECT_INPUT_EVENT_MODE_ASYNC;
-
-/**
- * Basic implementation of {@link IInputForwarder}.
- */
-class InputForwarder extends IInputForwarder.Stub {
-
- private final InputManagerInternal mInputManagerInternal;
- private final int mDisplayId;
-
- InputForwarder(int displayId) {
- mDisplayId = displayId;
- mInputManagerInternal = LocalServices.getService(InputManagerInternal.class);
- }
-
- @Override
- public boolean forwardEvent(InputEvent event) {
- event.setDisplayId(mDisplayId);
- return mInputManagerInternal.injectInputEvent(event, INJECT_INPUT_EVENT_MODE_ASYNC);
- }
-}
\ No newline at end of file
diff --git a/services/core/java/com/android/server/input/InputManagerService.java b/services/core/java/com/android/server/input/InputManagerService.java
index 28393a2..87c7441 100644
--- a/services/core/java/com/android/server/input/InputManagerService.java
+++ b/services/core/java/com/android/server/input/InputManagerService.java
@@ -17,7 +17,6 @@
package com.android.server.input;
import android.annotation.NonNull;
-import android.app.IInputForwarder;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
@@ -1685,29 +1684,6 @@
nativeMonitor(mPtr);
}
- // Binder call
- @Override
- public IInputForwarder createInputForwarder(int displayId) throws RemoteException {
- if (!checkCallingPermission(android.Manifest.permission.INJECT_EVENTS,
- "createInputForwarder()")) {
- throw new SecurityException("Requires INJECT_EVENTS permission");
- }
- final DisplayManager displayManager = mContext.getSystemService(DisplayManager.class);
- final Display display = displayManager.getDisplay(displayId);
- if (display == null) {
- throw new IllegalArgumentException(
- "Can't create input forwarder for non-existent displayId: " + displayId);
- }
- final int callingUid = Binder.getCallingUid();
- final int displayOwnerUid = display.getOwnerUid();
- if (callingUid != displayOwnerUid) {
- throw new SecurityException(
- "Only owner of the display can forward input events to it.");
- }
-
- return new InputForwarder(displayId);
- }
-
// Native callback.
private void notifyConfigurationChanged(long whenNanos) {
mWindowManagerCallbacks.notifyConfigurationChanged();
diff --git a/services/core/java/com/android/server/locksettings/recoverablekeystore/certificate/CertXml.java b/services/core/java/com/android/server/locksettings/recoverablekeystore/certificate/CertXml.java
index c62a31e..ff22a8d 100644
--- a/services/core/java/com/android/server/locksettings/recoverablekeystore/certificate/CertXml.java
+++ b/services/core/java/com/android/server/locksettings/recoverablekeystore/certificate/CertXml.java
@@ -20,6 +20,8 @@
import com.android.internal.annotations.VisibleForTesting;
+import org.w3c.dom.Element;
+
import java.security.SecureRandom;
import java.security.cert.CertPath;
import java.security.cert.X509Certificate;
@@ -28,8 +30,6 @@
import java.util.Date;
import java.util.List;
-import org.w3c.dom.Element;
-
/**
* Parses and holds the XML file containing the list of THM public-key certificates and related
* metadata.
@@ -38,24 +38,20 @@
private static final String METADATA_NODE_TAG = "metadata";
private static final String METADATA_SERIAL_NODE_TAG = "serial";
- private static final String METADATA_REFRESH_INTERVAL_NODE_TAG = "refresh-interval";
private static final String ENDPOINT_CERT_LIST_TAG = "endpoints";
private static final String ENDPOINT_CERT_ITEM_TAG = "cert";
private static final String INTERMEDIATE_CERT_LIST_TAG = "intermediates";
private static final String INTERMEDIATE_CERT_ITEM_TAG = "cert";
private final long serial;
- private final long refreshInterval;
private final List<X509Certificate> intermediateCerts;
private final List<X509Certificate> endpointCerts;
private CertXml(
long serial,
- long refreshInterval,
List<X509Certificate> intermediateCerts,
List<X509Certificate> endpointCerts) {
this.serial = serial;
- this.refreshInterval = refreshInterval;
this.intermediateCerts = intermediateCerts;
this.endpointCerts = endpointCerts;
}
@@ -65,15 +61,6 @@
return serial;
}
- /**
- * Gets the refresh interval in the XML file containing public-key certificates. The refresh
- * interval denotes the number of seconds that the client should follow to contact the server to
- * refresh the XML file.
- */
- public long getRefreshInterval() {
- return refreshInterval;
- }
-
@VisibleForTesting
List<X509Certificate> getAllIntermediateCerts() {
return intermediateCerts;
@@ -121,7 +108,6 @@
Element rootNode = CertUtils.getXmlRootNode(bytes);
return new CertXml(
parseSerial(rootNode),
- parseRefreshInterval(rootNode),
parseIntermediateCerts(rootNode),
parseEndpointCerts(rootNode));
}
@@ -136,16 +122,6 @@
return Long.parseLong(contents.get(0));
}
- private static long parseRefreshInterval(Element rootNode) throws CertParsingException {
- List<String> contents =
- CertUtils.getXmlNodeContents(
- CertUtils.MUST_EXIST_EXACTLY_ONE,
- rootNode,
- METADATA_NODE_TAG,
- METADATA_REFRESH_INTERVAL_NODE_TAG);
- return Long.parseLong(contents.get(0));
- }
-
private static List<X509Certificate> parseIntermediateCerts(Element rootNode)
throws CertParsingException {
List<String> contents =
diff --git a/services/core/java/com/android/server/pm/ApexManager.java b/services/core/java/com/android/server/pm/ApexManager.java
index dac4b6f..8051abb 100644
--- a/services/core/java/com/android/server/pm/ApexManager.java
+++ b/services/core/java/com/android/server/pm/ApexManager.java
@@ -27,6 +27,7 @@
import android.content.pm.PackageParser.PackageParserException;
import android.os.RemoteException;
import android.os.ServiceManager;
+import android.os.ServiceManager.ServiceNotFoundException;
import android.util.Slog;
import com.android.internal.util.IndentingPrintWriter;
@@ -50,8 +51,12 @@
private final Map<String, PackageInfo> mActivePackagesCache;
ApexManager() {
- mApexService = IApexService.Stub.asInterface(
- ServiceManager.getService("apexservice"));
+ try {
+ mApexService = IApexService.Stub.asInterface(
+ ServiceManager.getServiceOrThrow("apexservice"));
+ } catch (ServiceNotFoundException e) {
+ throw new IllegalStateException("Required service apexservice not available");
+ }
mActivePackagesCache = populateActivePackagesCache();
}
@@ -151,7 +156,7 @@
}
/**
- * Mark a staged session previously submitted using {@cde submitStagedSession} as ready to be
+ * Mark a staged session previously submitted using {@code submitStagedSession} as ready to be
* applied at next reboot.
*
* @param sessionId the identifier of the {@link PackageInstallerSession} being marked as ready.
@@ -167,6 +172,27 @@
}
/**
+ * Marks a staged session as successful.
+ *
+ * <p>Only activated session can be marked as successful.
+ *
+ * @param sessionId the identifier of the {@link PackageInstallerSession} being marked as
+ * successful.
+ */
+ void markStagedSessionSuccessful(int sessionId) {
+ try {
+ mApexService.markStagedSessionSuccessful(sessionId);
+ } catch (RemoteException re) {
+ Slog.e(TAG, "Unable to contact apexservice", re);
+ throw new RuntimeException(re);
+ } catch (Exception e) {
+ // It is fine to just log an exception in this case. APEXd will be able to recover in
+ // case markStagedSessionSuccessful fails.
+ Slog.e(TAG, "Failed to mark session " + sessionId + " as successful", e);
+ }
+ }
+
+ /**
* Dumps various state information to the provided {@link PrintWriter} object.
*
* @param pw the {@link PrintWriter} object to send information to.
@@ -196,7 +222,7 @@
ipw.increaseIndent();
final ApexSessionInfo[] sessions = mApexService.getSessions();
for (ApexSessionInfo si : sessions) {
- ipw.println("Session ID: " + Integer.toString(si.sessionId));
+ ipw.println("Session ID: " + si.sessionId);
ipw.increaseIndent();
if (si.isUnknown) {
ipw.println("State: UNKNOWN");
@@ -206,8 +232,6 @@
ipw.println("State: STAGED");
} else if (si.isActivated) {
ipw.println("State: ACTIVATED");
- } else if (si.isActivationPendingRetry) {
- ipw.println("State: ACTIVATION PENDING RETRY");
} else if (si.isActivationFailed) {
ipw.println("State: ACTIVATION FAILED");
}
diff --git a/services/core/java/com/android/server/pm/DynamicCodeLoggingService.java b/services/core/java/com/android/server/pm/DynamicCodeLoggingService.java
index 5b765df..d53d81c 100644
--- a/services/core/java/com/android/server/pm/DynamicCodeLoggingService.java
+++ b/services/core/java/com/android/server/pm/DynamicCodeLoggingService.java
@@ -28,7 +28,7 @@
import android.util.EventLog;
import android.util.Log;
-import com.android.server.pm.dex.DexLogger;
+import com.android.server.pm.dex.DynamicCodeLogger;
import java.util.ArrayList;
import java.util.List;
@@ -38,9 +38,10 @@
/**
* Scheduled jobs related to logging of app dynamic code loading. The idle logging job runs daily
- * while idle and charging and calls {@link DexLogger} to write dynamic code information to the
- * event log. The audit watching job scans the event log periodically while idle to find AVC audit
- * messages indicating use of dynamic native code and adds the information to {@link DexLogger}.
+ * while idle and charging and calls {@link DynamicCodeLogger} to write dynamic code information
+ * to the event log. The audit watching job scans the event log periodically while idle to find AVC
+ * audit messages indicating use of dynamic native code and adds the information to
+ * {@link DynamicCodeLogger}.
* {@hide}
*/
public class DynamicCodeLoggingService extends JobService {
@@ -130,9 +131,9 @@
}
}
- private static DexLogger getDexLogger() {
+ private static DynamicCodeLogger getDynamicCodeLogger() {
PackageManagerService pm = (PackageManagerService) ServiceManager.getService("package");
- return pm.getDexManager().getDexLogger();
+ return pm.getDexManager().getDynamicCodeLogger();
}
private class IdleLoggingThread extends Thread {
@@ -149,14 +150,14 @@
Log.d(TAG, "Starting IdleLoggingJob run");
}
- DexLogger dexLogger = getDexLogger();
- for (String packageName : dexLogger.getAllPackagesWithDynamicCodeLoading()) {
+ DynamicCodeLogger dynamicCodeLogger = getDynamicCodeLogger();
+ for (String packageName : dynamicCodeLogger.getAllPackagesWithDynamicCodeLoading()) {
if (mIdleLoggingStopRequested) {
Log.w(TAG, "Stopping IdleLoggingJob run at scheduler request");
return;
}
- dexLogger.logDynamicCodeLoading(packageName);
+ dynamicCodeLogger.logDynamicCodeLoading(packageName);
}
jobFinished(mParams, /* reschedule */ false);
@@ -191,7 +192,7 @@
private boolean processAuditEvents() {
// Scan the event log for SELinux (avc) audit messages indicating when an
// (untrusted) app has executed native code from an app data
- // file. Matches are recorded in DexLogger.
+ // file. Matches are recorded in DynamicCodeLogger.
//
// These messages come from the kernel audit system via logd. (Note that
// some devices may not generate these messages at all, or the format may
@@ -213,7 +214,7 @@
// On each run we process all the matching events in the log. This may
// mean re-processing events we have already seen, and in any case there
// may be duplicate events for the same app+file. These are de-duplicated
- // by DexLogger.
+ // by DynamicCodeLogger.
//
// Note that any app can write a message to the event log, including one
// that looks exactly like an AVC audit message, so the information may
@@ -228,7 +229,7 @@
return true;
}
- DexLogger dexLogger = getDexLogger();
+ DynamicCodeLogger dynamicCodeLogger = getDynamicCodeLogger();
List<EventLog.Event> events = new ArrayList<>();
EventLog.readEvents(tags, events);
@@ -267,7 +268,7 @@
// hex-encodes the bytes; we need to undo that.
path = unhex(matcher.group(2));
}
- dexLogger.recordNative(uid, path);
+ dynamicCodeLogger.recordNative(uid, path);
}
return true;
diff --git a/services/core/java/com/android/server/pm/OWNERS b/services/core/java/com/android/server/pm/OWNERS
index 640b155..8ce2568 100644
--- a/services/core/java/com/android/server/pm/OWNERS
+++ b/services/core/java/com/android/server/pm/OWNERS
@@ -9,6 +9,10 @@
toddke@android.com
toddke@google.com
+# apex support
+per-file ApexManager.java = dariofreni@google.com, narayan@google.com, toddke@android.com, toddke@google.com
+per-file StagingManager.java = dariofreni@google.com, narayan@google.com, toddke@android.com, toddke@google.com
+
# dex
per-file AbstractStatsBase.java = agampe@google.com
per-file AbstractStatsBase.java = calin@google.com
diff --git a/services/core/java/com/android/server/pm/StagingManager.java b/services/core/java/com/android/server/pm/StagingManager.java
index 6c212d6..d1ebc94 100644
--- a/services/core/java/com/android/server/pm/StagingManager.java
+++ b/services/core/java/com/android/server/pm/StagingManager.java
@@ -247,7 +247,8 @@
}
private void resumeSession(@NonNull PackageInstallerSession session) {
- if (sessionContainsApex(session)) {
+ boolean hasApex = sessionContainsApex(session);
+ if (hasApex) {
// Check with apexservice whether the apex packages have been activated.
ApexSessionInfo apexSessionInfo = mApexManager.getStagedSessionInfo(session.sessionId);
if (apexSessionInfo == null) {
@@ -271,7 +272,7 @@
mBgHandler.post(() -> preRebootVerification(session));
return;
}
- if (!apexSessionInfo.isActivated) {
+ if (!apexSessionInfo.isActivated && !apexSessionInfo.isSuccess) {
// In all the remaining cases apexd will try to apply the session again at next
// boot. Nothing to do here for now.
Slog.w(TAG, "Staged session " + session.sessionId + " scheduled to be applied "
@@ -287,7 +288,11 @@
+ "more information.");
return;
}
+
session.setStagedSessionApplied();
+ if (hasApex) {
+ mApexManager.markStagedSessionSuccessful(session.sessionId);
+ }
}
private String findFirstAPKInDir(File stageDir) {
diff --git a/services/core/java/com/android/server/pm/dex/DexManager.java b/services/core/java/com/android/server/pm/dex/DexManager.java
index ee6995b..3b805d51 100644
--- a/services/core/java/com/android/server/pm/dex/DexManager.java
+++ b/services/core/java/com/android/server/pm/dex/DexManager.java
@@ -86,11 +86,11 @@
// encode and save the dex usage data.
private final PackageDexUsage mPackageDexUsage;
- // DexLogger handles recording of dynamic code loading - which is similar to PackageDexUsage
- // but records a different aspect of the data.
+ // DynamicCodeLogger handles recording of dynamic code loading - which is similar to
+ // PackageDexUsage but records a different aspect of the data.
// (It additionally includes DEX files loaded with unsupported class loaders, and doesn't
// record class loaders or ISAs.)
- private final DexLogger mDexLogger;
+ private final DynamicCodeLogger mDynamicCodeLogger;
private final IPackageManager mPackageManager;
private final PackageDexOptimizer mPackageDexOptimizer;
@@ -126,11 +126,11 @@
mPackageDexOptimizer = pdo;
mInstaller = installer;
mInstallLock = installLock;
- mDexLogger = new DexLogger(pms, installer);
+ mDynamicCodeLogger = new DynamicCodeLogger(pms, installer);
}
- public DexLogger getDexLogger() {
- return mDexLogger;
+ public DynamicCodeLogger getDynamicCodeLogger() {
+ return mDynamicCodeLogger;
}
/**
@@ -230,8 +230,8 @@
if (!primaryOrSplit) {
// Record loading of a DEX file from an app data directory.
- mDexLogger.recordDex(loaderUserId, dexPath, searchResult.mOwningPackageName,
- loadingAppInfo.packageName);
+ mDynamicCodeLogger.recordDex(loaderUserId, dexPath,
+ searchResult.mOwningPackageName, loadingAppInfo.packageName);
}
if (classLoaderContexts != null) {
@@ -269,7 +269,7 @@
loadInternal(existingPackages);
} catch (Exception e) {
mPackageDexUsage.clear();
- mDexLogger.clear();
+ mDynamicCodeLogger.clear();
Slog.w(TAG, "Exception while loading. Starting with a fresh state.", e);
}
}
@@ -320,12 +320,12 @@
if (mPackageDexUsage.removePackage(packageName)) {
mPackageDexUsage.maybeWriteAsync();
}
- mDexLogger.removePackage(packageName);
+ mDynamicCodeLogger.removePackage(packageName);
} else {
if (mPackageDexUsage.removeUserPackage(packageName, userId)) {
mPackageDexUsage.maybeWriteAsync();
}
- mDexLogger.removeUserPackage(packageName, userId);
+ mDynamicCodeLogger.removeUserPackage(packageName, userId);
}
}
@@ -404,9 +404,9 @@
}
try {
- mDexLogger.readAndSync(packageToUsersMap);
+ mDynamicCodeLogger.readAndSync(packageToUsersMap);
} catch (Exception e) {
- mDexLogger.clear();
+ mDynamicCodeLogger.clear();
Slog.w(TAG, "Exception while loading package dynamic code usage. "
+ "Starting with a fresh state.", e);
}
@@ -692,7 +692,7 @@
*/
public void writePackageDexUsageNow() {
mPackageDexUsage.writeNow();
- mDexLogger.writeNow();
+ mDynamicCodeLogger.writeNow();
}
/**
diff --git a/services/core/java/com/android/server/pm/dex/DexLogger.java b/services/core/java/com/android/server/pm/dex/DynamicCodeLogger.java
similarity index 95%
rename from services/core/java/com/android/server/pm/dex/DexLogger.java
rename to services/core/java/com/android/server/pm/dex/DynamicCodeLogger.java
index 59cc0cf..2c75bcd 100644
--- a/services/core/java/com/android/server/pm/dex/DexLogger.java
+++ b/services/core/java/com/android/server/pm/dex/DynamicCodeLogger.java
@@ -11,7 +11,7 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
package com.android.server.pm.dex;
@@ -44,12 +44,12 @@
import java.util.Set;
/**
- * This class is responsible for logging data about secondary dex files and, despite the name,
- * native code executed from an app's private directory. The data logged includes hashes of the
- * name and content of each file.
+ * This class is responsible for logging data about secondary dex files and native code executed
+ * from an app's private directory. The data logged includes hashes of the name and content of each
+ * file.
*/
-public class DexLogger {
- private static final String TAG = "DexLogger";
+public class DynamicCodeLogger {
+ private static final String TAG = "DynamicCodeLogger";
// Event log tag & subtags used for SafetyNet logging of dynamic code loading (DCL) -
// see b/63927552.
@@ -61,12 +61,12 @@
private final PackageDynamicCodeLoading mPackageDynamicCodeLoading;
private final Installer mInstaller;
- public DexLogger(IPackageManager pms, Installer installer) {
+ DynamicCodeLogger(IPackageManager pms, Installer installer) {
this(pms, installer, new PackageDynamicCodeLoading());
}
@VisibleForTesting
- DexLogger(IPackageManager pms, Installer installer,
+ DynamicCodeLogger(IPackageManager pms, Installer installer,
PackageDynamicCodeLoading packageDynamicCodeLoading) {
mPackageManager = pms;
mPackageDynamicCodeLoading = packageDynamicCodeLoading;
@@ -217,7 +217,7 @@
/**
* Record that an app running in the specified uid has executed native code from the file at
- * {@link path}.
+ * {@param path}.
*/
public void recordNative(int loadingUid, String path) {
String[] packages;
diff --git a/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java b/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java
index bd577598..dacc6cd 100644
--- a/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java
+++ b/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java
@@ -1462,14 +1462,15 @@
outGrantExceptions.get(packageName);
if (packageExceptions == null) {
// The package must be on the system image
- if (!isSystemPackage(packageName)) {
- Log.w(TAG, "Unknown package:" + packageName);
+ PackageInfo packageInfo = getSystemPackageInfo(packageName);
+ if (!isSystemPackage(packageInfo)) {
+ Log.w(TAG, "Unknown system package:" + packageName);
XmlUtils.skipCurrentTag(parser);
continue;
}
// The package must support runtime permissions
- if (!doesPackageSupportRuntimePermissions(getSystemPackageInfo(packageName))) {
+ if (!doesPackageSupportRuntimePermissions(packageInfo)) {
Log.w(TAG, "Skipping non supporting runtime permissions package:"
+ packageName);
XmlUtils.skipCurrentTag(parser);
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 f56b984..8df5a71 100644
--- a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
+++ b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
@@ -1181,11 +1181,9 @@
@NonNull int[] updatedUserIds) {
AppOpsManager appOpsManager = mContext.getSystemService(AppOpsManager.class);
- if (pkg.applicationInfo.targetSdkVersion < Build.VERSION_CODES.M) {
- return updatedUserIds;
- }
-
String pkgName = pkg.packageName;
+ boolean supportsRuntimePermissions = pkg.applicationInfo.targetSdkVersion
+ >= Build.VERSION_CODES.M;
int[] users = UserManagerService.getInstance().getUserIds();
int numUsers = users.length;
@@ -1210,15 +1208,17 @@
if ((flags & (FLAG_PERMISSION_GRANTED_BY_DEFAULT
| FLAG_PERMISSION_POLICY_FIXED | FLAG_PERMISSION_SYSTEM_FIXED))
== 0) {
- int revokeResult = ps.revokeRuntimePermission(bp, userId);
- if (revokeResult
- != PERMISSION_OPERATION_FAILURE) {
-
- if (DEBUG_PERMISSIONS) {
- Slog.i(TAG, "Revoking runtime permission " + permission
- + " for " + pkgName
- + " as it is now requested");
+ if (supportsRuntimePermissions) {
+ int revokeResult = ps.revokeRuntimePermission(bp, userId);
+ if (revokeResult != PERMISSION_OPERATION_FAILURE) {
+ if (DEBUG_PERMISSIONS) {
+ Slog.i(TAG, "Revoking runtime permission "
+ + permission + " for " + pkgName
+ + " as it is now requested");
+ }
}
+ } else {
+ setAppOpMode(permission, pkg, userId, MODE_IGNORED);
}
List<String> fgPerms = mBackgroundPermissions.get(permission);
diff --git a/services/core/java/com/android/server/power/PowerManagerService.java b/services/core/java/com/android/server/power/PowerManagerService.java
index 1782b6a..176dbbf 100644
--- a/services/core/java/com/android/server/power/PowerManagerService.java
+++ b/services/core/java/com/android/server/power/PowerManagerService.java
@@ -538,6 +538,9 @@
// True if we are currently in VR Mode.
private boolean mIsVrModeEnabled;
+ // True if we in the process of performing a forceSuspend
+ private boolean mForceSuspendActive;
+
private final class ForegroundProfileObserver extends SynchronousUserSwitchObserver {
@Override
public void onUserSwitching(int newUserId) throws RemoteException {}
@@ -684,6 +687,11 @@
public void nativeSetFeature(int featureId, int data) {
PowerManagerService.nativeSetFeature(featureId, data);
}
+
+ /** Wrapper for PowerManager.nativeForceSuspend */
+ public boolean nativeForceSuspend() {
+ return PowerManagerService.nativeForceSuspend();
+ }
}
@VisibleForTesting
@@ -718,6 +726,7 @@
private static native void nativeSetAutoSuspend(boolean enable);
private static native void nativeSendPowerHint(int hintId, int data);
private static native void nativeSetFeature(int featureId, int data);
+ private static native boolean nativeForceSuspend();
public PowerManagerService(Context context) {
this(context, new Injector());
@@ -1427,7 +1436,7 @@
}
if (eventTime < mLastSleepTime || mWakefulness == WAKEFULNESS_AWAKE
- || !mBootCompleted || !mSystemReady) {
+ || !mBootCompleted || !mSystemReady || mForceSuspendActive) {
return false;
}
@@ -1463,8 +1472,13 @@
}
}
- // This method is called goToSleep for historical reasons but we actually start
- // dozing before really going to sleep.
+ /**
+ * Puts the system in doze.
+ *
+ * This method is called goToSleep for historical reasons but actually attempts to DOZE,
+ * and only tucks itself in to SLEEP if requested with the flag
+ * {@link PowerManager.GO_TO_SLEEP_FLAG_NO_DOZE}.
+ */
@SuppressWarnings("deprecation")
private boolean goToSleepNoUpdateLocked(long eventTime, int reason, int flags, int uid) {
if (DEBUG_SPEW) {
@@ -1481,35 +1495,10 @@
Trace.traceBegin(Trace.TRACE_TAG_POWER, "goToSleep");
try {
- switch (reason) {
- case PowerManager.GO_TO_SLEEP_REASON_DEVICE_ADMIN:
- Slog.i(TAG, "Going to sleep due to device administration policy "
- + "(uid " + uid +")...");
- break;
- case PowerManager.GO_TO_SLEEP_REASON_TIMEOUT:
- Slog.i(TAG, "Going to sleep due to screen timeout (uid " + uid +")...");
- break;
- case PowerManager.GO_TO_SLEEP_REASON_LID_SWITCH:
- Slog.i(TAG, "Going to sleep due to lid switch (uid " + uid +")...");
- break;
- case PowerManager.GO_TO_SLEEP_REASON_POWER_BUTTON:
- Slog.i(TAG, "Going to sleep due to power button (uid " + uid +")...");
- break;
- case PowerManager.GO_TO_SLEEP_REASON_SLEEP_BUTTON:
- Slog.i(TAG, "Going to sleep due to sleep button (uid " + uid +")...");
- break;
- case PowerManager.GO_TO_SLEEP_REASON_HDMI:
- Slog.i(TAG, "Going to sleep due to HDMI standby (uid " + uid +")...");
- break;
- case PowerManager.GO_TO_SLEEP_REASON_ACCESSIBILITY:
- Slog.i(TAG, "Going to sleep by an accessibility service request (uid "
- + uid +")...");
- break;
- default:
- Slog.i(TAG, "Going to sleep by application request (uid " + uid +")...");
- reason = PowerManager.GO_TO_SLEEP_REASON_APPLICATION;
- break;
- }
+ reason = Math.min(PowerManager.GO_TO_SLEEP_REASON_MAX,
+ Math.max(reason, PowerManager.GO_TO_SLEEP_REASON_MIN));
+ Slog.i(TAG, "Going to sleep due to " + PowerManager.sleepReasonToString(reason)
+ + " (uid " + uid + ")...");
mLastSleepTime = eventTime;
mLastSleepReason = reason;
@@ -3063,10 +3052,10 @@
if (appid >= Process.FIRST_APPLICATION_UID) {
// Cached inactive processes are never allowed to hold wake locks.
if (mConstants.NO_CACHED_WAKE_LOCKS) {
- disabled = !wakeLock.mUidState.mActive &&
- wakeLock.mUidState.mProcState
+ disabled = mForceSuspendActive
+ || (!wakeLock.mUidState.mActive && wakeLock.mUidState.mProcState
!= ActivityManager.PROCESS_STATE_NONEXISTENT &&
- wakeLock.mUidState.mProcState > ActivityManager.PROCESS_STATE_RECEIVER;
+ wakeLock.mUidState.mProcState > ActivityManager.PROCESS_STATE_RECEIVER);
}
if (mDeviceIdleMode) {
// If we are in idle mode, we will also ignore all partial wake locks that are
@@ -3241,6 +3230,34 @@
}
}
+ private boolean forceSuspendInternal(int uid) {
+ try {
+ synchronized (mLock) {
+ mForceSuspendActive = true;
+ // Place the system in an non-interactive state
+ goToSleepInternal(SystemClock.uptimeMillis(),
+ PowerManager.GO_TO_SLEEP_REASON_FORCE_SUSPEND,
+ PowerManager.GO_TO_SLEEP_FLAG_NO_DOZE, uid);
+
+ // Disable all the partial wake locks as well
+ updateWakeLockDisabledStatesLocked();
+ }
+
+ Slog.i(TAG, "Force-Suspending (uid " + uid + ")...");
+ boolean success = mNativeWrapper.nativeForceSuspend();
+ if (!success) {
+ Slog.i(TAG, "Force-Suspending failed in native.");
+ }
+ return success;
+ } finally {
+ synchronized (mLock) {
+ mForceSuspendActive = false;
+ // Re-enable wake locks once again.
+ updateWakeLockDisabledStatesLocked();
+ }
+ }
+ }
+
/**
* Low-level function turn the device off immediately, without trying
* to be clean. Most people should use {@link ShutdownThread} for a clean shutdown.
@@ -4743,6 +4760,20 @@
}
}
+ @Override // binder call
+ public boolean forceSuspend() {
+ mContext.enforceCallingOrSelfPermission(
+ android.Manifest.permission.DEVICE_POWER, null);
+
+ final int uid = Binder.getCallingUid();
+ final long ident = Binder.clearCallingIdentity();
+ try {
+ return forceSuspendInternal(uid);
+ } finally {
+ Binder.restoreCallingIdentity(ident);
+ }
+ }
+
@Override // Binder call
protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return;
diff --git a/services/core/java/com/android/server/role/RoleManagerService.java b/services/core/java/com/android/server/role/RoleManagerService.java
index d853121..c145a22 100644
--- a/services/core/java/com/android/server/role/RoleManagerService.java
+++ b/services/core/java/com/android/server/role/RoleManagerService.java
@@ -196,7 +196,7 @@
}
performInitialGrantsIfNecessary(userId);
}
- }, UserHandle.SYSTEM, intentFilter, null /* broadcastPermission */, null /* handler */);
+ }, UserHandle.ALL, intentFilter, null, null);
getContext().getContentResolver().registerContentObserver(
Settings.Global.getUriFor(Settings.Global.SMS_ACCESS_RESTRICTION_ENABLED), false,
diff --git a/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java b/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java
index ceaf829..05d3c17 100644
--- a/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java
+++ b/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java
@@ -16,6 +16,7 @@
package com.android.server.rollback;
+import android.annotation.NonNull;
import android.app.AppOpsManager;
import android.content.BroadcastReceiver;
import android.content.Context;
@@ -842,6 +843,7 @@
String packageName = newPackage.packageName;
for (PackageRollbackInfo info : rd.packages) {
if (info.getPackageName().equals(packageName)) {
+ info.getInstalledUsers().addAll(IntArray.wrap(installedUsers));
AppDataRollbackHelper.SnapshotAppDataResult rs =
mAppDataRollbackHelper.snapshotAppData(packageName, installedUsers);
info.getPendingBackups().addAll(rs.pendingBackups);
@@ -874,7 +876,7 @@
* the child sessions, not the parent session.
*/
private boolean enableRollbackForSession(PackageInstaller.SessionInfo session,
- int[] installedUsers, boolean snapshotUserData) {
+ @NonNull int[] installedUsers, boolean snapshotUserData) {
// TODO: Don't attempt to enable rollback for split installs.
final int installFlags = session.installFlags;
if ((installFlags & PackageManager.INSTALL_ENABLE_ROLLBACK) == 0) {
@@ -1016,7 +1018,7 @@
}
if (!session.isMultiPackage()) {
- if (!enableRollbackForSession(session, null, false)) {
+ if (!enableRollbackForSession(session, new int[0], false)) {
Log.e(TAG, "Unable to enable rollback for session: " + sessionId);
result.offer(false);
return;
@@ -1030,7 +1032,7 @@
result.offer(false);
return;
}
- if (!enableRollbackForSession(childSession, null, false)) {
+ if (!enableRollbackForSession(childSession, new int[0], false)) {
Log.e(TAG, "Unable to enable rollback for session: " + sessionId);
result.offer(false);
return;
diff --git a/services/core/java/com/android/server/rollback/TEST_MAPPING b/services/core/java/com/android/server/rollback/TEST_MAPPING
index c1d95ac..6be93a0 100644
--- a/services/core/java/com/android/server/rollback/TEST_MAPPING
+++ b/services/core/java/com/android/server/rollback/TEST_MAPPING
@@ -2,6 +2,9 @@
"presubmit": [
{
"name": "RollbackTest"
+ },
+ {
+ "name": "StagedRollbackTest"
}
]
}
diff --git a/services/core/java/com/android/server/trust/TrustManagerService.java b/services/core/java/com/android/server/trust/TrustManagerService.java
index 423ec4c..c7044a1 100644
--- a/services/core/java/com/android/server/trust/TrustManagerService.java
+++ b/services/core/java/com/android/server/trust/TrustManagerService.java
@@ -366,17 +366,22 @@
} catch (RemoteException e) {
}
- if (mSettingsObserver.getTrustAgentsExtendUnlock()) {
- trusted = trusted && (!showingKeyguard || isFromUnlock) && userId == mCurrentUser;
- if (DEBUG) {
- Slog.d(TAG, "Extend unlock setting trusted as " + Boolean.toString(trusted)
- + " && " + Boolean.toString(!showingKeyguard)
- + " && " + Boolean.toString(userId == mCurrentUser));
- }
- }
-
boolean changed;
synchronized (mUserIsTrusted) {
+ if (mSettingsObserver.getTrustAgentsExtendUnlock()) {
+ // In extend unlock trust agents can only set the device to trusted if it already
+ // trusted or the device is unlocked. Attempting to set the device as trusted
+ // when the device is locked will be ignored.
+ changed = mUserIsTrusted.get(userId) != trusted;
+ trusted = trusted
+ && (!showingKeyguard || isFromUnlock || !changed)
+ && userId == mCurrentUser;
+ if (DEBUG) {
+ Slog.d(TAG, "Extend unlock setting trusted as " + Boolean.toString(trusted)
+ + " && " + Boolean.toString(!showingKeyguard)
+ + " && " + Boolean.toString(userId == mCurrentUser));
+ }
+ }
changed = mUserIsTrusted.get(userId) != trusted;
mUserIsTrusted.put(userId, trusted);
}
diff --git a/services/core/java/com/android/server/utils/FlagNamespaceUtils.java b/services/core/java/com/android/server/utils/FlagNamespaceUtils.java
new file mode 100644
index 0000000..f26121e
--- /dev/null
+++ b/services/core/java/com/android/server/utils/FlagNamespaceUtils.java
@@ -0,0 +1,133 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.utils;
+
+import android.annotation.Nullable;
+import android.provider.DeviceConfig;
+
+import com.android.server.RescueParty;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * Utilities for interacting with the {@link android.provider.DeviceConfig}.
+ *
+ * @hide
+ */
+public final class FlagNamespaceUtils {
+ /**
+ * Special String used for communicating through {@link #RESET_PLATFORM_PACKAGE_FLAG} that
+ * Settings were reset by the RescueParty, no actual namespace with this name exists in
+ * {@link DeviceConfig}.
+ */
+ public static final String NAMESPACE_NO_PACKAGE = "no_package";
+
+ /**
+ * Name of the special namespace in DeviceConfig table used for communicating resets.
+ */
+ private static final String NAMESPACE_RESCUE_PARTY = "rescue_party_namespace";
+ /**
+ * Flag in the {@link DeviceConfig} in {@link #NAMESPACE_RESCUE_PARTY}, holding all known {@link
+ * DeviceConfig} namespaces, as a {@link #DELIMITER} separated String. It's updated after the
+ * first time flags are written to the new namespace in the {@link DeviceConfig}.
+ */
+ private static final String ALL_KNOWN_NAMESPACES_FLAG = "all_known_namespaces";
+ /**
+ * Flag in the {@link DeviceConfig} in {@link #NAMESPACE_RESCUE_PARTY} with integer counter
+ * suffix added to it, holding {@link DeviceConfig} namespace value whose flags were recently
+ * reset by the {@link RescueParty}. It's updated by {@link RescueParty} every time given
+ * namespace flags are reset.
+ */
+ private static final String RESET_PLATFORM_PACKAGE_FLAG = "reset_platform_package";
+ private static final String DELIMITER = ":";
+ /**
+ * Maximum value of the counter used in combination with {@link #RESET_PLATFORM_PACKAGE_FLAG}
+ * when communicating recently reset by the RescueParty namespace values.
+ */
+ private static final int MAX_COUNTER_VALUE = 50;
+
+ private static int sKnownResetNamespacesFlagCounter = -1;
+
+ /**
+ * Sets the union of {@link #RESET_PLATFORM_PACKAGE_FLAG} with
+ * {@link #sKnownResetNamespacesFlagCounter} in the DeviceConfig for each namespace
+ * in the consumed namespacesList. These flags are used for communicating the namespaces
+ * (aka platform packages) whose flags in {@link DeviceConfig} were just reset
+ * by the RescueParty.
+ */
+ public static void addToKnownResetNamespaces(@Nullable List<String> namespacesList) {
+ if (namespacesList == null) {
+ return;
+ }
+ for (String namespace : namespacesList) {
+ addToKnownResetNamespaces(namespace);
+ }
+ }
+
+ /**
+ * Sets the union of {@link #RESET_PLATFORM_PACKAGE_FLAG} with
+ * {@link #sKnownResetNamespacesFlagCounter} in the DeviceConfig for the consumed namespace.
+ * This flag is used for communicating the namespace (aka platform package) whose flags
+ * in {@link DeviceConfig} were just reset by the RescueParty.
+ */
+ public static void addToKnownResetNamespaces(String namespace) {
+ int nextFlagCounter = incrementAndRetrieveResetNamespacesFlagCounter();
+ DeviceConfig.setProperty(NAMESPACE_RESCUE_PARTY,
+ RESET_PLATFORM_PACKAGE_FLAG + nextFlagCounter,
+ namespace, /*makeDefault=*/ true);
+ }
+
+ /**
+ * Reset all namespaces in DeviceConfig with consumed resetMode.
+ */
+ public static void resetDeviceConfig(int resetMode) {
+ List<String> allKnownNamespaces = getAllKnownDeviceConfigNamespacesList();
+ for (String namespace : allKnownNamespaces) {
+ DeviceConfig.resetToDefaults(resetMode, namespace);
+ }
+ addToKnownResetNamespaces(allKnownNamespaces);
+ }
+
+ /**
+ * Returns a list of all known DeviceConfig namespaces, except for the special {@link
+ * #NAMESPACE_RESCUE_PARTY}
+ */
+ private static List<String> getAllKnownDeviceConfigNamespacesList() {
+ String namespacesStr = DeviceConfig.getProperty(NAMESPACE_RESCUE_PARTY,
+ ALL_KNOWN_NAMESPACES_FLAG);
+ List<String> namespacesList = toStringList(namespacesStr);
+ namespacesList.remove(NAMESPACE_RESCUE_PARTY);
+ return namespacesList;
+ }
+
+ private static List<String> toStringList(String serialized) {
+ if (serialized == null || serialized.length() == 0) {
+ return new ArrayList<>();
+ }
+ return Arrays.asList(serialized.split(DELIMITER));
+ }
+
+ private static int incrementAndRetrieveResetNamespacesFlagCounter() {
+ sKnownResetNamespacesFlagCounter++;
+ if (sKnownResetNamespacesFlagCounter == MAX_COUNTER_VALUE) {
+ sKnownResetNamespacesFlagCounter = 0;
+ }
+ return sKnownResetNamespacesFlagCounter;
+ }
+}
diff --git a/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java b/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
index b0ef8a0..071dde7 100644
--- a/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
+++ b/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
@@ -2243,12 +2243,9 @@
synchronized (mLock) {
mInAmbientMode = inAmbientMode;
final WallpaperData data = mWallpaperMap.get(mCurrentUserId);
- final boolean hasConnection = data != null && data.connection != null;
- final WallpaperInfo info = hasConnection ? data.connection.mInfo : null;
-
// The wallpaper info is null for image wallpaper, also use the engine in this case.
- if (hasConnection && (info == null && isAodImageWallpaperEnabled()
- || info != null && info.supportsAmbientMode())) {
+ if (data != null && data.connection != null && (data.connection.mInfo == null
+ || data.connection.mInfo.supportsAmbientMode())) {
// TODO(multi-display) Extends this method with specific display.
engine = data.connection.getDisplayConnectorOrCreate(DEFAULT_DISPLAY).mEngine;
} else {
diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java
index f33c518..087de69 100644
--- a/services/core/java/com/android/server/wm/ActivityRecord.java
+++ b/services/core/java/com/android/server/wm/ActivityRecord.java
@@ -87,8 +87,6 @@
import static android.os.Build.VERSION_CODES.O;
import static android.os.Process.SYSTEM_UID;
import static android.view.Display.INVALID_DISPLAY;
-import static android.view.WindowManagerPolicyConstants.NAV_BAR_LEFT;
-import static android.view.WindowManagerPolicyConstants.NAV_BAR_RIGHT;
import static com.android.server.am.ActivityRecordProto.CONFIGURATION_CONTAINER;
import static com.android.server.am.ActivityRecordProto.FRONT_OF_TASK;
@@ -2828,28 +2826,6 @@
outAppBounds.setEmpty();
}
- // TODO(b/112288258): Remove below calculation because the position information in bounds
- // will be replaced by the offset of surface.
- final Rect appBounds = parentConfig.windowConfiguration.getAppBounds();
- if (appBounds != null) {
- final Rect outBounds = inOutConfig.windowConfiguration.getBounds();
- final int activityWidth = outBounds.width();
- final int navBarPosition = mAtmService.mWindowManager.getNavBarPosition(getDisplayId());
- if (navBarPosition == NAV_BAR_LEFT) {
- // Position the activity frame on the opposite side of the nav bar.
- outBounds.left = appBounds.right - activityWidth;
- outBounds.right = appBounds.right;
- } else if (navBarPosition == NAV_BAR_RIGHT) {
- // Position the activity frame on the opposite side of the nav bar.
- outBounds.left = 0;
- outBounds.right = activityWidth + appBounds.left;
- } else if (appBounds.width() > activityWidth) {
- // Horizontally center the frame.
- outBounds.left = appBounds.left + (appBounds.width() - activityWidth) / 2;
- outBounds.right = outBounds.left + activityWidth;
- }
- }
-
task.computeConfigResourceOverrides(inOutConfig, parentConfig, insideParentBounds);
}
diff --git a/services/core/java/com/android/server/wm/ActivityStackSupervisor.java b/services/core/java/com/android/server/wm/ActivityStackSupervisor.java
index 0a3c2fb..6ffd554 100644
--- a/services/core/java/com/android/server/wm/ActivityStackSupervisor.java
+++ b/services/core/java/com/android/server/wm/ActivityStackSupervisor.java
@@ -978,12 +978,20 @@
r.notifyUnknownVisibilityLaunched();
}
- // Post message to start process to avoid possible deadlock of calling into AMS with the
- // ATMS lock held.
- final Message msg = PooledLambda.obtainMessage(
- ActivityManagerInternal::startProcess, mService.mAmInternal, r.processName,
- r.info.applicationInfo, knownToBeDead, "activity", r.intent.getComponent());
- mService.mH.sendMessage(msg);
+ try {
+ if (Trace.isTagEnabled(TRACE_TAG_ACTIVITY_MANAGER)) {
+ Trace.traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "dispatchingStartProcess:"
+ + r.processName);
+ }
+ // Post message to start process to avoid possible deadlock of calling into AMS with the
+ // ATMS lock held.
+ final Message msg = PooledLambda.obtainMessage(
+ ActivityManagerInternal::startProcess, mService.mAmInternal, r.processName,
+ r.info.applicationInfo, knownToBeDead, "activity", r.intent.getComponent());
+ mService.mH.sendMessage(msg);
+ } finally {
+ Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
+ }
}
boolean checkStartAnyActivityPermission(Intent intent, ActivityInfo aInfo, String resultWho,
@@ -2332,6 +2340,20 @@
if (!task.canBeLaunchedOnDisplay(actualDisplayId)) {
throw new IllegalStateException("Task resolved to incompatible display");
}
+
+ final ActivityDisplay preferredDisplay =
+ mRootActivityContainer.getActivityDisplay(preferredDisplayId);
+
+ final boolean singleTaskInstance = preferredDisplay != null
+ && preferredDisplay.isSingleTaskInstance();
+
+ if (singleTaskInstance) {
+ // Suppress the warning toast if the preferredDisplay was set to singleTask.
+ // The singleTaskInstance displays will only contain one task and any attempt to
+ // launch new task will re-route to the default display.
+ return;
+ }
+
if (preferredDisplayId != actualDisplayId) {
Slog.w(TAG, "Failed to put " + task + " on display " + preferredDisplayId);
// Display a warning toast that we failed to put a task on a secondary display.
diff --git a/services/core/java/com/android/server/wm/ActivityStartController.java b/services/core/java/com/android/server/wm/ActivityStartController.java
index 43c1206..b287a0b 100644
--- a/services/core/java/com/android/server/wm/ActivityStartController.java
+++ b/services/core/java/com/android/server/wm/ActivityStartController.java
@@ -46,6 +46,7 @@
import android.view.RemoteAnimationAdapter;
import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.util.ArrayUtils;
import com.android.server.am.ActivityManagerService;
import com.android.server.am.PendingIntentRecord;
import com.android.server.wm.ActivityStackSupervisor.PendingActivityLaunch;
@@ -368,67 +369,70 @@
}
final long origId = Binder.clearCallingIdentity();
try {
+ intents = ArrayUtils.filterNotNull(intents, Intent[]::new);
+ final ActivityStarter[] starters = new ActivityStarter[intents.length];
+ // Do not hold WM global lock on this loop because when resolving intent, it may
+ // potentially acquire activity manager lock that leads to deadlock.
+ for (int i = 0; i < intents.length; i++) {
+ Intent intent = intents[i];
+
+ // Refuse possible leaked file descriptors.
+ if (intent.hasFileDescriptors()) {
+ throw new IllegalArgumentException("File descriptors passed in Intent");
+ }
+
+ // Don't modify the client's object!
+ intent = new Intent(intent);
+
+ // Collect information about the target of the Intent.
+ ActivityInfo aInfo = mSupervisor.resolveActivity(intent, resolvedTypes[i],
+ 0 /* startFlags */, null /* profilerInfo */, userId,
+ ActivityStarter.computeResolveFilterUid(
+ callingUid, realCallingUid, UserHandle.USER_NULL));
+ aInfo = mService.mAmInternal.getActivityInfoForUser(aInfo, userId);
+
+ if (aInfo != null && (aInfo.applicationInfo.privateFlags
+ & ApplicationInfo.PRIVATE_FLAG_CANT_SAVE_STATE) != 0) {
+ throw new IllegalArgumentException("FLAG_CANT_SAVE_STATE not supported here");
+ }
+
+ final boolean top = i == intents.length - 1;
+ final SafeActivityOptions checkedOptions = top
+ ? options
+ : null;
+ starters[i] = obtainStarter(intent, reason)
+ .setCaller(caller)
+ .setResolvedType(resolvedTypes[i])
+ .setActivityInfo(aInfo)
+ .setResultTo(resultTo)
+ .setRequestCode(-1)
+ .setCallingPid(callingPid)
+ .setCallingUid(callingUid)
+ .setCallingPackage(callingPackage)
+ .setRealCallingPid(realCallingPid)
+ .setRealCallingUid(realCallingUid)
+ .setActivityOptions(checkedOptions)
+ .setComponentSpecified(intent.getComponent() != null)
+
+ // Top activity decides on animation being run, so we allow only for the
+ // top one as otherwise an activity below might consume it.
+ .setAllowPendingRemoteAnimationRegistryLookup(top /* allowLookup*/)
+ .setOriginatingPendingIntent(originatingPendingIntent)
+ .setAllowBackgroundActivityStart(allowBackgroundActivityStart);
+ }
+
+ final ActivityRecord[] outActivity = new ActivityRecord[1];
+ // Lock the loop to ensure the activities launched in a sequence.
synchronized (mService.mGlobalLock) {
- ActivityRecord[] outActivity = new ActivityRecord[1];
- for (int i=0; i < intents.length; i++) {
- Intent intent = intents[i];
- if (intent == null) {
- continue;
+ for (int i = 0; i < starters.length; i++) {
+ final int startResult = starters[i].setOutActivity(outActivity).execute();
+ if (startResult < START_SUCCESS) {
+ // Abort by error result and recycle unused starters.
+ for (int j = i + 1; j < starters.length; j++) {
+ mFactory.recycle(starters[j]);
+ }
+ return startResult;
}
-
- // Refuse possible leaked file descriptors
- if (intent != null && intent.hasFileDescriptors()) {
- throw new IllegalArgumentException("File descriptors passed in Intent");
- }
-
- boolean componentSpecified = intent.getComponent() != null;
-
- // Don't modify the client's object!
- intent = new Intent(intent);
-
- // Collect information about the target of the Intent.
- ActivityInfo aInfo = mSupervisor.resolveActivity(intent, resolvedTypes[i], 0,
- null, userId, ActivityStarter.computeResolveFilterUid(
- callingUid, realCallingUid, UserHandle.USER_NULL));
- aInfo = mService.mAmInternal.getActivityInfoForUser(aInfo, userId);
-
- if (aInfo != null &&
- (aInfo.applicationInfo.privateFlags
- & ApplicationInfo.PRIVATE_FLAG_CANT_SAVE_STATE) != 0) {
- throw new IllegalArgumentException(
- "FLAG_CANT_SAVE_STATE not supported here");
- }
-
- final boolean top = i == intents.length - 1;
- final SafeActivityOptions checkedOptions = top
- ? options
- : null;
- final int res = obtainStarter(intent, reason)
- .setCaller(caller)
- .setResolvedType(resolvedTypes[i])
- .setActivityInfo(aInfo)
- .setResultTo(resultTo)
- .setRequestCode(-1)
- .setCallingPid(callingPid)
- .setCallingUid(callingUid)
- .setCallingPackage(callingPackage)
- .setRealCallingPid(realCallingPid)
- .setRealCallingUid(realCallingUid)
- .setActivityOptions(checkedOptions)
- .setComponentSpecified(componentSpecified)
- .setOutActivity(outActivity)
-
- // Top activity decides on animation being run, so we allow only for the
- // top one as otherwise an activity below might consume it.
- .setAllowPendingRemoteAnimationRegistryLookup(top /* allowLookup*/)
- .setOriginatingPendingIntent(originatingPendingIntent)
- .setAllowBackgroundActivityStart(allowBackgroundActivityStart)
- .execute();
-
- if (res < 0) {
- return res;
- }
-
resultTo = outActivity[0] != null ? outActivity[0].appToken : null;
}
}
diff --git a/services/core/java/com/android/server/wm/ActivityStarter.java b/services/core/java/com/android/server/wm/ActivityStarter.java
index d40948b..538813e 100644
--- a/services/core/java/com/android/server/wm/ActivityStarter.java
+++ b/services/core/java/com/android/server/wm/ActivityStarter.java
@@ -98,6 +98,7 @@
import android.content.pm.ResolveInfo;
import android.content.pm.UserInfo;
import android.content.res.Configuration;
+import android.content.res.Resources;
import android.graphics.Rect;
import android.os.Binder;
import android.os.Bundle;
@@ -115,6 +116,7 @@
import android.util.Slog;
import android.widget.Toast;
+import com.android.internal.R;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.app.HeavyWeightSwitcherActivity;
import com.android.internal.app.IVoiceInteractor;
@@ -761,11 +763,11 @@
abort |= (abortBackgroundStart && !mService.isBackgroundActivityStartsEnabled());
// TODO: remove this toast after feature development is done
if (abortBackgroundStart) {
- final String toastMsg = abort
- ? "Background activity start from " + callingPackage
- + " blocked. See go/q-bg-block."
- : "This background activity start from " + callingPackage
- + " will be blocked in future Q builds. See go/q-bg-block.";
+ final Resources res = mService.mContext.getResources();
+ final String toastMsg = res.getString(abort
+ ? R.string.activity_starter_block_bg_activity_starts_enforcing
+ : R.string.activity_starter_block_bg_activity_starts_permissive,
+ callingPackage);
mService.mUiHandler.post(() -> {
Toast.makeText(mService.mContext, toastMsg, Toast.LENGTH_LONG).show();
});
diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
index 258819f..9b35e85 100644
--- a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
@@ -2467,7 +2467,7 @@
}
final Rect destBounds = new Rect();
stack.getAnimationOrCurrentBounds(destBounds);
- if (!destBounds.isEmpty() || !destBounds.equals(compareBounds)) {
+ if (destBounds.isEmpty() || !destBounds.equals(compareBounds)) {
Slog.w(TAG, "The current stack bounds does not matched! It may be obsolete.");
return;
}
@@ -3202,23 +3202,34 @@
}
@Override
- public void exitFreeformMode(IBinder token) {
+ public void toggleFreeformWindowingMode(IBinder token) {
synchronized (mGlobalLock) {
long ident = Binder.clearCallingIdentity();
try {
final ActivityRecord r = ActivityRecord.forTokenLocked(token);
if (r == null) {
throw new IllegalArgumentException(
- "exitFreeformMode: No activity record matching token=" + token);
+ "toggleFreeformWindowingMode: No activity record matching token="
+ + token);
}
final ActivityStack stack = r.getActivityStack();
- if (stack == null || !stack.inFreeformWindowingMode()) {
- throw new IllegalStateException(
- "exitFreeformMode: You can only go fullscreen from freeform.");
+ if (stack == null) {
+ throw new IllegalStateException("toggleFreeformWindowingMode: the activity "
+ + "doesn't have a stack");
}
- stack.setWindowingMode(WINDOWING_MODE_FULLSCREEN);
+ if (!stack.inFreeformWindowingMode()
+ && stack.getWindowingMode() != WINDOWING_MODE_FULLSCREEN) {
+ throw new IllegalStateException("toggleFreeformWindowingMode: You can only "
+ + "toggle between fullscreen and freeform.");
+ }
+
+ if (stack.inFreeformWindowingMode()) {
+ stack.setWindowingMode(WINDOWING_MODE_FULLSCREEN);
+ } else {
+ stack.setWindowingMode(WINDOWING_MODE_FREEFORM);
+ }
} finally {
Binder.restoreCallingIdentity(ident);
}
@@ -5923,14 +5934,12 @@
Binder.restoreCallingIdentity(ident);
}
- synchronized (mGlobalLock) {
- return getActivityStartController().startActivitiesInPackage(
- packageUid, packageName,
- intents, resolvedTypes, null /* resultTo */,
- SafeActivityOptions.fromBundle(bOptions), userId,
- false /* validateIncomingUser */, null /* originatingPendingIntent */,
- false /* allowBackgroundActivityStart */);
- }
+ return getActivityStartController().startActivitiesInPackage(
+ packageUid, packageName,
+ intents, resolvedTypes, null /* resultTo */,
+ SafeActivityOptions.fromBundle(bOptions), userId,
+ false /* validateIncomingUser */, null /* originatingPendingIntent */,
+ false /* allowBackgroundActivityStart */);
}
@Override
diff --git a/services/core/java/com/android/server/wm/AppTransition.java b/services/core/java/com/android/server/wm/AppTransition.java
index 6dc73bb..19ff438 100644
--- a/services/core/java/com/android/server/wm/AppTransition.java
+++ b/services/core/java/com/android/server/wm/AppTransition.java
@@ -1879,6 +1879,9 @@
mNextAppTransitionAnimationsSpecsFuture = specsFuture;
mNextAppTransitionScaleUp = scaleUp;
mNextAppTransitionFutureCallback = callback;
+ if (isReady()) {
+ fetchAppTransitionSpecsFromFuture();
+ }
}
}
diff --git a/services/core/java/com/android/server/wm/ConfigurationContainer.java b/services/core/java/com/android/server/wm/ConfigurationContainer.java
index 97062a6..5c528c7 100644
--- a/services/core/java/com/android/server/wm/ConfigurationContainer.java
+++ b/services/core/java/com/android/server/wm/ConfigurationContainer.java
@@ -568,7 +568,7 @@
final long token = proto.start(fieldId);
mRequestedOverrideConfiguration.writeToProto(proto, OVERRIDE_CONFIGURATION,
- logLevel != WindowTraceLogLevel.CRITICAL);
+ logLevel == WindowTraceLogLevel.CRITICAL);
if (logLevel == WindowTraceLogLevel.ALL) {
mFullConfiguration.writeToProto(proto, FULL_CONFIGURATION, false /* critical */);
mMergedOverrideConfiguration.writeToProto(proto, MERGED_OVERRIDE_CONFIGURATION,
diff --git a/services/core/java/com/android/server/wm/DockedStackDividerController.java b/services/core/java/com/android/server/wm/DockedStackDividerController.java
index ea65dd9..1d76a71 100644
--- a/services/core/java/com/android/server/wm/DockedStackDividerController.java
+++ b/services/core/java/com/android/server/wm/DockedStackDividerController.java
@@ -396,6 +396,10 @@
if (mAdjustedForIme != adjustedForIme || (adjustedForIme && mImeHeight != imeHeight)
|| mAdjustedForDivider != adjustedForDivider) {
if (animate && !mAnimatingForMinimizedDockedStack) {
+ // Notify SystemUI to set the target docked stack size according current docked
+ // state without animation when calling startImeAdjustAnimation.
+ notifyDockedStackMinimizedChanged(mMinimizedDock, false /* animate */,
+ isHomeStackResizable());
startImeAdjustAnimation(adjustedForIme, adjustedForDivider, imeWin);
} else {
// Animation might be delayed, so only notify if we don't run an animation.
@@ -889,7 +893,10 @@
}
if (mAnimatingForMinimizedDockedStack) {
return animateForMinimizedDockedStack(now);
- } else if (mAnimatingForIme) {
+ } else if (mAnimatingForIme && !mDisplayContent.mAppTransition.isRunning()) {
+ // To prevent task stack resize animation may flicking when playing app transition
+ // animation & IME window enter animation in parallel, make sure app transition is done
+ // and then start to animate for IME.
return animateForIme(now);
}
return false;
diff --git a/services/core/java/com/android/server/wm/RootActivityContainer.java b/services/core/java/com/android/server/wm/RootActivityContainer.java
index 5c91d9e..6988357 100644
--- a/services/core/java/com/android/server/wm/RootActivityContainer.java
+++ b/services/core/java/com/android/server/wm/RootActivityContainer.java
@@ -1126,6 +1126,13 @@
if (!stack.isFocusableAndVisible() || topRunningActivity == null) {
continue;
}
+ if (stack == targetStack) {
+ // Simply update the result for targetStack because the targetStack had
+ // already resumed in above. We don't want to resume it again, especially in
+ // some cases, it would cause a second launch failure if app process was dead.
+ resumedOnDisplay |= result;
+ continue;
+ }
if (topRunningActivity.isState(RESUMED)) {
// Kick off any lingering app transitions form the MoveTaskToFront operation.
stack.executeAppTransition(targetOptions);
diff --git a/services/core/java/com/android/server/wm/TaskRecord.java b/services/core/java/com/android/server/wm/TaskRecord.java
index 59d7560..9d3112f 100644
--- a/services/core/java/com/android/server/wm/TaskRecord.java
+++ b/services/core/java/com/android/server/wm/TaskRecord.java
@@ -2134,7 +2134,7 @@
if (inOutConfig.screenHeightDp == Configuration.SCREEN_HEIGHT_DP_UNDEFINED) {
final int overrideScreenHeightDp = (int) (mTmpStableBounds.height() / density);
inOutConfig.screenHeightDp = insideParentBounds
- ? Math.min(overrideScreenHeightDp, parentConfig.screenWidthDp)
+ ? Math.min(overrideScreenHeightDp, parentConfig.screenHeightDp)
: overrideScreenHeightDp;
}
diff --git a/services/core/java/com/android/server/wm/TaskStack.java b/services/core/java/com/android/server/wm/TaskStack.java
index 7b742fd..b915199 100644
--- a/services/core/java/com/android/server/wm/TaskStack.java
+++ b/services/core/java/com/android/server/wm/TaskStack.java
@@ -1163,6 +1163,14 @@
}
private boolean adjustForIME(final WindowState imeWin) {
+ // To prevent task stack resize animation may flicking when playing app transition
+ // animation & IME window enter animation in parallel, we need to make sure app
+ // transition is done and then adjust task size for IME, skip the new adjusted frame when
+ // app transition is still running.
+ if (getDisplayContent().mAppTransition.isRunning()) {
+ return false;
+ }
+
final int dockedSide = getDockSide();
final boolean dockedTopOrBottom = dockedSide == DOCKED_TOP || dockedSide == DOCKED_BOTTOM;
if (imeWin == null || !dockedTopOrBottom) {
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index 3430987..21a557e 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -2164,9 +2164,6 @@
// A modal window uses the whole compatibility bounds.
flags |= FLAG_NOT_TOUCH_MODAL;
mTmpRect.set(mAppToken.getResolvedOverrideBounds());
- // TODO(b/112288258): Remove the forced offset when the override bounds always
- // starts from zero (See {@link ActivityRecord#resolveOverrideConfiguration}).
- mTmpRect.offsetTo(0, 0);
} else {
// Non-modal uses the application based frame.
mTmpRect.set(mWindowFrames.mCompatFrame);
diff --git a/services/core/jni/com_android_server_power_PowerManagerService.cpp b/services/core/jni/com_android_server_power_PowerManagerService.cpp
index 9be728b..ec7a78b 100644
--- a/services/core/jni/com_android_server_power_PowerManagerService.cpp
+++ b/services/core/jni/com_android_server_power_PowerManagerService.cpp
@@ -295,6 +295,12 @@
}
}
+static bool nativeForceSuspend(JNIEnv* /* env */, jclass /* clazz */) {
+ bool retval = false;
+ getSuspendControl()->forceSuspend(&retval);
+ return retval;
+}
+
// ----------------------------------------------------------------------------
static const JNINativeMethod gPowerManagerServiceMethods[] = {
@@ -303,6 +309,8 @@
(void*) nativeInit },
{ "nativeAcquireSuspendBlocker", "(Ljava/lang/String;)V",
(void*) nativeAcquireSuspendBlocker },
+ { "nativeForceSuspend", "()Z",
+ (void*) nativeForceSuspend },
{ "nativeReleaseSuspendBlocker", "(Ljava/lang/String;)V",
(void*) nativeReleaseSuspendBlocker },
{ "nativeSetInteractive", "(Z)V",
diff --git a/services/devicepolicy/TEST_MAPPING b/services/devicepolicy/TEST_MAPPING
new file mode 100644
index 0000000..ab85a68
--- /dev/null
+++ b/services/devicepolicy/TEST_MAPPING
@@ -0,0 +1,7 @@
+{
+ "postsubmit": [
+ {
+ "name": "CtsDevicePolicyManagerTestCases"
+ }
+ ]
+}
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index 9523202..ae48dad 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -5181,7 +5181,7 @@
Preconditions.checkNotNull(who, "ComponentName is null");
final int userHandle = mInjector.userHandleGetCallingUserId();
synchronized (getLockObject()) {
- ActiveAdmin ap = getActiveAdminForCallerLocked(
+ final ActiveAdmin ap = getActiveAdminForCallerLocked(
who, DeviceAdminInfo.USES_POLICY_FORCE_LOCK, parent);
if (ap.maximumTimeToUnlock != timeMs) {
ap.maximumTimeToUnlock = timeMs;
@@ -8388,7 +8388,7 @@
return true;
}
- Log.w(LOG_TAG, String.format("Package if %s (uid=%d, pid=%d) cannot access Device IDs",
+ 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/tests/servicestests/assets/KeyStoreRecoveryControllerTest/xml/invalid-cert-file-two-refresh-intervals.xml b/services/tests/servicestests/assets/KeyStoreRecoveryControllerTest/xml/invalid-cert-file-two-refresh-intervals.xml
deleted file mode 100644
index 0f4e8a3..0000000
--- a/services/tests/servicestests/assets/KeyStoreRecoveryControllerTest/xml/invalid-cert-file-two-refresh-intervals.xml
+++ /dev/null
@@ -1,46 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<certificates>
- <metadata>
- <serial>
- 1000
- </serial>
- <creation-time>
- 1515697631
- </creation-time>
- <refresh-interval>
- 2592000
- </refresh-interval>
- <refresh-interval>
- 2592000
- </refresh-interval>
- <previous>
- <serial>
- 0
- </serial>
- <hash>
- 47DEQpj8HBSa+/TImW+5JCeuQeRkm5NMpJWZG3hSuFU=
- </hash>
- </previous>
- </metadata>
- <endpoints>
- <cert>
- MIIDCDCB8aADAgECAgYBYOlweDswDQYJKoZIhvcNAQELBQAwLTErMCkGA1UEAwwi
- R29vZ2xlIENyeXB0QXV0aFZhdWx0IEludGVybWVkaWF0ZTAeFw0xODAxMTEwODE1
- NTBaFw0yMDAxMTIwODE1NTBaMCkxJzAlBgNVBAMTHkdvb2dsZSBDcnlwdEF1dGhW
- YXVsdCBJbnN0YW5jZTBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABLgAERiYHfBu
- tJT+htocB40BtDr2jdxh0EZJlQ8QhpMkZuA/0t/zeSAdkVWw5b16izJ9JVOi/KVl
- 4b0hRH54UvowDQYJKoZIhvcNAQELBQADggIBABZALhC9j3hpZ0AgN0tsqAP2Ix21
- tNOcvo/aFJuSFanOM4DZbycZEYAo5rorvuFu7eXETBKDGnI5xreNAoQsaj/dyCHu
- HKIn5P7yCmKvG2sV2TQ5go+0xV2x8BhTrtUWLeHvUbM3fXipa3NrordbA8MgzXwr
- GR1Y1FuMOn5n4kiuHJ2sQTbDdzSQSK5VpH+6rjARlfOCyLUX0u8UKRRH81qhIQWb
- UFMp9q1CVfiLP2O3CdDdpZXCysdflIb62TWnma+I8jqMryyxrMVs9kpfa8zkX9qe
- 33Vxp+QaQTqQ07/7KYVw869MeFn+bXeHnjUhqGY6S8M71vrTMG3M5p8Sq9LmV8Y5
- 7YB5uqKap2Inf0FOuJS7h7nVVzU/kOFkepaQVHyScwTPuuXNgpQg8XZnN/AWfRwJ
- hf5zE6vXXTHMzQA1mY2eEhxGfpryv7LH8pvfcyTakdBlw8aMJjKdre8xLLGZeVCa
- 79plkfYD0rMrxtRHCGyTKGzUcx/B9kYJK5qBgJiDJLKF3XwGbAs/F8CyEPihjvj4
- M2EoeyhmHWKLYsps6+uTksJ+PxZU14M7672K2y8BdulyfkZIhili118XnRykKkMf
- JLQJKMqZx5O0B9bF8yQdcGKEGEwMQt5ENdH8HeiwLm4QS3VzFXYetgUPCM5lPDIp
- BuwwuQxvQDF4pmQd
- </cert>
- </endpoints>
-</certificates>
diff --git a/services/tests/servicestests/assets/KeyStoreRecoveryControllerTest/xml/invalid-cert-file-no-refresh-interval.xml b/services/tests/servicestests/assets/KeyStoreRecoveryControllerTest/xml/valid-cert-file-no-refresh-interval.xml
similarity index 100%
rename from services/tests/servicestests/assets/KeyStoreRecoveryControllerTest/xml/invalid-cert-file-no-refresh-interval.xml
rename to services/tests/servicestests/assets/KeyStoreRecoveryControllerTest/xml/valid-cert-file-no-refresh-interval.xml
diff --git a/services/tests/servicestests/src/com/android/server/am/UserControllerTest.java b/services/tests/servicestests/src/com/android/server/am/UserControllerTest.java
index bd03a8d..04abeca1 100644
--- a/services/tests/servicestests/src/com/android/server/am/UserControllerTest.java
+++ b/services/tests/servicestests/src/com/android/server/am/UserControllerTest.java
@@ -403,7 +403,8 @@
protected int broadcastIntent(Intent intent, String resolvedType,
IIntentReceiver resultTo, int resultCode, String resultData, Bundle resultExtras,
String[] requiredPermissions, int appOp, Bundle bOptions, boolean ordered,
- boolean sticky, int callingPid, int callingUid, int userId) {
+ boolean sticky, int callingPid, int callingUid, int realCallingUid,
+ int realCallingPid, int userId) {
Log.i(TAG, "broadcastIntentLocked " + intent);
mSentIntents.add(intent);
return 0;
diff --git a/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/certificate/CertXmlTest.java b/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/certificate/CertXmlTest.java
index bbcc411..9836c64 100644
--- a/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/certificate/CertXmlTest.java
+++ b/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/certificate/CertXmlTest.java
@@ -47,7 +47,6 @@
public void parse_succeeds() throws Exception {
CertXml certXml = CertXml.parse(certXmlBytes);
assertThat(certXml.getSerial()).isEqualTo(1000L);
- assertThat(certXml.getRefreshInterval()).isEqualTo(2592000L);
}
@Test
@@ -75,6 +74,13 @@
}
@Test
+ public void parse_doesNotThrowIfNoRefreshInterval() throws Exception {
+ CertXml.parse(
+ TestData.readTestFile(
+ "xml/valid-cert-file-no-refresh-interval.xml"));
+ }
+
+ @Test
public void parse_throwsIfNoEndpointCert() throws Exception {
CertParsingException expected =
expectThrows(
@@ -87,18 +93,6 @@
}
@Test
- public void parse_throwsIfNoRefreshInterval() throws Exception {
- CertParsingException expected =
- expectThrows(
- CertParsingException.class,
- () ->
- CertXml.parse(
- TestData.readTestFile(
- "xml/invalid-cert-file-no-refresh-interval.xml")));
- assertThat(expected.getMessage()).contains("exactly one");
- }
-
- @Test
public void parse_throwsIfNoSerial() throws Exception {
CertParsingException expected =
expectThrows(
@@ -111,19 +105,6 @@
}
@Test
- public void parse_throwsIfTwoRefreshIntervals() throws Exception {
- CertParsingException expected =
- expectThrows(
- CertParsingException.class,
- () ->
- CertXml.parse(
- TestData.readTestFile(
- "xml/invalid-cert-file-two-refresh-intervals"
- + ".xml")));
- assertThat(expected.getMessage()).contains("exactly one");
- }
-
- @Test
public void parse_throwsIfTwoSerials() throws Exception {
CertParsingException expected =
expectThrows(
diff --git a/services/tests/servicestests/src/com/android/server/pm/dex/DexManagerTests.java b/services/tests/servicestests/src/com/android/server/pm/dex/DexManagerTests.java
index 48ab8d6..0196279 100644
--- a/services/tests/servicestests/src/com/android/server/pm/dex/DexManagerTests.java
+++ b/services/tests/servicestests/src/com/android/server/pm/dex/DexManagerTests.java
@@ -568,7 +568,8 @@
}
private PackageDynamicCode getPackageDynamicCodeInfo(TestData testData) {
- return mDexManager.getDexLogger().getPackageDynamicCodeInfo(testData.getPackageName());
+ return mDexManager.getDynamicCodeLogger()
+ .getPackageDynamicCodeInfo(testData.getPackageName());
}
private void assertNoUseInfo(TestData testData) {
diff --git a/services/tests/servicestests/src/com/android/server/pm/dex/DexLoggerTests.java b/services/tests/servicestests/src/com/android/server/pm/dex/DynamicCodeLoggerTests.java
similarity index 85%
rename from services/tests/servicestests/src/com/android/server/pm/dex/DexLoggerTests.java
rename to services/tests/servicestests/src/com/android/server/pm/dex/DynamicCodeLoggerTests.java
index 6da202b..7992ba3 100644
--- a/services/tests/servicestests/src/com/android/server/pm/dex/DexLoggerTests.java
+++ b/services/tests/servicestests/src/com/android/server/pm/dex/DynamicCodeLoggerTests.java
@@ -53,7 +53,7 @@
@RunWith(AndroidJUnit4.class)
@SmallTest
-public class DexLoggerTests {
+public class DynamicCodeLoggerTests {
private static final String OWNING_PACKAGE_NAME = "package.name";
private static final String VOLUME_UUID = "volUuid";
private static final String FILE_PATH = "/bar/foo.jar";
@@ -85,7 +85,7 @@
@Mock IPackageManager mPM;
@Mock Installer mInstaller;
- private DexLogger mDexLogger;
+ private DynamicCodeLogger mDynamicCodeLogger;
private final ListMultimap<Integer, String> mMessagesForUid = ArrayListMultimap.create();
private boolean mWriteTriggered = false;
@@ -106,7 +106,7 @@
};
// For test purposes capture log messages as well as sending to the event log.
- mDexLogger = new DexLogger(mPM, mInstaller, packageDynamicCodeLoading) {
+ mDynamicCodeLogger = new DynamicCodeLogger(mPM, mInstaller, packageDynamicCodeLoading) {
@Override
void writeDclEvent(String subtag, int uid, String message) {
super.writeDclEvent(subtag, uid, message);
@@ -131,13 +131,13 @@
whenFileIsHashed(FILE_PATH, doReturn(CONTENT_HASH_BYTES));
recordLoad(OWNING_PACKAGE_NAME, FILE_PATH);
- mDexLogger.logDynamicCodeLoading(OWNING_PACKAGE_NAME);
+ mDynamicCodeLogger.logDynamicCodeLoading(OWNING_PACKAGE_NAME);
assertThat(mMessagesForUid.keys()).containsExactly(OWNER_UID);
assertThat(mMessagesForUid).containsEntry(OWNER_UID, EXPECTED_MESSAGE_WITH_CONTENT_HASH);
assertThat(mWriteTriggered).isFalse();
- assertThat(mDexLogger.getAllPackagesWithDynamicCodeLoading())
+ assertThat(mDynamicCodeLogger.getAllPackagesWithDynamicCodeLoading())
.containsExactly(OWNING_PACKAGE_NAME);
}
@@ -146,14 +146,14 @@
whenFileIsHashed(FILE_PATH, doReturn(EMPTY_BYTES));
recordLoad(OWNING_PACKAGE_NAME, FILE_PATH);
- mDexLogger.logDynamicCodeLoading(OWNING_PACKAGE_NAME);
+ mDynamicCodeLogger.logDynamicCodeLoading(OWNING_PACKAGE_NAME);
assertThat(mMessagesForUid.keys()).containsExactly(OWNER_UID);
assertThat(mMessagesForUid).containsEntry(OWNER_UID, EXPECTED_MESSAGE_WITHOUT_CONTENT_HASH);
// File should be removed from the DCL list, since we can't hash it.
assertThat(mWriteTriggered).isTrue();
- assertThat(mDexLogger.getAllPackagesWithDynamicCodeLoading()).isEmpty();
+ assertThat(mDynamicCodeLogger.getAllPackagesWithDynamicCodeLoading()).isEmpty();
}
@Test
@@ -162,24 +162,24 @@
doThrow(new InstallerException("Intentional failure for test")));
recordLoad(OWNING_PACKAGE_NAME, FILE_PATH);
- mDexLogger.logDynamicCodeLoading(OWNING_PACKAGE_NAME);
+ mDynamicCodeLogger.logDynamicCodeLoading(OWNING_PACKAGE_NAME);
assertThat(mMessagesForUid.keys()).containsExactly(OWNER_UID);
assertThat(mMessagesForUid).containsEntry(OWNER_UID, EXPECTED_MESSAGE_WITHOUT_CONTENT_HASH);
// File should be removed from the DCL list, since we can't hash it.
assertThat(mWriteTriggered).isTrue();
- assertThat(mDexLogger.getAllPackagesWithDynamicCodeLoading()).isEmpty();
+ assertThat(mDynamicCodeLogger.getAllPackagesWithDynamicCodeLoading()).isEmpty();
}
@Test
public void testOneLoader_ownFile_unknownPath() {
recordLoad(OWNING_PACKAGE_NAME, "other/path");
- mDexLogger.logDynamicCodeLoading(OWNING_PACKAGE_NAME);
+ mDynamicCodeLogger.logDynamicCodeLoading(OWNING_PACKAGE_NAME);
assertThat(mMessagesForUid).isEmpty();
assertThat(mWriteTriggered).isTrue();
- assertThat(mDexLogger.getAllPackagesWithDynamicCodeLoading()).isEmpty();
+ assertThat(mDynamicCodeLogger.getAllPackagesWithDynamicCodeLoading()).isEmpty();
}
@Test
@@ -189,7 +189,7 @@
setPackageUid(OWNING_PACKAGE_NAME, -1);
recordLoad(OWNING_PACKAGE_NAME, filePath);
- mDexLogger.logDynamicCodeLoading(OWNING_PACKAGE_NAME);
+ mDynamicCodeLogger.logDynamicCodeLoading(OWNING_PACKAGE_NAME);
assertThat(mMessagesForUid).isEmpty();
}
@@ -200,7 +200,7 @@
setPackageUid("other.package.name", 1001);
recordLoad("other.package.name", FILE_PATH);
- mDexLogger.logDynamicCodeLoading(OWNING_PACKAGE_NAME);
+ mDynamicCodeLogger.logDynamicCodeLoading(OWNING_PACKAGE_NAME);
assertThat(mMessagesForUid.keys()).containsExactly(1001);
assertThat(mMessagesForUid).containsEntry(1001, EXPECTED_MESSAGE_WITH_CONTENT_HASH);
@@ -213,7 +213,7 @@
setPackageUid("other.package.name", -1);
recordLoad("other.package.name", FILE_PATH);
- mDexLogger.logDynamicCodeLoading(OWNING_PACKAGE_NAME);
+ mDynamicCodeLogger.logDynamicCodeLoading(OWNING_PACKAGE_NAME);
assertThat(mMessagesForUid).isEmpty();
assertThat(mWriteTriggered).isFalse();
@@ -224,14 +224,14 @@
whenFileIsHashed(FILE_PATH, doReturn(CONTENT_HASH_BYTES));
recordLoadNative(FILE_PATH);
- mDexLogger.logDynamicCodeLoading(OWNING_PACKAGE_NAME);
+ mDynamicCodeLogger.logDynamicCodeLoading(OWNING_PACKAGE_NAME);
assertThat(mMessagesForUid.keys()).containsExactly(OWNER_UID);
assertThat(mMessagesForUid)
.containsEntry(OWNER_UID, EXPECTED_MESSAGE_NATIVE_WITH_CONTENT_HASH);
assertThat(mWriteTriggered).isFalse();
- assertThat(mDexLogger.getAllPackagesWithDynamicCodeLoading())
+ assertThat(mDynamicCodeLogger.getAllPackagesWithDynamicCodeLoading())
.containsExactly(OWNING_PACKAGE_NAME);
}
@@ -247,7 +247,7 @@
recordLoad("other.package.name1", otherDexPath);
recordLoad("other.package.name2", FILE_PATH);
recordLoad(OWNING_PACKAGE_NAME, FILE_PATH);
- mDexLogger.logDynamicCodeLoading(OWNING_PACKAGE_NAME);
+ mDynamicCodeLogger.logDynamicCodeLoading(OWNING_PACKAGE_NAME);
assertThat(mMessagesForUid.keys()).containsExactly(1001, 1001, 1002, OWNER_UID);
assertThat(mMessagesForUid).containsEntry(1001, EXPECTED_MESSAGE_WITH_CONTENT_HASH);
@@ -256,10 +256,10 @@
assertThat(mMessagesForUid).containsEntry(OWNER_UID, EXPECTED_MESSAGE_WITH_CONTENT_HASH);
assertThat(mWriteTriggered).isTrue();
- assertThat(mDexLogger.getAllPackagesWithDynamicCodeLoading())
+ assertThat(mDynamicCodeLogger.getAllPackagesWithDynamicCodeLoading())
.containsExactly(OWNING_PACKAGE_NAME);
- // Check the DexLogger caching is working
+ // Check the DynamicCodeLogger caching is working
verify(mPM, atMost(1)).getPackageInfo(OWNING_PACKAGE_NAME, /*flags*/ 0, OWNER_USER_ID);
}
@@ -267,7 +267,7 @@
public void testUnknownOwner() {
reset(mPM);
recordLoad(OWNING_PACKAGE_NAME, FILE_PATH);
- mDexLogger.logDynamicCodeLoading("other.package.name");
+ mDynamicCodeLogger.logDynamicCodeLoading("other.package.name");
assertThat(mMessagesForUid).isEmpty();
assertThat(mWriteTriggered).isFalse();
@@ -278,11 +278,11 @@
public void testUninstalledPackage() {
reset(mPM);
recordLoad(OWNING_PACKAGE_NAME, FILE_PATH);
- mDexLogger.logDynamicCodeLoading(OWNING_PACKAGE_NAME);
+ mDynamicCodeLogger.logDynamicCodeLoading(OWNING_PACKAGE_NAME);
assertThat(mMessagesForUid).isEmpty();
assertThat(mWriteTriggered).isTrue();
- assertThat(mDexLogger.getAllPackagesWithDynamicCodeLoading()).isEmpty();
+ assertThat(mDynamicCodeLogger.getAllPackagesWithDynamicCodeLoading()).isEmpty();
}
private void setPackageUid(String packageName, int uid) throws Exception {
@@ -295,7 +295,8 @@
}
private void recordLoad(String loadingPackageName, String dexPath) {
- mDexLogger.recordDex(OWNER_USER_ID, dexPath, OWNING_PACKAGE_NAME, loadingPackageName);
+ mDynamicCodeLogger.recordDex(
+ OWNER_USER_ID, dexPath, OWNING_PACKAGE_NAME, loadingPackageName);
mWriteTriggered = false;
}
@@ -304,7 +305,7 @@
String[] packageNames = { OWNING_PACKAGE_NAME };
when(mPM.getPackagesForUid(loadingUid)).thenReturn(packageNames);
- mDexLogger.recordNative(loadingUid, nativePath);
+ mDynamicCodeLogger.recordNative(loadingUid, nativePath);
mWriteTriggered = false;
}
}
diff --git a/services/tests/servicestests/src/com/android/server/power/PowerManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/power/PowerManagerServiceTest.java
index 63341b6..911c4a2 100644
--- a/services/tests/servicestests/src/com/android/server/power/PowerManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/power/PowerManagerServiceTest.java
@@ -21,15 +21,21 @@
import static com.google.common.truth.Truth.assertThat;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import android.app.ActivityManagerInternal;
+import android.attention.AttentionManagerInternal;
import android.content.Context;
import android.hardware.display.DisplayManagerInternal;
import android.hardware.display.DisplayManagerInternal.DisplayPowerRequest;
import android.os.BatteryManagerInternal;
+import android.os.Binder;
import android.os.Looper;
import android.os.PowerManager;
import android.os.PowerSaveState;
@@ -53,6 +59,9 @@
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
+import java.util.HashMap;
+import java.util.Map;
+
/**
* Tests for {@link com.android.server.power.PowerManagerService}
*/
@@ -67,6 +76,7 @@
private @Mock DisplayManagerInternal mDisplayManagerInternalMock;
private @Mock BatteryManagerInternal mBatteryManagerInternalMock;
private @Mock ActivityManagerInternal mActivityManagerInternalMock;
+ private @Mock AttentionManagerInternal mAttentionManagerInternalMock;
private @Mock PowerManagerService.NativeWrapper mNativeWrapperMock;
private @Mock Notifier mNotifierMock;
private PowerManagerService mService;
@@ -93,6 +103,7 @@
addLocalServiceMock(DisplayManagerInternal.class, mDisplayManagerInternalMock);
addLocalServiceMock(BatteryManagerInternal.class, mBatteryManagerInternalMock);
addLocalServiceMock(ActivityManagerInternal.class, mActivityManagerInternalMock);
+ addLocalServiceMock(AttentionManagerInternal.class, mAttentionManagerInternalMock);
mService = new PowerManagerService(getContext(), new Injector() {
Notifier createNotifier(Looper looper, Context context, IBatteryStats batteryStats,
@@ -210,4 +221,80 @@
mService.onUserActivity();
assertThat(mService.wasDeviceIdleForInternal(interval)).isFalse();
}
+
+ @SmallTest
+ public void testForceSuspend_putsDeviceToSleep() {
+ mService.systemReady(null);
+ mService.onBootPhase(SystemService.PHASE_BOOT_COMPLETED);
+
+ // Verify that we start awake
+ assertThat(mService.getWakefulness()).isEqualTo(WAKEFULNESS_AWAKE);
+
+ // Grab the wakefulness value when PowerManager finally calls into the
+ // native component to actually perform the suspend.
+ when(mNativeWrapperMock.nativeForceSuspend()).then(inv -> {
+ assertThat(mService.getWakefulness()).isEqualTo(WAKEFULNESS_ASLEEP);
+ return true;
+ });
+
+ boolean retval = mService.getBinderServiceInstance().forceSuspend();
+ assertThat(retval).isTrue();
+
+ // Still asleep when the function returns.
+ assertThat(mService.getWakefulness()).isEqualTo(WAKEFULNESS_ASLEEP);
+ }
+
+ @SmallTest
+ public void testForceSuspend_pakeLocksDisabled() {
+ final String tag = "TestWakelockTag_098213";
+ final int flags = PowerManager.PARTIAL_WAKE_LOCK;
+ final String pkg = getContext().getOpPackageName();
+
+ // Set up the Notification mock to keep track of the wakelocks that are currently
+ // active or disabled. We'll use this to verify that wakelocks are disabled when
+ // they should be.
+ final Map<String, Integer> wakelockMap = new HashMap<>(1);
+ doAnswer(inv -> {
+ wakelockMap.put((String) inv.getArguments()[1], (int) inv.getArguments()[0]);
+ return null;
+ }).when(mNotifierMock).onWakeLockAcquired(anyInt(), anyString(), anyString(), anyInt(),
+ anyInt(), any(), any());
+ doAnswer(inv -> {
+ wakelockMap.remove((String) inv.getArguments()[1]);
+ return null;
+ }).when(mNotifierMock).onWakeLockReleased(anyInt(), anyString(), anyString(), anyInt(),
+ anyInt(), any(), any());
+
+ //
+ // TEST STARTS HERE
+ //
+ mService.systemReady(null);
+ mService.onBootPhase(SystemService.PHASE_BOOT_COMPLETED);
+
+ // Verify that we start awake
+ assertThat(mService.getWakefulness()).isEqualTo(WAKEFULNESS_AWAKE);
+
+ // Create a wakelock
+ mService.getBinderServiceInstance().acquireWakeLock(new Binder(), flags, tag, pkg,
+ null /* workSource */, null /* historyTag */);
+ assertThat(wakelockMap.get(tag)).isEqualTo(flags); // Verify wakelock is active.
+
+ // Confirm that the wakelocks have been disabled when the forceSuspend is in flight.
+ when(mNativeWrapperMock.nativeForceSuspend()).then(inv -> {
+ // Verify that the wakelock is disabled by the time we get to the native force
+ // suspend call.
+ assertThat(wakelockMap.containsKey(tag)).isFalse();
+ return true;
+ });
+
+ assertThat(mService.getBinderServiceInstance().forceSuspend()).isTrue();
+ assertThat(wakelockMap.get(tag)).isEqualTo(flags);
+
+ }
+
+ @SmallTest
+ public void testForceSuspend_forceSuspendFailurePropogated() {
+ when(mNativeWrapperMock.nativeForceSuspend()).thenReturn(false);
+ assertThat(mService.getBinderServiceInstance().forceSuspend()).isFalse();
+ }
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
index 8c36905..a1db3e8 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
@@ -27,9 +27,6 @@
import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.when;
-import static com.android.server.policy.WindowManagerPolicy.NAV_BAR_BOTTOM;
-import static com.android.server.policy.WindowManagerPolicy.NAV_BAR_LEFT;
-import static com.android.server.policy.WindowManagerPolicy.NAV_BAR_RIGHT;
import static com.android.server.wm.ActivityStack.ActivityState.INITIALIZING;
import static com.android.server.wm.ActivityStack.ActivityState.PAUSING;
import static com.android.server.wm.ActivityStack.ActivityState.RESUMED;
@@ -158,35 +155,6 @@
assertTrue(mActivity.isState(STOPPED));
}
- @Test
- public void testPositionLimitedAspectRatioNavBarBottom() {
- verifyPositionWithLimitedAspectRatio(NAV_BAR_BOTTOM, new Rect(0, 0, 1000, 2000), 1.5f,
- new Rect(0, 0, 1000, 1500));
- }
-
- @Test
- public void testPositionLimitedAspectRatioNavBarLeft() {
- verifyPositionWithLimitedAspectRatio(NAV_BAR_LEFT, new Rect(0, 0, 2000, 1000), 1.5f,
- new Rect(500, 0, 2000, 1000));
- }
-
- @Test
- public void testPositionLimitedAspectRatioNavBarRight() {
- verifyPositionWithLimitedAspectRatio(NAV_BAR_RIGHT, new Rect(0, 0, 2000, 1000), 1.5f,
- new Rect(0, 0, 1500, 1000));
- }
-
- private void verifyPositionWithLimitedAspectRatio(int navBarPosition, Rect taskBounds,
- float aspectRatio, Rect expectedActivityBounds) {
- // Verify with nav bar on the right.
- when(mService.mWindowManager.getNavBarPosition(mActivity.getDisplayId()))
- .thenReturn(navBarPosition);
- mTask.getConfiguration().windowConfiguration.setAppBounds(taskBounds);
- mActivity.info.maxAspectRatio = aspectRatio;
- ensureActivityConfiguration();
- assertEquals(expectedActivityBounds, mActivity.getBounds());
- }
-
private void ensureActivityConfiguration() {
mActivity.ensureActivityConfiguration(0 /* globalChanges */, false /* preserveWindow */);
}
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 a62bc71..2452ef0 100644
--- a/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java
@@ -61,7 +61,6 @@
import android.platform.test.annotations.Presubmit;
import android.util.DisplayMetrics;
import android.view.DisplayCutout;
-import android.view.DisplayInfo;
import android.view.Gravity;
import android.view.MotionEvent;
import android.view.Surface;
@@ -87,18 +86,22 @@
* Tests for the {@link DisplayContent} class.
*
* Build/Install/Run:
- * atest FrameworksServicesTests:DisplayContentTests
+ * atest WmTests:DisplayContentTests
*/
@SmallTest
@Presubmit
public class DisplayContentTests extends WindowTestsBase {
@Test
- @FlakyTest(bugId = 77772044)
+ @FlakyTest(detail = "Promote to presubmit when shown to be stable.")
public void testForAllWindows() {
final WindowState exitingAppWindow = createWindow(null, TYPE_BASE_APPLICATION,
mDisplayContent, "exiting app");
final AppWindowToken exitingAppToken = exitingAppWindow.mAppToken;
+ // Wait until everything in animation handler get executed to prevent the exiting window
+ // from being removed during WindowSurfacePlacer Traversal.
+ waitUntilHandlersIdle();
+
exitingAppToken.mIsExiting = true;
exitingAppToken.getTask().mStack.mExitingAppTokens.add(exitingAppToken);
diff --git a/services/tests/wmtests/src/com/android/server/wm/InsetsStateControllerTest.java b/services/tests/wmtests/src/com/android/server/wm/InsetsStateControllerTest.java
index bc62e8c..2d906d1 100644
--- a/services/tests/wmtests/src/com/android/server/wm/InsetsStateControllerTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/InsetsStateControllerTest.java
@@ -19,6 +19,7 @@
import static android.view.InsetsState.TYPE_IME;
import static android.view.InsetsState.TYPE_NAVIGATION_BAR;
import static android.view.InsetsState.TYPE_TOP_BAR;
+import static android.view.ViewRootImpl.NEW_INSETS_MODE_FULL;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION;
import static org.junit.Assert.assertEquals;
@@ -28,15 +29,33 @@
import android.platform.test.annotations.Presubmit;
import android.view.InsetsSourceControl;
import android.view.InsetsState;
+import android.view.ViewRootImpl;
import androidx.test.filters.FlakyTest;
import androidx.test.filters.SmallTest;
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
import org.junit.Test;
@SmallTest
@Presubmit
public class InsetsStateControllerTest extends WindowTestsBase {
+ private static int sPreviousNewInsetsMode;
+
+ @BeforeClass
+ public static void setUpOnce() {
+ // TODO: Make use of SettingsSession when it becomes feasible for this.
+ sPreviousNewInsetsMode = ViewRootImpl.sNewInsetsMode;
+ // To let the insets provider control the insets visibility, the insets mode has to be
+ // NEW_INSETS_MODE_FULL.
+ ViewRootImpl.sNewInsetsMode = NEW_INSETS_MODE_FULL;
+ }
+
+ @AfterClass
+ public static void tearDownOnce() {
+ ViewRootImpl.sNewInsetsMode = sPreviousNewInsetsMode;
+ }
@Test
public void testStripForDispatch_notOwn() {
@@ -47,7 +66,7 @@
assertNotNull(getController().getInsetsForDispatch(app).getSource(TYPE_TOP_BAR));
}
- @FlakyTest(bugId = 69229402)
+ @FlakyTest(detail = "Promote to pre-submit once confirmed stable.")
@Test
public void testStripForDispatch_own() {
final WindowState topBar = createWindow(null, TYPE_APPLICATION, "parentWindow");
@@ -57,7 +76,7 @@
assertEquals(new InsetsState(), getController().getInsetsForDispatch(topBar));
}
- @FlakyTest(bugId = 124088319)
+ @FlakyTest(detail = "Promote to pre-submit once confirmed stable.")
@Test
public void testStripForDispatch_navBar() {
final WindowState navBar = createWindow(null, TYPE_APPLICATION, "parentWindow");
@@ -69,7 +88,7 @@
assertEquals(new InsetsState(), getController().getInsetsForDispatch(navBar));
}
- @FlakyTest(bugId = 124088319)
+ @FlakyTest(detail = "Promote to pre-submit once confirmed stable.")
@Test
public void testBarControllingWinChanged() {
final WindowState navBar = createWindow(null, TYPE_APPLICATION, "parentWindow");
@@ -82,7 +101,7 @@
assertEquals(2, controls.length);
}
- @FlakyTest(bugId = 124088319)
+ @FlakyTest(detail = "Promote to pre-submit once confirmed stable.")
@Test
public void testControlRevoked() {
final WindowState topBar = createWindow(null, TYPE_APPLICATION, "parentWindow");
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 bcf9dd2..388f98f 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TaskRecordTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskRecordTests.java
@@ -24,6 +24,7 @@
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE;
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_PORTRAIT;
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
+import static android.util.DisplayMetrics.DENSITY_DEFAULT;
import static com.android.server.wm.WindowContainer.POSITION_TOP;
@@ -307,6 +308,41 @@
assertEquals(fullScreenBounds, task.getBounds());
}
+ @Test
+ public void testComputeConfigResourceOverrides() {
+ final TaskRecord task = new TaskBuilder(mSupervisor).build();
+ final Configuration inOutConfig = new Configuration();
+ final Configuration parentConfig = new Configuration();
+ final int longSide = 1200;
+ final int shortSide = 600;
+ parentConfig.densityDpi = 400;
+ parentConfig.screenHeightDp = 200; // 200 * 400 / 160 = 500px
+ parentConfig.screenWidthDp = 100; // 100 * 400 / 160 = 250px
+
+ // Portrait bounds.
+ inOutConfig.windowConfiguration.getBounds().set(0, 0, shortSide, longSide);
+ // By default, the parent bounds should limit the existing input bounds.
+ task.computeConfigResourceOverrides(inOutConfig, parentConfig);
+
+ assertEquals(parentConfig.screenHeightDp, inOutConfig.screenHeightDp);
+ assertEquals(parentConfig.screenWidthDp, inOutConfig.screenWidthDp);
+ assertEquals(Configuration.ORIENTATION_PORTRAIT, inOutConfig.orientation);
+
+ inOutConfig.setToDefaults();
+ // Landscape bounds.
+ inOutConfig.windowConfiguration.getBounds().set(0, 0, longSide, shortSide);
+ // Without limiting to be inside the parent bounds, the out screen size should keep relative
+ // to the input bounds.
+ task.computeConfigResourceOverrides(inOutConfig, parentConfig,
+ false /* insideParentBounds */);
+
+ assertEquals(shortSide * DENSITY_DEFAULT / parentConfig.densityDpi,
+ inOutConfig.screenHeightDp);
+ assertEquals(longSide * DENSITY_DEFAULT / parentConfig.densityDpi,
+ inOutConfig.screenWidthDp);
+ assertEquals(Configuration.ORIENTATION_LANDSCAPE, inOutConfig.orientation);
+ }
+
/** Ensures that the alias intent won't have target component resolved. */
@Test
public void testTaskIntentActivityAlias() {
diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskStackChangedListenerTest.java b/services/tests/wmtests/src/com/android/server/wm/TaskStackChangedListenerTest.java
index dcca316..42a205a 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TaskStackChangedListenerTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskStackChangedListenerTest.java
@@ -100,7 +100,7 @@
}
@Test
- @FlakyTest(bugId = 119893767)
+ @FlakyTest(detail = "Promote to presubmit when shown to be stable.")
public void testTaskDescriptionChanged() throws Exception {
final Object[] params = new Object[2];
final CountDownLatch latch = new CountDownLatch(1);
@@ -122,14 +122,18 @@
}
}
});
- final Activity activity = startTestActivity(ActivityTaskDescriptionChange.class);
+
+ int taskId;
+ synchronized (sLock) {
+ taskId = startTestActivity(ActivityTaskDescriptionChange.class).getTaskId();
+ }
waitForCallback(latch);
- assertEquals(activity.getTaskId(), params[0]);
+ assertEquals(taskId, params[0]);
assertEquals("Test Label", ((TaskDescription) params[1]).getLabel());
}
@Test
- @FlakyTest(bugId = 119893767)
+ @FlakyTest(detail = "Promote to presubmit when shown to be stable.")
public void testActivityRequestedOrientationChanged() throws Exception {
final int[] params = new int[2];
final CountDownLatch latch = new CountDownLatch(1);
@@ -142,9 +146,12 @@
latch.countDown();
}
});
- final Activity activity = startTestActivity(ActivityRequestedOrientationChange.class);
+ int taskId;
+ synchronized (sLock) {
+ taskId = startTestActivity(ActivityRequestedOrientationChange.class).getTaskId();
+ }
waitForCallback(latch);
- assertEquals(activity.getTaskId(), params[0]);
+ assertEquals(taskId, params[0]);
assertEquals(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT, params[1]);
}
@@ -152,7 +159,7 @@
* Tests for onTaskCreated, onTaskMovedToFront, onTaskRemoved and onTaskRemovalStarted.
*/
@Test
- @FlakyTest(bugId = 119893767)
+ @FlakyTest(detail = "Promote to presubmit when shown to be stable.")
public void testTaskChangeCallBacks() throws Exception {
final Object[] params = new Object[2];
final CountDownLatch taskCreatedLaunchLatch = new CountDownLatch(1);
@@ -245,7 +252,7 @@
private void waitForCallback(CountDownLatch latch) {
try {
- final boolean result = latch.await(2, TimeUnit.SECONDS);
+ final boolean result = latch.await(4, TimeUnit.SECONDS);
if (!result) {
throw new RuntimeException("Timed out waiting for task stack change notification");
}
@@ -324,7 +331,11 @@
protected void onPostResume() {
super.onPostResume();
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
- finish();
+ synchronized (sLock) {
+ // Hold the lock to ensure no one is trying to access fields of this Activity in
+ // this test.
+ finish();
+ }
}
}
@@ -333,7 +344,11 @@
protected void onPostResume() {
super.onPostResume();
setTaskDescription(new TaskDescription("Test Label"));
- finish();
+ synchronized (sLock) {
+ // Hold the lock to ensure no one is trying to access fields of this Activity in
+ // this test.
+ finish();
+ }
}
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java
index 3eb9085..b0e20b8 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java
@@ -35,6 +35,7 @@
import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD;
import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.doNothing;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.mock;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.never;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.reset;
@@ -54,7 +55,6 @@
import static org.mockito.ArgumentMatchers.anyLong;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.eq;
-import static org.mockito.Mockito.doNothing;
import android.graphics.Insets;
import android.graphics.Matrix;
@@ -87,6 +87,7 @@
*/
@SmallTest
@Presubmit
+@FlakyTest(bugId = 124127512)
public class WindowStateTests extends WindowTestsBase {
private static int sPreviousNewInsetsMode;
@@ -389,6 +390,7 @@
}
@Test
+ @FlakyTest(bugId = 74078662)
public void testLayoutSeqResetOnReparent() {
final WindowState app = createWindow(null, TYPE_APPLICATION, "app");
app.mLayoutSeq = 1;
@@ -445,6 +447,7 @@
}
@Test
+ @FlakyTest(bugId = 74078662)
public void testDisplayCutoutIsCalculatedRelativeToFrame() {
final WindowState app = createWindow(null, TYPE_APPLICATION, "app");
WindowFrames wf = app.getWindowFrames();
diff --git a/telecomm/java/android/telecom/Log.java b/telecomm/java/android/telecom/Log.java
index 0eb9917..16791a4 100644
--- a/telecomm/java/android/telecom/Log.java
+++ b/telecomm/java/android/telecom/Log.java
@@ -18,7 +18,6 @@
import android.content.Context;
import android.net.Uri;
-import android.os.AsyncTask;
import android.os.Build;
import android.telecom.Logging.EventManager;
import android.telecom.Logging.Session;
@@ -29,8 +28,6 @@
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.IndentingPrintWriter;
-import java.security.MessageDigest;
-import java.security.NoSuchAlgorithmException;
import java.util.IllegalFormatException;
import java.util.Locale;
@@ -373,6 +370,12 @@
return FORCE_LOGGING || android.util.Log.isLoggable(TAG, level);
}
+ /**
+ * Generates an obfuscated string for a calling handle in {@link Uri} format, or a raw phone
+ * phone number in {@link String} format.
+ * @param pii The information to obfuscate.
+ * @return The obfuscated string.
+ */
public static String piiHandle(Object pii) {
if (pii == null || VERBOSE) {
return String.valueOf(pii);
@@ -389,16 +392,7 @@
String textToObfuscate = uri.getSchemeSpecificPart();
if (PhoneAccount.SCHEME_TEL.equals(scheme)) {
- int numDigitsToObfuscate = getDialableCount(textToObfuscate)
- - NUM_DIALABLE_DIGITS_TO_LOG;
- for (int i = 0; i < textToObfuscate.length(); i++) {
- char c = textToObfuscate.charAt(i);
- boolean isDialable = PhoneNumberUtils.isDialable(c);
- if (isDialable) {
- numDigitsToObfuscate--;
- }
- sb.append(isDialable && numDigitsToObfuscate >= 0 ? "*" : c);
- }
+ obfuscatePhoneNumber(sb, textToObfuscate);
} else if (PhoneAccount.SCHEME_SIP.equals(scheme)) {
for (int i = 0; i < textToObfuscate.length(); i++) {
char c = textToObfuscate.charAt(i);
@@ -410,12 +404,34 @@
} else {
sb.append(pii(pii));
}
+ } else if (pii instanceof String) {
+ String number = (String) pii;
+ obfuscatePhoneNumber(sb, number);
}
return sb.toString();
}
/**
+ * Obfuscates a phone number, allowing NUM_DIALABLE_DIGITS_TO_LOG digits to be exposed for the
+ * phone number.
+ * @param sb String buffer to write obfuscated number to.
+ * @param phoneNumber The number to obfuscate.
+ */
+ private static void obfuscatePhoneNumber(StringBuilder sb, String phoneNumber) {
+ int numDigitsToObfuscate = getDialableCount(phoneNumber)
+ - NUM_DIALABLE_DIGITS_TO_LOG;
+ for (int i = 0; i < phoneNumber.length(); i++) {
+ char c = phoneNumber.charAt(i);
+ boolean isDialable = PhoneNumberUtils.isDialable(c);
+ if (isDialable) {
+ numDigitsToObfuscate--;
+ }
+ sb.append(isDialable && numDigitsToObfuscate >= 0 ? "*" : c);
+ }
+ }
+
+ /**
* Determines the number of dialable characters in a string.
* @param toCount The string to count dialable characters in.
* @return The count of dialable characters.
diff --git a/telephony/java/android/telephony/LocationAccessPolicy.java b/telephony/java/android/telephony/LocationAccessPolicy.java
index 24db438..d98f37d 100644
--- a/telephony/java/android/telephony/LocationAccessPolicy.java
+++ b/telephony/java/android/telephony/LocationAccessPolicy.java
@@ -42,7 +42,7 @@
public final class LocationAccessPolicy {
private static final String TAG = "LocationAccessPolicy";
private static final boolean DBG = false;
- public static final int MAX_SDK_FOR_ANY_ENFORCEMENT = Build.VERSION_CODES.P;
+ public static final int MAX_SDK_FOR_ANY_ENFORCEMENT = Build.VERSION_CODES.CUR_DEVELOPMENT;
public enum LocationPermissionResult {
ALLOWED,
@@ -198,14 +198,14 @@
// If the app fails for some reason, see if it should be allowed to proceed.
if (minSdkVersion > MAX_SDK_FOR_ANY_ENFORCEMENT) {
String errorMsg = "Allowing " + query.callingPackage + " " + locationTypeForLog
- + " because we're not enforcing API " + query.minSdkVersionForFine + " yet."
+ + " because we're not enforcing API " + minSdkVersion + " yet."
+ " Please fix this app because it will break in the future. Called from "
+ query.method;
logError(context, errorMsg);
return null;
} else if (!isAppAtLeastSdkVersion(context, query.callingPackage, minSdkVersion)) {
String errorMsg = "Allowing " + query.callingPackage + " " + locationTypeForLog
- + " because it doesn't target API " + query.minSdkVersionForFine + " yet."
+ + " because it doesn't target API " + minSdkVersion + " yet."
+ " Please fix this app. Called from " + query.method;
logError(context, errorMsg);
return null;
diff --git a/telephony/java/android/telephony/PhoneStateListener.java b/telephony/java/android/telephony/PhoneStateListener.java
index 3ce646c..ffebc04 100644
--- a/telephony/java/android/telephony/PhoneStateListener.java
+++ b/telephony/java/android/telephony/PhoneStateListener.java
@@ -297,14 +297,17 @@
public static final int LISTEN_PHONE_CAPABILITY_CHANGE = 0x00200000;
/**
- * Listen for changes to preferred data subId.
- * See {@link SubscriptionManager#setPreferredDataSubId(int)}
- * for more details.
+ * Listen for changes to active data subId. Active data subscription
+ * is whichever is being used for Internet data. For most of the case, it's
+ * default data subscription but it could be others. For example, when data is
+ * switched to opportunistic subscription, that becomes the active data sub.
*
- * @see #onPreferredDataSubIdChanged
+ * Requires Permission: {@link android.Manifest.permission#READ_PHONE_STATE
+ * READ_PHONE_STATE}
+ * @see #onActiveDataSubIdChanged
* @hide
*/
- public static final int LISTEN_PREFERRED_DATA_SUBID_CHANGE = 0x00400000;
+ public static final int LISTEN_ACTIVE_DATA_SUBID_CHANGE = 0x00400000;
/**
* Listen for changes to the radio power state.
@@ -710,14 +713,14 @@
}
/**
- * Callback invoked when preferred data subId changes. Requires
- * the READ_PRIVILEGED_PHONE_STATE permission.
- * @param subId the new preferred data subId. If it's INVALID_SUBSCRIPTION_ID,
- * it means it's unset and defaultDataSub is used to determine which
- * modem is preferred.
+ * Callback invoked when active data subId changes. Requires
+ * the READ_PHONE_STATE permission.
+ * @param subId current data subId used for Internet data. It will be default data subscription
+ * most cases. And it could be other subscriptions for example opportunistic
+ * subscription if data is switched onto it.
* @hide
*/
- public void onPreferredDataSubIdChanged(int subId) {
+ public void onActiveDataSubIdChanged(int subId) {
// default implementation empty
}
@@ -1001,12 +1004,12 @@
() -> mExecutor.execute(() -> psl.onCallAttributesChanged(callAttributes)));
}
- public void onPreferredDataSubIdChanged(int subId) {
+ public void onActiveDataSubIdChanged(int subId) {
PhoneStateListener psl = mPhoneStateListenerWeakRef.get();
if (psl == null) return;
Binder.withCleanCallingIdentity(
- () -> mExecutor.execute(() -> psl.onPreferredDataSubIdChanged(subId)));
+ () -> mExecutor.execute(() -> psl.onActiveDataSubIdChanged(subId)));
}
public void onImsCallDisconnectCauseChanged(ImsReasonInfo disconnectCause) {
diff --git a/telephony/java/android/telephony/ims/ImsCallProfile.java b/telephony/java/android/telephony/ims/ImsCallProfile.java
index d5c7079..47c8de5 100644
--- a/telephony/java/android/telephony/ims/ImsCallProfile.java
+++ b/telephony/java/android/telephony/ims/ImsCallProfile.java
@@ -548,7 +548,8 @@
+ ", emergencyServiceCategories=" + mEmergencyServiceCategories
+ ", emergencyUrns=" + mEmergencyUrns
+ ", emergencyCallRouting=" + mEmergencyCallRouting
- + ", emergencyCallTesting=" + mEmergencyCallTesting + " }";
+ + ", emergencyCallTesting=" + mEmergencyCallTesting
+ + ", hasKnownUserIntentEmergency=" + mHasKnownUserIntentEmergency + " }";
}
@Override
@@ -567,6 +568,7 @@
out.writeStringList(mEmergencyUrns);
out.writeInt(mEmergencyCallRouting);
out.writeBoolean(mEmergencyCallTesting);
+ out.writeBoolean(mHasKnownUserIntentEmergency);
}
private void readFromParcel(Parcel in) {
@@ -578,6 +580,7 @@
mEmergencyUrns = in.createStringArrayList();
mEmergencyCallRouting = in.readInt();
mEmergencyCallTesting = in.readBoolean();
+ mHasKnownUserIntentEmergency = in.readBoolean();
}
public static final Creator<ImsCallProfile> CREATOR = new Creator<ImsCallProfile>() {
diff --git a/telephony/java/com/android/internal/telephony/IPhoneStateListener.aidl b/telephony/java/com/android/internal/telephony/IPhoneStateListener.aidl
index 322ce45..4a263f0 100644
--- a/telephony/java/com/android/internal/telephony/IPhoneStateListener.aidl
+++ b/telephony/java/com/android/internal/telephony/IPhoneStateListener.aidl
@@ -54,7 +54,7 @@
void onCarrierNetworkChange(in boolean active);
void onUserMobileDataStateChanged(in boolean enabled);
void onPhoneCapabilityChanged(in PhoneCapability capability);
- void onPreferredDataSubIdChanged(in int subId);
+ void onActiveDataSubIdChanged(in int subId);
void onRadioPowerStateChanged(in int state);
void onCallAttributesChanged(in CallAttributes callAttributes);
void onEmergencyNumberListChanged(in Map emergencyNumberList);
diff --git a/telephony/java/com/android/internal/telephony/ITelephonyRegistry.aidl b/telephony/java/com/android/internal/telephony/ITelephonyRegistry.aidl
index e9eba32..a922ab6 100644
--- a/telephony/java/com/android/internal/telephony/ITelephonyRegistry.aidl
+++ b/telephony/java/com/android/internal/telephony/ITelephonyRegistry.aidl
@@ -81,7 +81,7 @@
void notifyCarrierNetworkChange(in boolean active);
void notifyUserMobileDataStateChangedForPhoneId(in int phoneId, in int subId, in boolean state);
void notifyPhoneCapabilityChanged(in PhoneCapability capability);
- void notifyPreferredDataSubIdChanged(int preferredSubId);
+ void notifyActiveDataSubIdChanged(int activeDataSubId);
void notifyRadioPowerStateChanged(in int state);
void notifyEmergencyNumberList();
void notifyCallQualityChanged(in CallQuality callQuality, int phoneId);
diff --git a/tests/DexLoggerIntegrationTests/src/com/android/server/pm/dex/DexLoggerIntegrationTests.java b/tests/DexLoggerIntegrationTests/src/com/android/server/pm/dex/DexLoggerIntegrationTests.java
index e92cc56..99d1f5ff4 100644
--- a/tests/DexLoggerIntegrationTests/src/com/android/server/pm/dex/DexLoggerIntegrationTests.java
+++ b/tests/DexLoggerIntegrationTests/src/com/android/server/pm/dex/DexLoggerIntegrationTests.java
@@ -49,13 +49,13 @@
import java.util.concurrent.TimeUnit;
/**
- * Integration tests for {@link com.android.server.pm.dex.DexLogger}.
+ * Integration tests for {@link DynamicCodeLogger}, formerly known as {@code DexLogger}.
*
* The setup for the test dynamically loads code in a jar extracted
* from our assets (a secondary dex file).
*
* We then use shell commands to trigger dynamic code logging (and wait
- * for it to complete). This causes DexLogger to log the hash of the
+ * for it to complete). This causes DynamicCodeLogger to log the hash of the
* file's name and content. We verify that this message appears in
* the event log.
*
@@ -65,6 +65,8 @@
@RunWith(JUnit4.class)
public final class DexLoggerIntegrationTests {
+ private static final String SHA_256 = "SHA-256";
+
// Event log tag used for SNET related events
private static final int SNET_TAG = 0x534e4554;
@@ -76,6 +78,13 @@
private static final int IDLE_LOGGING_JOB_ID = 2030028;
private static final int AUDIT_WATCHING_JOB_ID = 203142925;
+ // For tests that rely on parsing audit logs, how often to retry. (There are many reasons why
+ // we might not see the audit logs, including throttling and delays in log generation, so to
+ // avoid flakiness we run these tests multiple times, allowing progressively longer between
+ // code loading and checking the logs on each try.)
+ private static final int AUDIT_LOG_RETRIES = 10;
+ private static final int RETRY_DELAY_MS = 2_000;
+
private static Context sContext;
private static int sMyUid;
@@ -99,7 +108,7 @@
}
@Test
- public void testDexLoggerGeneratesEvents_standardClassLoader() throws Exception {
+ public void testGeneratesEvents_standardClassLoader() throws Exception {
File privateCopyFile = privateFile("copied.jar");
// Obtained via "echo -n copied.jar | sha256sum"
String expectedNameHash =
@@ -121,7 +130,7 @@
}
@Test
- public void testDexLoggerGeneratesEvents_unknownClassLoader() throws Exception {
+ public void testGeneratesEvents_unknownClassLoader() throws Exception {
File privateCopyFile = privateFile("copied2.jar");
String expectedNameHash =
"202158B6A3169D78F1722487205A6B036B3F2F5653FDCFB4E74710611AC7EB93";
@@ -143,79 +152,66 @@
}
@Test
- public void testDexLoggerGeneratesEvents_nativeLibrary() throws Exception {
- File privateCopyFile = privateFile("copied.so");
- String expectedNameHash =
- "996223BAD4B4FE75C57A3DEC61DB9C0B38E0A7AD479FC95F33494F4BC55A0F0E";
- String expectedContentHash =
- copyAndHashResource(libraryPath("DexLoggerNativeTestLibrary.so"), privateCopyFile);
+ public void testGeneratesEvents_nativeLibrary() throws Exception {
+ new TestNativeCodeWithRetries() {
+ @Override
+ protected void loadNativeCode(int tryNumber) throws Exception {
+ // We need to use a different file name for each retry, because once a file is
+ // loaded, re-loading it has no effect.
+ String privateCopyName = "copied" + tryNumber + ".so";
+ File privateCopyFile = privateFile(privateCopyName);
+ mExpectedNameHash = hashOf(privateCopyName);
+ mExpectedContentHash = copyAndHashResource(
+ libraryPath("DexLoggerNativeTestLibrary.so"), privateCopyFile);
- System.load(privateCopyFile.toString());
-
- // Run the job to scan generated audit log entries
- runDynamicCodeLoggingJob(AUDIT_WATCHING_JOB_ID);
-
- // And then make sure we log events about it
- long previousEventNanos = mostRecentEventTimeNanos();
- runDynamicCodeLoggingJob(IDLE_LOGGING_JOB_ID);
-
- assertDclLoggedSince(previousEventNanos, DCL_NATIVE_SUBTAG,
- expectedNameHash, expectedContentHash);
+ System.load(privateCopyFile.toString());
+ }
+ }.runTest();
}
@Test
- public void testDexLoggerGeneratesEvents_nativeLibrary_escapedName() throws Exception {
- // A file name with a space will be escaped in the audit log; verify we un-escape it
- // correctly.
- File privateCopyFile = privateFile("second copy.so");
- String expectedNameHash =
- "8C39990C560B4F36F83E208E279F678746FE23A790E4C50F92686584EA2041CA";
- String expectedContentHash =
- copyAndHashResource(libraryPath("DexLoggerNativeTestLibrary.so"), privateCopyFile);
+ public void testGeneratesEvents_nativeLibrary_escapedName() throws Exception {
+ new TestNativeCodeWithRetries() {
+ @Override
+ protected void loadNativeCode(int tryNumber) throws Exception {
+ // A file name with a space will be escaped in the audit log; verify we un-escape it
+ // correctly.
+ String privateCopyName = "second copy " + tryNumber + ".so";
+ File privateCopyFile = privateFile(privateCopyName);
+ mExpectedNameHash = hashOf(privateCopyName);
+ mExpectedContentHash = copyAndHashResource(
+ libraryPath("DexLoggerNativeTestLibrary.so"), privateCopyFile);
- System.load(privateCopyFile.toString());
-
- // Run the job to scan generated audit log entries
- runDynamicCodeLoggingJob(AUDIT_WATCHING_JOB_ID);
-
- // And then make sure we log events about it
- long previousEventNanos = mostRecentEventTimeNanos();
- runDynamicCodeLoggingJob(IDLE_LOGGING_JOB_ID);
-
- assertDclLoggedSince(previousEventNanos, DCL_NATIVE_SUBTAG,
- expectedNameHash, expectedContentHash);
+ System.load(privateCopyFile.toString());
+ }
+ }.runTest();
}
@Test
- public void testDexLoggerGeneratesEvents_nativeExecutable() throws Exception {
- File privateCopyFile = privateFile("test_executable");
- String expectedNameHash =
- "3FBEC3F925A132D18F347F11AE9A5BB8DE1238828F8B4E064AA86EB68BD46DCF";
- String expectedContentHash =
- copyAndHashResource("/DexLoggerNativeExecutable", privateCopyFile);
- assertThat(privateCopyFile.setExecutable(true)).isTrue();
+ public void testGeneratesEvents_nativeExecutable() throws Exception {
+ new TestNativeCodeWithRetries() {
+ @Override
+ protected void loadNativeCode(int tryNumber) throws Exception {
+ String privateCopyName = "test_executable" + tryNumber;
+ File privateCopyFile = privateFile(privateCopyName);
+ mExpectedNameHash = hashOf(privateCopyName);
+ mExpectedContentHash = copyAndHashResource(
+ "/DexLoggerNativeExecutable", privateCopyFile);
+ assertThat(privateCopyFile.setExecutable(true)).isTrue();
- Process process = Runtime.getRuntime().exec(privateCopyFile.toString());
- int exitCode = process.waitFor();
- assertThat(exitCode).isEqualTo(0);
-
- // Run the job to scan generated audit log entries
- runDynamicCodeLoggingJob(AUDIT_WATCHING_JOB_ID);
-
- // And then make sure we log events about it
- long previousEventNanos = mostRecentEventTimeNanos();
- runDynamicCodeLoggingJob(IDLE_LOGGING_JOB_ID);
-
- assertDclLoggedSince(previousEventNanos, DCL_NATIVE_SUBTAG,
- expectedNameHash, expectedContentHash);
+ Process process = Runtime.getRuntime().exec(privateCopyFile.toString());
+ int exitCode = process.waitFor();
+ assertThat(exitCode).isEqualTo(0);
+ }
+ }.runTest();
}
@Test
- public void testDexLoggerGeneratesEvents_spoofed_validFile() throws Exception {
+ public void testGeneratesEvents_spoofed_validFile() throws Exception {
File privateCopyFile = privateFile("spoofed");
- String expectedContentHash =
- copyAndHashResource("/DexLoggerNativeExecutable", privateCopyFile);
+ String expectedContentHash = copyAndHashResource(
+ "/DexLoggerNativeExecutable", privateCopyFile);
EventLog.writeEvent(EventLog.getTagCode("auditd"),
"type=1400 avc: granted { execute_no_trans } "
@@ -239,7 +235,7 @@
}
@Test
- public void testDexLoggerGeneratesEvents_spoofed_pathTraversal() throws Exception {
+ public void testGeneratesEvents_spoofed_pathTraversal() throws Exception {
File privateDir = privateFile("x").getParentFile();
// Transform /a/b/c -> /a/b/c/../../.. so we get back to the root
@@ -276,7 +272,7 @@
}
@Test
- public void testDexLoggerGeneratesEvents_spoofed_otherAppFile() throws Exception {
+ public void testGeneratesEvents_spoofed_otherAppFile() throws Exception {
File ourPath = sContext.getDatabasePath("android_pay");
File targetPath = new File(ourPath.toString()
.replace("com.android.frameworks.dexloggertest", "com.google.android.gms"));
@@ -304,6 +300,40 @@
assertNoDclLoggedSince(previousEventNanos, DCL_NATIVE_SUBTAG, expectedNameHash);
}
+ // Abstract out the logic for running a native code loading test multiple times if needed and
+ // leaving time for audit messages to reach the log.
+ private abstract class TestNativeCodeWithRetries {
+ String mExpectedContentHash;
+ String mExpectedNameHash;
+
+ abstract void loadNativeCode(int tryNumber) throws Exception;
+
+ final void runTest() throws Exception {
+ List<String> messages = null;
+
+ for (int i = 0; i < AUDIT_LOG_RETRIES; i++) {
+ loadNativeCode(i);
+
+ SystemClock.sleep(i * RETRY_DELAY_MS);
+
+ // Run the job to scan generated audit log entries
+ runDynamicCodeLoggingJob(AUDIT_WATCHING_JOB_ID);
+
+ // And then make sure we log events about it
+ long previousEventNanos = mostRecentEventTimeNanos();
+ runDynamicCodeLoggingJob(IDLE_LOGGING_JOB_ID);
+
+ messages = findMatchingEvents(
+ previousEventNanos, DCL_NATIVE_SUBTAG, mExpectedNameHash);
+ if (!messages.isEmpty()) {
+ break;
+ }
+ }
+
+ assertHasDclLog(messages, mExpectedContentHash);
+ }
+ }
+
private static File privateFile(String name) {
return new File(sContext.getDir("dcl", Context.MODE_PRIVATE), name);
}
@@ -315,7 +345,7 @@
}
private static String copyAndHashResource(String resourcePath, File copyTo) throws Exception {
- MessageDigest hasher = MessageDigest.getInstance("SHA-256");
+ MessageDigest hasher = MessageDigest.getInstance(SHA_256);
// Copy the jar from our Java resources to a private data directory
Class<?> thisClass = DexLoggerIntegrationTests.class;
@@ -334,6 +364,16 @@
// Compute the SHA-256 of the file content so we can check that it is the same as the value
// we see logged.
+ return toHexString(hasher);
+ }
+
+ private String hashOf(String input) throws Exception {
+ MessageDigest hasher = MessageDigest.getInstance(SHA_256);
+ hasher.update(input.getBytes());
+ return toHexString(hasher);
+ }
+
+ private static String toHexString(MessageDigest hasher) {
Formatter formatter = new Formatter();
for (byte b : hasher.digest()) {
formatter.format("%02X", b);
@@ -388,6 +428,10 @@
List<String> messages =
findMatchingEvents(previousEventNanos, expectedSubTag, expectedNameHash);
+ assertHasDclLog(messages, expectedContentHash);
+ }
+
+ private static void assertHasDclLog(List<String> messages, String expectedContentHash) {
assertWithMessage("Expected exactly one matching log entry").that(messages).hasSize(1);
assertThat(messages.get(0)).endsWith(expectedContentHash);
}
diff --git a/tests/HwAccelerationTest/Android.bp b/tests/HwAccelerationTest/Android.bp
new file mode 100644
index 0000000..37d3f5d
--- /dev/null
+++ b/tests/HwAccelerationTest/Android.bp
@@ -0,0 +1,22 @@
+//
+// Copyright (C) 2010 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT 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 {
+ name: "HwAccelerationTest",
+ srcs: ["**/*.java"],
+ platform_apis: true,
+ certificate: "platform",
+}
diff --git a/tests/HwAccelerationTest/Android.mk b/tests/HwAccelerationTest/Android.mk
deleted file mode 100644
index 79072fa..0000000
--- a/tests/HwAccelerationTest/Android.mk
+++ /dev/null
@@ -1,28 +0,0 @@
-#
-# Copyright (C) 2010 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES := $(call all-subdir-java-files)
-
-LOCAL_PACKAGE_NAME := HwAccelerationTest
-LOCAL_PRIVATE_PLATFORM_APIS := true
-LOCAL_CERTIFICATE := platform
-
-LOCAL_MODULE_TAGS := tests
-
-include $(BUILD_PACKAGE)
diff --git a/tests/Internal/src/com/android/internal/colorextraction/ColorExtractorTest.java b/tests/Internal/src/com/android/internal/colorextraction/ColorExtractorTest.java
index cb6a83d..39608a4 100644
--- a/tests/Internal/src/com/android/internal/colorextraction/ColorExtractorTest.java
+++ b/tests/Internal/src/com/android/internal/colorextraction/ColorExtractorTest.java
@@ -56,7 +56,7 @@
@Test
public void ColorExtractor_extractWhenInitialized() {
ExtractionType type = mock(Tonal.class);
- new ColorExtractor(mContext, type);
+ new ColorExtractor(mContext, type, true);
// 1 for lock and 1 for system
verify(type, times(2))
.extractInto(any(), any(), any(), any());
@@ -83,7 +83,7 @@
outGradientColorsDark.set(colorsExpectedDark);
outGradientColorsExtraDark.set(colorsExpectedExtraDark);
};
- ColorExtractor extractor = new ColorExtractor(mContext, type);
+ ColorExtractor extractor = new ColorExtractor(mContext, type, true);
GradientColors colors = extractor.getColors(WallpaperManager.FLAG_SYSTEM,
ColorExtractor.TYPE_NORMAL);
@@ -98,7 +98,7 @@
public void addOnColorsChangedListener_invokesListener() {
ColorExtractor.OnColorsChangedListener mockedListeners =
mock(ColorExtractor.OnColorsChangedListener.class);
- ColorExtractor extractor = new ColorExtractor(mContext, new Tonal(mContext));
+ ColorExtractor extractor = new ColorExtractor(mContext, new Tonal(mContext), true);
extractor.addOnColorsChangedListener(mockedListeners);
extractor.onColorsChanged(new WallpaperColors(Color.valueOf(Color.RED), null, null),
diff --git a/tests/JankBench/Android.bp b/tests/JankBench/Android.bp
new file mode 100644
index 0000000..166639d
--- /dev/null
+++ b/tests/JankBench/Android.bp
@@ -0,0 +1,21 @@
+android_test {
+ name: "JankBench",
+ manifest: "app/src/main/AndroidManifest.xml",
+ sdk_version: "current",
+ // omit gradle 'build' dir
+ srcs: ["app/src/main/java/**/*.java"],
+ // use appcompat/support lib from the tree, so improvements/
+ // regressions are reflected in test data
+ resource_dirs: ["app/src/main/res"],
+ static_libs: [
+ "com.google.android.material_material",
+ "androidx.legacy_legacy-support-v4",
+ "androidx.appcompat_appcompat",
+ "androidx.cardview_cardview",
+ "androidx.recyclerview_recyclerview",
+ "androidx.leanback_leanback",
+ "apache-commons-math",
+ "junit",
+ ],
+ test_suites: ["device-tests"],
+}
diff --git a/tests/JankBench/Android.mk b/tests/JankBench/Android.mk
deleted file mode 100644
index 89c21b7..0000000
--- a/tests/JankBench/Android.mk
+++ /dev/null
@@ -1,38 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_TAGS := tests
-
-LOCAL_MANIFEST_FILE := app/src/main/AndroidManifest.xml
-
-LOCAL_SDK_VERSION := current
-
-LOCAL_USE_AAPT2 := true
-
-# omit gradle 'build' dir
-LOCAL_SRC_FILES := $(call all-java-files-under,app/src/main/java)
-
-# use appcompat/support lib from the tree, so improvements/
-# regressions are reflected in test data
-LOCAL_RESOURCE_DIR := \
- $(LOCAL_PATH)/app/src/main/res \
-
-
-LOCAL_STATIC_ANDROID_LIBRARIES := \
- com.google.android.material_material \
- androidx.legacy_legacy-support-v4 \
- androidx.appcompat_appcompat \
- androidx.cardview_cardview \
- androidx.recyclerview_recyclerview \
- androidx.leanback_leanback \
-
-LOCAL_STATIC_JAVA_LIBRARIES := \
- apache-commons-math \
- junit
-
-
-LOCAL_PACKAGE_NAME := JankBench
-
-LOCAL_COMPATIBILITY_SUITE := device-tests
-
-include $(BUILD_PACKAGE)
diff --git a/tests/JankBench/app/src/main/jni/Android.bp.converted b/tests/JankBench/app/src/main/jni/Android.bp.converted
new file mode 100644
index 0000000..9fecf15
--- /dev/null
+++ b/tests/JankBench/app/src/main/jni/Android.bp.converted
@@ -0,0 +1,27 @@
+// Copyright (C) 2015 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+cc_library_shared {
+ name: "libnativebench",
+ cflags: [
+ "-Wno-unused-parameter",
+ "-Wno-unused-variable",
+ ],
+ srcs: [
+ "Bench.cpp",
+ "WorkerPool.cpp",
+ "test.cpp",
+ ],
+ host_ldlibs: ["-llog"],
+}
diff --git a/tests/JankBench/app/src/main/jni/Android.mk b/tests/JankBench/app/src/main/jni/Android.mk
deleted file mode 100644
index 8ba874de..0000000
--- a/tests/JankBench/app/src/main/jni/Android.mk
+++ /dev/null
@@ -1,31 +0,0 @@
-# Copyright (C) 2015 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-LOCAL_PATH := $(call my-dir)
-LOCAL_SDK_VERSION := 26
-
-include $(CLEAR_VARS)
-
-LOCAL_CFLAGS = -Wno-unused-parameter
-
-LOCAL_MODULE:= libnativebench
-
-LOCAL_SRC_FILES := \
- Bench.cpp \
- WorkerPool.cpp \
- test.cpp
-
-LOCAL_LDLIBS := -llog
-
-include $(BUILD_SHARED_LIBRARY)
diff --git a/tests/RollbackTest/Android.mk b/tests/RollbackTest/Android.mk
index 40d4eff..0967ad3 100644
--- a/tests/RollbackTest/Android.mk
+++ b/tests/RollbackTest/Android.mk
@@ -71,7 +71,7 @@
# RollbackTest
include $(CLEAR_VARS)
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
+LOCAL_SRC_FILES := $(call all-java-files-under, RollbackTest/src)
LOCAL_PACKAGE_NAME := RollbackTest
LOCAL_MODULE_TAGS := tests
LOCAL_STATIC_JAVA_LIBRARIES := android-support-test
@@ -84,10 +84,21 @@
$(ROLLBACK_TEST_APP_BV1) \
$(ROLLBACK_TEST_APP_BV2) \
$(ROLLBACK_TEST_APEX_V2)
+LOCAL_MANIFEST_FILE := RollbackTest/AndroidManifest.xml
LOCAL_SDK_VERSION := system_current
LOCAL_TEST_CONFIG := RollbackTest.xml
include $(BUILD_PACKAGE)
+# StagedRollbackTest
+include $(CLEAR_VARS)
+LOCAL_SRC_FILES := $(call all-java-files-under, StagedRollbackTest/src)
+LOCAL_MODULE := StagedRollbackTest
+LOCAL_MODULE_TAGS := tests
+LOCAL_JAVA_LIBRARIES := tradefed
+LOCAL_COMPATIBILITY_SUITE := general-tests
+LOCAL_TEST_CONFIG := StagedRollbackTest.xml
+include $(BUILD_HOST_JAVA_LIBRARY)
+
# Clean up local variables
ROLLBACK_TEST_APP_AV1 :=
ROLLBACK_TEST_APP_AV2 :=
diff --git a/tests/RollbackTest/README.txt b/tests/RollbackTest/README.txt
new file mode 100644
index 0000000..c0b718a
--- /dev/null
+++ b/tests/RollbackTest/README.txt
@@ -0,0 +1,23 @@
+This directory contains a test for the rollback manager service.
+
+Directory structure
+===================
+RollbackTest
+ - device driven test for rollbacks not involving staged rollbacks.
+
+StagedRollbackTest
+ - device driven test for staged rollbacks.
+
+TestApp
+ - source for dummy apks used in testing.
+
+TestApex
+ - source for dummy apex modules used in testing.
+
+Running the tests
+=================
+
+You can manually run the tests as follows:
+
+ atest RollbackTest
+ atest StagedRollbackTest
diff --git a/tests/RollbackTest/RollbackTest.xml b/tests/RollbackTest/RollbackTest.xml
index adbad56..ac39f85 100644
--- a/tests/RollbackTest/RollbackTest.xml
+++ b/tests/RollbackTest/RollbackTest.xml
@@ -21,5 +21,9 @@
<test class="com.android.tradefed.testtype.AndroidJUnitTest" >
<option name="package" value="com.android.tests.rollback" />
<option name="runner" value="android.support.test.runner.AndroidJUnitRunner" />
+
+ <!-- Exclude the StagedRollbackTest tests, which needs to be specially
+ driven from the StagedRollbackTest host test -->
+ <option name="exclude-filter" value="com.android.tests.rollback.StagedRollbackTest" />
</test>
</configuration>
diff --git a/tests/RollbackTest/AndroidManifest.xml b/tests/RollbackTest/RollbackTest/AndroidManifest.xml
similarity index 100%
rename from tests/RollbackTest/AndroidManifest.xml
rename to tests/RollbackTest/RollbackTest/AndroidManifest.xml
diff --git a/tests/RollbackTest/src/com/android/tests/rollback/LocalIntentSender.java b/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/LocalIntentSender.java
similarity index 100%
rename from tests/RollbackTest/src/com/android/tests/rollback/LocalIntentSender.java
rename to tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/LocalIntentSender.java
diff --git a/tests/RollbackTest/src/com/android/tests/rollback/RollbackBroadcastReceiver.java b/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/RollbackBroadcastReceiver.java
similarity index 100%
rename from tests/RollbackTest/src/com/android/tests/rollback/RollbackBroadcastReceiver.java
rename to tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/RollbackBroadcastReceiver.java
diff --git a/tests/RollbackTest/src/com/android/tests/rollback/RollbackTest.java b/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/RollbackTest.java
similarity index 92%
rename from tests/RollbackTest/src/com/android/tests/rollback/RollbackTest.java
rename to tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/RollbackTest.java
index f07ae9f..f3edf09 100644
--- a/tests/RollbackTest/src/com/android/tests/rollback/RollbackTest.java
+++ b/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/RollbackTest.java
@@ -16,6 +16,10 @@
package com.android.tests.rollback;
+import static com.android.tests.rollback.RollbackTestUtils.assertPackageRollbackInfoEquals;
+import static com.android.tests.rollback.RollbackTestUtils.assertRollbackInfoEquals;
+import static com.android.tests.rollback.RollbackTestUtils.getUniqueRollbackInfoForPackage;
+
import android.Manifest;
import android.app.ActivityManager;
import android.content.BroadcastReceiver;
@@ -24,7 +28,6 @@
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.VersionedPackage;
-import android.content.rollback.PackageRollbackInfo;
import android.content.rollback.RollbackInfo;
import android.content.rollback.RollbackManager;
import android.os.Handler;
@@ -42,7 +45,6 @@
import org.junit.runners.JUnit4;
import java.util.Collections;
-import java.util.List;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.SynchronousQueue;
@@ -617,17 +619,6 @@
}
}
- // Helper function to test the value of a PackageRollbackInfo
- private void assertPackageRollbackInfoEquals(String packageName,
- long versionRolledBackFrom, long versionRolledBackTo,
- PackageRollbackInfo info) {
- assertEquals(packageName, info.getPackageName());
- assertEquals(packageName, info.getVersionRolledBackFrom().getPackageName());
- assertEquals(versionRolledBackFrom, info.getVersionRolledBackFrom().getLongVersionCode());
- assertEquals(packageName, info.getVersionRolledBackTo().getPackageName());
- assertEquals(versionRolledBackTo, info.getVersionRolledBackTo().getLongVersionCode());
- }
-
/**
* Test bad update automatic rollback.
*/
@@ -713,23 +704,6 @@
}
}
- // Helper function to test the value of a RollbackInfo with single package
- private void assertRollbackInfoEquals(String packageName,
- long versionRolledBackFrom, long versionRolledBackTo,
- RollbackInfo info, VersionedPackage... causePackages) {
- assertNotNull(info);
- assertEquals(1, info.getPackages().size());
- assertPackageRollbackInfoEquals(packageName, versionRolledBackFrom, versionRolledBackTo,
- info.getPackages().get(0));
- assertEquals(causePackages.length, info.getCausePackages().size());
- for (int i = 0; i < causePackages.length; ++i) {
- assertEquals(causePackages[i].getPackageName(),
- info.getCausePackages().get(i).getPackageName());
- assertEquals(causePackages[i].getLongVersionCode(),
- info.getCausePackages().get(i).getLongVersionCode());
- }
- }
-
// Helper function to test that the given rollback info is a rollback for
// the atomic set {A2, B2} -> {A1, B1}.
private void assertRollbackInfoForAandB(RollbackInfo rollback) {
@@ -743,23 +717,4 @@
assertPackageRollbackInfoEquals(TEST_APP_A, 2, 1, rollback.getPackages().get(1));
}
}
-
- // Helper function to return the RollbackInfo with a given package in the
- // list of rollbacks. Throws an assertion failure if there is more than
- // one such rollback info. Returns null if there are no such rollback
- // infos.
- private RollbackInfo getUniqueRollbackInfoForPackage(List<RollbackInfo> rollbacks,
- String packageName) {
- RollbackInfo found = null;
- for (RollbackInfo rollback : rollbacks) {
- for (PackageRollbackInfo info : rollback.getPackages()) {
- if (packageName.equals(info.getPackageName())) {
- assertNull(found);
- found = rollback;
- break;
- }
- }
- }
- return found;
- }
}
diff --git a/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/RollbackTestUtils.java b/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/RollbackTestUtils.java
new file mode 100644
index 0000000..280ee1d
--- /dev/null
+++ b/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/RollbackTestUtils.java
@@ -0,0 +1,375 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.tests.rollback;
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.content.pm.PackageInfo;
+import android.content.pm.PackageInstaller;
+import android.content.pm.PackageManager;
+import android.content.pm.VersionedPackage;
+import android.content.rollback.PackageRollbackInfo;
+import android.content.rollback.RollbackInfo;
+import android.content.rollback.RollbackManager;
+import android.support.test.InstrumentationRegistry;
+import android.util.Log;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.Arrays;
+import java.util.List;
+import java.util.concurrent.BlockingQueue;
+import java.util.concurrent.LinkedBlockingQueue;
+
+/**
+ * Utilities to facilitate testing rollbacks.
+ */
+class RollbackTestUtils {
+
+ private static final String TAG = "RollbackTest";
+
+ static RollbackManager getRollbackManager() {
+ Context context = InstrumentationRegistry.getContext();
+ RollbackManager rm = (RollbackManager) context.getSystemService(Context.ROLLBACK_SERVICE);
+ if (rm == null) {
+ throw new AssertionError("Failed to get RollbackManager");
+ }
+ return rm;
+ }
+
+ /**
+ * Returns the version of the given package installed on device.
+ * Returns -1 if the package is not currently installed.
+ */
+ static long getInstalledVersion(String packageName) {
+ Context context = InstrumentationRegistry.getContext();
+ PackageManager pm = context.getPackageManager();
+ try {
+ PackageInfo info = pm.getPackageInfo(packageName, 0);
+ return info.getLongVersionCode();
+ } catch (PackageManager.NameNotFoundException e) {
+ return -1;
+ }
+ }
+
+ private static void assertStatusSuccess(Intent result) {
+ int status = result.getIntExtra(PackageInstaller.EXTRA_STATUS,
+ PackageInstaller.STATUS_FAILURE);
+ if (status == -1) {
+ throw new AssertionError("PENDING USER ACTION");
+ } else if (status > 0) {
+ String message = result.getStringExtra(PackageInstaller.EXTRA_STATUS_MESSAGE);
+ throw new AssertionError(message == null ? "UNKNOWN FAILURE" : message);
+ }
+ }
+
+ /**
+ * Uninstalls the given package.
+ * Does nothing if the package is not installed.
+ * @throws AssertionError if package can't be uninstalled.
+ */
+ static void uninstall(String packageName) throws InterruptedException, IOException {
+ // No need to uninstall if the package isn't installed.
+ if (getInstalledVersion(packageName) == -1) {
+ return;
+ }
+
+ Context context = InstrumentationRegistry.getContext();
+ PackageManager packageManager = context.getPackageManager();
+ PackageInstaller packageInstaller = packageManager.getPackageInstaller();
+ packageInstaller.uninstall(packageName, LocalIntentSender.getIntentSender());
+ assertStatusSuccess(LocalIntentSender.getIntentSenderResult());
+ }
+
+ /**
+ * Commit the given rollback.
+ * @throws AssertionError if the rollback fails.
+ */
+ static void rollback(int rollbackId, VersionedPackage... causePackages)
+ throws InterruptedException {
+ RollbackManager rm = getRollbackManager();
+ rm.commitRollback(rollbackId, Arrays.asList(causePackages),
+ LocalIntentSender.getIntentSender());
+ Intent result = LocalIntentSender.getIntentSenderResult();
+ int status = result.getIntExtra(RollbackManager.EXTRA_STATUS,
+ RollbackManager.STATUS_FAILURE);
+ if (status != RollbackManager.STATUS_SUCCESS) {
+ String message = result.getStringExtra(RollbackManager.EXTRA_STATUS_MESSAGE);
+ throw new AssertionError(message);
+ }
+ }
+
+ /**
+ * Installs the apk with the given name.
+ *
+ * @param resourceName name of class loader resource for the apk to
+ * install.
+ * @param enableRollback if rollback should be enabled.
+ * @throws AssertionError if the installation fails.
+ */
+ static void install(String resourceName, boolean enableRollback)
+ throws InterruptedException, IOException {
+ Context context = InstrumentationRegistry.getContext();
+ PackageInstaller.Session session = null;
+ PackageInstaller packageInstaller = context.getPackageManager().getPackageInstaller();
+ PackageInstaller.SessionParams params = new PackageInstaller.SessionParams(
+ PackageInstaller.SessionParams.MODE_FULL_INSTALL);
+ if (enableRollback) {
+ params.setEnableRollback();
+ }
+ int sessionId = packageInstaller.createSession(params);
+ session = packageInstaller.openSession(sessionId);
+
+ ClassLoader loader = RollbackTest.class.getClassLoader();
+ try (OutputStream packageInSession = session.openWrite("package", 0, -1);
+ InputStream is = loader.getResourceAsStream(resourceName);) {
+ byte[] buffer = new byte[4096];
+ int n;
+ while ((n = is.read(buffer)) >= 0) {
+ packageInSession.write(buffer, 0, n);
+ }
+ }
+
+ // Commit the session (this will start the installation workflow).
+ session.commit(LocalIntentSender.getIntentSender());
+ assertStatusSuccess(LocalIntentSender.getIntentSenderResult());
+ }
+
+ /** Launches {@code packageName} with {@link Intent#ACTION_MAIN}. */
+ static void launchPackage(String packageName)
+ throws InterruptedException, IOException {
+ Context context = InstrumentationRegistry.getContext();
+ Intent intent = new Intent(Intent.ACTION_MAIN);
+ intent.setPackage(packageName);
+ intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ intent.addCategory(Intent.CATEGORY_LAUNCHER);
+ context.startActivity(intent);
+ }
+
+ /**
+ * Installs the apks with the given resource names as an atomic set.
+ * <p>
+ * In case of staged installs, this function will return succesfully after
+ * the staged install has been committed and is ready for the device to
+ * reboot.
+ *
+ * @param staged if the rollback should be staged.
+ * @param enableRollback if rollback should be enabled.
+ * @param resourceNames names of the class loader resource for the apks to
+ * install.
+ * @throws AssertionError if the installation fails.
+ */
+ private static void install(boolean staged, boolean enableRollback,
+ String... resourceNames) throws InterruptedException, IOException {
+ Context context = InstrumentationRegistry.getContext();
+ PackageInstaller packageInstaller = context.getPackageManager().getPackageInstaller();
+
+ PackageInstaller.SessionParams multiPackageParams = new PackageInstaller.SessionParams(
+ PackageInstaller.SessionParams.MODE_FULL_INSTALL);
+ multiPackageParams.setMultiPackage();
+ if (staged) {
+ multiPackageParams.setStaged();
+ }
+ if (enableRollback) {
+ // TODO: Do we set this on the parent params, the child params, or
+ // both?
+ multiPackageParams.setEnableRollback();
+ }
+ int multiPackageId = packageInstaller.createSession(multiPackageParams);
+ PackageInstaller.Session multiPackage = packageInstaller.openSession(multiPackageId);
+
+ for (String resourceName : resourceNames) {
+ PackageInstaller.Session session = null;
+ PackageInstaller.SessionParams params = new PackageInstaller.SessionParams(
+ PackageInstaller.SessionParams.MODE_FULL_INSTALL);
+ if (staged) {
+ params.setStaged();
+ }
+ if (enableRollback) {
+ params.setEnableRollback();
+ }
+ int sessionId = packageInstaller.createSession(params);
+ session = packageInstaller.openSession(sessionId);
+
+ ClassLoader loader = RollbackTest.class.getClassLoader();
+ try (OutputStream packageInSession = session.openWrite("package", 0, -1);
+ InputStream is = loader.getResourceAsStream(resourceName);) {
+ byte[] buffer = new byte[4096];
+ int n;
+ while ((n = is.read(buffer)) >= 0) {
+ packageInSession.write(buffer, 0, n);
+ }
+ }
+ multiPackage.addChildSessionId(sessionId);
+ }
+
+ // Commit the session (this will start the installation workflow).
+ multiPackage.commit(LocalIntentSender.getIntentSender());
+ assertStatusSuccess(LocalIntentSender.getIntentSenderResult());
+
+ if (staged) {
+ waitForSessionReady(multiPackageId);
+ }
+ }
+
+ /**
+ * Installs the apks with the given resource names as an atomic set.
+ *
+ * @param enableRollback if rollback should be enabled.
+ * @param resourceNames names of the class loader resource for the apks to
+ * install.
+ * @throws AssertionError if the installation fails.
+ */
+ static void installMultiPackage(boolean enableRollback, String... resourceNames)
+ throws InterruptedException, IOException {
+ install(false, enableRollback, resourceNames);
+ }
+
+ /**
+ * Installs the apks with the given resource names as a staged atomic set.
+ *
+ * @param enableRollback if rollback should be enabled.
+ * @param resourceNames names of the class loader resource for the apks to
+ * install.
+ * @throws AssertionError if the installation fails.
+ */
+ static void installStaged(boolean enableRollback, String... resourceNames)
+ throws InterruptedException, IOException {
+ install(true, enableRollback, resourceNames);
+ }
+
+ static void adoptShellPermissionIdentity(String... permissions) {
+ InstrumentationRegistry
+ .getInstrumentation()
+ .getUiAutomation()
+ .adoptShellPermissionIdentity(permissions);
+ }
+
+ static void dropShellPermissionIdentity() {
+ InstrumentationRegistry
+ .getInstrumentation()
+ .getUiAutomation()
+ .dropShellPermissionIdentity();
+ }
+
+ /**
+ * Returns the RollbackInfo with a given package in the list of rollbacks.
+ * Throws an assertion failure if there is more than one such rollback
+ * info. Returns null if there are no such rollback infos.
+ */
+ static RollbackInfo getUniqueRollbackInfoForPackage(List<RollbackInfo> rollbacks,
+ String packageName) {
+ RollbackInfo found = null;
+ for (RollbackInfo rollback : rollbacks) {
+ for (PackageRollbackInfo info : rollback.getPackages()) {
+ if (packageName.equals(info.getPackageName())) {
+ assertNull(found);
+ found = rollback;
+ break;
+ }
+ }
+ }
+ return found;
+ }
+
+ /**
+ * Asserts that the given PackageRollbackInfo has the expected package
+ * name and versions.
+ */
+ static void assertPackageRollbackInfoEquals(String packageName,
+ long versionRolledBackFrom, long versionRolledBackTo,
+ PackageRollbackInfo info) {
+ assertEquals(packageName, info.getPackageName());
+ assertEquals(packageName, info.getVersionRolledBackFrom().getPackageName());
+ assertEquals(versionRolledBackFrom, info.getVersionRolledBackFrom().getLongVersionCode());
+ assertEquals(packageName, info.getVersionRolledBackTo().getPackageName());
+ assertEquals(versionRolledBackTo, info.getVersionRolledBackTo().getLongVersionCode());
+ }
+
+ /**
+ * Asserts that the given RollbackInfo has a single package with expected
+ * package name and versions.
+ */
+ static void assertRollbackInfoEquals(String packageName,
+ long versionRolledBackFrom, long versionRolledBackTo,
+ RollbackInfo info, VersionedPackage... causePackages) {
+ assertNotNull(info);
+ assertEquals(1, info.getPackages().size());
+ assertPackageRollbackInfoEquals(packageName, versionRolledBackFrom, versionRolledBackTo,
+ info.getPackages().get(0));
+ assertEquals(causePackages.length, info.getCausePackages().size());
+ for (int i = 0; i < causePackages.length; ++i) {
+ assertEquals(causePackages[i].getPackageName(),
+ info.getCausePackages().get(i).getPackageName());
+ assertEquals(causePackages[i].getLongVersionCode(),
+ info.getCausePackages().get(i).getLongVersionCode());
+ }
+ }
+
+ /**
+ * Waits for the given session to be marked as ready.
+ * Throws an assertion if the session fails.
+ */
+ static void waitForSessionReady(int sessionId) {
+ BlockingQueue<PackageInstaller.SessionInfo> sessionStatus = new LinkedBlockingQueue<>();
+ BroadcastReceiver sessionUpdatedReceiver = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ PackageInstaller.SessionInfo info =
+ intent.getParcelableExtra(PackageInstaller.EXTRA_SESSION);
+ if (info != null && info.getSessionId() == sessionId) {
+ if (info.isSessionReady() || info.isSessionFailed()) {
+ try {
+ sessionStatus.put(info);
+ } catch (InterruptedException e) {
+ Log.e(TAG, "Failed to put session info.", e);
+ }
+ }
+ }
+ }
+ };
+ IntentFilter sessionUpdatedFilter =
+ new IntentFilter(PackageInstaller.ACTION_SESSION_UPDATED);
+
+ Context context = InstrumentationRegistry.getContext();
+ context.registerReceiver(sessionUpdatedReceiver, sessionUpdatedFilter);
+
+ PackageInstaller installer = context.getPackageManager().getPackageInstaller();
+ PackageInstaller.SessionInfo info = installer.getSessionInfo(sessionId);
+
+ try {
+ if (info.isSessionReady() || info.isSessionFailed()) {
+ sessionStatus.put(info);
+ }
+
+ info = sessionStatus.take();
+ context.unregisterReceiver(sessionUpdatedReceiver);
+ if (info.isSessionFailed()) {
+ throw new AssertionError(info.getStagedSessionErrorMessage());
+ }
+ } catch (InterruptedException e) {
+ throw new AssertionError(e);
+ }
+ }
+}
diff --git a/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/StagedRollbackTest.java b/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/StagedRollbackTest.java
new file mode 100644
index 0000000..297bf86
--- /dev/null
+++ b/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/StagedRollbackTest.java
@@ -0,0 +1,131 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.tests.rollback;
+
+import static com.android.tests.rollback.RollbackTestUtils.assertRollbackInfoEquals;
+import static com.android.tests.rollback.RollbackTestUtils.getUniqueRollbackInfoForPackage;
+
+import android.Manifest;
+import android.content.rollback.RollbackInfo;
+import android.content.rollback.RollbackManager;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotEquals;
+import static org.junit.Assert.assertTrue;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+/**
+ * Tests for rollback of staged installs.
+ * <p>
+ * Note: These tests require reboot in between test phases. They are run
+ * specially so that the testFooEnableRollback, testFooCommitRollback, and
+ * testFooConfirmRollback phases of each test are run in order with reboots in
+ * between them.
+ */
+@RunWith(JUnit4.class)
+public class StagedRollbackTest {
+
+ private static final String TAG = "RollbackTest";
+ private static final String TEST_APP_A = "com.android.tests.rollback.testapp.A";
+
+ /**
+ * Adopts common shell permissions needed for rollback tests.
+ */
+ @Before
+ public void adoptShellPermissions() {
+ RollbackTestUtils.adoptShellPermissionIdentity(
+ Manifest.permission.INSTALL_PACKAGES,
+ Manifest.permission.DELETE_PACKAGES,
+ Manifest.permission.MANAGE_ROLLBACKS);
+ }
+
+ /**
+ * Drops shell permissions needed for rollback tests.
+ */
+ @After
+ public void dropShellPermissions() {
+ RollbackTestUtils.dropShellPermissionIdentity();
+ }
+
+
+ /**
+ * Test basic rollbacks. Enable rollback phase.
+ */
+ @Test
+ public void testBasicEnableRollback() throws Exception {
+ RollbackTestUtils.uninstall(TEST_APP_A);
+ assertEquals(-1, RollbackTestUtils.getInstalledVersion(TEST_APP_A));
+
+ RollbackTestUtils.install("RollbackTestAppAv1.apk", false);
+ assertEquals(1, RollbackTestUtils.getInstalledVersion(TEST_APP_A));
+
+ RollbackTestUtils.installStaged(true, "RollbackTestAppAv2.apk");
+
+ // At this point, the host test driver will reboot the device and run
+ // testBasicCommitRollback().
+ }
+
+ /**
+ * Test basic rollbacks. Commit rollback phase.
+ */
+ @Test
+ public void testBasicCommitRollback() throws Exception {
+ assertEquals(2, RollbackTestUtils.getInstalledVersion(TEST_APP_A));
+
+ RollbackManager rm = RollbackTestUtils.getRollbackManager();
+ RollbackInfo rollback = getUniqueRollbackInfoForPackage(
+ rm.getAvailableRollbacks(), TEST_APP_A);
+ assertRollbackInfoEquals(TEST_APP_A, 2, 1, rollback);
+ assertTrue(rollback.isStaged());
+
+ RollbackTestUtils.rollback(rollback.getRollbackId());
+
+ rollback = getUniqueRollbackInfoForPackage(
+ rm.getRecentlyCommittedRollbacks(), TEST_APP_A);
+ assertRollbackInfoEquals(TEST_APP_A, 2, 1, rollback);
+ assertTrue(rollback.isStaged());
+ assertNotEquals(-1, rollback.getCommittedSessionId());
+
+ RollbackTestUtils.waitForSessionReady(rollback.getCommittedSessionId());
+
+ // The app should not be rolled back until after reboot.
+ assertEquals(2, RollbackTestUtils.getInstalledVersion(TEST_APP_A));
+
+ // At this point, the host test driver will reboot the device and run
+ // testBasicConfirmRollback().
+ }
+
+ /**
+ * Test basic rollbacks. Confirm rollback phase.
+ */
+ @Test
+ public void testBasicConfirmRollback() throws Exception {
+ assertEquals(1, RollbackTestUtils.getInstalledVersion(TEST_APP_A));
+
+ RollbackManager rm = RollbackTestUtils.getRollbackManager();
+ RollbackInfo rollback = getUniqueRollbackInfoForPackage(
+ rm.getRecentlyCommittedRollbacks(), TEST_APP_A);
+ assertRollbackInfoEquals(TEST_APP_A, 2, 1, rollback);
+ assertTrue(rollback.isStaged());
+ assertNotEquals(-1, rollback.getCommittedSessionId());
+ }
+}
diff --git a/tests/RollbackTest/StagedRollbackTest.xml b/tests/RollbackTest/StagedRollbackTest.xml
new file mode 100644
index 0000000..2750d37
--- /dev/null
+++ b/tests/RollbackTest/StagedRollbackTest.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+<configuration description="Runs the staged rollback tests">
+ <option name="test-suite-tag" value="StagedRollbackTest" />
+ <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
+ <option name="cleanup-apks" value="true" />
+ <option name="test-file-name" value="RollbackTest.apk" />
+ </target_preparer>
+ <test class="com.android.tradefed.testtype.HostTest" >
+ <option name="class" value="com.android.tests.rollback.host.StagedRollbackTest" />
+ </test>
+</configuration>
diff --git a/tests/RollbackTest/StagedRollbackTest/src/com/android/tests/rollback/host/StagedRollbackTest.java b/tests/RollbackTest/StagedRollbackTest/src/com/android/tests/rollback/host/StagedRollbackTest.java
new file mode 100644
index 0000000..6cb0dd0
--- /dev/null
+++ b/tests/RollbackTest/StagedRollbackTest/src/com/android/tests/rollback/host/StagedRollbackTest.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.tests.rollback.host;
+
+import static org.junit.Assert.assertTrue;
+
+import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
+import com.android.tradefed.testtype.junit4.BaseHostJUnit4Test;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+/**
+ * Runs the staged rollback tests.
+ */
+@RunWith(DeviceJUnit4ClassRunner.class)
+public class StagedRollbackTest extends BaseHostJUnit4Test {
+
+ /**
+ * Runs the given phase of a test by calling into the device.
+ * Throws an exception if the test phase fails.
+ * <p>
+ * For example, <code>runPhase("testBasicEnableRollback");</code>
+ */
+ private void runPhase(String phase) throws Exception {
+ assertTrue(runDeviceTests("com.android.tests.rollback",
+ "com.android.tests.rollback.StagedRollbackTest",
+ phase));
+ }
+
+ /**
+ * Tests staged rollbacks.
+ */
+ @Test
+ public void testBasic() throws Exception {
+ runPhase("testBasicEnableRollback");
+ getDevice().reboot();
+ runPhase("testBasicCommitRollback");
+ getDevice().reboot();
+ runPhase("testBasicConfirmRollback");
+ }
+}
diff --git a/tests/RollbackTest/TEST_MAPPING b/tests/RollbackTest/TEST_MAPPING
index c1d95ac..6be93a0 100644
--- a/tests/RollbackTest/TEST_MAPPING
+++ b/tests/RollbackTest/TEST_MAPPING
@@ -2,6 +2,9 @@
"presubmit": [
{
"name": "RollbackTest"
+ },
+ {
+ "name": "StagedRollbackTest"
}
]
}
diff --git a/tests/RollbackTest/src/com/android/tests/rollback/RollbackTestUtils.java b/tests/RollbackTest/src/com/android/tests/rollback/RollbackTestUtils.java
deleted file mode 100644
index 60c7a59..0000000
--- a/tests/RollbackTest/src/com/android/tests/rollback/RollbackTestUtils.java
+++ /dev/null
@@ -1,222 +0,0 @@
-/*
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.tests.rollback;
-
-import android.content.Context;
-import android.content.Intent;
-import android.content.pm.PackageInfo;
-import android.content.pm.PackageInstaller;
-import android.content.pm.PackageManager;
-import android.content.pm.VersionedPackage;
-import android.content.rollback.RollbackManager;
-import android.support.test.InstrumentationRegistry;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.util.Arrays;
-
-/**
- * Utilities to facilitate testing rollbacks.
- */
-class RollbackTestUtils {
-
- private static final String TAG = "RollbackTest";
-
- static RollbackManager getRollbackManager() {
- Context context = InstrumentationRegistry.getContext();
- RollbackManager rm = (RollbackManager) context.getSystemService(Context.ROLLBACK_SERVICE);
- if (rm == null) {
- throw new AssertionError("Failed to get RollbackManager");
- }
- return rm;
- }
-
- /**
- * Returns the version of the given package installed on device.
- * Returns -1 if the package is not currently installed.
- */
- static long getInstalledVersion(String packageName) {
- Context context = InstrumentationRegistry.getContext();
- PackageManager pm = context.getPackageManager();
- try {
- PackageInfo info = pm.getPackageInfo(packageName, 0);
- return info.getLongVersionCode();
- } catch (PackageManager.NameNotFoundException e) {
- return -1;
- }
- }
-
- private static void assertStatusSuccess(Intent result) {
- int status = result.getIntExtra(PackageInstaller.EXTRA_STATUS,
- PackageInstaller.STATUS_FAILURE);
- if (status == -1) {
- throw new AssertionError("PENDING USER ACTION");
- } else if (status > 0) {
- String message = result.getStringExtra(PackageInstaller.EXTRA_STATUS_MESSAGE);
- throw new AssertionError(message == null ? "UNKNOWN FAILURE" : message);
- }
- }
-
- /**
- * Uninstalls the given package.
- * Does nothing if the package is not installed.
- * @throws AssertionError if package can't be uninstalled.
- */
- static void uninstall(String packageName) throws InterruptedException, IOException {
- // No need to uninstall if the package isn't installed.
- if (getInstalledVersion(packageName) == -1) {
- return;
- }
-
- Context context = InstrumentationRegistry.getContext();
- PackageManager packageManager = context.getPackageManager();
- PackageInstaller packageInstaller = packageManager.getPackageInstaller();
- packageInstaller.uninstall(packageName, LocalIntentSender.getIntentSender());
- assertStatusSuccess(LocalIntentSender.getIntentSenderResult());
- }
-
- /**
- * Commit the given rollback.
- * @throws AssertionError if the rollback fails.
- */
- static void rollback(int rollbackId, VersionedPackage... causePackages)
- throws InterruptedException {
- RollbackManager rm = getRollbackManager();
- rm.commitRollback(rollbackId, Arrays.asList(causePackages),
- LocalIntentSender.getIntentSender());
- Intent result = LocalIntentSender.getIntentSenderResult();
- int status = result.getIntExtra(RollbackManager.EXTRA_STATUS,
- RollbackManager.STATUS_FAILURE);
- if (status != RollbackManager.STATUS_SUCCESS) {
- String message = result.getStringExtra(RollbackManager.EXTRA_STATUS_MESSAGE);
- throw new AssertionError(message);
- }
- }
-
- /**
- * Installs the apk with the given name.
- *
- * @param resourceName name of class loader resource for the apk to
- * install.
- * @param enableRollback if rollback should be enabled.
- * @throws AssertionError if the installation fails.
- */
- static void install(String resourceName, boolean enableRollback)
- throws InterruptedException, IOException {
- Context context = InstrumentationRegistry.getContext();
- PackageInstaller.Session session = null;
- PackageInstaller packageInstaller = context.getPackageManager().getPackageInstaller();
- PackageInstaller.SessionParams params = new PackageInstaller.SessionParams(
- PackageInstaller.SessionParams.MODE_FULL_INSTALL);
- if (enableRollback) {
- params.setEnableRollback();
- }
- int sessionId = packageInstaller.createSession(params);
- session = packageInstaller.openSession(sessionId);
-
- ClassLoader loader = RollbackTest.class.getClassLoader();
- try (OutputStream packageInSession = session.openWrite("package", 0, -1);
- InputStream is = loader.getResourceAsStream(resourceName);) {
- byte[] buffer = new byte[4096];
- int n;
- while ((n = is.read(buffer)) >= 0) {
- packageInSession.write(buffer, 0, n);
- }
- }
-
- // Commit the session (this will start the installation workflow).
- session.commit(LocalIntentSender.getIntentSender());
- assertStatusSuccess(LocalIntentSender.getIntentSenderResult());
- }
-
- /** Launches {@code packageName} with {@link Intent#ACTION_MAIN}. */
- static void launchPackage(String packageName)
- throws InterruptedException, IOException {
- Context context = InstrumentationRegistry.getContext();
- Intent intent = new Intent(Intent.ACTION_MAIN);
- intent.setPackage(packageName);
- intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
- intent.addCategory(Intent.CATEGORY_LAUNCHER);
- context.startActivity(intent);
- }
-
- /**
- * Installs the apks with the given resource names as an atomic set.
- *
- * @param enableRollback if rollback should be enabled.
- * @param resourceNames names of the class loader resource for the apks to
- * install.
- * @throws AssertionError if the installation fails.
- */
- static void installMultiPackage(boolean enableRollback, String... resourceNames)
- throws InterruptedException, IOException {
- Context context = InstrumentationRegistry.getContext();
- PackageInstaller packageInstaller = context.getPackageManager().getPackageInstaller();
-
- PackageInstaller.SessionParams multiPackageParams = new PackageInstaller.SessionParams(
- PackageInstaller.SessionParams.MODE_FULL_INSTALL);
- multiPackageParams.setMultiPackage();
- if (enableRollback) {
- // TODO: Do we set this on the parent params, the child params, or
- // both?
- multiPackageParams.setEnableRollback();
- }
- int multiPackageId = packageInstaller.createSession(multiPackageParams);
- PackageInstaller.Session multiPackage = packageInstaller.openSession(multiPackageId);
-
- for (String resourceName : resourceNames) {
- PackageInstaller.Session session = null;
- PackageInstaller.SessionParams params = new PackageInstaller.SessionParams(
- PackageInstaller.SessionParams.MODE_FULL_INSTALL);
- if (enableRollback) {
- params.setEnableRollback();
- }
- int sessionId = packageInstaller.createSession(params);
- session = packageInstaller.openSession(sessionId);
-
- ClassLoader loader = RollbackTest.class.getClassLoader();
- try (OutputStream packageInSession = session.openWrite("package", 0, -1);
- InputStream is = loader.getResourceAsStream(resourceName);) {
- byte[] buffer = new byte[4096];
- int n;
- while ((n = is.read(buffer)) >= 0) {
- packageInSession.write(buffer, 0, n);
- }
- }
- multiPackage.addChildSessionId(sessionId);
- }
-
- // Commit the session (this will start the installation workflow).
- multiPackage.commit(LocalIntentSender.getIntentSender());
- assertStatusSuccess(LocalIntentSender.getIntentSenderResult());
- }
-
- static void adoptShellPermissionIdentity(String... permissions) {
- InstrumentationRegistry
- .getInstrumentation()
- .getUiAutomation()
- .adoptShellPermissionIdentity(permissions);
- }
-
- static void dropShellPermissionIdentity() {
- InstrumentationRegistry
- .getInstrumentation()
- .getUiAutomation()
- .dropShellPermissionIdentity();
- }
-}
diff --git a/tests/UiBench/Android.bp b/tests/UiBench/Android.bp
new file mode 100644
index 0000000..e0608e2
--- /dev/null
+++ b/tests/UiBench/Android.bp
@@ -0,0 +1,19 @@
+android_test {
+ name: "UiBench",
+ sdk_version: "current",
+ min_sdk_version: "21",
+ // omit gradle 'build' dir
+ srcs: ["src/**/*.java"],
+ // use appcompat/support lib from the tree, so improvements/
+ // regressions are reflected in test data
+ resource_dirs: ["res"],
+ static_libs: [
+ "com.google.android.material_material",
+ "androidx.legacy_legacy-support-v4",
+ "androidx.appcompat_appcompat",
+ "androidx.cardview_cardview",
+ "androidx.recyclerview_recyclerview",
+ "androidx.leanback_leanback",
+ ],
+ test_suites: ["device-tests"],
+}
diff --git a/tests/UiBench/Android.mk b/tests/UiBench/Android.mk
deleted file mode 100644
index 608bf2f..0000000
--- a/tests/UiBench/Android.mk
+++ /dev/null
@@ -1,29 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_TAGS := tests
-LOCAL_SDK_VERSION := current
-LOCAL_MIN_SDK_VERSION := 21
-
-# omit gradle 'build' dir
-LOCAL_SRC_FILES := $(call all-java-files-under,src)
-
-# use appcompat/support lib from the tree, so improvements/
-# regressions are reflected in test data
-LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res
-
-LOCAL_USE_AAPT2 := true
-
-LOCAL_STATIC_ANDROID_LIBRARIES := \
- com.google.android.material_material \
- androidx.legacy_legacy-support-v4 \
- androidx.appcompat_appcompat \
- androidx.cardview_cardview \
- androidx.recyclerview_recyclerview \
- androidx.leanback_leanback
-
-LOCAL_PACKAGE_NAME := UiBench
-
-LOCAL_COMPATIBILITY_SUITE := device-tests
-
-include $(BUILD_PACKAGE)
diff --git a/tests/UsageStatsTest/Android.bp b/tests/UsageStatsTest/Android.bp
new file mode 100644
index 0000000..0808b05
--- /dev/null
+++ b/tests/UsageStatsTest/Android.bp
@@ -0,0 +1,8 @@
+android_test {
+ name: "UsageStatsTest",
+ // Only compile source java files in this apk.
+ srcs: ["src/**/*.java"],
+ static_libs: ["androidx.legacy_legacy-support-v4"],
+ certificate: "platform",
+ platform_apis: true,
+}
diff --git a/tests/UsageStatsTest/Android.mk b/tests/UsageStatsTest/Android.mk
deleted file mode 100644
index 5eed38c..0000000
--- a/tests/UsageStatsTest/Android.mk
+++ /dev/null
@@ -1,17 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_TAGS := tests
-
-# Only compile source java files in this apk.
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-
-LOCAL_USE_AAPT2 := true
-LOCAL_STATIC_ANDROID_LIBRARIES := androidx.legacy_legacy-support-v4
-
-LOCAL_CERTIFICATE := platform
-
-LOCAL_PACKAGE_NAME := UsageStatsTest
-LOCAL_PRIVATE_PLATFORM_APIS := true
-
-include $(BUILD_PACKAGE)
diff --git a/tests/libs-permissions/Android.bp b/tests/libs-permissions/Android.bp
new file mode 100644
index 0000000..c7c4b10
--- /dev/null
+++ b/tests/libs-permissions/Android.bp
@@ -0,0 +1,29 @@
+java_library {
+ name: "com.android.test.libs.product",
+ installable: true,
+ product_specific: true,
+ srcs: ["product/java/**/*.java"],
+ required: ["com.android.test.libs.product.xml"],
+}
+
+prebuilt_etc {
+ name: "com.android.test.libs.product.xml",
+ src: "product/com.android.test.libs.product.xml",
+ sub_dir: "permissions",
+ product_specific: true,
+}
+
+java_library {
+ name: "com.android.test.libs.product_services",
+ installable: true,
+ product_services_specific: true,
+ srcs: ["product_services/java/**/*.java"],
+ required: ["com.android.test.libs.product_services.xml"],
+}
+
+prebuilt_etc {
+ name: "com.android.test.libs.product_services.xml",
+ src: "product_services/com.android.test.libs.product_services.xml",
+ sub_dir: "permissions",
+ product_services_specific: true,
+}
diff --git a/tests/libs-permissions/Android.mk b/tests/libs-permissions/Android.mk
deleted file mode 100644
index f4250c8..0000000
--- a/tests/libs-permissions/Android.mk
+++ /dev/null
@@ -1,29 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-
-include $(CLEAR_VARS)
-LOCAL_MODULE := com.android.test.libs.product
-LOCAL_PRODUCT_MODULE := true
-LOCAL_SRC_FILES := $(call all-java-files-under, product/java)
-LOCAL_REQUIRED_MODULES := com.android.test.libs.product.xml
-include $(BUILD_JAVA_LIBRARY)
-
-include $(CLEAR_VARS)
-LOCAL_MODULE := com.android.test.libs.product.xml
-LOCAL_MODULE_CLASS := ETC
-LOCAL_MODULE_PATH := $(TARGET_OUT_PRODUCT_ETC)/permissions
-LOCAL_SRC_FILES:= product/com.android.test.libs.product.xml
-include $(BUILD_PREBUILT)
-
-include $(CLEAR_VARS)
-LOCAL_MODULE := com.android.test.libs.product_services
-LOCAL_PRODUCT_SERVICES_MODULE := true
-LOCAL_SRC_FILES := $(call all-java-files-under, product_services/java)
-LOCAL_REQUIRED_MODULES := com.android.test.libs.product_services.xml
-include $(BUILD_JAVA_LIBRARY)
-
-include $(CLEAR_VARS)
-LOCAL_MODULE := com.android.test.libs.product_services.xml
-LOCAL_MODULE_CLASS := ETC
-LOCAL_MODULE_PATH := $(TARGET_OUT_PRODUCT_SERVICES_ETC)/permissions
-LOCAL_SRC_FILES:= product_services/com.android.test.libs.product_services.xml
-include $(BUILD_PREBUILT)
diff --git a/tests/net/java/com/android/server/connectivity/VpnTest.java b/tests/net/java/com/android/server/connectivity/VpnTest.java
index f169d6b..b5d1ff9 100644
--- a/tests/net/java/com/android/server/connectivity/VpnTest.java
+++ b/tests/net/java/com/android/server/connectivity/VpnTest.java
@@ -28,6 +28,7 @@
import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR;
import static android.net.NetworkCapabilities.TRANSPORT_VPN;
import static android.net.NetworkCapabilities.TRANSPORT_WIFI;
+import static android.net.RouteInfo.RTN_UNREACHABLE;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
@@ -89,6 +90,7 @@
import org.mockito.MockitoAnnotations;
import java.net.Inet4Address;
+import java.net.Inet6Address;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.Arrays;
@@ -775,6 +777,16 @@
// V4 does not, but V6 has sufficient coverage again
lp.addRoute(new RouteInfo(new IpPrefix("::/1")));
assertTrue(Vpn.providesRoutesToMostDestinations(lp));
+
+ lp.clear();
+ // V4-unreachable route should not be treated as sufficient coverage
+ lp.addRoute(new RouteInfo(new IpPrefix(Inet4Address.ANY, 0), RTN_UNREACHABLE));
+ assertFalse(Vpn.providesRoutesToMostDestinations(lp));
+
+ lp.clear();
+ // V6-unreachable route should not be treated as sufficient coverage
+ lp.addRoute(new RouteInfo(new IpPrefix(Inet6Address.ANY, 0), RTN_UNREACHABLE));
+ assertFalse(Vpn.providesRoutesToMostDestinations(lp));
}
@Test
diff --git a/tests/privapp-permissions/Android.bp b/tests/privapp-permissions/Android.bp
new file mode 100644
index 0000000..ca7864f
--- /dev/null
+++ b/tests/privapp-permissions/Android.bp
@@ -0,0 +1,61 @@
+android_app {
+ name: "PrivAppPermissionTest",
+ sdk_version: "current",
+ privileged: true,
+ manifest: "system/AndroidManifest.xml",
+ required: ["privapp-permissions-test.xml"],
+}
+
+prebuilt_etc {
+ name: "privapp-permissions-test.xml",
+ src: "system/privapp-permissions-test.xml",
+ sub_dir: "permissions",
+}
+
+android_app {
+ name: "VendorPrivAppPermissionTest",
+ sdk_version: "current",
+ privileged: true,
+ manifest: "vendor/AndroidManifest.xml",
+ vendor: true,
+ required: ["vendorprivapp-permissions-test.xml"],
+}
+
+prebuilt_etc {
+ name: "vendorprivapp-permissions-test.xml",
+ src: "vendor/privapp-permissions-test.xml",
+ sub_dir: "permissions",
+ proprietary: true,
+}
+
+android_app {
+ name: "ProductPrivAppPermissionTest",
+ sdk_version: "current",
+ privileged: true,
+ manifest: "product/AndroidManifest.xml",
+ product_specific: true,
+ required: ["productprivapp-permissions-test.xml"],
+}
+
+prebuilt_etc {
+ name: "productprivapp-permissions-test.xml",
+ src: "product/privapp-permissions-test.xml",
+ sub_dir: "permissions",
+ product_specific: true,
+}
+
+android_app {
+ name: "ProductServicesPrivAppPermissionTest",
+ sdk_version: "current",
+ privileged: true,
+ manifest: "product_services/AndroidManifest.xml",
+ product_services_specific: true,
+ required: ["product_servicesprivapp-permissions-test.xml"],
+}
+
+prebuilt_etc {
+ name: "product_servicesprivapp-permissions-test.xml",
+ src: "product_services/privapp-permissions-test.xml",
+ sub_dir: "permissions",
+ product_services_specific: true,
+}
diff --git a/tests/privapp-permissions/Android.mk b/tests/privapp-permissions/Android.mk
deleted file mode 100644
index 1149b8a..0000000
--- a/tests/privapp-permissions/Android.mk
+++ /dev/null
@@ -1,64 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-
-include $(CLEAR_VARS)
-LOCAL_PACKAGE_NAME := PrivAppPermissionTest
-LOCAL_SDK_VERSION := current
-LOCAL_PRIVILEGED_MODULE := true
-LOCAL_MANIFEST_FILE := system/AndroidManifest.xml
-LOCAL_REQUIRED_MODULES := privapp-permissions-test.xml
-include $(BUILD_PACKAGE)
-
-include $(CLEAR_VARS)
-LOCAL_MODULE := privapp-permissions-test.xml
-LOCAL_MODULE_CLASS := ETC
-LOCAL_MODULE_PATH := $(TARGET_OUT_ETC)/permissions
-LOCAL_SRC_FILES:= system/privapp-permissions-test.xml
-include $(BUILD_PREBUILT)
-
-include $(CLEAR_VARS)
-LOCAL_PACKAGE_NAME := VendorPrivAppPermissionTest
-LOCAL_SDK_VERSION := current
-LOCAL_PRIVILEGED_MODULE := true
-LOCAL_MANIFEST_FILE := vendor/AndroidManifest.xml
-LOCAL_VENDOR_MODULE := true
-LOCAL_REQUIRED_MODULES := vendorprivapp-permissions-test.xml
-include $(BUILD_PACKAGE)
-
-include $(CLEAR_VARS)
-LOCAL_MODULE := vendorprivapp-permissions-test.xml
-LOCAL_MODULE_CLASS := ETC
-LOCAL_MODULE_PATH := $(TARGET_OUT_VENDOR_ETC)/permissions
-LOCAL_SRC_FILES:= vendor/privapp-permissions-test.xml
-include $(BUILD_PREBUILT)
-
-include $(CLEAR_VARS)
-LOCAL_PACKAGE_NAME := ProductPrivAppPermissionTest
-LOCAL_SDK_VERSION := current
-LOCAL_PRIVILEGED_MODULE := true
-LOCAL_MANIFEST_FILE := product/AndroidManifest.xml
-LOCAL_PRODUCT_MODULE := true
-LOCAL_REQUIRED_MODULES := productprivapp-permissions-test.xml
-include $(BUILD_PACKAGE)
-
-include $(CLEAR_VARS)
-LOCAL_MODULE := productprivapp-permissions-test.xml
-LOCAL_MODULE_CLASS := ETC
-LOCAL_MODULE_PATH := $(TARGET_OUT_PRODUCT_ETC)/permissions
-LOCAL_SRC_FILES:= product/privapp-permissions-test.xml
-include $(BUILD_PREBUILT)
-
-include $(CLEAR_VARS)
-LOCAL_PACKAGE_NAME := ProductServicesPrivAppPermissionTest
-LOCAL_SDK_VERSION := current
-LOCAL_PRIVILEGED_MODULE := true
-LOCAL_MANIFEST_FILE := product_services/AndroidManifest.xml
-LOCAL_PRODUCT_SERVICES_MODULE := true
-LOCAL_REQUIRED_MODULES := product_servicesprivapp-permissions-test.xml
-include $(BUILD_PACKAGE)
-
-include $(CLEAR_VARS)
-LOCAL_MODULE := product_servicesprivapp-permissions-test.xml
-LOCAL_MODULE_CLASS := ETC
-LOCAL_MODULE_PATH := $(TARGET_OUT_PRODUCT_SERVICES_ETC)/permissions
-LOCAL_SRC_FILES:= product_services/privapp-permissions-test.xml
-include $(BUILD_PREBUILT)
diff --git a/tools/aapt2/ResourceParser.cpp b/tools/aapt2/ResourceParser.cpp
index c188782..d0237f8 100644
--- a/tools/aapt2/ResourceParser.cpp
+++ b/tools/aapt2/ResourceParser.cpp
@@ -1637,7 +1637,9 @@
if (!(plural->values[index] = ParseXml(
parser, android::ResTable_map::TYPE_STRING, kNoRawString))) {
error = true;
+ continue;
}
+
plural->values[index]->SetSource(item_source);
} else if (!ShouldIgnoreElement(element_namespace, element_name)) {
diff --git a/tools/aapt2/cmd/Link.cpp b/tools/aapt2/cmd/Link.cpp
index 4961aa5..22edd2f 100644
--- a/tools/aapt2/cmd/Link.cpp
+++ b/tools/aapt2/cmd/Link.cpp
@@ -268,6 +268,7 @@
bool update_proguard_spec = false;
OutputFormat output_format = OutputFormat::kApk;
std::unordered_set<std::string> extensions_to_not_compress;
+ Maybe<std::regex> regex_to_not_compress;
};
// A sampling of public framework resource IDs.
@@ -377,11 +378,18 @@
}
}
+// TODO(rtmitchell): turn this function into a variable that points to a method that retrieves the
+// compression flag
uint32_t ResourceFileFlattener::GetCompressionFlags(const StringPiece& str) {
if (options_.do_not_compress_anything) {
return 0;
}
+ if (options_.regex_to_not_compress
+ && std::regex_search(str.to_string(), options_.regex_to_not_compress.value())) {
+ return 0;
+ }
+
for (const std::string& extension : options_.extensions_to_not_compress) {
if (util::EndsWith(str, extension)) {
return 0;
@@ -1531,7 +1539,11 @@
for (auto& entry : merged_assets) {
uint32_t compression_flags = ArchiveEntry::kCompress;
std::string extension = file::GetExtension(entry.first).to_string();
- if (options_.extensions_to_not_compress.count(extension) > 0) {
+
+ if (options_.do_not_compress_anything
+ || options_.extensions_to_not_compress.count(extension) > 0
+ || (options_.regex_to_not_compress
+ && std::regex_search(extension, options_.regex_to_not_compress.value()))) {
compression_flags = 0u;
}
@@ -1559,6 +1571,7 @@
file_flattener_options.keep_raw_values = keep_raw_values;
file_flattener_options.do_not_compress_anything = options_.do_not_compress_anything;
file_flattener_options.extensions_to_not_compress = options_.extensions_to_not_compress;
+ file_flattener_options.regex_to_not_compress = options_.regex_to_not_compress;
file_flattener_options.no_auto_version = options_.no_auto_version;
file_flattener_options.no_version_vectors = options_.no_version_vectors;
file_flattener_options.no_version_transitions = options_.no_version_transitions;
@@ -2166,6 +2179,20 @@
}
}
+ if (no_compress_regex) {
+ std::string regex = no_compress_regex.value();
+ if (util::StartsWith(regex, "@")) {
+ const std::string path = regex.substr(1, regex.size() -1);
+ std::string error;
+ if (!file::AppendSetArgsFromFile(path, &options_.extensions_to_not_compress, &error)) {
+ context.GetDiagnostics()->Error(DiagMessage(path) << error);
+ return 1;
+ }
+ } else {
+ options_.regex_to_not_compress = GetRegularExpression(no_compress_regex.value());
+ }
+ }
+
// Populate some default no-compress extensions that are already compressed.
options_.extensions_to_not_compress.insert(
{".jpg", ".jpeg", ".png", ".gif", ".wav", ".mp2", ".mp3", ".ogg",
diff --git a/tools/aapt2/cmd/Link.h b/tools/aapt2/cmd/Link.h
index 590a6bb..1fc149a 100644
--- a/tools/aapt2/cmd/Link.h
+++ b/tools/aapt2/cmd/Link.h
@@ -17,6 +17,8 @@
#ifndef AAPT2_LINK_H
#define AAPT2_LINK_H
+#include <regex>
+
#include "Command.h"
#include "Diagnostics.h"
#include "Resource.h"
@@ -63,6 +65,7 @@
bool no_xml_namespaces = false;
bool do_not_compress_anything = false;
std::unordered_set<std::string> extensions_to_not_compress;
+ Maybe<std::regex> regex_to_not_compress;
// Static lib options.
bool no_static_lib_packages = false;
@@ -250,6 +253,11 @@
&options_.do_not_compress_anything);
AddOptionalSwitch("--keep-raw-values", "Preserve raw attribute values in xml files.",
&options_.keep_raw_values);
+ AddOptionalFlag("--no-compress-regex",
+ "Do not compress extensions matching the regular expression. Remember to\n"
+ " use the '$' symbol for end of line. Uses a non case-sensitive\n"
+ " ECMAScript regular expression grammar.",
+ &no_compress_regex);
AddOptionalSwitch("--warn-manifest-validation",
"Treat manifest validation errors as warnings.",
&options_.manifest_fixer_options.warn_validation);
@@ -283,6 +291,7 @@
std::vector<std::string> configs_;
Maybe<std::string> preferred_density_;
Maybe<std::string> product_list_;
+ Maybe<std::string> no_compress_regex;
bool legacy_x_flag_ = false;
bool require_localization_ = false;
bool verbose_ = false;
diff --git a/tools/aapt2/cmd/Util.cpp b/tools/aapt2/cmd/Util.cpp
index 792120e..e2c65ba7 100644
--- a/tools/aapt2/cmd/Util.cpp
+++ b/tools/aapt2/cmd/Util.cpp
@@ -435,4 +435,11 @@
}
}
+std::regex GetRegularExpression(const std::string &input) {
+ // Standard ECMAScript grammar plus case insensitive.
+ std::regex case_insensitive(
+ input, std::regex_constants::icase | std::regex_constants::ECMAScript);
+ return case_insensitive;
+}
+
} // namespace aapt
diff --git a/tools/aapt2/cmd/Util.h b/tools/aapt2/cmd/Util.h
index cf1443e..2a7c62e 100644
--- a/tools/aapt2/cmd/Util.h
+++ b/tools/aapt2/cmd/Util.h
@@ -17,6 +17,8 @@
#ifndef AAPT_SPLIT_UTIL_H
#define AAPT_SPLIT_UTIL_H
+#include <regex>
+
#include "androidfw/StringPiece.h"
#include "AppInfo.h"
@@ -72,6 +74,9 @@
// versionCodeMajor if the version code requires more than 32 bits.
void SetLongVersionCode(xml::Element* manifest, uint64_t version_code);
+// Returns a case insensitive regular expression based on the input.
+std::regex GetRegularExpression(const std::string &input);
+
} // namespace aapt
#endif /* AAPT_SPLIT_UTIL_H */
diff --git a/tools/aapt2/cmd/Util_test.cpp b/tools/aapt2/cmd/Util_test.cpp
index f92f1e3..7e49261 100644
--- a/tools/aapt2/cmd/Util_test.cpp
+++ b/tools/aapt2/cmd/Util_test.cpp
@@ -383,4 +383,12 @@
EXPECT_NE(*adjusted_contraints[1].configs.begin(), ConfigDescription::DefaultConfig());
}
+TEST(UtilTest, RegularExperssions) {
+ std::string valid(".bc$");
+ std::regex expression = GetRegularExpression(valid);
+ EXPECT_TRUE(std::regex_search("file.abc", expression));
+ EXPECT_TRUE(std::regex_search("file.123bc", expression));
+ EXPECT_FALSE(std::regex_search("abc.zip", expression));
+}
+
} // namespace aapt
diff --git a/tools/aapt2/integration-tests/Android.mk b/tools/aapt2/integration-tests/Android.mk
deleted file mode 100644
index 6361f9b..0000000
--- a/tools/aapt2/integration-tests/Android.mk
+++ /dev/null
@@ -1,2 +0,0 @@
-LOCAL_PATH := $(call my-dir)
-include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/tools/aapt2/integration-tests/AutoVersionTest/Android.bp b/tools/aapt2/integration-tests/AutoVersionTest/Android.bp
new file mode 100644
index 0000000..79fb573
--- /dev/null
+++ b/tools/aapt2/integration-tests/AutoVersionTest/Android.bp
@@ -0,0 +1,20 @@
+//
+// Copyright (C) 2017 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+android_test {
+ name: "AaptAutoVersionTest",
+ sdk_version: "current",
+}
diff --git a/tools/aapt2/integration-tests/BasicTest/Android.bp b/tools/aapt2/integration-tests/BasicTest/Android.bp
new file mode 100644
index 0000000..a94a01f
--- /dev/null
+++ b/tools/aapt2/integration-tests/BasicTest/Android.bp
@@ -0,0 +1,20 @@
+//
+// Copyright (C) 2017 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+android_test {
+ name: "AaptBasicTest",
+ sdk_version: "current",
+}
diff --git a/tools/aapt2/integration-tests/BasicTest/Android.mk b/tools/aapt2/integration-tests/BasicTest/Android.mk
deleted file mode 100644
index d160554..0000000
--- a/tools/aapt2/integration-tests/BasicTest/Android.mk
+++ /dev/null
@@ -1,24 +0,0 @@
-#
-# Copyright (C) 2017 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-LOCAL_PATH := $(call my-dir)
-
-include $(CLEAR_VARS)
-LOCAL_USE_AAPT2 := true
-LOCAL_PACKAGE_NAME := AaptBasicTest
-LOCAL_SDK_VERSION := current
-LOCAL_MODULE_TAGS := tests
-include $(BUILD_PACKAGE)
diff --git a/tools/aapt2/integration-tests/StaticLibTest/Android.mk b/tools/aapt2/integration-tests/StaticLibTest/Android.mk
deleted file mode 100644
index 6361f9b..0000000
--- a/tools/aapt2/integration-tests/StaticLibTest/Android.mk
+++ /dev/null
@@ -1,2 +0,0 @@
-LOCAL_PATH := $(call my-dir)
-include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/tools/aapt2/integration-tests/StaticLibTest/App/Android.bp b/tools/aapt2/integration-tests/StaticLibTest/App/Android.bp
new file mode 100644
index 0000000..9aadff3
--- /dev/null
+++ b/tools/aapt2/integration-tests/StaticLibTest/App/Android.bp
@@ -0,0 +1,34 @@
+//
+// Copyright (C) 2016 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+android_test {
+
+ name: "AaptTestStaticLib_App",
+ sdk_version: "current",
+ srcs: ["src/**/*.java"],
+ asset_dirs: [
+ "assets",
+ "assets2",
+ ],
+ static_libs: [
+ "AaptTestStaticLib_LibOne",
+ "AaptTestStaticLib_LibTwo",
+ ],
+ aaptflags: [
+ "--no-version-vectors",
+ "--no-version-transitions",
+ ],
+}
diff --git a/tools/aapt2/integration-tests/StaticLibTest/App/Android.mk b/tools/aapt2/integration-tests/StaticLibTest/App/Android.mk
deleted file mode 100644
index 3cce35d..0000000
--- a/tools/aapt2/integration-tests/StaticLibTest/App/Android.mk
+++ /dev/null
@@ -1,30 +0,0 @@
-#
-# Copyright (C) 2016 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-LOCAL_PATH := $(call my-dir)
-
-include $(CLEAR_VARS)
-LOCAL_USE_AAPT2 := true
-LOCAL_PACKAGE_NAME := AaptTestStaticLib_App
-LOCAL_SDK_VERSION := current
-LOCAL_MODULE_TAGS := tests
-LOCAL_SRC_FILES := $(call all-java-files-under,src)
-LOCAL_ASSET_DIR := $(LOCAL_PATH)/assets $(LOCAL_PATH)/assets2
-LOCAL_STATIC_ANDROID_LIBRARIES := \
- AaptTestStaticLib_LibOne \
- AaptTestStaticLib_LibTwo
-LOCAL_AAPT_FLAGS := --no-version-vectors --no-version-transitions
-include $(BUILD_PACKAGE)
diff --git a/tools/aapt2/integration-tests/StaticLibTest/LibOne/Android.bp b/tools/aapt2/integration-tests/StaticLibTest/LibOne/Android.bp
new file mode 100644
index 0000000..4c81813
--- /dev/null
+++ b/tools/aapt2/integration-tests/StaticLibTest/LibOne/Android.bp
@@ -0,0 +1,22 @@
+//
+// Copyright (C) 2016 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+android_library {
+ name: "AaptTestStaticLib_LibOne",
+ sdk_version: "current",
+ srcs: ["src/**/*.java"],
+ resource_dirs: ["res"],
+}
diff --git a/tools/aapt2/integration-tests/StaticLibTest/LibOne/Android.mk b/tools/aapt2/integration-tests/StaticLibTest/LibOne/Android.mk
deleted file mode 100644
index da25f64..0000000
--- a/tools/aapt2/integration-tests/StaticLibTest/LibOne/Android.mk
+++ /dev/null
@@ -1,29 +0,0 @@
-#
-# Copyright (C) 2016 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-LOCAL_PATH := $(call my-dir)
-
-include $(CLEAR_VARS)
-LOCAL_USE_AAPT2 := true
-LOCAL_MODULE := AaptTestStaticLib_LibOne
-LOCAL_SDK_VERSION := current
-LOCAL_MODULE_TAGS := tests
-LOCAL_SRC_FILES := $(call all-java-files-under,src)
-LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res
-
-# We need this to compile the Java sources of AaptTestStaticLib_LibTwo using javac.
-LOCAL_JAR_EXCLUDE_FILES := none
-include $(BUILD_STATIC_JAVA_LIBRARY)
diff --git a/tools/aapt2/integration-tests/StaticLibTest/LibTwo/Android.bp b/tools/aapt2/integration-tests/StaticLibTest/LibTwo/Android.bp
new file mode 100644
index 0000000..7c4f7ed
--- /dev/null
+++ b/tools/aapt2/integration-tests/StaticLibTest/LibTwo/Android.bp
@@ -0,0 +1,23 @@
+//
+// Copyright (C) 2016 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+android_library {
+ name: "AaptTestStaticLib_LibTwo",
+ sdk_version: "current",
+ srcs: ["src/**/*.java"],
+ resource_dirs: ["res"],
+ libs: ["AaptTestStaticLib_LibOne"],
+}
diff --git a/tools/aapt2/integration-tests/StaticLibTest/LibTwo/Android.mk b/tools/aapt2/integration-tests/StaticLibTest/LibTwo/Android.mk
deleted file mode 100644
index 27a3134..0000000
--- a/tools/aapt2/integration-tests/StaticLibTest/LibTwo/Android.mk
+++ /dev/null
@@ -1,28 +0,0 @@
-#
-# Copyright (C) 2016 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-LOCAL_PATH := $(call my-dir)
-
-include $(CLEAR_VARS)
-LOCAL_USE_AAPT2 := true
-LOCAL_MODULE := AaptTestStaticLib_LibTwo
-LOCAL_SDK_VERSION := current
-LOCAL_MODULE_TAGS := tests
-LOCAL_SRC_FILES := $(call all-java-files-under,src)
-LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res
-LOCAL_SHARED_ANDROID_LIBRARIES := AaptTestStaticLib_LibOne
-include $(BUILD_STATIC_JAVA_LIBRARY)
-
diff --git a/tools/aapt2/integration-tests/SymlinkTest/Android.bp b/tools/aapt2/integration-tests/SymlinkTest/Android.bp
new file mode 100644
index 0000000..68e6148
--- /dev/null
+++ b/tools/aapt2/integration-tests/SymlinkTest/Android.bp
@@ -0,0 +1,20 @@
+//
+// Copyright (C) 2017 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+android_test {
+ name: "AaptSymlinkTest",
+ sdk_version: "current",
+}
diff --git a/tools/aapt2/integration-tests/SymlinkTest/Android.mk b/tools/aapt2/integration-tests/SymlinkTest/Android.mk
deleted file mode 100644
index 8da1141..0000000
--- a/tools/aapt2/integration-tests/SymlinkTest/Android.mk
+++ /dev/null
@@ -1,24 +0,0 @@
-#
-# Copyright (C) 2017 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-LOCAL_PATH := $(call my-dir)
-
-include $(CLEAR_VARS)
-LOCAL_USE_AAPT2 := true
-LOCAL_PACKAGE_NAME := AaptSymlinkTest
-LOCAL_SDK_VERSION := current
-LOCAL_MODULE_TAGS := tests
-include $(BUILD_PACKAGE)
diff --git a/tools/aapt2/util/Files.cpp b/tools/aapt2/util/Files.cpp
index 7b268bb..604b257 100644
--- a/tools/aapt2/util/Files.cpp
+++ b/tools/aapt2/util/Files.cpp
@@ -251,6 +251,25 @@
return true;
}
+bool AppendSetArgsFromFile(const StringPiece& path, std::unordered_set<std::string>* out_argset,
+ std::string* out_error) {
+ std::string contents;
+ if(!ReadFileToString(path.to_string(), &contents, true /*follow_symlinks*/)) {
+ if (out_error) {
+ *out_error = "failed to read argument-list file";
+ }
+ return false;
+ }
+
+ for (StringPiece line : util::Tokenize(contents, ' ')) {
+ line = util::TrimWhitespace(line);
+ if (!line.empty()) {
+ out_argset->insert(line.to_string());
+ }
+ }
+ return true;
+}
+
bool FileFilter::SetPattern(const StringPiece& pattern) {
pattern_tokens_ = util::SplitAndLowercase(pattern, ':');
return true;
diff --git a/tools/aapt2/util/Files.h b/tools/aapt2/util/Files.h
index 5839552..481a4cd 100644
--- a/tools/aapt2/util/Files.h
+++ b/tools/aapt2/util/Files.h
@@ -19,6 +19,7 @@
#include <memory>
#include <string>
+#include <unordered_set>
#include <vector>
#include "android-base/macros.h"
@@ -86,6 +87,10 @@
bool AppendArgsFromFile(const android::StringPiece& path, std::vector<std::string>* out_arglist,
std::string* out_error);
+// Reads the file at path and appends each line to the outargset set.
+bool AppendSetArgsFromFile(const android::StringPiece& path,
+ std::unordered_set<std::string>* out_argset, std::string* out_error);
+
// Filter that determines which resource files/directories are
// processed by AAPT. Takes a pattern string supplied by the user.
// Pattern format is specified in the FileFilter::SetPattern() method.
diff --git a/wifi/java/android/net/wifi/WifiManager.java b/wifi/java/android/net/wifi/WifiManager.java
index 5e5a595..7caace6 100644
--- a/wifi/java/android/net/wifi/WifiManager.java
+++ b/wifi/java/android/net/wifi/WifiManager.java
@@ -2136,17 +2136,26 @@
}
/**
+ * @deprecated Please use {@link android.content.pm.PackageManager#hasSystemFeature(String)}
+ * with {@link android.content.pm.PackageManager#FEATURE_WIFI_RTT} and
+ * {@link android.content.pm.PackageManager#FEATURE_WIFI_AWARE}.
+ *
* @return true if this adapter supports Device-to-device RTT
* @hide
*/
+ @Deprecated
@SystemApi
public boolean isDeviceToDeviceRttSupported() {
return isFeatureSupported(WIFI_FEATURE_D2D_RTT);
}
/**
+ * @deprecated Please use {@link android.content.pm.PackageManager#hasSystemFeature(String)}
+ * with {@link android.content.pm.PackageManager#FEATURE_WIFI_RTT}.
+ *
* @return true if this adapter supports Device-to-AP RTT
*/
+ @Deprecated
public boolean isDeviceToApRttSupported() {
return isFeatureSupported(WIFI_FEATURE_D2AP_RTT);
}