diff options
305 files changed, 6095 insertions, 1965 deletions
diff --git a/apct-tests/perftests/autofill/Android.bp b/apct-tests/perftests/autofill/Android.bp new file mode 100644 index 000000000000..65c28fb4d0a7 --- /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 f4da40b3175a..000000000000 --- 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 000000000000..508bf6007a9f --- /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 5852044effa8..000000000000 --- 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 000000000000..be85816629c1 --- /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 19f83c8f5bb0..000000000000 --- 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 4ac827afb54b..833b87b92102 100644 --- a/api/current.txt +++ b/api/current.txt @@ -9409,7 +9409,6 @@ package android.content { 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 @@ package android.content { 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 @@ package android.content { 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 @@ package android.content { 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 @@ package android.content { 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 @@ package android.content { 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 @@ package android.media { 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 @@ package android.net.wifi { 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 @@ package android.os { 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.media { 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 @@ package android.service.wallpaper { 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 @@ package android.view.contentcapture { 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 @@ package android.view.contentcapture { 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 @@ package android.view.contentcapture { 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 @@ package android.view.inspector { 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 128ee99c27ad..5c89b05d327e 100644 --- a/api/system-current.txt +++ b/api/system-current.txt @@ -454,6 +454,7 @@ package android.app { 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 @@ package android.content { } 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 @@ package android.media { 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 @@ package android.media.audiopolicy { 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 @@ package android.net.wifi { 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 @@ package android.service.autofill.augmented { 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 @@ package android.service.contentcapture { 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.euicc { 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.autofill { 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 @@ package android.view.contentcapture { 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 01678b1c1066..963584c47f2a 100644 --- a/api/test-current.txt +++ b/api/test-current.txt @@ -1301,7 +1301,7 @@ package android.os { 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 @@ package android.service.autofill.augmented { 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 @@ package android.service.contentcapture { 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.autofill { 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 @@ package android.view.contentcapture { 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 ea7274f3ea58..4a66715ad2b8 100644 --- a/cmds/idmap2/idmap2d/aidl/android/os/IIdmap2.aidl +++ b/cmds/idmap2/idmap2d/aidl/android/os/IIdmap2.aidl @@ -24,6 +24,7 @@ interface IIdmap2 { 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 99b5f0ff3c2d..ec498ffb393c 100644 --- a/cmds/idmap2/libidmap2/Idmap.cpp +++ b/cmds/idmap2/libidmap2/Idmap.cpp @@ -284,7 +284,7 @@ std::unique_ptr<const Idmap> Idmap::FromBinaryStream(std::istream& stream, 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 @@ bool CheckOverlayable(const LoadedPackage& target_package, } // 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 0f87ef0c4ea9..6649288dfa41 100644 --- a/cmds/idmap2/libidmap2/Policies.cpp +++ b/cmds/idmap2/libidmap2/Policies.cpp @@ -35,6 +35,7 @@ const std::map<android::StringPiece, PolicyFlags> kStringToFlag = { {"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 0e0e25f4f0f3..9a0412efbde4 100644 --- a/cmds/idmap2/tests/BinaryStreamVisitorTests.cpp +++ b/cmds/idmap2/tests/BinaryStreamVisitorTests.cpp @@ -129,28 +129,31 @@ TEST(BinaryStreamVisitorTests, CreateIdmapFromApkAssetsInteropWithLoadedIdmap) { 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 8514e12e8c17..2e85eb6215d1 100644 --- a/cmds/idmap2/tests/FileUtilsTests.cpp +++ b/cmds/idmap2/tests/FileUtilsTests.cpp @@ -39,12 +39,13 @@ TEST(FileUtilsTests, FindFilesFindEverythingNonRecursive) { [](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 @@ TEST(FileUtilsTests, FindFilesFindApkFilesRecursive) { 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 1216f9ec736a..a6a2ada76712 100644 --- a/cmds/idmap2/tests/Idmap2BinaryTests.cpp +++ b/cmds/idmap2/tests/Idmap2BinaryTests.cpp @@ -132,9 +132,9 @@ TEST_F(Idmap2BinaryTests, Dump) { 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 @@ TEST_F(Idmap2BinaryTests, Lookup) { "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 b40521f054af..53ec03ba3d5e 100644 --- a/cmds/idmap2/tests/IdmapTests.cpp +++ b/cmds/idmap2/tests/IdmapTests.cpp @@ -191,8 +191,8 @@ TEST(IdmapTests, CreateIdmapFromApkAssets) { 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 @@ TEST(IdmapTests, CreateIdmapFromApkAssets) { 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 @@ TEST(IdmapOverlayableTests, CreateIdmapFromApkAssetsPolicySystemPublic) { 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 @@ TEST(IdmapOverlayableTests, CreateIdmapFromApkAssetsPolicySystemPublicInvalid) { 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 @@ TEST(IdmapOverlayableTests, CreateIdmapFromApkAssetsPolicySystemPublicInvalidIgn 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 @@ TEST(IdmapOverlayableTests, CreateIdmapFromApkAssetsNoDefinedOverlayable) { 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 @@ TEST(IdmapOverlayableTests, CreateIdmapFromApkAssetsNoDefinedOverlayableAndNoTar 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 a5588c330d85..7ec13ed0ade7 100644 --- a/cmds/idmap2/tests/RawPrintVisitorTests.cpp +++ b/cmds/idmap2/tests/RawPrintVisitorTests.cpp @@ -52,8 +52,8 @@ TEST(RawPrintVisitorTests, CreateRawPrintVisitor) { 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 index e60da803388b..e879f443c7b1 100644..100755 --- 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 000000000000..5dacebded529 --- /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 index 7ec6e1146060..fdd8301c3b7d 100644..100755 --- 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 000000000000..59e7d8ed69c1 --- /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 Binary files differnew file mode 100644 index 000000000000..b2c490dcbb90 --- /dev/null +++ b/cmds/idmap2/tests/data/signature-overlay/signature-overlay.apk diff --git a/cmds/idmap2/tests/data/system-overlay-invalid/build b/cmds/idmap2/tests/data/system-overlay-invalid/build index 920e1f8ad6f3..920e1f8ad6f3 100644..100755 --- a/cmds/idmap2/tests/data/system-overlay-invalid/build +++ b/cmds/idmap2/tests/data/system-overlay-invalid/build 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 af1bea16daee..02704009d743 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 Binary files differindex 710ed9067f69..9448939b5636 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 diff --git a/cmds/idmap2/tests/data/system-overlay/build b/cmds/idmap2/tests/data/system-overlay/build index be0d2390f535..be0d2390f535 100644..100755 --- a/cmds/idmap2/tests/data/system-overlay/build +++ b/cmds/idmap2/tests/data/system-overlay/build diff --git a/cmds/idmap2/tests/data/target/build b/cmds/idmap2/tests/data/target/build index 137ddb5ecaa1..e6df742cc9da 100644..100755 --- a/cmds/idmap2/tests/data/target/build +++ b/cmds/idmap2/tests/data/target/build @@ -17,5 +17,5 @@ aapt2 link --manifest AndroidManifest.xml -A assets -o target.apk compiled.flata 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 02d25630546f..0bf83fa50b75 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 partition restrictins --> + <!-- Resources with signature restrictions --> + <policy type="signature"> + <item type="string" name="policy_signature" /> + </policy> + + <!-- 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 0d337f3890a8..edd53f4c9b52 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 Binary files differindex 8676cbb9dc3f..908b54a2f0c3 100644 --- a/cmds/idmap2/tests/data/target/target-no-overlayable.apk +++ b/cmds/idmap2/tests/data/target/target-no-overlayable.apk diff --git a/cmds/idmap2/tests/data/target/target.apk b/cmds/idmap2/tests/data/target/target.apk Binary files differindex ecbe87578684..da3c1aef5fba 100644 --- a/cmds/idmap2/tests/data/target/target.apk +++ b/cmds/idmap2/tests/data/target/target.apk diff --git a/cmds/statsd/src/atoms.proto b/cmds/statsd/src/atoms.proto index 2585a5b27681..d78647eebe1f 100644 --- a/cmds/statsd/src/atoms.proto +++ b/cmds/statsd/src/atoms.proto @@ -246,6 +246,7 @@ message Atom { 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 @@ message ServiceLaunchReported { 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 e55c96443198..d29feddc0963 100644 --- a/core/java/android/app/Activity.java +++ b/core/java/android/app/Activity.java @@ -3783,14 +3783,14 @@ public class Activity extends ContextThemeWrapper /** - * 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 cc419b8d837a..790863713b19 100644 --- a/core/java/android/app/ActivityThread.java +++ b/core/java/android/app/ActivityThread.java @@ -3229,8 +3229,9 @@ public final class ActivityThread extends ClientTransactionHandler { 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 69c3632b7ab2..062a462b71fd 100644 --- a/core/java/android/app/BroadcastOptions.java +++ b/core/java/android/app/BroadcastOptions.java @@ -33,6 +33,7 @@ public class BroadcastOptions { 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 @@ public class BroadcastOptions { = "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 @@ public class BroadcastOptions { 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 @@ public class BroadcastOptions { } /** + * 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 @@ public class BroadcastOptions { 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 2b765b2284e7..497d5ba5fd93 100644 --- a/core/java/android/app/IActivityTaskManager.aidl +++ b/core/java/android/app/IActivityTaskManager.aidl @@ -215,7 +215,7 @@ interface IActivityTaskManager { 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 f0f7d899ff07..28c79aadf84e 100644 --- a/core/java/android/app/WallpaperInfo.java +++ b/core/java/android/app/WallpaperInfo.java @@ -371,10 +371,17 @@ public final class WallpaperInfo implements Parcelable { * 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 806536b6947c..3587c68ef234 100644 --- a/core/java/android/app/admin/DevicePolicyManager.java +++ b/core/java/android/app/admin/DevicePolicyManager.java @@ -7036,9 +7036,9 @@ public class DevicePolicyManager { } /** - * 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 @@ public class DevicePolicyManager { * 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 0b5bdb5bfd4f..93bf5188705c 100644 --- a/core/java/android/content/ContentProviderClient.java +++ b/core/java/android/content/ContentProviderClient.java @@ -626,15 +626,14 @@ public class ContentProviderClient implements ContentInterface, AutoCloseable { 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 bbfa5cceec1d..0e11d4e12f3d 100644 --- a/core/java/android/content/ContentResolver.java +++ b/core/java/android/content/ContentResolver.java @@ -3148,14 +3148,17 @@ public abstract class ContentResolver implements ContentInterface { } /** - * 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 @@ public abstract class ContentResolver implements ContentInterface { } /** - * 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 fd7b37210822..767d3f668313 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 @@ public class ContentUris { * @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 @@ public class ContentUris { * * @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 @@ public class ContentUris { * * @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 @@ public class ContentUris { * @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 a5e7e95f0874..b67349f2004f 100644 --- a/core/java/android/content/Intent.java +++ b/core/java/android/content/Intent.java @@ -37,6 +37,7 @@ import android.content.pm.ShortcutInfo; 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 @@ public class Intent implements Parcelable, Cloneable { @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 @@ public class Intent implements Parcelable, Cloneable { "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 class Intent implements Parcelable, Cloneable { */ 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 000000000000..9548f9c32d90 --- /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 ceeecbc311d8..0e869c8c19fd 100644 --- a/core/java/android/database/sqlite/SQLiteOpenHelper.java +++ b/core/java/android/database/sqlite/SQLiteOpenHelper.java @@ -48,6 +48,9 @@ import java.io.File; * * <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 ea489c456f3d..03e850716bc2 100644 --- a/core/java/android/database/sqlite/SQLiteQueryBuilder.java +++ b/core/java/android/database/sqlite/SQLiteQueryBuilder.java @@ -68,16 +68,16 @@ public class SQLiteQueryBuilder { } /** - * 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 @@ public class SQLiteQueryBuilder { } /** - * 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 @@ public class SQLiteQueryBuilder { } /** - * 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 @@ public class SQLiteQueryBuilder { * 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 @@ public class SQLiteQueryBuilder { * 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 @@ public class SQLiteQueryBuilder { * 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 @@ public class SQLiteQueryBuilder { * 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 @@ public class SQLiteQueryBuilder { * * @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 @@ public class SQLiteQueryBuilder { * * @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 @@ public class SQLiteQueryBuilder { } /** - * 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 @@ public class SQLiteQueryBuilder { * 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 @@ public class SQLiteQueryBuilder { } /** - * 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 @@ public class SQLiteQueryBuilder { * 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 @@ public class SQLiteQueryBuilder { * @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 @@ public class SQLiteQueryBuilder { } /** - * 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 0384faa88be5..316572cfd14e 100644 --- a/core/java/android/os/FileUtils.java +++ b/core/java/android/os/FileUtils.java @@ -85,7 +85,7 @@ import java.util.zip.CheckedInputStream; /** * 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 @@ public class FileUtils { * 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 @@ public class FileUtils { * @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 ec6da24dc2b1..4a14eced7d87 100644 --- a/core/java/android/os/GraphicsEnvironment.java +++ b/core/java/android/os/GraphicsEnvironment.java @@ -25,7 +25,6 @@ import android.content.pm.PackageManager; 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 @@ public class GraphicsEnvironment { 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 15aaa946e602..90a5f7660e0d 100644 --- a/core/java/android/os/storage/StorageManager.java +++ b/core/java/android/os/storage/StorageManager.java @@ -1561,7 +1561,13 @@ public class StorageManager { 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 5d298bf29bd5..a465b3271407 100644 --- a/core/java/android/provider/Settings.java +++ b/core/java/android/provider/Settings.java @@ -11731,6 +11731,14 @@ public final class Settings { 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 8695da237f97..ce83a57bf68b 100644 --- a/core/java/android/service/autofill/augmented/AugmentedAutofillService.java +++ b/core/java/android/service/autofill/augmented/AugmentedAutofillService.java @@ -126,6 +126,14 @@ public abstract class AugmentedAutofillService extends Service { } /** + * 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 @@ public abstract class AugmentedAutofillService extends Service { @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 b60fbc593b1c..d361a2c50935 100644 --- a/core/java/android/service/contentcapture/ContentCaptureService.java +++ b/core/java/android/service/contentcapture/ContentCaptureService.java @@ -284,6 +284,24 @@ public abstract class ContentCaptureService extends Service { } /** + * 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 2a729b6dc874..8bc8defede80 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 @@ import java.util.List; */ 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 2961426278dc..bddc5ef3dd2d 100644 --- a/core/java/android/service/notification/Adjustment.java +++ b/core/java/android/service/notification/Adjustment.java @@ -20,9 +20,17 @@ import android.app.Notification; 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 @@ public final class Adjustment implements Parcelable { * @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 @@ public final class Adjustment implements Parcelable { } /** + * 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 @@ public final class Adjustment implements Parcelable { 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 b197c8a8a388..c042a8c8ae1c 100644 --- a/core/java/android/service/wallpaper/WallpaperService.java +++ b/core/java/android/service/wallpaper/WallpaperService.java @@ -1068,9 +1068,13 @@ public abstract class WallpaperService extends Service { * 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 2b440dc80cfd..a78f2b073a3a 100644 --- a/core/java/android/view/View.java +++ b/core/java/android/view/View.java @@ -9463,17 +9463,24 @@ public class View implements Drawable.Callback, KeyEvent.Callback, * 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 097f368ac2a8..3544a8733c68 100644 --- a/core/java/android/view/Window.java +++ b/core/java/android/view/Window.java @@ -622,11 +622,10 @@ public abstract class Window { /** @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 e3833c01eeaf..453c5e32a178 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 @@ public final class WindowManagerGlobal { 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 6a9759db78a0..8bb4d210ad44 100644 --- a/core/java/android/view/contentcapture/ContentCaptureContext.java +++ b/core/java/android/view/contentcapture/ContentCaptureContext.java @@ -23,7 +23,7 @@ import android.annotation.TestApi; 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 @@ public final class ContentCaptureContext implements Parcelable { // 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 @@ public final class ContentCaptureContext implements Parcelable { 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 @@ public final class ContentCaptureContext implements Parcelable { 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 @@ public final class ContentCaptureContext implements Parcelable { * 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,60 +212,52 @@ public final class ContentCaptureContext implements Parcelable { } /** + * 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; /** - * Sets extra options associated with this context. + * Creates a new builder. * - * <p>It can be used to provide vendor-specific data that can be modified and examined. + * <p>The context must have an id, which is usually one of the following: * - * @param extras extra options. - * @return this builder. + * <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). * - * @throws IllegalStateException if {@link #build()} was already called. + * @param id id associated with this context. */ - @NonNull - public Builder setExtras(@NonNull Bundle extras) { - mExtras = Preconditions.checkNotNull(extras); - throwIfDestroyed(); - return this; + // TODO(b/123577059): make sure this is well documented and understandable + public Builder(@NonNull LocusId id) { + mId = Preconditions.checkNotNull(id); } /** - * Sets the {@link Uri} associated with this context. + * Sets extra options associated with this context. * - * <p>See {@link View#setContentCaptureSession(ContentCaptureSession)} for an example. + * <p>It can be used to provide vendor-specific data that can be modified and examined. * - * @param uri URI associated with this context. + * @param extras extra options. * @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); + public Builder setExtras(@NonNull Bundle extras) { + mExtras = Preconditions.checkNotNull(extras); throwIfDestroyed(); return this; } @@ -297,15 +265,12 @@ public final class ContentCaptureContext implements Parcelable { /** * 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 @@ public final class ContentCaptureContext implements Parcelable { */ // 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 @@ public final class ContentCaptureContext implements Parcelable { // 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 final class ContentCaptureContext implements Parcelable { 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 @@ public final class ContentCaptureContext implements Parcelable { 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 99063083e229..87e358c1165f 100644 --- a/core/java/android/view/contentcapture/ContentCaptureManager.java +++ b/core/java/android/view/contentcapture/ContentCaptureManager.java @@ -327,39 +327,8 @@ public final class ContentCaptureManager { 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 26cf34c1b88e..e3b0372a8cc7 100644 --- a/core/java/android/view/contentcapture/IContentCaptureManager.aidl +++ b/core/java/android/view/contentcapture/IContentCaptureManager.aidl @@ -67,9 +67,4 @@ oneway interface IContentCaptureManager { * 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 8fedcd54b1fc..7d66af92e9f6 100644 --- a/core/java/android/view/contentcapture/UserDataRemovalRequest.java +++ b/core/java/android/view/contentcapture/UserDataRemovalRequest.java @@ -17,7 +17,7 @@ package android.view.contentcapture; 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 @@ public final class UserDataRemovalRequest implements Parcelable { 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 @@ public final class UserDataRemovalRequest implements Parcelable { 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 @@ public final class UserDataRemovalRequest implements Parcelable { } /** - * 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 final class UserDataRemovalRequest implements Parcelable { 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 @@ public final class UserDataRemovalRequest implements Parcelable { @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 final class UserDataRemovalRequest implements Parcelable { public UserDataRemovalRequest build() { throwIfDestroyed(); - Preconditions.checkState(mForEverything || mUris != null); + Preconditions.checkState(mForEverything || mLocusIds != null); mDestroyed = true; return new UserDataRemovalRequest(this); @@ -168,11 +164,11 @@ public final class UserDataRemovalRequest implements Parcelable { 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 @@ public final class UserDataRemovalRequest implements Parcelable { }; /** - * 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 000000000000..69d004e860fd --- /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 2009fd50137a..0fbd4dca700b 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.UserHandle; 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,27 +621,39 @@ public class ChooserActivity extends ResolverActivity { } } + /** + * 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); - } 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); + 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); + } - cursor.moveToFirst(); - fileName = cursor.getString(nameIndex); - if (flagsIndex != -1) { - hasThumbnail = (cursor.getInt(flagsIndex) - & DocumentsContract.Document.FLAG_SUPPORTS_THUMBNAIL) != 0; + 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 (TextUtils.isEmpty(fileName)) { diff --git a/core/java/com/android/internal/os/ZygoteConnection.java b/core/java/com/android/internal/os/ZygoteConnection.java index 9cf7e2770e86..8a878e22a7e3 100644 --- a/core/java/com/android/internal/os/ZygoteConnection.java +++ b/core/java/com/android/internal/os/ZygoteConnection.java @@ -338,13 +338,25 @@ class ZygoteConnection { 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 @@ class ZygoteConnection { 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 24269efc3f26..2c17540eb6c6 100644 --- a/core/java/com/android/internal/os/ZygoteServer.java +++ b/core/java/com/android/internal/os/ZygoteServer.java @@ -283,8 +283,6 @@ class ZygoteServer { * 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 @@ class ZygoteServer { } 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 21558d3d3518..e90a8d5826f2 100644 --- a/core/java/com/android/internal/widget/DecorCaptionView.java +++ b/core/java/com/android/internal/widget/DecorCaptionView.java @@ -329,13 +329,13 @@ public class DecorCaptionView extends ViewGroup implements View.OnTouchListener, } /** - * 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 @@ public class DecorCaptionView extends ViewGroup implements View.OnTouchListener, @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 74061367804e..30e9937c7d7c 100644 --- a/core/jni/Android.bp +++ b/core/jni/Android.bp @@ -163,6 +163,7 @@ cc_library_shared { "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 c45900c098b3..019ade9a3914 100644 --- a/core/jni/AndroidRuntime.cpp +++ b/core/jni/AndroidRuntime.cpp @@ -109,6 +109,7 @@ extern int register_android_media_AudioRecord(JNIEnv *env); 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 @@ extern int register_com_android_internal_util_VirtualRefBasePtr(JNIEnv *env); // 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 @@ int AndroidRuntime::startVm(JavaVM** pJavaVM, JNIEnv** pEnv, bool zygote) 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 @@ static const RegJNIRec gRegJNI[] = { 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 000000000000..a18e80a4e6e1 --- /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 2aa5cb41d5ab..ecc2dd0d3598 100644 --- a/core/jni/android_view_ThreadedRenderer.cpp +++ b/core/jni/android_view_ThreadedRenderer.cpp @@ -1029,6 +1029,10 @@ static void android_view_ThreadedRenderer_setForceDark(JNIEnv* env, jobject claz proxy->setForceDark(enable); } +static void android_view_ThreadedRenderer_preload(JNIEnv*, jclass) { + RenderProxy::preload(); +} + // ---------------------------------------------------------------------------- // FrameMetricsObserver // ---------------------------------------------------------------------------- @@ -1144,6 +1148,7 @@ static const JNINativeMethod gMethods[] = { { "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 4649b5262723..15ceca96313e 100644 --- a/core/jni/com_android_internal_os_Zygote.cpp +++ b/core/jni/com_android_internal_os_Zygote.cpp @@ -666,7 +666,7 @@ static void CreateSubDirs(int dirfd, const std::string& parentDirPath, 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 @@ static void EnsurePkgSpecificDirs(const std::string& path, 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 @@ static void CreatePkgSandboxSource(const std::string& sandboxSource, fail_fn_t f 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 66e18bb19c44..01f37f07e5ca 100755 --- a/core/jni/runtime_native_boot-flags-test.sh +++ b/core/jni/runtime_native_boot-flags-test.sh @@ -172,12 +172,14 @@ function check_no_zygote_gc_runtime_option { 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 @@ function test_android_runtime_flag { 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 @@ function test_android_runtime_flag { 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 @@ case $(adb shell getprop ro.zygote) in (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 224f54c64b63..088669da7b91 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 5948f2988bc4..09fb663468f5 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 7ef5e022c1c4..1ebd6e931ab6 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 bb5e8dfa8620..46cac7a49f13 100644 --- a/core/tests/coretests/src/android/provider/SettingsBackupTest.java +++ b/core/tests/coretests/src/android/provider/SettingsBackupTest.java @@ -122,6 +122,7 @@ public class SettingsBackupTest { 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 a97c3fa362eb..a5ac2707b620 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 com.google.common.truth.Truth.assertThat; 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 @@ public class ContentCaptureEventTest { 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 @@ public class ContentCaptureEventTest { 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 @@ public class ContentCaptureEventTest { assertThat(event.getContentCaptureContext()).isNull(); } - @Test public void testContextUpdated_directly() { final ContentCaptureEvent event = new ContentCaptureEvent("42", TYPE_CONTEXT_UPDATED) @@ -239,7 +242,7 @@ public class ContentCaptureEventTest { 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 7f104b1b0a14..f27f3f9ca427 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.not; 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.ClipboardManager; 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 @@ public class ChooserActivityTest { 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 096b78b95fbd..57c84ff5c8ac 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 @@ package com.android.internal.app; 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 @@ public class ChooserWrapperActivity extends ChooserActivity { 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 class ChooserWrapperActivity extends ChooserActivity { 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 @@ public class ChooserWrapperActivity extends ChooserActivity { 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 99d8c1b42a4a..b020556cd15f 100644 --- a/graphics/java/android/graphics/HardwareRenderer.java +++ b/graphics/java/android/graphics/HardwareRenderer.java @@ -1027,6 +1027,18 @@ public class HardwareRenderer { */ 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 ef9255f66695..e93e757410e0 100644 --- a/graphics/java/android/graphics/Typeface.java +++ b/graphics/java/android/graphics/Typeface.java @@ -128,7 +128,8 @@ public class Typeface { // 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 0335a7c6bd7d..793dd8d39376 100644 --- a/libs/hwui/Android.bp +++ b/libs/hwui/Android.bp @@ -318,6 +318,7 @@ cc_test { "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 720c60362a55..34f76d9b3579 100644 --- a/libs/hwui/renderthread/RenderProxy.cpp +++ b/libs/hwui/renderthread/RenderProxy.cpp @@ -381,6 +381,14 @@ void RenderProxy::releaseVDAtlasEntries() { }); } +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 6e1bfd74528a..a1a5551722bc 100644 --- a/libs/hwui/renderthread/RenderProxy.h +++ b/libs/hwui/renderthread/RenderProxy.h @@ -131,6 +131,8 @@ public: 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 fc63819120d6..08edd20c0a0d 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 @@ void RenderThread::initThreadLocals() { mRenderState = new RenderState(*this); mVkManager = new VulkanManager(); mCacheManager = new CacheManager(mDisplayInfo); - if (Properties::getRenderPipelineType() == RenderPipelineType::SkiaVulkan) { - requireVkContext(); - } } void RenderThread::requireGlContext() { @@ -346,6 +344,7 @@ void RenderThread::requestVsync() { bool RenderThread::threadLoop() { setpriority(PRIO_PROCESS, 0, PRIORITY_DISPLAY); + Looper::setForThread(mLooper); if (gOnStartHook) { gOnStartHook("RenderThread"); } @@ -408,6 +407,17 @@ bool RenderThread::isCurrent() { 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 419e7c7a6b51..329b4b99c911 100644 --- a/libs/hwui/renderthread/RenderThread.h +++ b/libs/hwui/renderthread/RenderThread.h @@ -115,6 +115,8 @@ public: 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 1e685abd8afa..3b43f1297597 100644 --- a/libs/hwui/renderthread/VulkanManager.cpp +++ b/libs/hwui/renderthread/VulkanManager.cpp @@ -360,7 +360,7 @@ void VulkanManager::initialize() { } } -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 97636865a629..95c9630fb728 100644 --- a/libs/hwui/renderthread/VulkanManager.h +++ b/libs/hwui/renderthread/VulkanManager.h @@ -150,7 +150,7 @@ public: // 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 000000000000..af8ae7841af2 --- /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 1f8400a7ef66..4c6945ae8d3f 100644 --- a/media/apex/java/android/media/MediaSession2.java +++ b/media/apex/java/android/media/MediaSession2.java @@ -353,6 +353,7 @@ public class MediaSession2 implements AutoCloseable { } mConnectedControllers.put(controller, controllerInfo); } + mCallback.onPostConnect(MediaSession2.this, controllerInfo); connected = true; } finally { if (!connected) { @@ -744,6 +745,17 @@ public class MediaSession2 implements AutoCloseable { } /** + * 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 000000000000..8bdb8a63f470 --- /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 ccf49bd774a8..21b194d73ff9 100644 --- a/media/java/android/media/ThumbnailUtils.java +++ b/media/java/android/media/ThumbnailUtils.java @@ -122,6 +122,9 @@ public class ThumbnailUtils { * @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 @@ public class ThumbnailUtils { * @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 @@ public class ThumbnailUtils { * @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 000000000000..bec11bcfab5d --- /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 000000000000..b8364091ff12 --- /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 000000000000..5ead30bccbcc --- /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 000000000000..af6e8bfdbd83 --- /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 000000000000..b0222da9405b --- /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 532d272f70f3..000000000000 --- 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 ca343d1d0bef..8077431e9da2 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.app.ActivityManager; 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 @@ public class NotificationsUI extends SystemUI 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 @@ public class NotificationsUI extends SystemUI closeCarNotifications(DEFAULT_FLING_VELOCITY); } }); - mCarNotificationListener.registerAsSystemService(mContext, mCarUxRestrictionManagerWrapper, - mClickHandlerFactory); + mCar = Car.createCar(mContext, mCarConnectionListener); mCar.connect(); NotificationGestureListener gestureListener = new NotificationGestureListener(); @@ -131,8 +150,6 @@ public class NotificationsUI extends SystemUI 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 c5a951ca5249..369bb9fdd9dd 100644 --- a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java +++ b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java @@ -512,32 +512,52 @@ public class CarStatusBar extends StatusBar implements } @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 { - mFullscreenUserSwitcher.hide(); + 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(); + } + } + + // 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. + } + } + public void postDismissKeyguard() { mHandler.post(this::dismissKeyguard); } diff --git a/packages/CarrierDefaultApp/Android.bp b/packages/CarrierDefaultApp/Android.bp new file mode 100644 index 000000000000..c1b0b2da2cb5 --- /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 df88afdcf041..000000000000 --- 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 6ebb57586ff6..000000000000 --- 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 000000000000..96144cf76ff7 --- /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 4c6388110ebf..000000000000 --- 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 000000000000..a379bfccbe29 --- /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 000000000000..824cc6992491 --- /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 000000000000..5d8950467b7b --- /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 000000000000..9199986d1348 --- /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 000000000000..2bd6d7e93d66 --- /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 000000000000..c992cfdc1fcc --- /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 000000000000..8a388a472579 --- /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 000000000000..e1b801670267 --- /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 000000000000..8748e205d212 --- /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 000000000000..a9fb9ff3d9d1 --- /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 000000000000..220553cfcd30 --- /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 000000000000..0ad921a79dd6 --- /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 000000000000..ebd9cb192216 --- /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 000000000000..7601e40428c1 --- /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 000000000000..b58f2c55d1af --- /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 000000000000..2d562136849a --- /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 000000000000..91c7643150d1 --- /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 000000000000..91c7643150d1 --- /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 000000000000..91c7643150d1 --- /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 000000000000..91c7643150d1 --- /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 000000000000..e052e61ac10b --- /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 000000000000..0552ee7ab9f3 --- /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 000000000000..c9e218e334f1 --- /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 000000000000..1ac26f712a18 --- /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 000000000000..26e19792b4c6 --- /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 000000000000..b43fe290ad04 --- /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 000000000000..fbc18f60c751 --- /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 000000000000..05e340299aef --- /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 000000000000..881d6aaea693 --- /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 000000000000..6f85022a31fb --- /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 000000000000..508850765cbd --- /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 000000000000..4afcb630a8ed --- /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 000000000000..7b71939476fb --- /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 000000000000..19920b24fe3f --- /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 000000000000..8dee4a34f3ef --- /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 000000000000..efd77fe7b60f --- /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 000000000000..4bf94474ccb1 --- /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 000000000000..a602061f71f1 --- /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 000000000000..b95fae5327ee --- /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 000000000000..8c39e701c9c6 --- /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 000000000000..6fa899a1ac2f --- /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 000000000000..18ab5e6f9d22 --- /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 000000000000..42efac4c0674 --- /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 000000000000..e21bb02ed9ab --- /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 000000000000..17702f58d90a --- /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 000000000000..63efea7ab046 --- /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 000000000000..f6375515cbe4 --- /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 000000000000..ddaa60146267 --- /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 000000000000..ba8840c1645c --- /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 000000000000..4c2e41177658 --- /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 000000000000..950e4e4fa346 --- /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 000000000000..5add54ae1505 --- /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 000000000000..45348c04f6ca --- /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 000000000000..5a50f157b132 --- /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 000000000000..3fba5ffd9b3b --- /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 000000000000..0b49f473e853 --- /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 000000000000..348104f844ab --- /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 000000000000..12177ca92362 --- /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 000000000000..b5a9e1c66f29 --- /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 000000000000..70a408f6a1bb --- /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 000000000000..c622cedc990b --- /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 000000000000..b18c3ad260c3 --- /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 000000000000..a64c544736e9 --- /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 000000000000..b18c3ad260c3 --- /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 000000000000..1c7860203cc7 --- /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 000000000000..74b91002a2d1 --- /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 000000000000..89f4409c0158 --- /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 000000000000..21b3b30cab32 --- /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 000000000000..5645fb13e5db --- /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 000000000000..793554f8d40d --- /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 000000000000..eac68058cfa2 --- /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 000000000000..7d2ad85ba321 --- /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 000000000000..8308bbd3d78a --- /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 000000000000..05110374ba30 --- /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 000000000000..ebcc7f5c10ec --- /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 000000000000..3240794631d7 --- /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 000000000000..444b0d80c01f --- /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 000000000000..9c20ed4faa71 --- /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 000000000000..bed8d4d26bf3 --- /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 000000000000..e9ad738d99f7 --- /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 000000000000..c7d82ad806de --- /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 000000000000..29e128c7a40e --- /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 000000000000..8e962185ab8d --- /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 000000000000..dd055d0b239f --- /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 000000000000..2c46d599bf35 --- /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 000000000000..80a24ff0e225 --- /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 000000000000..d4ba6e8980e6 --- /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 10c35c07ccf9..000000000000 --- 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 1c1c72c46206..32acad4d5ab0 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 000000000000..b265158220da --- /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 43de8e5315cc..000000000000 --- 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 000000000000..e794f726dba6 --- /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/FusedLocation/Android.mk b/packages/FusedLocation/Android.mk deleted file mode 100644 index d795870251db..000000000000 --- a/packages/FusedLocation/Android.mk +++ /dev/null @@ -1,29 +0,0 @@ -# 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. - -LOCAL_PATH:= $(call my-dir) -include $(CLEAR_VARS) - -LOCAL_MODULE_TAGS := optional - -LOCAL_SRC_FILES := $(call all-subdir-java-files) - -LOCAL_JAVA_LIBRARIES := com.android.location.provider - -LOCAL_PACKAGE_NAME := FusedLocation -LOCAL_PRIVATE_PLATFORM_APIS := true -LOCAL_CERTIFICATE := platform -LOCAL_PRIVILEGED_MODULE := true - -include $(BUILD_PACKAGE) diff --git a/packages/LocalTransport/Android.bp b/packages/LocalTransport/Android.bp new file mode 100644 index 000000000000..2c990fed1688 --- /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 3484b0f7a537..000000000000 --- 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 ec4a47930fad..4b846b0fb372 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 @@ public class NetworkMonitor extends StateMachine { // 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 000000000000..ac3abaca7a39 --- /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 2c076159ec12..000000000000 --- 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 000000000000..1c97fc37cf50 --- /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 ccde5716ef93..000000000000 --- 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 ac97adb2c5c5..000000000000 --- 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 000000000000..5380832a17d4 --- /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 2e07ab18d71a..000000000000 --- 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 000000000000..586292efa20b --- /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 b9b29e752193..000000000000 --- 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 Binary files differdeleted file mode 100644 index 67f072f54795..000000000000 --- a/packages/SystemUI/res-keyguard/drawable-xxxhdpi/bubble_preview.png +++ /dev/null diff --git a/packages/SystemUI/res-keyguard/drawable-xxxhdpi/stretch_preview.png b/packages/SystemUI/res-keyguard/drawable-xxxhdpi/stretch_preview.png Binary files differdeleted file mode 100644 index 63927bc4deaf..000000000000 --- a/packages/SystemUI/res-keyguard/drawable-xxxhdpi/stretch_preview.png +++ /dev/null diff --git a/packages/SystemUI/res-keyguard/drawable-xxxhdpi/type_preview.png b/packages/SystemUI/res-keyguard/drawable-xxxhdpi/type_preview.png Binary files differdeleted file mode 100644 index a538149ca3d8..000000000000 --- a/packages/SystemUI/res-keyguard/drawable-xxxhdpi/type_preview.png +++ /dev/null diff --git a/packages/SystemUI/res/layout/home_handle.xml b/packages/SystemUI/res/layout/home_handle.xml new file mode 100644 index 000000000000..48ea5c47bc7c --- /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 76eb85eb4695..4396a42929ba 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 8ecca26bffa9..371a0604c45b 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 01595f0705be..0fde2de1e2f1 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 078108d658ee..c5dc3244d0a3 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 @@ public final class ClockManager { @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 @@ public final class ClockManager { 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 @@ public final class ClockManager { .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 @@ public final class ClockManager { register(); } mListeners.add(listener); - if (mClockExtension != null) { - mClockExtension.reload(); - } + reload(); } /** @@ -168,7 +191,66 @@ public final class ClockManager { 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 @@ public final class ClockManager { 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 @@ public final class ClockManager { 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 7fdd2357bc8e..000000000000 --- 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 e35cf113c111..22753805c95e 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 @@ public class ImageClock extends FrameLayout { 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 class ImageClock extends FrameLayout { 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 @@ public class ImageClock extends FrameLayout { @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 3c9a4f821c62..34c855bc33d3 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 @@ public class StretchAnalogClock extends View { 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 @@ public class StretchAnalogClock extends View { @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 6f1b59c69865..7bce3c5cb63f 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 @@ public class TypographicClock extends TextView { 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 class TypographicClock extends TextView { 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 class TypographicClock extends TextView { */ 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 4778434e2052..4fe09a92a1de 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 @@ class Bubble { 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 6dee8ad846af..c2327ad41d3e 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 @@ public class BubbleExpandedView extends LinearLayout implements View.OnClickList 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 @@ public class BubbleExpandedView extends LinearLayout implements View.OnClickList 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 @@ public class BubbleExpandedView extends LinearLayout implements View.OnClickList 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 @@ public class BubbleExpandedView extends LinearLayout implements View.OnClickList 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 @@ public class BubbleExpandedView extends LinearLayout implements View.OnClickList 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 @@ public class BubbleExpandedView extends LinearLayout implements View.OnClickList 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 @@ public class BubbleExpandedView extends LinearLayout implements View.OnClickList } 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 eae17eea1937..5546e4c50174 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 @@ public class BubbleStackView extends FrameLayout { private int mExpandedAnimateXDistance; private int mExpandedAnimateYDistance; private int mStatusBarHeight; + private int mPipDismissHeight; private Bubble mExpandedBubble; private boolean mIsExpanded; @@ -159,6 +160,8 @@ public class BubbleStackView extends FrameLayout { 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 class BubbleStackView extends FrameLayout { */ 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 @@ public class BubbleStackView extends FrameLayout { } /** + * 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 @@ public class BubbleStackView extends FrameLayout { 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 9fd26b80e385..f0d9be1e484a 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 @@ public class ExpandedAnimationController } /** 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 df763151cdd7..9bca2cc434ac 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.text.style.StyleSpan; 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 @@ public class MediaProjectionPermissionActivity extends Activity 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 @@ public class MediaProjectionPermissionActivity extends Activity 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 class MediaProjectionPermissionActivity extends Activity 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 @@ public class MediaProjectionPermissionActivity extends Activity } } - @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 b34907dfebf1..b65c4a5f71d8 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 @@ public class NotificationContentInflater { 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 @@ public class NotificationContentInflater { // 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 @@ public class NotificationContentInflater { } @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 @@ public class NotificationContentInflater { 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 @@ public class NotificationContentInflater { 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 @@ public class NotificationContentInflater { 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 @@ public class NotificationContentInflater { 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 @@ public class NotificationContentInflater { 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 @@ public class NotificationContentInflater { 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 @@ public class NotificationContentInflater { } @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 @@ public class NotificationContentInflater { * @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 @@ public class NotificationContentInflater { 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 @@ public class NotificationContentInflater { 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 @@ public class NotificationContentInflater { 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 @@ public class NotificationContentInflater { @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 @@ public class NotificationContentInflater { // 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 cc8adde2ed04..38df17ab52fd 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 @@ public class ContextualButtonGroup extends ButtonDispatcher { * 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 5ccb9b294718..b622688a8ac6 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 @@ package com.android.systemui.statusbar.phone; 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 class LightBarTransitionsController implements Dumpable, Callbacks, 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 b4f850b033e8..cf3f89ef8788 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.os.Looper; 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 @@ public class NavBarTintController { // 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 @@ public class NavBarTintController { 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 @@ public class NavBarTintController { // 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 @@ public class NavBarTintController { 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 class NavBarTintController { 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 538d79717293..1eb499048db8 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 @@ public class NavigationBarFragment extends LifecycleFragment implements Callback // 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 7c31dae2a746..c9fa89e7cb97 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 class NavigationBarInflaterView extends FrameLayout 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 @@ public class NavigationBarInflaterView extends FrameLayout 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 8152206aa2ed..d6d3d0807659 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_ 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 @@ public class NavigationBarView extends FrameLayout implements PluginListener<Nav mRightEdgePanel.setDimensions(width, height); } } + + @Override + public void onHomeHandleVisiblilityChanged(boolean visible) { + showHomeHandle(visible); + } }; public NavigationBarView(Context context, AttributeSet attrs) { @@ -376,6 +382,7 @@ public class NavigationBarView extends FrameLayout implements PluginListener<Nav 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 @@ public class NavigationBarView extends FrameLayout implements PluginListener<Nav .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 @@ public class NavigationBarView extends FrameLayout implements PluginListener<Nav 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 @@ public class NavigationBarView extends FrameLayout implements PluginListener<Nav 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 @@ public class NavigationBarView extends FrameLayout implements PluginListener<Nav 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 @@ public class NavigationBarView extends FrameLayout implements PluginListener<Nav // 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 000000000000..968074c6af59 --- /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 8421e23e97b0..2c31e2cfea2e 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.annotation.IntDef; 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 @@ public class NavigationPrototypeController extends ContentObserver { 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 @@ public class NavigationPrototypeController extends ContentObserver { 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 @@ public class NavigationPrototypeController extends ContentObserver { } 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 @@ public class NavigationPrototypeController extends ContentObserver { 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 @@ public class NavigationPrototypeController extends ContentObserver { 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 f813ac693d42..58701e72e406 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 @@ package com.android.keyguard.clock; 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 @@ import org.mockito.MockitoAnnotations; @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 @@ public final class ClockManagerTest extends SysuiTestCase { 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 1a3b198ac0d6..000000000000 --- 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 dfaa76a58e2d..99dc9f87520f 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 class NotificationContentInflaterTest extends SysuiTestCase { 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 class NotificationContentInflaterTest extends SysuiTestCase { 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 @@ public class NotificationContentInflaterTest extends SysuiTestCase { 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 @@ public class NotificationContentInflaterTest extends SysuiTestCase { 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 @@ public class NotificationContentInflaterTest extends SysuiTestCase { } 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 000000000000..6f2f50c0ddd4 --- /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 850764645644..000000000000 --- 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 000000000000..1bec49234b6a --- /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 91526dd19ce0..000000000000 --- 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 000000000000..25c6121324ea --- /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 c4c2240f102c..000000000000 --- 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 000000000000..56020cd573b1 --- /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 a6426a6ce217..000000000000 --- 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 4254a0ba200a..2e40c1acfa2c 100644 --- a/packages/WallpaperBackup/src/com/android/wallpaperbackup/WallpaperBackupAgent.java +++ b/packages/WallpaperBackup/src/com/android/wallpaperbackup/WallpaperBackupAgent.java @@ -115,8 +115,10 @@ public class WallpaperBackupAgent extends BackupAgent { // 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 000000000000..40c423520081 --- /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 2fa1ddee0fd9..000000000000 --- 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 1294dbbbfa87..7ce13c2f59e9 100644 --- a/packages/overlays/Android.mk +++ b/packages/overlays/Android.mk @@ -44,6 +44,7 @@ include $(CLEAR_VARS) LOCAL_MODULE := frameworks-base-overlays-debug LOCAL_REQUIRED_MODULES := \ ExperimentNavigationBarFloatingOverlay \ + ExperimentNavigationBarVisualInsetOverlay \ ExperimentNavigationBarDefaultOverlay \ ExperimentNavigationBarSlimOverlay32 \ ExperimentNavigationBarSlimOverlay40 \ diff --git a/tests/HwAccelerationTest/Android.mk b/packages/overlays/ExperimentNavigationBarVisualInsetOverlay/Android.mk index 79072faeaa0e..56bf51642c9d 100644 --- a/tests/HwAccelerationTest/Android.mk +++ b/packages/overlays/ExperimentNavigationBarVisualInsetOverlay/Android.mk @@ -1,11 +1,11 @@ # -# Copyright (C) 2010 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, @@ -17,12 +17,14 @@ LOCAL_PATH:= $(call my-dir) include $(CLEAR_VARS) +LOCAL_RRO_THEME := ExperimentNavigationBarVisualInset +LOCAL_CERTIFICATE := platform + LOCAL_SRC_FILES := $(call all-subdir-java-files) -LOCAL_PACKAGE_NAME := HwAccelerationTest -LOCAL_PRIVATE_PLATFORM_APIS := true -LOCAL_CERTIFICATE := platform +LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res -LOCAL_MODULE_TAGS := tests +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 000000000000..3ea5dc4716ff --- /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 000000000000..d35a744e4e59 --- /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 000000000000..84dfcb76706b --- /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 000000000000..93b2d956cf6f --- /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 be9ba4351056..000000000000 --- 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 000000000000..87aa7637df8e --- /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 ce1715f08be5..000000000000 --- 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 4bd50ec21d84..45ceeda689f7 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 @@ public final class ContentCaptureManagerService extends } @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 360f064bdf0d..9e159600e42c 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.Bundle; 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 @@ final class ContentCapturePerUserService // 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 62da3f8e01ba..6e5d31640e4f 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.SparseArray; import android.util.StatsLog; import com.android.internal.util.ArrayUtils; +import com.android.server.utils.FlagNamespaceUtils; import java.io.File; @@ -194,6 +195,8 @@ public class RescueParty { 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 @@ public class RescueParty { 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 81209763d3a8..fd946cdfa48a 100644 --- a/services/core/java/com/android/server/TelephonyRegistry.java +++ b/services/core/java/com/android/server/TelephonyRegistry.java @@ -237,7 +237,7 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { 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 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { 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 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { 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 class TelephonyRegistry extends ITelephonyRegistry.Stub { } } - 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 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { 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 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { 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 026430b5469d..aebe2b78a853 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 @@ public final class ActiveServices { 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 @@ public final class ActiveServices { } } 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 @@ public final class ActiveServices { // 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 3c0430fe0adf..bfe1f6ad6390 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 @@ public class ActivityManagerService extends IActivityManager.Stub + " 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 @@ public class ActivityManagerService extends IActivityManager.Stub @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 0d49e4cdc9d0..3a61dd987cf5 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 @@ public final class ProcessList { // 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 @@ public final class ProcessList { 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 @@ public final class ProcessList { 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 da547eaf8db2..59fffb40fba7 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 @@ public class Vpn { 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 bd577598a617..dacc6cd0fe76 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 @@ public final class DefaultPermissionGrantPolicy { 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 000000000000..f26121eac939 --- /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 c685b05e99e0..6ffd5543439c 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 @@ public class ActivityStackSupervisor implements RecentTasks.Callbacks { 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 43c12064a3c1..b287a0b011e7 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.util.proto.ProtoOutputStream; 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 @@ public class ActivityStartController { } final long origId = Binder.clearCallingIdentity(); try { - synchronized (mService.mGlobalLock) { - ActivityRecord[] outActivity = new ActivityRecord[1]; - for (int i=0; i < intents.length; i++) { - Intent intent = intents[i]; - if (intent == null) { - continue; - } - - // Refuse possible leaked file descriptors - if (intent != null && intent.hasFileDescriptors()) { - throw new IllegalArgumentException("File descriptors passed in Intent"); - } - - boolean componentSpecified = intent.getComponent() != null; + 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); + // 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); + // 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"); - } + 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(); + 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); + } - if (res < 0) { - return res; + final ActivityRecord[] outActivity = new ActivityRecord[1]; + // Lock the loop to ensure the activities launched in a sequence. + synchronized (mService.mGlobalLock) { + 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; } - 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 d40948b305a2..538813e9b21c 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.PackageManager; 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.Pools.SynchronizedPool; 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 @@ class ActivityStarter { 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 258819fdece9..9b35e85a85f4 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 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { } 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 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { } @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"); + } + + if (!stack.inFreeformWindowingMode() + && stack.getWindowingMode() != WINDOWING_MODE_FULLSCREEN) { + throw new IllegalStateException("toggleFreeformWindowingMode: You can only " + + "toggle between fullscreen and freeform."); } - stack.setWindowingMode(WINDOWING_MODE_FULLSCREEN); + if (stack.inFreeformWindowingMode()) { + stack.setWindowingMode(WINDOWING_MODE_FULLSCREEN); + } else { + stack.setWindowingMode(WINDOWING_MODE_FREEFORM); + } } finally { Binder.restoreCallingIdentity(ident); } @@ -5923,14 +5934,12 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { 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 5c91d9e6fff2..698835772df5 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 @@ class RootActivityContainer extends ConfigurationContainer 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 9767efd95e55..ae48dad7b8f9 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 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { 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 a62bc713db40..2452ef0425e1 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.os.SystemClock; 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 @@ import java.util.List; * 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 dcca3167c752..42a205a2fb3d 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 @@ public class TaskStackChangedListenerTest { } @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 @@ public class TaskStackChangedListenerTest { } } }); - 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 @@ public class TaskStackChangedListenerTest { 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 @@ public class TaskStackChangedListenerTest { * 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 @@ public class TaskStackChangedListenerTest { 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 @@ public class TaskStackChangedListenerTest { 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 @@ public class TaskStackChangedListenerTest { 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 0eb991777d74..16791a4b8680 100644 --- a/telecomm/java/android/telecom/Log.java +++ b/telecomm/java/android/telecom/Log.java @@ -18,7 +18,6 @@ package android.telecom; 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 android.text.TextUtils; 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 @@ public class Log { 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 @@ public class Log { 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 @@ public class Log { } 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 24db438580c9..d98f37d976df 100644 --- a/telephony/java/android/telephony/LocationAccessPolicy.java +++ b/telephony/java/android/telephony/LocationAccessPolicy.java @@ -42,7 +42,7 @@ import java.util.List; 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 @@ public final class LocationAccessPolicy { // 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 3ce646cb400b..ffebc04c39e6 100644 --- a/telephony/java/android/telephony/PhoneStateListener.java +++ b/telephony/java/android/telephony/PhoneStateListener.java @@ -297,14 +297,17 @@ public class PhoneStateListener { 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 @@ public class PhoneStateListener { } /** - * 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 @@ public class PhoneStateListener { () -> 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 d5c70793d3bc..47c8de52820e 100644 --- a/telephony/java/android/telephony/ims/ImsCallProfile.java +++ b/telephony/java/android/telephony/ims/ImsCallProfile.java @@ -548,7 +548,8 @@ public final class ImsCallProfile implements Parcelable { + ", emergencyServiceCategories=" + mEmergencyServiceCategories + ", emergencyUrns=" + mEmergencyUrns + ", emergencyCallRouting=" + mEmergencyCallRouting - + ", emergencyCallTesting=" + mEmergencyCallTesting + " }"; + + ", emergencyCallTesting=" + mEmergencyCallTesting + + ", hasKnownUserIntentEmergency=" + mHasKnownUserIntentEmergency + " }"; } @Override @@ -567,6 +568,7 @@ public final class ImsCallProfile implements Parcelable { out.writeStringList(mEmergencyUrns); out.writeInt(mEmergencyCallRouting); out.writeBoolean(mEmergencyCallTesting); + out.writeBoolean(mHasKnownUserIntentEmergency); } private void readFromParcel(Parcel in) { @@ -578,6 +580,7 @@ public final class ImsCallProfile implements Parcelable { 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 322ce45797ec..4a263f060ca5 100644 --- a/telephony/java/com/android/internal/telephony/IPhoneStateListener.aidl +++ b/telephony/java/com/android/internal/telephony/IPhoneStateListener.aidl @@ -54,7 +54,7 @@ oneway interface IPhoneStateListener { 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 e9eba324acb0..a922ab601442 100644 --- a/telephony/java/com/android/internal/telephony/ITelephonyRegistry.aidl +++ b/telephony/java/com/android/internal/telephony/ITelephonyRegistry.aidl @@ -81,7 +81,7 @@ interface ITelephonyRegistry { 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 000000000000..37d3f5d4d97f --- /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/JankBench/Android.bp b/tests/JankBench/Android.bp new file mode 100644 index 000000000000..166639d2e7db --- /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 89c21b7fb605..000000000000 --- 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 000000000000..9fecf1599fd9 --- /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 8ba874de0e8a..000000000000 --- 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 000000000000..e0608e288459 --- /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 608bf2f226f5..000000000000 --- 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 000000000000..0808b05ec053 --- /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 5eed38c86657..000000000000 --- 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 000000000000..c7c4b10a8405 --- /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 f4250c8b4e97..000000000000 --- 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 f169d6b5bee3..b5d1ff9a0298 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.NET_CAPABILITY_NOT_ROAMING; 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.Mock; 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 @@ public class VpnTest { // 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 000000000000..ca7864f047c7 --- /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 1149b8a8fe40..000000000000 --- 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 4961aa51dc16..22edd2f2055a 100644 --- a/tools/aapt2/cmd/Link.cpp +++ b/tools/aapt2/cmd/Link.cpp @@ -268,6 +268,7 @@ struct ResourceFileFlattenerOptions { 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 @@ ResourceFileFlattener::ResourceFileFlattener(const ResourceFileFlattenerOptions& } } +// 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 @@ class Linker { 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 @@ class Linker { 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 @@ int LinkCommand::Action(const std::vector<std::string>& args) { } } + 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 590a6bb19e30..1fc149ab41af 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 @@ struct LinkOptions { 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 @@ class LinkCommand : public Command { &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 @@ class LinkCommand : public Command { 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 792120e449ae..e2c65ba74271 100644 --- a/tools/aapt2/cmd/Util.cpp +++ b/tools/aapt2/cmd/Util.cpp @@ -435,4 +435,11 @@ void SetLongVersionCode(xml::Element* manifest, uint64_t version) { } } +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 cf1443e30e1f..2a7c62eef678 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 @@ std::string MakePackageSafeName(const std::string &name); // 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 f92f1e3c4c7e..7e492610b658 100644 --- a/tools/aapt2/cmd/Util_test.cpp +++ b/tools/aapt2/cmd/Util_test.cpp @@ -383,4 +383,12 @@ TEST (UtilTest, AdjustSplitConstraintsForMinSdk) { 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 7b268bb283f4..604b2575daa1 100644 --- a/tools/aapt2/util/Files.cpp +++ b/tools/aapt2/util/Files.cpp @@ -251,6 +251,25 @@ bool AppendArgsFromFile(const StringPiece& path, std::vector<std::string>* out_a 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 58395526b193..481a4cdb6ad0 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 @@ Maybe<android::FileMap> MmapPath(const std::string& path, std::string* out_error 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 5e5a59566ce5..7caace6ec854 100644 --- a/wifi/java/android/net/wifi/WifiManager.java +++ b/wifi/java/android/net/wifi/WifiManager.java @@ -2136,17 +2136,26 @@ public class WifiManager { } /** + * @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); } |