Merge "Services: Add more PMS presubmits"
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/current.txt b/api/current.txt
index 4ac827a..833b87b 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -9409,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;
@@ -9593,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 {
@@ -10223,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";
@@ -10286,6 +10284,7 @@
field public static final String ACTION_USER_PRESENT = "android.intent.action.USER_PRESENT";
field public static final String ACTION_USER_UNLOCKED = "android.intent.action.USER_UNLOCKED";
field public static final String ACTION_VIEW = "android.intent.action.VIEW";
+ field public static final String ACTION_VIEW_LOCUS = "android.intent.action.VIEW_LOCUS";
field public static final String ACTION_VOICE_COMMAND = "android.intent.action.VOICE_COMMAND";
field @Deprecated public static final String ACTION_WALLPAPER_CHANGED = "android.intent.action.WALLPAPER_CHANGED";
field public static final String ACTION_WEB_SEARCH = "android.intent.action.WEB_SEARCH";
@@ -10370,6 +10369,7 @@
field public static final String EXTRA_INTENT = "android.intent.extra.INTENT";
field public static final String EXTRA_KEY_EVENT = "android.intent.extra.KEY_EVENT";
field public static final String EXTRA_LOCAL_ONLY = "android.intent.extra.LOCAL_ONLY";
+ field public static final String EXTRA_LOCUS_ID = "android.intent.extra.LOCUS_ID";
field public static final String EXTRA_MIME_TYPES = "android.intent.extra.MIME_TYPES";
field public static final String EXTRA_NOT_UNKNOWN_SOURCE = "android.intent.extra.NOT_UNKNOWN_SOURCE";
field public static final String EXTRA_ORIGINATING_URI = "android.intent.extra.ORIGINATING_URI";
@@ -10622,6 +10622,14 @@
method @Deprecated public void onLoadComplete(android.content.Loader<D>, D);
}
+ public final class LocusId implements android.os.Parcelable {
+ ctor public LocusId(@NonNull android.net.Uri);
+ method public int describeContents();
+ method @NonNull public android.net.Uri getUri();
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator<android.content.LocusId> CREATOR;
+ }
+
public class MutableContextWrapper extends android.content.ContextWrapper {
ctor public MutableContextWrapper(android.content.Context);
method public void setBaseContext(android.content.Context);
@@ -26019,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);
}
@@ -29939,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();
@@ -34607,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;
@@ -41568,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";
@@ -42137,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();
@@ -53474,16 +53481,17 @@
public final class ContentCaptureContext implements android.os.Parcelable {
method public int describeContents();
+ method public static android.view.contentcapture.ContentCaptureContext forLocusId(@NonNull android.net.Uri);
+ method @Nullable public android.os.Bundle getExtras();
+ method @NonNull public android.content.LocusId getLocusId();
method public void writeToParcel(android.os.Parcel, int);
field public static final android.os.Parcelable.Creator<android.view.contentcapture.ContentCaptureContext> CREATOR;
}
public static final class ContentCaptureContext.Builder {
- ctor public ContentCaptureContext.Builder();
+ ctor public ContentCaptureContext.Builder(@NonNull android.content.LocusId);
method public android.view.contentcapture.ContentCaptureContext build();
- method @NonNull public android.view.contentcapture.ContentCaptureContext.Builder setAction(@NonNull String);
method @NonNull public android.view.contentcapture.ContentCaptureContext.Builder setExtras(@NonNull android.os.Bundle);
- method @NonNull public android.view.contentcapture.ContentCaptureContext.Builder setUri(@NonNull android.net.Uri);
}
public final class ContentCaptureManager {
@@ -53516,8 +53524,8 @@
public final class UserDataRemovalRequest implements android.os.Parcelable {
method public int describeContents();
+ method @NonNull public java.util.List<android.view.contentcapture.UserDataRemovalRequest.LocusIdRequest> getLocusIdRequests();
method @NonNull public String getPackageName();
- method @NonNull public java.util.List<android.view.contentcapture.UserDataRemovalRequest.UriRequest> getUriRequests();
method public boolean isForEverything();
method public void writeToParcel(android.os.Parcel, int);
field public static final android.os.Parcelable.Creator<android.view.contentcapture.UserDataRemovalRequest> CREATOR;
@@ -53525,13 +53533,13 @@
public static final class UserDataRemovalRequest.Builder {
ctor public UserDataRemovalRequest.Builder();
- method public android.view.contentcapture.UserDataRemovalRequest.Builder addUri(@NonNull android.net.Uri, boolean);
+ method public android.view.contentcapture.UserDataRemovalRequest.Builder addLocusId(@NonNull android.content.LocusId, boolean);
method @NonNull public android.view.contentcapture.UserDataRemovalRequest build();
method @NonNull public android.view.contentcapture.UserDataRemovalRequest.Builder forEverything();
}
- public final class UserDataRemovalRequest.UriRequest {
- method @NonNull public android.net.Uri getUri();
+ public final class UserDataRemovalRequest.LocusIdRequest {
+ method @NonNull public android.content.LocusId getLocusId();
method @NonNull public boolean isRecursive();
}
@@ -54023,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 128ee99..5c89b05 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -454,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();
@@ -1300,9 +1301,9 @@
}
public abstract class ContentResolver {
- method public android.os.Bundle getCache(android.net.Uri);
+ 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 {
@@ -3496,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
@@ -3616,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 {
@@ -4642,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();
@@ -6288,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";
}
@@ -6355,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);
@@ -6536,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";
}
@@ -9339,14 +9379,11 @@
package android.view.contentcapture {
public final class ContentCaptureContext implements android.os.Parcelable {
- method @Nullable public String getAction();
method @Nullable public android.content.ComponentName getActivityComponent();
method public int getDisplayId();
- method @Nullable public android.os.Bundle getExtras();
method public int getFlags();
method @Nullable public android.view.contentcapture.ContentCaptureSessionId getParentSessionId();
method public int getTaskId();
- method @Nullable public android.net.Uri getUri();
field public static final int FLAG_DISABLED_BY_APP = 1; // 0x1
field public static final int FLAG_DISABLED_BY_FLAG_SECURE = 2; // 0x2
}
@@ -9372,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 01678b1..963584c 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -1301,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);
}
@@ -2057,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";
}
@@ -2114,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);
@@ -2725,14 +2728,11 @@
package android.view.contentcapture {
public final class ContentCaptureContext implements android.os.Parcelable {
- method @Nullable public String getAction();
method @Nullable public android.content.ComponentName getActivityComponent();
method public int getDisplayId();
- method @Nullable public android.os.Bundle getExtras();
method public int getFlags();
method @Nullable public android.view.contentcapture.ContentCaptureSessionId getParentSessionId();
method public int getTaskId();
- method @Nullable public android.net.Uri getUri();
field public static final int FLAG_DISABLED_BY_APP = 1; // 0x1
field public static final int FLAG_DISABLED_BY_FLAG_SECURE = 2; // 0x2
}
@@ -2758,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/packages/CompanionDeviceManager/Android.mk b/cmds/idmap2/tests/data/signature-overlay/build
old mode 100644
new mode 100755
similarity index 60%
rename from packages/CompanionDeviceManager/Android.mk
rename to cmds/idmap2/tests/data/signature-overlay/build
index 7ec6e11..fdd8301
--- a/packages/CompanionDeviceManager/Android.mk
+++ b/cmds/idmap2/tests/data/signature-overlay/build
@@ -1,4 +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,17 +12,15 @@
# 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)
+aapt2 compile --dir res -o compiled.flata
-LOCAL_MODULE_TAGS := optional
+aapt2 link \
+ --no-resource-removal \
+ -I "$FRAMEWORK_RES_APK" \
+ --manifest AndroidManifest.xml \
+ -o signature-overlay.apk \
+ compiled.flata
-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))
+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 2585a5b..d78647e 100644
--- a/cmds/statsd/src/atoms.proto
+++ b/cmds/statsd/src/atoms.proto
@@ -246,6 +246,7 @@
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.
@@ -3338,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 //
//////////////////////////////////////////////////////////////////////
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/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/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/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/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 bbfa5cc..0e11d4e 100644
--- a/core/java/android/content/ContentResolver.java
+++ b/core/java/android/content/ContentResolver.java
@@ -3148,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());
@@ -3165,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());
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 a5e7e95..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";
/**
@@ -4336,6 +4344,18 @@
"android.intent.action.DEVICE_CUSTOMIZATION_READY";
+ /**
+ * Activity Action: Display an activity state associated with an unique {@link LocusId}.
+ *
+ * <p>For example, a chat app could use the context to resume a conversation between 2 users.
+ *
+ * <p>Input: {@link #EXTRA_LOCUS_ID} specifies the unique identifier of the locus in the
+ * app domain. Should be stable across reboots and backup / restore.
+ * <p>Output: nothing.
+ */
+ @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
+ public static final String ACTION_VIEW_LOCUS = "android.intent.action.VIEW_LOCUS";
+
// ---------------------------------------------------------------------
// ---------------------------------------------------------------------
// Standard intent categories (see addCategory()).
@@ -5534,6 +5554,15 @@
*/
public static final int EXTRA_MEDIA_RESOURCE_TYPE_AUDIO_CODEC = 1;
+ /**
+ * Intent extra: ID of the context used on {@link #ACTION_VIEW_LOCUS}.
+ *
+ * <p>
+ * Type: {@link LocusId}
+ * </p>
+ */
+ public static final String EXTRA_LOCUS_ID = "android.intent.extra.LOCUS_ID";
+
// ---------------------------------------------------------------------
// ---------------------------------------------------------------------
// Intent flags (see mFlags variable).
diff --git a/core/java/android/content/LocusId.java b/core/java/android/content/LocusId.java
new file mode 100644
index 0000000..9548f9c
--- /dev/null
+++ b/core/java/android/content/LocusId.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 android.content;
+
+import android.annotation.NonNull;
+import android.net.Uri;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import com.android.internal.util.Preconditions;
+
+import java.io.PrintWriter;
+
+/**
+ * Identifier for an unique state in the application.
+ *
+ * <p>Should be stable across reboots and backup / restore.
+ *
+ * <p>For example, a chat app could use the context to resume a conversation between 2 users.
+ */
+// TODO(b/123577059): make sure this is well documented and understandable
+public final class LocusId implements Parcelable {
+
+ private final Uri mUri;
+
+ /**
+ * Default constructor.
+ */
+ public LocusId(@NonNull Uri uri) {
+ mUri = Preconditions.checkNotNull(uri);
+ }
+
+ /**
+ * Gets the {@code uri} associated with the locus.
+ */
+ @NonNull
+ public Uri getUri() {
+ return mUri;
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ((mUri == null) ? 0 : mUri.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) return true;
+ if (obj == null) return false;
+ if (getClass() != obj.getClass()) return false;
+ final LocusId other = (LocusId) obj;
+ if (mUri == null) {
+ if (other.mUri != null) return false;
+ } else {
+ if (!mUri.equals(other.mUri)) return false;
+ }
+ return true;
+ }
+
+ @Override
+ public String toString() {
+ return "LocusId[uri=" + getSanitizedUri() + "]";
+ }
+
+ /** @hide */
+ public void dump(@NonNull PrintWriter pw) {
+ pw.print("uri:"); pw.println(getSanitizedUri());
+ }
+
+ private String getSanitizedUri() {
+ final int size = mUri.toString().length();
+ return size + "_chars";
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ dest.writeParcelable(mUri, flags);
+ }
+
+ public static final Parcelable.Creator<LocusId> CREATOR =
+ new Parcelable.Creator<LocusId>() {
+
+ @Override
+ public LocusId createFromParcel(Parcel source) {
+ final Uri uri = source.readParcelable(null);
+ return new LocusId(uri);
+ }
+
+ @Override
+ public LocusId[] newArray(int size) {
+ return new LocusId[size];
+ }
+ };
+}
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/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 ec6da24..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;
@@ -677,25 +676,6 @@
return true;
}
- /**
- * 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();
- }
-
private static String chooseAbi(ApplicationInfo ai) {
final String isa = VMRuntime.getCurrentInstructionSet();
if (ai.primaryCpuAbi != null &&
diff --git a/core/java/android/os/storage/StorageManager.java b/core/java/android/os/storage/StorageManager.java
index 15aaa94..90a5f76 100644
--- a/core/java/android/os/storage/StorageManager.java
+++ b/core/java/android/os/storage/StorageManager.java
@@ -1561,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/provider/Settings.java b/core/java/android/provider/Settings.java
index 5d298bf..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:
*
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 b60fbc5..d361a2c 100644
--- a/core/java/android/service/contentcapture/ContentCaptureService.java
+++ b/core/java/android/service/contentcapture/ContentCaptureService.java
@@ -284,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/view/View.java b/core/java/android/view/View.java
index 2b440dc..a78f2b0 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -9463,17 +9463,24 @@
* the Content Capture events associated with this view or its view hierarchy (if it's a
* {@link ViewGroup}).
*
+ * <p>For example, if your activity is associated with a web domain, first you would need to
+ * set the context for the main DOM:
+ *
+ * <pre>
+ * ContentCaptureSession mainSession = rootView.getContentCaptureSession();
+ * mainSession.setContentCaptureContext(ContentCaptureContext.forLocusId(Uri.parse(myUrl));
+ * <pre>
+ *
+ * <p>Then if the page had an {@code IFRAME}, you would create a new session for it:
+ *
* <p>For example, if your activity is associated with a web domain, you could create a session
* {@code onCreate()} and associate it with the root view of the activity:
*
* <pre>
- * ContentCaptureSession oldSession = rootView.getContentCaptureSession();
- * if (oldSession != null) {
- * ContentCaptureSession newSession = oldSession.createContentCaptureSession(new
- * ContentCaptureContext.Builder().setUri(myUrl).build());
- * rootView.setContentCaptureSession(newSession);
- * }
- * </pre>
+ * ContentCaptureSession iframeSession = mainSession.createContentCaptureSession(
+ * ContentCaptureContext.forLocusId(Uri.parse(iframeUrl)));
+ * iframeView.setContentCaptureSession(iframeSession);
+ * <pre>
*
* @param contentCaptureSession a session created by
* {@link ContentCaptureSession#createContentCaptureSession(
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/ContentCaptureContext.java b/core/java/android/view/contentcapture/ContentCaptureContext.java
index 6a9759d..8bb4d21 100644
--- a/core/java/android/view/contentcapture/ContentCaptureContext.java
+++ b/core/java/android/view/contentcapture/ContentCaptureContext.java
@@ -23,7 +23,7 @@
import android.app.TaskInfo;
import android.content.ComponentName;
import android.content.Context;
-import android.content.Intent;
+import android.content.LocusId;
import android.net.Uri;
import android.os.Bundle;
import android.os.Parcel;
@@ -88,8 +88,7 @@
// Fields below are set by app on Builder
private final @Nullable Bundle mExtras;
- private final @Nullable Uri mUri;
- private final @Nullable String mAction;
+ private final @Nullable LocusId mId;
// Fields below are set by server when the session starts
private final @Nullable ComponentName mComponentName;
@@ -106,13 +105,11 @@
if (clientContext != null) {
mHasClientContext = true;
mExtras = clientContext.mExtras;
- mUri = clientContext.mUri;
- mAction = clientContext.mAction;
+ mId = clientContext.mId;
} else {
mHasClientContext = false;
mExtras = null;
- mUri = null;
- mAction = null;
+ mId = null;
}
mComponentName = Preconditions.checkNotNull(componentName);
mTaskId = taskId;
@@ -123,8 +120,7 @@
private ContentCaptureContext(@NonNull Builder builder) {
mHasClientContext = true;
mExtras = builder.mExtras;
- mUri = builder.mUri;
- mAction = builder.mAction;
+ mId = builder.mId;
mComponentName = null;
mTaskId = mFlags = 0;
@@ -135,38 +131,18 @@
* Gets the (optional) extras set by the app (through {@link Builder#setExtras(Bundle)}).
*
* <p>It can be used to provide vendor-specific data that can be modified and examined.
- *
- * @hide
*/
- @SystemApi
- @TestApi
@Nullable
public Bundle getExtras() {
return mExtras;
}
/**
- * Gets the (optional) URI set by the app (through {@link Builder#setUri(Uri)}).
- *
- * @hide
+ * Gets the context id.
*/
- @SystemApi
- @TestApi
- @Nullable
- public Uri getUri() {
- return mUri;
- }
-
- /**
- * Gets the (optional) action set by the app (through {@link Builder#setAction(String)}).
- *
- * @hide
- */
- @SystemApi
- @TestApi
- @Nullable
- public String getAction() {
- return mAction;
+ @NonNull
+ public LocusId getLocusId() {
+ return mId;
}
/**
@@ -236,13 +212,38 @@
}
/**
+ * Helper that creates a {@link ContentCaptureContext} associated with the given {@code uri}.
+ */
+ public static ContentCaptureContext forLocusId(@NonNull Uri uri) {
+ return new Builder(new LocusId(uri)).build();
+ }
+
+ /**
* Builder for {@link ContentCaptureContext} objects.
*/
public static final class Builder {
private Bundle mExtras;
- private Uri mUri;
+ private final LocusId mId;
private boolean mDestroyed;
- private String mAction;
+
+ /**
+ * Creates a new builder.
+ *
+ * <p>The context must have an id, which is usually one of the following:
+ *
+ * <ul>
+ * <li>A URL representing a web page (or {@code IFRAME}) that's being rendered by the
+ * activity (See {@link View#setContentCaptureSession(ContentCaptureSession)} for an
+ * example).
+ * <li>A unique identifier of the application state (for example, a conversation between
+ * 2 users in a chat app).
+ *
+ * @param id id associated with this context.
+ */
+ // TODO(b/123577059): make sure this is well documented and understandable
+ public Builder(@NonNull LocusId id) {
+ mId = Preconditions.checkNotNull(id);
+ }
/**
* Sets extra options associated with this context.
@@ -262,50 +263,14 @@
}
/**
- * Sets the {@link Uri} associated with this context.
- *
- * <p>See {@link View#setContentCaptureSession(ContentCaptureSession)} for an example.
- *
- * @param uri URI associated with this context.
- * @return this builder.
- *
- * @throws IllegalStateException if {@link #build()} was already called.
- */
- @NonNull
- public Builder setUri(@NonNull Uri uri) {
- mUri = Preconditions.checkNotNull(uri);
- throwIfDestroyed();
- return this;
- }
-
- /**
- * Sets an {@link Intent#getAction() intent action} associated with this context.
- *
- * @param action intent action
- *
- * @return this builder
- *
- * @throws IllegalStateException if {@link #build()} was already called.
- */
- @NonNull
- public Builder setAction(@NonNull String action) {
- mAction = Preconditions.checkNotNull(action);
- throwIfDestroyed();
- return this;
- }
-
- /**
* Builds the {@link ContentCaptureContext}.
*
- * @throws IllegalStateException if {@link #build()} was already called or no call to either
- * {@link #setExtras(Bundle)}, {@link #setAction(String)}, or {@link #setUri(Uri)} was made.
+ * @throws IllegalStateException if {@link #build()} was already called.
*
* @return the built {@code ContentCaptureContext}
*/
public ContentCaptureContext build() {
throwIfDestroyed();
- Preconditions.checkState(mExtras != null || mUri != null || mAction != null,
- "Must call setUri() or setExtras() or setUri() before calling build()");
mDestroyed = true;
return new ContentCaptureContext(this);
}
@@ -320,7 +285,12 @@
*/
// TODO(b/111276913): dump to proto as well
public void dump(PrintWriter pw) {
- pw.print("comp="); pw.print(ComponentName.flattenToShortString(mComponentName));
+ if (mComponentName != null) {
+ pw.print("activity="); pw.print(mComponentName.flattenToShortString());
+ }
+ if (mId != null) {
+ pw.print(", id="); mId.dump(pw);
+ }
pw.print(", taskId="); pw.print(mTaskId);
pw.print(", displayId="); pw.print(mDisplayId);
if (mParentSessionId != null) {
@@ -333,38 +303,31 @@
// NOTE: cannot dump because it could contain PII
pw.print(", hasExtras");
}
- if (mUri != null) {
- // NOTE: cannot dump because it could contain PII
- pw.print(", hasUri");
- }
- if (mAction != null) {
- // NOTE: cannot dump because it could contain PII
- pw.print(", hasAction");
- }
+ }
+
+ private boolean fromServer() {
+ return mComponentName != null;
}
@Override
public String toString() {
- final StringBuilder builder = new StringBuilder("Context[act=")
- .append(ComponentName.flattenToShortString(mComponentName))
+ final StringBuilder builder = new StringBuilder("Context[");
+
+ if (fromServer()) {
+ builder.append("act=").append(ComponentName.flattenToShortString(mComponentName))
.append(", taskId=").append(mTaskId)
.append(", displayId=").append(mDisplayId)
.append(", flags=").append(mFlags);
+ } else {
+ builder.append("id=").append(mId);
+ if (mExtras != null) {
+ // NOTE: cannot print because it could contain PII
+ builder.append(", hasExtras");
+ }
+ }
if (mParentSessionId != null) {
builder.append(", parentId=").append(mParentSessionId);
}
- if (mExtras != null) {
- // NOTE: cannot print because it could contain PII
- builder.append(", hasExtras");
- }
- if (mUri != null) {
- // NOTE: cannot print because it could contain PII
- builder.append(", hasUri");
- }
- if (mAction != null) {
- // NOTE: cannot print because it could contain PII
- builder.append(", hasAction");
- }
return builder.append(']').toString();
}
@@ -377,12 +340,11 @@
public void writeToParcel(Parcel parcel, int flags) {
parcel.writeInt(mHasClientContext ? 1 : 0);
if (mHasClientContext) {
- parcel.writeParcelable(mUri, flags);
- parcel.writeString(mAction);
+ parcel.writeParcelable(mId, flags);
parcel.writeBundle(mExtras);
}
parcel.writeParcelable(mComponentName, flags);
- if (mComponentName != null) {
+ if (fromServer()) {
parcel.writeInt(mTaskId);
parcel.writeInt(mDisplayId);
parcel.writeInt(mFlags);
@@ -399,12 +361,9 @@
final ContentCaptureContext clientContext;
if (hasClientContext) {
// Must reconstruct the client context using the Builder API
- final Builder builder = new Builder();
- final Uri uri = parcel.readParcelable(null);
- final String action = parcel.readString();
+ final LocusId id = parcel.readParcelable(null);
final Bundle extras = parcel.readBundle();
- if (uri != null) builder.setUri(uri);
- if (action != null) builder.setAction(action);
+ final Builder builder = new Builder(id);
if (extras != null) builder.setExtras(extras);
clientContext = new ContentCaptureContext(builder);
} else {
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/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/contentcapture/UserDataRemovalRequest.java b/core/java/android/view/contentcapture/UserDataRemovalRequest.java
index 8fedcd5..7d66af9 100644
--- a/core/java/android/view/contentcapture/UserDataRemovalRequest.java
+++ b/core/java/android/view/contentcapture/UserDataRemovalRequest.java
@@ -17,7 +17,7 @@
import android.annotation.NonNull;
import android.app.ActivityThread;
-import android.net.Uri;
+import android.content.LocusId;
import android.os.Parcel;
import android.os.Parcelable;
import android.util.IntArray;
@@ -36,16 +36,16 @@
private final String mPackageName;
private final boolean mForEverything;
- private ArrayList<UriRequest> mUriRequests;
+ private ArrayList<LocusIdRequest> mLocusIdRequests;
private UserDataRemovalRequest(@NonNull Builder builder) {
mPackageName = ActivityThread.currentActivityThread().getApplication().getPackageName();
mForEverything = builder.mForEverything;
- if (builder.mUris != null) {
- final int size = builder.mUris.size();
- mUriRequests = new ArrayList<>(size);
+ if (builder.mLocusIds != null) {
+ final int size = builder.mLocusIds.size();
+ mLocusIdRequests = new ArrayList<>(size);
for (int i = 0; i < size; i++) {
- mUriRequests.add(new UriRequest(builder.mUris.get(i),
+ mLocusIdRequests.add(new LocusIdRequest(builder.mLocusIds.get(i),
builder.mRecursive.get(i) == 1));
}
}
@@ -56,9 +56,9 @@
mForEverything = parcel.readBoolean();
if (!mForEverything) {
final int size = parcel.readInt();
- mUriRequests = new ArrayList<>(size);
+ mLocusIdRequests = new ArrayList<>(size);
for (int i = 0; i < size; i++) {
- mUriRequests.add(new UriRequest((Uri) parcel.readValue(null),
+ mLocusIdRequests.add(new LocusIdRequest((LocusId) parcel.readValue(null),
parcel.readBoolean()));
}
}
@@ -80,11 +80,11 @@
}
/**
- * Gets the list of {@code Uri}s the apps is requesting to remove.
+ * Gets the list of {@code LousId}s the apps is requesting to remove.
*/
@NonNull
- public List<UriRequest> getUriRequests() {
- return mUriRequests;
+ public List<LocusIdRequest> getLocusIdRequests() {
+ return mLocusIdRequests;
}
/**
@@ -93,7 +93,7 @@
public static final class Builder {
private boolean mForEverything;
- private ArrayList<Uri> mUris;
+ private ArrayList<LocusId> mLocusIds;
private IntArray mRecursive;
private boolean mDestroyed;
@@ -106,36 +106,32 @@
@NonNull
public Builder forEverything() {
throwIfDestroyed();
- if (mUris != null) {
- throw new IllegalStateException("Already added Uris");
- }
+ Preconditions.checkState(mLocusIds == null, "Already added LocusIds");
mForEverything = true;
return this;
}
/**
- * Request service to remove data associated with a given {@link Uri}.
+ * Request service to remove data associated with a given {@link LocusId}.
*
- * @param uri URI being requested to be removed.
- * @param recursive whether it should remove the data associated with just the URI or its
- * tree of descendants.
+ * @param locusId the {@link LocusId} being requested to be removed.
+ * @param recursive whether it should remove the data associated with just the
+ * {@code LocusId} or its tree of descendants.
*
* @return this builder
*/
- public Builder addUri(@NonNull Uri uri, boolean recursive) {
+ public Builder addLocusId(@NonNull LocusId locusId, boolean recursive) {
throwIfDestroyed();
- if (mForEverything) {
- throw new IllegalStateException("Already is for everything");
- }
- Preconditions.checkNotNull(uri);
+ Preconditions.checkState(!mForEverything, "Already is for everything");
+ Preconditions.checkNotNull(locusId);
- if (mUris == null) {
- mUris = new ArrayList<>();
+ if (mLocusIds == null) {
+ mLocusIds = new ArrayList<>();
mRecursive = new IntArray();
}
- mUris.add(uri);
+ mLocusIds.add(locusId);
mRecursive.add(recursive ? 1 : 0);
return this;
}
@@ -147,7 +143,7 @@
public UserDataRemovalRequest build() {
throwIfDestroyed();
- Preconditions.checkState(mForEverything || mUris != null);
+ Preconditions.checkState(mForEverything || mLocusIds != null);
mDestroyed = true;
return new UserDataRemovalRequest(this);
@@ -168,11 +164,11 @@
parcel.writeString(mPackageName);
parcel.writeBoolean(mForEverything);
if (!mForEverything) {
- final int size = mUriRequests.size();
+ final int size = mLocusIdRequests.size();
parcel.writeInt(size);
for (int i = 0; i < size; i++) {
- final UriRequest request = mUriRequests.get(i);
- parcel.writeValue(request.getUri());
+ final LocusIdRequest request = mLocusIdRequests.get(i);
+ parcel.writeValue(request.getLocusId());
parcel.writeBoolean(request.isRecursive());
}
}
@@ -193,28 +189,28 @@
};
/**
- * Representation of a request to remove data associated with an {@link Uri}.
+ * Representation of a request to remove data associated with a {@link LocusId}.
*/
- public final class UriRequest {
- private final @NonNull Uri mUri;
+ public final class LocusIdRequest {
+ private final @NonNull LocusId mLocusId;
private final boolean mRecursive;
- private UriRequest(@NonNull Uri uri, boolean recursive) {
- this.mUri = uri;
+ private LocusIdRequest(@NonNull LocusId locusId, boolean recursive) {
+ this.mLocusId = locusId;
this.mRecursive = recursive;
}
/**
- * Gets the URI per se.
+ * Gets the {@code LocusId} per se.
*/
@NonNull
- public Uri getUri() {
- return mUri;
+ public LocusId getLocusId() {
+ return mLocusId;
}
/**
- * Checks whether the request is to remove just the data associated with the URI per se, or
- * also its descendants.
+ * Checks whether the request is to remove just the data associated with the {@link LocusId}
+ * per se, or also its descendants.
*/
@NonNull
public boolean isRecursive() {
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/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/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/ZygoteServer.java b/core/java/com/android/internal/os/ZygoteServer.java
index 24269ef..2c17540 100644
--- a/core/java/com/android/internal/os/ZygoteServer.java
+++ b/core/java/com/android/internal/os/ZygoteServer.java
@@ -283,8 +283,6 @@
* passed up from blastulaMain.
*/
private Runnable fillBlastulaPool(int[] sessionSocketRawFDs) {
- Log.i(TAG, "FDHUNT - Marker 2 - fillBlastulaPool");
-
if (mBlastulaPoolEnabled) {
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "Zygote:FillBlastulaPool");
@@ -447,8 +445,6 @@
} else {
// Either the blastula pool event FD or a blastula reporting pipe.
- Log.i(TAG, "FDHUNT - Marker 1 - runSelectLoop");
-
// If this is the event FD the payload will be the number of blastulas removed.
// If this is a reporting pipe FD the payload will be the PID of the blastula
// that was just specialized.
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 c45900c..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;
@@ -785,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=");
@@ -1495,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_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 4649b52..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)));
}
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/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/provider/SettingsBackupTest.java b/core/tests/coretests/src/android/provider/SettingsBackupTest.java
index bb5e8df..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,
diff --git a/core/tests/coretests/src/android/view/contentcapture/ContentCaptureEventTest.java b/core/tests/coretests/src/android/view/contentcapture/ContentCaptureEventTest.java
index a97c3fa..a5ac270 100644
--- a/core/tests/coretests/src/android/view/contentcapture/ContentCaptureEventTest.java
+++ b/core/tests/coretests/src/android/view/contentcapture/ContentCaptureEventTest.java
@@ -24,6 +24,8 @@
import static org.testng.Assert.assertThrows;
+import android.content.LocusId;
+import android.net.Uri;
import android.os.Parcel;
import android.os.SystemClock;
import android.view.autofill.AutofillId;
@@ -45,9 +47,11 @@
private static final long MY_EPOCH = SystemClock.uptimeMillis();
+ private static final LocusId ID = new LocusId(Uri.parse("WHATEVER"));
+
// Not using @Mock because it's final - no need to be fancy here....
- private final ContentCaptureContext mClientContext = new ContentCaptureContext.Builder()
- .setAction("WHATEVER").build();
+ private final ContentCaptureContext mClientContext =
+ new ContentCaptureContext.Builder(ID).build();
@Test
public void testSetAutofillId_null() {
@@ -177,7 +181,7 @@
assertThat(event.getViewNode()).isNull();
final ContentCaptureContext clientContext = event.getContentCaptureContext();
assertThat(clientContext).isNotNull();
- assertThat(clientContext.getAction()).isEqualTo("WHATEVER");
+ assertThat(clientContext.getLocusId()).isEqualTo(ID);
}
@Test
@@ -210,7 +214,6 @@
assertThat(event.getContentCaptureContext()).isNull();
}
-
@Test
public void testContextUpdated_directly() {
final ContentCaptureEvent event = new ContentCaptureEvent("42", TYPE_CONTEXT_UPDATED)
@@ -239,7 +242,7 @@
assertThat(event.getViewNode()).isNull();
final ContentCaptureContext clientContext = event.getContentCaptureContext();
assertThat(clientContext).isNotNull();
- assertThat(clientContext.getAction()).isEqualTo("WHATEVER");
+ assertThat(clientContext.getLocusId()).isEqualTo(ID);
}
// TODO(b/123036895): add test for all events type (right now we're just testing the 3 types
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/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/apex/java/android/media/MediaSession2.java b/media/apex/java/android/media/MediaSession2.java
index 1f8400a..4c6945a 100644
--- a/media/apex/java/android/media/MediaSession2.java
+++ b/media/apex/java/android/media/MediaSession2.java
@@ -353,6 +353,7 @@
}
mConnectedControllers.put(controller, controllerInfo);
}
+ mCallback.onPostConnect(MediaSession2.this, controllerInfo);
connected = true;
} finally {
if (!connected) {
@@ -744,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/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/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/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/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/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/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/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/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 8ecca26..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>
@@ -1008,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/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/BubbleExpandedView.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleExpandedView.java
index 6dee8ad..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
@@ -343,6 +352,28 @@
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) {
@@ -407,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 eae17eea..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(),
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/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/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/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/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/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 360f064..9e15960 100644
--- a/services/contentcapture/java/com/android/server/contentcapture/ContentCapturePerUserService.java
+++ b/services/contentcapture/java/com/android/server/contentcapture/ContentCapturePerUserService.java
@@ -44,6 +44,7 @@
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;
@@ -467,5 +468,18 @@
// 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 3c0430f..bfe1f6a 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -14455,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,
@@ -17906,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/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/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/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/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/wm/ActivityStackSupervisor.java b/services/core/java/com/android/server/wm/ActivityStackSupervisor.java
index c685b05..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,
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/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/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index 9767efd..ae48dad 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -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/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/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/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/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/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/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/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/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);
}