diff options
301 files changed, 5539 insertions, 2568 deletions
diff --git a/apct-tests/perftests/core/src/android/text/DynamicLayoutPerfTest.java b/apct-tests/perftests/core/src/android/text/DynamicLayoutPerfTest.java index e644a1f3ca64..b4c7f543946a 100644 --- a/apct-tests/perftests/core/src/android/text/DynamicLayoutPerfTest.java +++ b/apct-tests/perftests/core/src/android/text/DynamicLayoutPerfTest.java @@ -16,35 +16,28 @@ package android.text; -import android.app.Activity; +import static android.text.Layout.Alignment.ALIGN_NORMAL; + import android.graphics.Canvas; import android.graphics.Paint; import android.graphics.Paint.FontMetricsInt; -import android.os.Bundle; import android.perftests.utils.BenchmarkState; import android.perftests.utils.PerfStatusReporter; import android.perftests.utils.StubActivity; - -import android.support.test.InstrumentationRegistry; import android.support.test.filters.LargeTest; import android.support.test.rule.ActivityTestRule; -import android.support.test.runner.AndroidJUnit4; import android.text.style.ReplacementSpan; import android.util.ArraySet; -import static android.text.Layout.Alignment.ALIGN_NORMAL; - -import java.util.Arrays; -import java.util.Collection; -import java.util.Locale; -import java.util.Random; - -import org.junit.Assert; import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; -import org.junit.runners.Parameterized.Parameters; import org.junit.runners.Parameterized; +import org.junit.runners.Parameterized.Parameters; + +import java.util.Arrays; +import java.util.Collection; +import java.util.Random; @LargeTest @RunWith(Parameterized.class) diff --git a/apct-tests/perftests/core/src/android/widget/EditTextBackspacePerfTest.java b/apct-tests/perftests/core/src/android/widget/EditTextBackspacePerfTest.java index 40b56f4a59fd..d219d3a28189 100644 --- a/apct-tests/perftests/core/src/android/widget/EditTextBackspacePerfTest.java +++ b/apct-tests/perftests/core/src/android/widget/EditTextBackspacePerfTest.java @@ -16,31 +16,26 @@ package android.widget; -import android.app.Activity; -import android.os.Bundle; import android.perftests.utils.BenchmarkState; import android.perftests.utils.PerfStatusReporter; import android.perftests.utils.StubActivity; +import android.support.test.InstrumentationRegistry; +import android.support.test.filters.LargeTest; +import android.support.test.rule.ActivityTestRule; import android.text.Selection; import android.view.KeyEvent; import android.view.View.MeasureSpec; import android.view.ViewGroup; -import android.support.test.InstrumentationRegistry; -import android.support.test.filters.LargeTest; -import android.support.test.rule.ActivityTestRule; -import android.support.test.runner.AndroidJUnit4; - -import java.util.Arrays; -import java.util.Collection; -import java.util.Locale; - import org.junit.Assert; import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; -import org.junit.runners.Parameterized.Parameters; import org.junit.runners.Parameterized; +import org.junit.runners.Parameterized.Parameters; + +import java.util.Arrays; +import java.util.Collection; @LargeTest @RunWith(Parameterized.class) diff --git a/apct-tests/perftests/core/src/android/widget/EditTextCursorMovementPerfTest.java b/apct-tests/perftests/core/src/android/widget/EditTextCursorMovementPerfTest.java index b100acba767d..b6cf7d3f49c2 100644 --- a/apct-tests/perftests/core/src/android/widget/EditTextCursorMovementPerfTest.java +++ b/apct-tests/perftests/core/src/android/widget/EditTextCursorMovementPerfTest.java @@ -16,31 +16,26 @@ package android.widget; -import android.app.Activity; -import android.os.Bundle; import android.perftests.utils.BenchmarkState; import android.perftests.utils.PerfStatusReporter; import android.perftests.utils.StubActivity; +import android.support.test.InstrumentationRegistry; +import android.support.test.filters.LargeTest; +import android.support.test.rule.ActivityTestRule; import android.text.Selection; import android.view.KeyEvent; import android.view.View.MeasureSpec; import android.view.ViewGroup; -import android.support.test.InstrumentationRegistry; -import android.support.test.filters.LargeTest; -import android.support.test.rule.ActivityTestRule; -import android.support.test.runner.AndroidJUnit4; - -import java.util.Arrays; -import java.util.Collection; -import java.util.Locale; - import org.junit.Assert; import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; -import org.junit.runners.Parameterized.Parameters; import org.junit.runners.Parameterized; +import org.junit.runners.Parameterized.Parameters; + +import java.util.Arrays; +import java.util.Collection; @LargeTest @RunWith(Parameterized.class) diff --git a/apct-tests/perftests/core/src/android/widget/TextViewSetTextLocalePerfTest.java b/apct-tests/perftests/core/src/android/widget/TextViewSetTextLocalePerfTest.java index 7fc5e4f8635c..e95676b272fd 100644 --- a/apct-tests/perftests/core/src/android/widget/TextViewSetTextLocalePerfTest.java +++ b/apct-tests/perftests/core/src/android/widget/TextViewSetTextLocalePerfTest.java @@ -16,27 +16,21 @@ package android.widget; -import android.app.Activity; -import android.os.Bundle; -import android.perftests.utils.PerfStatusReporter; -import android.util.Log; - import android.perftests.utils.BenchmarkState; +import android.perftests.utils.PerfStatusReporter; import android.perftests.utils.StubActivity; import android.support.test.filters.LargeTest; -import android.support.test.runner.AndroidJUnit4; import android.support.test.rule.ActivityTestRule; -import android.support.test.InstrumentationRegistry; - -import java.util.Locale; -import java.util.Collection; -import java.util.Arrays; -import org.junit.Test; import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; import org.junit.runners.Parameterized; import org.junit.runners.Parameterized.Parameters; -import org.junit.runner.RunWith; + +import java.util.Arrays; +import java.util.Collection; +import java.util.Locale; @LargeTest @RunWith(Parameterized.class) diff --git a/api/current.txt b/api/current.txt index 2368231508b6..c6770898a903 100644 --- a/api/current.txt +++ b/api/current.txt @@ -8972,6 +8972,7 @@ package android.content { field public static final java.lang.String HARDWARE_PROPERTIES_SERVICE = "hardware_properties"; field public static final java.lang.String INPUT_METHOD_SERVICE = "input_method"; field public static final java.lang.String INPUT_SERVICE = "input"; + field public static final java.lang.String IPSEC_SERVICE = "ipsec"; field public static final java.lang.String JOB_SCHEDULER_SERVICE = "jobscheduler"; field public static final java.lang.String KEYGUARD_SERVICE = "keyguard"; field public static final java.lang.String LAUNCHER_APPS_SERVICE = "launcherapps"; @@ -25639,6 +25640,67 @@ package android.net { field public static final android.os.Parcelable.Creator<android.net.IpPrefix> CREATOR; } + public final class IpSecAlgorithm implements android.os.Parcelable { + ctor public IpSecAlgorithm(java.lang.String, byte[]); + ctor public IpSecAlgorithm(java.lang.String, byte[], int); + method public int describeContents(); + method public byte[] getKey(); + method public java.lang.String getName(); + method public int getTruncationLengthBits(); + method public void writeToParcel(android.os.Parcel, int); + field public static final java.lang.String AUTH_HMAC_MD5 = "hmac(md5)"; + field public static final java.lang.String AUTH_HMAC_SHA1 = "hmac(sha1)"; + field public static final java.lang.String AUTH_HMAC_SHA256 = "hmac(sha256)"; + field public static final java.lang.String AUTH_HMAC_SHA384 = "hmac(sha384)"; + field public static final java.lang.String AUTH_HMAC_SHA512 = "hmac(sha512)"; + field public static final android.os.Parcelable.Creator<android.net.IpSecAlgorithm> CREATOR; + field public static final java.lang.String CRYPT_AES_CBC = "cbc(aes)"; + } + + public final class IpSecManager { + method public void applyTransportModeTransform(java.io.FileDescriptor, android.net.IpSecTransform) throws java.io.IOException; + method public android.net.IpSecManager.UdpEncapsulationSocket openUdpEncapsulationSocket(int) throws java.io.IOException, android.net.IpSecManager.ResourceUnavailableException; + method public android.net.IpSecManager.UdpEncapsulationSocket openUdpEncapsulationSocket() throws java.io.IOException, android.net.IpSecManager.ResourceUnavailableException; + method public void removeTransportModeTransform(java.io.FileDescriptor, android.net.IpSecTransform) throws java.io.IOException; + method public android.net.IpSecManager.SecurityParameterIndex reserveSecurityParameterIndex(int, java.net.InetAddress) throws android.net.IpSecManager.ResourceUnavailableException; + method public android.net.IpSecManager.SecurityParameterIndex reserveSecurityParameterIndex(int, java.net.InetAddress, int) throws android.net.IpSecManager.ResourceUnavailableException, android.net.IpSecManager.SpiUnavailableException; + field public static final int INVALID_SECURITY_PARAMETER_INDEX = 0; // 0x0 + } + + public static final class IpSecManager.ResourceUnavailableException extends android.util.AndroidException { + } + + public static final class IpSecManager.SecurityParameterIndex implements java.lang.AutoCloseable { + method public void close(); + method protected void finalize(); + method public int getSpi(); + } + + public static final class IpSecManager.SpiUnavailableException extends android.util.AndroidException { + method public int getSpi(); + } + + public static final class IpSecManager.UdpEncapsulationSocket implements java.lang.AutoCloseable { + method public void close() throws java.io.IOException; + method public int getPort(); + method public java.io.FileDescriptor getSocket(); + } + + public final class IpSecTransform implements java.lang.AutoCloseable { + method public void close(); + field public static final int DIRECTION_IN = 0; // 0x0 + field public static final int DIRECTION_OUT = 1; // 0x1 + } + + public static class IpSecTransform.Builder { + ctor public IpSecTransform.Builder(android.content.Context); + method public android.net.IpSecTransform buildTransportModeTransform(java.net.InetAddress) throws java.io.IOException, android.net.IpSecManager.ResourceUnavailableException, android.net.IpSecManager.SpiUnavailableException; + method public android.net.IpSecTransform.Builder setAuthentication(int, android.net.IpSecAlgorithm); + method public android.net.IpSecTransform.Builder setEncryption(int, android.net.IpSecAlgorithm); + method public android.net.IpSecTransform.Builder setIpv4Encapsulation(android.net.IpSecManager.UdpEncapsulationSocket, int); + method public android.net.IpSecTransform.Builder setSpi(int, android.net.IpSecManager.SecurityParameterIndex); + } + public class LinkAddress implements android.os.Parcelable { method public int describeContents(); method public java.net.InetAddress getAddress(); diff --git a/api/system-current.txt b/api/system-current.txt index cdd28b826179..bfd16612eb2b 100644 --- a/api/system-current.txt +++ b/api/system-current.txt @@ -9484,6 +9484,7 @@ package android.content { field public static final java.lang.String HDMI_CONTROL_SERVICE = "hdmi_control"; field public static final java.lang.String INPUT_METHOD_SERVICE = "input_method"; field public static final java.lang.String INPUT_SERVICE = "input"; + field public static final java.lang.String IPSEC_SERVICE = "ipsec"; field public static final java.lang.String JOB_SCHEDULER_SERVICE = "jobscheduler"; field public static final java.lang.String KEYGUARD_SERVICE = "keyguard"; field public static final java.lang.String LAUNCHER_APPS_SERVICE = "launcherapps"; @@ -27874,6 +27875,69 @@ package android.net { field public static final android.os.Parcelable.Creator<android.net.IpPrefix> CREATOR; } + public final class IpSecAlgorithm implements android.os.Parcelable { + ctor public IpSecAlgorithm(java.lang.String, byte[]); + ctor public IpSecAlgorithm(java.lang.String, byte[], int); + method public int describeContents(); + method public byte[] getKey(); + method public java.lang.String getName(); + method public int getTruncationLengthBits(); + method public void writeToParcel(android.os.Parcel, int); + field public static final java.lang.String AUTH_HMAC_MD5 = "hmac(md5)"; + field public static final java.lang.String AUTH_HMAC_SHA1 = "hmac(sha1)"; + field public static final java.lang.String AUTH_HMAC_SHA256 = "hmac(sha256)"; + field public static final java.lang.String AUTH_HMAC_SHA384 = "hmac(sha384)"; + field public static final java.lang.String AUTH_HMAC_SHA512 = "hmac(sha512)"; + field public static final android.os.Parcelable.Creator<android.net.IpSecAlgorithm> CREATOR; + field public static final java.lang.String CRYPT_AES_CBC = "cbc(aes)"; + } + + public final class IpSecManager { + method public void applyTransportModeTransform(java.io.FileDescriptor, android.net.IpSecTransform) throws java.io.IOException; + method public android.net.IpSecManager.UdpEncapsulationSocket openUdpEncapsulationSocket(int) throws java.io.IOException, android.net.IpSecManager.ResourceUnavailableException; + method public android.net.IpSecManager.UdpEncapsulationSocket openUdpEncapsulationSocket() throws java.io.IOException, android.net.IpSecManager.ResourceUnavailableException; + method public void removeTransportModeTransform(java.io.FileDescriptor, android.net.IpSecTransform) throws java.io.IOException; + method public android.net.IpSecManager.SecurityParameterIndex reserveSecurityParameterIndex(int, java.net.InetAddress) throws android.net.IpSecManager.ResourceUnavailableException; + method public android.net.IpSecManager.SecurityParameterIndex reserveSecurityParameterIndex(int, java.net.InetAddress, int) throws android.net.IpSecManager.ResourceUnavailableException, android.net.IpSecManager.SpiUnavailableException; + field public static final int INVALID_SECURITY_PARAMETER_INDEX = 0; // 0x0 + } + + public static final class IpSecManager.ResourceUnavailableException extends android.util.AndroidException { + } + + public static final class IpSecManager.SecurityParameterIndex implements java.lang.AutoCloseable { + method public void close(); + method protected void finalize(); + method public int getSpi(); + } + + public static final class IpSecManager.SpiUnavailableException extends android.util.AndroidException { + method public int getSpi(); + } + + public static final class IpSecManager.UdpEncapsulationSocket implements java.lang.AutoCloseable { + method public void close() throws java.io.IOException; + method public int getPort(); + method public java.io.FileDescriptor getSocket(); + } + + public final class IpSecTransform implements java.lang.AutoCloseable { + method public void close(); + field public static final int DIRECTION_IN = 0; // 0x0 + field public static final int DIRECTION_OUT = 1; // 0x1 + } + + public static class IpSecTransform.Builder { + ctor public IpSecTransform.Builder(android.content.Context); + method public android.net.IpSecTransform buildTransportModeTransform(java.net.InetAddress) throws java.io.IOException, android.net.IpSecManager.ResourceUnavailableException, android.net.IpSecManager.SpiUnavailableException; + method public android.net.IpSecTransform.Builder setAuthentication(int, android.net.IpSecAlgorithm); + method public android.net.IpSecTransform.Builder setEncryption(int, android.net.IpSecAlgorithm); + method public android.net.IpSecTransform.Builder setIpv4Encapsulation(android.net.IpSecManager.UdpEncapsulationSocket, int); + method public android.net.IpSecTransform.Builder setNattKeepalive(int); + method public android.net.IpSecTransform.Builder setSpi(int, android.net.IpSecManager.SecurityParameterIndex); + method public android.net.IpSecTransform.Builder setUnderlyingNetwork(android.net.Network); + } + public class LinkAddress implements android.os.Parcelable { method public int describeContents(); method public java.net.InetAddress getAddress(); diff --git a/api/test-current.txt b/api/test-current.txt index 90ecb8c82ceb..2512e8e666b5 100644 --- a/api/test-current.txt +++ b/api/test-current.txt @@ -9047,6 +9047,7 @@ package android.content { field public static final java.lang.String HARDWARE_PROPERTIES_SERVICE = "hardware_properties"; field public static final java.lang.String INPUT_METHOD_SERVICE = "input_method"; field public static final java.lang.String INPUT_SERVICE = "input"; + field public static final java.lang.String IPSEC_SERVICE = "ipsec"; field public static final java.lang.String JOB_SCHEDULER_SERVICE = "jobscheduler"; field public static final java.lang.String KEYGUARD_SERVICE = "keyguard"; field public static final java.lang.String LAUNCHER_APPS_SERVICE = "launcherapps"; @@ -25838,6 +25839,67 @@ package android.net { field public static final android.os.Parcelable.Creator<android.net.IpPrefix> CREATOR; } + public final class IpSecAlgorithm implements android.os.Parcelable { + ctor public IpSecAlgorithm(java.lang.String, byte[]); + ctor public IpSecAlgorithm(java.lang.String, byte[], int); + method public int describeContents(); + method public byte[] getKey(); + method public java.lang.String getName(); + method public int getTruncationLengthBits(); + method public void writeToParcel(android.os.Parcel, int); + field public static final java.lang.String AUTH_HMAC_MD5 = "hmac(md5)"; + field public static final java.lang.String AUTH_HMAC_SHA1 = "hmac(sha1)"; + field public static final java.lang.String AUTH_HMAC_SHA256 = "hmac(sha256)"; + field public static final java.lang.String AUTH_HMAC_SHA384 = "hmac(sha384)"; + field public static final java.lang.String AUTH_HMAC_SHA512 = "hmac(sha512)"; + field public static final android.os.Parcelable.Creator<android.net.IpSecAlgorithm> CREATOR; + field public static final java.lang.String CRYPT_AES_CBC = "cbc(aes)"; + } + + public final class IpSecManager { + method public void applyTransportModeTransform(java.io.FileDescriptor, android.net.IpSecTransform) throws java.io.IOException; + method public android.net.IpSecManager.UdpEncapsulationSocket openUdpEncapsulationSocket(int) throws java.io.IOException, android.net.IpSecManager.ResourceUnavailableException; + method public android.net.IpSecManager.UdpEncapsulationSocket openUdpEncapsulationSocket() throws java.io.IOException, android.net.IpSecManager.ResourceUnavailableException; + method public void removeTransportModeTransform(java.io.FileDescriptor, android.net.IpSecTransform) throws java.io.IOException; + method public android.net.IpSecManager.SecurityParameterIndex reserveSecurityParameterIndex(int, java.net.InetAddress) throws android.net.IpSecManager.ResourceUnavailableException; + method public android.net.IpSecManager.SecurityParameterIndex reserveSecurityParameterIndex(int, java.net.InetAddress, int) throws android.net.IpSecManager.ResourceUnavailableException, android.net.IpSecManager.SpiUnavailableException; + field public static final int INVALID_SECURITY_PARAMETER_INDEX = 0; // 0x0 + } + + public static final class IpSecManager.ResourceUnavailableException extends android.util.AndroidException { + } + + public static final class IpSecManager.SecurityParameterIndex implements java.lang.AutoCloseable { + method public void close(); + method protected void finalize(); + method public int getSpi(); + } + + public static final class IpSecManager.SpiUnavailableException extends android.util.AndroidException { + method public int getSpi(); + } + + public static final class IpSecManager.UdpEncapsulationSocket implements java.lang.AutoCloseable { + method public void close() throws java.io.IOException; + method public int getPort(); + method public java.io.FileDescriptor getSocket(); + } + + public final class IpSecTransform implements java.lang.AutoCloseable { + method public void close(); + field public static final int DIRECTION_IN = 0; // 0x0 + field public static final int DIRECTION_OUT = 1; // 0x1 + } + + public static class IpSecTransform.Builder { + ctor public IpSecTransform.Builder(android.content.Context); + method public android.net.IpSecTransform buildTransportModeTransform(java.net.InetAddress) throws java.io.IOException, android.net.IpSecManager.ResourceUnavailableException, android.net.IpSecManager.SpiUnavailableException; + method public android.net.IpSecTransform.Builder setAuthentication(int, android.net.IpSecAlgorithm); + method public android.net.IpSecTransform.Builder setEncryption(int, android.net.IpSecAlgorithm); + method public android.net.IpSecTransform.Builder setIpv4Encapsulation(android.net.IpSecManager.UdpEncapsulationSocket, int); + method public android.net.IpSecTransform.Builder setSpi(int, android.net.IpSecManager.SecurityParameterIndex); + } + public class LinkAddress implements android.os.Parcelable { method public int describeContents(); method public java.net.InetAddress getAddress(); diff --git a/cmds/bootanimation/Android.mk b/cmds/bootanimation/Android.mk index 73ec63f396b4..dbd774992031 100644 --- a/cmds/bootanimation/Android.mk +++ b/cmds/bootanimation/Android.mk @@ -24,6 +24,11 @@ LOCAL_SRC_FILES:= \ BootAnimationUtil.cpp \ ifeq ($(PRODUCT_IOT),true) + +LOCAL_SHARED_LIBRARIES += libchrome + +LOCAL_C_INCLUDES += external/libchrome + LOCAL_SRC_FILES += \ iot/iotbootanimation_main.cpp \ iot/BootAction.cpp @@ -77,13 +82,19 @@ LOCAL_SHARED_LIBRARIES := \ libutils \ libbinder \ libui \ - libskia \ + libhwui \ libEGL \ libGLESv1_CM \ libgui \ libtinyalsa \ libbase +ifeq ($(PRODUCT_IOT),true) + +LOCAL_INIT_RC := iot/bootanim_iot.rc + +endif # PRODUCT_IOT + ifdef TARGET_32_BIT_SURFACEFLINGER LOCAL_32_BIT_ONLY := true endif diff --git a/cmds/bootanimation/iot/BootAction.cpp b/cmds/bootanimation/iot/BootAction.cpp index 889eb2fbabce..2bc73439348b 100644 --- a/cmds/bootanimation/iot/BootAction.cpp +++ b/cmds/bootanimation/iot/BootAction.cpp @@ -18,25 +18,96 @@ #define LOG_TAG "BootAction" +#include <dlfcn.h> +#include <fcntl.h> + +#include <map> + +#include <android-base/file.h> #include <android-base/strings.h> +#include <base/json/json_parser.h> +#include <base/json/json_value_converter.h> #include <cpu-features.h> -#include <dlfcn.h> #include <pio/peripheral_manager_client.h> #include <utils/Log.h> +using android::base::ReadFileToString; +using android::base::RemoveFileIfExists; using android::base::Split; using android::base::Join; using android::base::StartsWith; using android::base::EndsWith; +using base::JSONReader; +using base::Value; namespace android { +// Brightness and volume are stored as integer strings in next_boot.json. +// They are divided by this constant to produce the actual float values in +// range [0.0, 1.0]. This constant must match its counterpart in +// DeviceManager. +constexpr const float kFloatScaleFactor = 1000.0f; + +constexpr const char* kNextBootFile = "/data/misc/bootanimation/next_boot.json"; +constexpr const char* kLastBootFile = "/data/misc/bootanimation/last_boot.json"; + +bool loadParameters(BootAction::SavedBootParameters* parameters) +{ + std::string contents; + if (!ReadFileToString(kLastBootFile, &contents)) { + if (errno != ENOENT) + ALOGE("Unable to read from %s: %s", kLastBootFile, strerror(errno)); + + return false; + } + + std::unique_ptr<Value> json = JSONReader::Read(contents); + if (json.get() == nullptr) return false; + + JSONValueConverter<BootAction::SavedBootParameters> converter; + if (!converter.Convert(*(json.get()), parameters)) return false; + + return true; +} + +void BootAction::SavedBootParameters::RegisterJSONConverter( + JSONValueConverter<SavedBootParameters> *converter) { + converter->RegisterIntField("brightness", &SavedBootParameters::brightness); + converter->RegisterIntField("volume", &SavedBootParameters::volume); + converter->RegisterRepeatedString("param_names", + &SavedBootParameters::param_names); + converter->RegisterRepeatedString("param_values", + &SavedBootParameters::param_values); +} + BootAction::~BootAction() { if (mLibHandle != nullptr) { dlclose(mLibHandle); } } +void BootAction::swapBootConfigs() { + // rename() will fail if next_boot.json doesn't exist, so delete + // last_boot.json manually first. + std::string err; + if (!RemoveFileIfExists(kLastBootFile, &err)) + ALOGE("Unable to delete last boot file: %s", err.c_str()); + + if (rename(kNextBootFile, kLastBootFile) && errno != ENOENT) + ALOGE("Unable to swap boot files: %s", strerror(errno)); + + int fd = open(kNextBootFile, O_CREAT, DEFFILEMODE); + if (fd == -1) { + ALOGE("Unable to create next boot file: %s", strerror(errno)); + } else { + // Make next_boot.json writible to everyone so DeviceManagementService + // can save parameters there. + if (fchmod(fd, DEFFILEMODE)) + ALOGE("Unable to set next boot file permissions: %s", strerror(errno)); + close(fd); + } +} + bool BootAction::init(const std::string& libraryPath) { APeripheralManagerClient* client = nullptr; ALOGD("Connecting to peripheralmanager"); @@ -51,6 +122,28 @@ bool BootAction::init(const std::string& libraryPath) { ALOGD("Peripheralmanager is up."); APeripheralManagerClient_delete(client); + float brightness = -1.0f; + float volume = -1.0f; + std::vector<BootParameter> parameters; + SavedBootParameters saved_parameters; + + if (loadParameters(&saved_parameters)) { + // TODO(b/65462981): Do something with brightness and volume? + brightness = saved_parameters.brightness / kFloatScaleFactor; + volume = saved_parameters.volume / kFloatScaleFactor; + + if (saved_parameters.param_names.size() == saved_parameters.param_values.size()) { + for (size_t i = 0; i < saved_parameters.param_names.size(); i++) { + parameters.push_back({ + .key = saved_parameters.param_names[i]->c_str(), + .value = saved_parameters.param_values[i]->c_str() + }); + } + } else { + ALOGW("Parameter names and values size mismatch"); + } + } + ALOGI("Loading boot action %s", libraryPath.c_str()); mLibHandle = dlopen(libraryPath.c_str(), RTLD_NOW); if (mLibHandle == nullptr) { @@ -82,7 +175,7 @@ bool BootAction::init(const std::string& libraryPath) { } ALOGD("Entering boot_action_init"); - bool result = mLibInit(); + bool result = mLibInit(parameters.data(), parameters.size()); ALOGD("Returned from boot_action_init"); return result; } diff --git a/cmds/bootanimation/iot/BootAction.h b/cmds/bootanimation/iot/BootAction.h index 495aa4f2180c..d8bff75d7408 100644 --- a/cmds/bootanimation/iot/BootAction.h +++ b/cmds/bootanimation/iot/BootAction.h @@ -17,16 +17,40 @@ #ifndef _BOOTANIMATION_BOOTACTION_H #define _BOOTANIMATION_BOOTACTION_H +#include <map> #include <string> +#include <base/json/json_value_converter.h> #include <utils/RefBase.h> +using base::JSONValueConverter; + namespace android { class BootAction : public RefBase { public: + struct BootParameter { + const char* key; + const char* value; + }; + + struct SavedBootParameters { + int brightness; + int volume; + ScopedVector<std::string> param_names; + ScopedVector<std::string> param_values; + static void RegisterJSONConverter( + JSONValueConverter<SavedBootParameters>* converter); + }; + ~BootAction(); + // Rename next_boot.json to last_boot.json so that we don't repeat + // parameters if there is a crash before the framework comes up. + // TODO(b/65462981): Is this what we want to do? Should we swap in the + // framework instead? + static void swapBootConfigs(); + // libraryPath is a fully qualified path to the target .so library. bool init(const std::string& libraryPath); @@ -41,7 +65,7 @@ public: void shutdown(); private: - typedef bool (*libInit)(); + typedef bool (*libInit)(const BootParameter* parameters, size_t num_parameters); typedef void (*libStartPart)(int partNumber, int playNumber); typedef void (*libShutdown)(); diff --git a/cmds/bootanimation/iot/bootanim_iot.rc b/cmds/bootanimation/iot/bootanim_iot.rc new file mode 100644 index 000000000000..2fc13364b53d --- /dev/null +++ b/cmds/bootanimation/iot/bootanim_iot.rc @@ -0,0 +1,2 @@ +on post-fs-data + mkdir /data/misc/bootanimation 0777 root root diff --git a/cmds/bootanimation/iot/iotbootanimation_main.cpp b/cmds/bootanimation/iot/iotbootanimation_main.cpp index d62478b27638..441a140178d4 100644 --- a/cmds/bootanimation/iot/iotbootanimation_main.cpp +++ b/cmds/bootanimation/iot/iotbootanimation_main.cpp @@ -64,6 +64,20 @@ class BootActionAnimationCallbacks : public android::BootAnimation::Callbacks {p void shutdown() override { if (mBootAction != nullptr) { + // If we have a bootaction we want to wait until we are actually + // told to shut down. If the animation exits early keep the action + // running. + char value[PROPERTY_VALUE_MAX] = {0}; + for (int exitRequested = 0; exitRequested == 0; ) { + property_get("service.bootanim.exit", value, "0"); + exitRequested = atoi(value); + + // Poll value at 10hz. + if (exitRequested == 0) { + usleep(100000); + } + } + mBootAction->shutdown(); // Give it two seconds to shut down. sleep(2); @@ -80,6 +94,10 @@ private: int main() { setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_DISPLAY); + // TODO(b/65462981): Should we set brightness/volume here in case the boot + // animation is disabled? + BootAction::swapBootConfigs(); + if (bootAnimationDisabled()) { ALOGI("boot animation disabled"); return 0; diff --git a/cmds/screencap/Android.mk b/cmds/screencap/Android.mk index b0dc42250fae..72e3c56bc6e4 100644 --- a/cmds/screencap/Android.mk +++ b/cmds/screencap/Android.mk @@ -8,7 +8,7 @@ LOCAL_SHARED_LIBRARIES := \ libcutils \ libutils \ libbinder \ - libskia \ + libhwui \ libui \ libgui diff --git a/cmds/statsd/Android.mk b/cmds/statsd/Android.mk index b9ee7ff201d5..3f120166d974 100644 --- a/cmds/statsd/Android.mk +++ b/cmds/statsd/Android.mk @@ -54,6 +54,7 @@ LOCAL_SRC_FILES := \ src/statsd_config.proto \ src/stats_constants.proto \ src/DropboxReader.cpp \ + src/matchers/LogEntryMatcherManager.cpp \ LOCAL_CFLAGS += \ @@ -107,6 +108,9 @@ LOCAL_MODULE := statsd_test LOCAL_COMPATIBILITY_SUITE := device-tests LOCAL_MODULE_TAGS := tests +LOCAL_C_INCLUDES += $(LOCAL_PATH)/src \ + STATSD_PROTO_INCLUDES + LOCAL_CFLAGS += \ -Wall \ -Werror \ @@ -115,21 +119,24 @@ LOCAL_CFLAGS += \ -Wno-unused-function \ -Wno-unused-parameter -LOCAL_C_INCLUDES += $(LOCAL_PATH)/src \ - STATSD_PROTO_INCLUDES - LOCAL_SRC_FILES := \ + src/stats_log.proto \ + src/statsd_config.proto \ + src/stats_constants.proto \ ../../core/java/android/os/IStatsCompanionService.aidl \ ../../core/java/android/os/IStatsManager.aidl \ src/StatsService.cpp \ tests/indexed_priority_queue_test.cpp \ + src/parse_util.cpp \ src/LogEntryPrinter.cpp \ src/LogReader.cpp \ + src/matchers/LogEntryMatcherManager.cpp \ tests/LogReader_test.cpp \ + tests/LogEntryMatcher_test.cpp \ LOCAL_STATIC_LIBRARIES := \ libgmock \ - statsd_proto + statsd_proto \ LOCAL_SHARED_LIBRARIES := \ libbase \ diff --git a/cmds/statsd/src/DropboxWriter.cpp b/cmds/statsd/src/DropboxWriter.cpp index 37df83463e45..b72e530e413a 100644 --- a/cmds/statsd/src/DropboxWriter.cpp +++ b/cmds/statsd/src/DropboxWriter.cpp @@ -31,18 +31,17 @@ namespace statsd { DropboxWriter::DropboxWriter(const string& tag) : mTag(tag), mLogReport(), mBufferSize(0) { } -void DropboxWriter::addStatsLogReport(const StatsLogReport& log) { - mLogReport = log; - flushIfNecessary(log); - mBufferSize += log.ByteSize(); +void DropboxWriter::addEventMetricData(const EventMetricData& eventMetricData) { + flushIfNecessary(eventMetricData); + EventMetricData* newEntry = mLogReport.mutable_event_metrics()->add_data(); + newEntry->CopyFrom(eventMetricData); + mBufferSize += eventMetricData.ByteSize(); } -void DropboxWriter::flushIfNecessary(const StatsLogReport& log) { - // TODO: Decide to flush depending on the serialized size of the StatsLogReport. - // if (entry.ByteSize() + mBufferSize > kMaxSerializedBytes) { - // flush(); - // } - flush(); +void DropboxWriter::flushIfNecessary(const EventMetricData& eventMetricData) { + if (eventMetricData.ByteSize() + mBufferSize > kMaxSerializedBytes) { + flush(); + } } void DropboxWriter::flush() { diff --git a/cmds/statsd/src/DropboxWriter.h b/cmds/statsd/src/DropboxWriter.h index 1fd0d757cca8..6107685c187f 100644 --- a/cmds/statsd/src/DropboxWriter.h +++ b/cmds/statsd/src/DropboxWriter.h @@ -32,7 +32,7 @@ public: */ DropboxWriter(const string& tag); - void addStatsLogReport(const StatsLogReport& log); + void addEventMetricData(const EventMetricData& eventMetricData); /* Request a flush to dropbox. */ void flush(); @@ -61,7 +61,7 @@ private: /* Check if the buffer size exceeds the max buffer size when the new entry is added, and flush the logs to dropbox if true. */ - void flushIfNecessary(const StatsLogReport& log); + void flushIfNecessary(const EventMetricData& eventMetricData); }; } // namespace statsd diff --git a/cmds/statsd/src/StatsLogProcessor.cpp b/cmds/statsd/src/StatsLogProcessor.cpp index 0c77ee5e69fc..280f9afcc66c 100644 --- a/cmds/statsd/src/StatsLogProcessor.cpp +++ b/cmds/statsd/src/StatsLogProcessor.cpp @@ -54,12 +54,8 @@ void StatsLogProcessor::OnLogEvent(const log_msg& msg) { // dump all statsd logs to dropbox for now. // TODO: Add filtering, aggregation, etc. if (err == NO_ERROR) { - StatsLogReport logReport; - logReport.set_start_report_millis(entry.tv_sec * 1000 + entry.tv_nsec / 1000 / 1000); - EventMetricData* eventMetricData = logReport.mutable_event_metrics()->add_data(); - *eventMetricData = parse(msg); - - m_dropbox_writer.addStatsLogReport(logReport); + EventMetricData eventMetricData = parse(msg); + m_dropbox_writer.addEventMetricData(eventMetricData); } } diff --git a/cmds/statsd/src/matchers/LogEntryMatcherManager.cpp b/cmds/statsd/src/matchers/LogEntryMatcherManager.cpp new file mode 100644 index 000000000000..bb0951ce4fab --- /dev/null +++ b/cmds/statsd/src/matchers/LogEntryMatcherManager.cpp @@ -0,0 +1,182 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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 "LogEntryMatcherManager.h" +#include <log/event_tag_map.h> +#include <log/logprint.h> +#include <utils/Errors.h> +#include <cutils/log.h> +#include <unordered_map> +#include <frameworks/base/cmds/statsd/src/statsd_config.pb.h> + +using std::unordered_map; +using std::string; + +namespace android { +namespace os { +namespace statsd { + +bool LogEntryMatcherManager::matches(const LogEntryMatcher &matcher, const int tagId, + const unordered_map<int, long> &intMap, + const unordered_map<int, string> &strMap, + const unordered_map<int, float> &floatMap, + const unordered_map<int, bool> &boolMap) { + if (matcher.has_combination()) { // Need to evaluate composite matching + switch (matcher.combination().operation()) { + case LogicalOperation::AND: + for (auto nestedMatcher : matcher.combination().matcher()) { + if (!matches(nestedMatcher, tagId, intMap, strMap, floatMap, boolMap)) { + return false; // return false if any nested matcher is false; + } + } + return true; // Otherwise, return true. + case LogicalOperation::OR: + for (auto nestedMatcher : matcher.combination().matcher()) { + if (matches(nestedMatcher, tagId, intMap, strMap, floatMap, boolMap)) { + return true; // return true if any nested matcher is true; + } + } + return false; + case LogicalOperation::NOT: + return !matches(matcher.combination().matcher(0), tagId, intMap, strMap, floatMap, + boolMap); + + // Case NAND is just inverting the return statement of AND + case LogicalOperation::NAND: + for (auto nestedMatcher : matcher.combination().matcher()) { + auto simple = nestedMatcher.simple_log_entry_matcher(); + if (!matches(nestedMatcher, tagId, intMap, strMap, floatMap, boolMap)) { + return true; // return false if any nested matcher is false; + } + } + return false; // Otherwise, return true. + case LogicalOperation::NOR: + for (auto nestedMatcher : matcher.combination().matcher()) { + if (matches(nestedMatcher, tagId, intMap, strMap, floatMap, boolMap)) { + return false; // return true if any nested matcher is true; + } + } + return true; + } + return false; + } else { + return matchesSimple(matcher.simple_log_entry_matcher(), tagId, intMap, strMap, floatMap, + boolMap); + } +} + +bool LogEntryMatcherManager::matchesSimple(const SimpleLogEntryMatcher &simpleMatcher, + const int tagId, + const unordered_map<int, long> &intMap, + const unordered_map<int, string> &strMap, + const unordered_map<int, float> &floatMap, + const unordered_map<int, bool> &boolMap) { + for (int i = 0; i < simpleMatcher.tag_size(); i++) { + if (simpleMatcher.tag(i) != tagId) { + continue; + } + + // now see if this event is interesting to us -- matches ALL the matchers + // defined in the metrics. + bool allMatched = true; + for (int j = 0; j < simpleMatcher.key_value_matcher_size(); j++) { + auto cur = simpleMatcher.key_value_matcher(j); + + // TODO: Check if this key is a magic key (eg package name). + int key = cur.key_matcher().key(); + + switch (cur.value_matcher_case()) { + case KeyValueMatcher::ValueMatcherCase::kEqString: { + auto it = strMap.find(key); + if (it == strMap.end() || cur.eq_string().compare(it->second) != 0) { + allMatched = false; + } + break; + } + case KeyValueMatcher::ValueMatcherCase::kEqInt: { + auto it = intMap.find(key); + if (it == intMap.end() || cur.eq_int() != it->second) { + allMatched = false; + } + break; + } + case KeyValueMatcher::ValueMatcherCase::kEqBool: { + auto it = boolMap.find(key); + if (it == boolMap.end() || cur.eq_bool() != it->second) { + allMatched = false; + } + break; + } + // Begin numeric comparisons + case KeyValueMatcher::ValueMatcherCase::kLtInt: { + auto it = intMap.find(key); + if (it == intMap.end() || cur.lt_int() <= it->second) { + allMatched = false; + } + break; + } + case KeyValueMatcher::ValueMatcherCase::kGtInt: { + auto it = intMap.find(key); + if (it == intMap.end() || cur.gt_int() >= it->second) { + allMatched = false; + } + break; + } + case KeyValueMatcher::ValueMatcherCase::kLtFloat: { + auto it = floatMap.find(key); + if (it == floatMap.end() || cur.lt_float() <= it->second) { + allMatched = false; + } + break; + } + case KeyValueMatcher::ValueMatcherCase::kGtFloat: { + auto it = floatMap.find(key); + if (it == floatMap.end() || cur.gt_float() >= it->second) { + allMatched = false; + } + break; + } + // Begin comparisons with equality + case KeyValueMatcher::ValueMatcherCase::kLteInt: { + auto it = intMap.find(key); + if (it == intMap.end() || cur.lte_int() < it->second) { + allMatched = false; + } + break; + } + case KeyValueMatcher::ValueMatcherCase::kGteInt: { + auto it = intMap.find(key); + if (it == intMap.end() || cur.gte_int() > it->second) { + allMatched = false; + } + break; + } + case KeyValueMatcher::ValueMatcherCase::VALUE_MATCHER_NOT_SET: + // If value matcher is not present, assume that we match. + break; + } + } + + if (allMatched) { + return true; + } + } + return false; +} + +} // namespace statsd +} // namespace os +} // namespace android diff --git a/cmds/statsd/src/matchers/LogEntryMatcherManager.h b/cmds/statsd/src/matchers/LogEntryMatcherManager.h new file mode 100644 index 000000000000..10ac0e2e9145 --- /dev/null +++ b/cmds/statsd/src/matchers/LogEntryMatcherManager.h @@ -0,0 +1,60 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef LOG_ENTRY_MATCHER_MANAGER_H +#define LOG_ENTRY_MATCHER_MANAGER_H + +#include "frameworks/base/cmds/statsd/src/statsd_config.pb.h" +#include <log/logprint.h> +#include <log/log_read.h> +#include <set> +#include <vector> +#include <unordered_map> + +using std::unordered_map; +using std::string; + +namespace android { +namespace os { +namespace statsd { + +/** + * Keeps track per log entry which simple log entry matchers match. + */ +class LogEntryMatcherManager { +public: + LogEntryMatcherManager(); + + ~LogEntryMatcherManager() {}; + + static bool matches(const LogEntryMatcher &matcher, const int tagId, + const unordered_map<int, long> &intMap, + const unordered_map<int, string> &strMap, + const unordered_map<int, float> &floatMap, + const unordered_map<int, bool> &boolMap); + + static bool matchesSimple(const SimpleLogEntryMatcher &simpleMatcher, + const int tagId, + const unordered_map<int, long> &intMap, + const unordered_map<int, string> &strMap, + const unordered_map<int, float> &floatMap, + const unordered_map<int, bool> &boolMap); +}; + +} // namespace statsd +} // namespace os +} // namespace android +#endif //LOG_ENTRY_MATCHER_MANAGER_H diff --git a/cmds/statsd/src/parse_util.cpp b/cmds/statsd/src/parse_util.cpp index b68f1355fef1..6464ee166dc9 100644 --- a/cmds/statsd/src/parse_util.cpp +++ b/cmds/statsd/src/parse_util.cpp @@ -25,11 +25,25 @@ using android::os::statsd::KeyValuePair; using android::os::statsd::TagId; using android::os::statsd::TagId_IsValid; -EventMetricData parse(log_msg msg) { +static inline uint32_t get4LE(const char* src) { + return src[0] | (src[1] << 8) | (src[2] << 16) | (src[3] << 24); +} + +EventMetricData parse(log_msg msg) +{ // dump all statsd logs to dropbox for now. // TODO: Add filtering, aggregation, etc. EventMetricData eventMetricData; + // set tag. + char* eventData = msg.msg(); + uint32_t tag = get4LE(eventData); + if (!TagId_IsValid(tag)) { + // return when an invalid tag is found. + return eventMetricData; + } + eventMetricData.set_tag(static_cast<TagId>(tag)); + // set timestamp of the event. KeyValuePair* keyValuePair = eventMetricData.add_key_value_pair(); keyValuePair->set_key(EVENT_TIMESTAMP); @@ -45,32 +59,23 @@ EventMetricData parse(log_msg msg) { memset(&elem, 0, sizeof(elem)); size_t index = 0; int32_t key = -1; - int32_t tag = -1; do { elem = android_log_read_next(context); switch ((int)elem.type) { case EVENT_TYPE_INT: - if (index == 0) { - tag = elem.data.int32; - if (TagId_IsValid(tag)) { - eventMetricData.set_tag(static_cast<TagId>(tag)); - } else { - break; - } - } else if (index % 2 == 1) { + if (index % 2 == 0) { key = elem.data.int32; } else if (KeyId_IsValid(key)) { int32_t val = elem.data.int32; KeyValuePair* keyValuePair = eventMetricData.add_key_value_pair(); keyValuePair->set_key(static_cast<KeyId>(key)); keyValuePair->set_value_int(val); - } else { } index++; break; case EVENT_TYPE_FLOAT: - if (index % 2 == 0 && KeyId_IsValid(key)) { + if (index % 2 == 1 && KeyId_IsValid(key)) { float val = elem.data.float32; KeyValuePair* keyValuePair = eventMetricData.add_key_value_pair(); keyValuePair->set_key(static_cast<KeyId>(key)); @@ -79,7 +84,7 @@ EventMetricData parse(log_msg msg) { index++; break; case EVENT_TYPE_STRING: - if (index % 2 == 0 && KeyId_IsValid(key)) { + if (index % 2 == 1 && KeyId_IsValid(key)) { char* val = elem.data.string; KeyValuePair* keyValuePair = eventMetricData.add_key_value_pair(); keyValuePair->set_key(static_cast<KeyId>(key)); @@ -88,7 +93,7 @@ EventMetricData parse(log_msg msg) { index++; break; case EVENT_TYPE_LONG: - if (index % 2 == 0 && KeyId_IsValid(key)) { + if (index % 2 == 1 && KeyId_IsValid(key)) { int64_t val = elem.data.int64; KeyValuePair* keyValuePair = eventMetricData.add_key_value_pair(); keyValuePair->set_key(static_cast<KeyId>(key)); diff --git a/cmds/statsd/src/statsd_config.proto b/cmds/statsd/src/statsd_config.proto index c6119df691a3..c7f030559cd3 100644 --- a/cmds/statsd/src/statsd_config.proto +++ b/cmds/statsd/src/statsd_config.proto @@ -19,14 +19,17 @@ message KeyValueMatcher { oneof value_matcher { bool eq_bool = 2; string eq_string = 3; - int32 eq_int32 = 4; - int64 eq_int64 = 5; - int32 lt_int32 = 6; - int32 gt_int32 = 7; - int64 lt_int64 = 8; - int64 gt_int64 = 9; - float lt_float = 10; - float gt_float = 11; + int32 eq_int = 4; + + // Numeric comparisons. Lt means strictly less than. + int64 lt_int = 5; + int64 gt_int = 6; + float lt_float = 7; + float gt_float = 8; + + // Numeric comparisons with equality. Lte means less than or equal. + int64 lte_int = 9; + int64 gte_int = 10; } } diff --git a/cmds/statsd/tests/LogEntryMatcher_test.cpp b/cmds/statsd/tests/LogEntryMatcher_test.cpp new file mode 100644 index 000000000000..eb807cad9085 --- /dev/null +++ b/cmds/statsd/tests/LogEntryMatcher_test.cpp @@ -0,0 +1,366 @@ +// Copyright (C) 2017 The Android Open Source Project +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#define LOG_TAG "statsd_test" + +#include "frameworks/base/cmds/statsd/src/statsd_config.pb.h" +#include "../src/matchers/LogEntryMatcherManager.h" +#include "../src/parse_util.h" +#include <log/logprint.h> +#include <log/log_read.h> +#include <log/log_event_list.h> +#include <gtest/gtest.h> + +#include <stdio.h> + +using namespace android::os::statsd; +using std::unordered_map; + +#ifdef __ANDROID__ +TEST(LogEntryMatcherTest, TestSimpleMatcher) { + // Set up the matcher + LogEntryMatcher matcher; + auto simpleMatcher = matcher.mutable_simple_log_entry_matcher(); + simpleMatcher->add_tag(TagId::WAKELOCK); + + unordered_map<int, long> intMap; + unordered_map<int, string> strMap; + unordered_map<int, float> floatMap; + unordered_map<int, bool> boolMap; + + EXPECT_TRUE(LogEntryMatcherManager::matches(matcher, TagId::WAKELOCK, intMap, strMap, floatMap, boolMap)); +} + +TEST(LogEntryMatcherTest, TestBoolMatcher) { + // Set up the matcher + LogEntryMatcher matcher; + auto simpleMatcher = matcher.mutable_simple_log_entry_matcher(); + simpleMatcher->add_tag(TagId::WAKELOCK); + auto keyValue = simpleMatcher->add_key_value_matcher(); + keyValue->mutable_key_matcher()->set_key(KeyId::STATE); + + + unordered_map<int, long> intMap; + unordered_map<int, string> strMap; + unordered_map<int, float> floatMap; + unordered_map<int, bool> boolMap; + + keyValue->set_eq_bool(true); + boolMap[KeyId::STATE] = true; + EXPECT_TRUE(LogEntryMatcherManager::matches(matcher, TagId::WAKELOCK, intMap, strMap, floatMap, + boolMap)); + + keyValue->set_eq_bool(false); + EXPECT_FALSE(LogEntryMatcherManager::matches(matcher, TagId::WAKELOCK, intMap, strMap, + floatMap, boolMap)); + + boolMap[TagId::WAKELOCK] = false; + EXPECT_TRUE(LogEntryMatcherManager::matches(matcher, TagId::WAKELOCK, intMap, strMap, floatMap, + boolMap)); +} + +TEST(LogEntryMatcherTest, TestStringMatcher) { + // Set up the matcher + LogEntryMatcher matcher; + auto simpleMatcher = matcher.mutable_simple_log_entry_matcher(); + simpleMatcher->add_tag(TagId::WAKELOCK); + auto keyValue = simpleMatcher->add_key_value_matcher(); + keyValue->mutable_key_matcher()->set_key(KeyId::STATE); + keyValue->set_eq_string("wakelock_name"); + + unordered_map<int, long> intMap; + unordered_map<int, string> strMap; + unordered_map<int, float> floatMap; + unordered_map<int, bool> boolMap; + + strMap[KeyId::STATE] = "wakelock_name"; + + EXPECT_TRUE(LogEntryMatcherManager::matches(matcher, TagId::WAKELOCK, intMap, strMap, floatMap, boolMap)); +} + +TEST(LogEntryMatcherTest, TestIntComparisonMatcher) { + // Set up the matcher + LogEntryMatcher matcher; + auto simpleMatcher = matcher.mutable_simple_log_entry_matcher(); + simpleMatcher->add_tag(TagId::WAKELOCK); + auto keyValue = simpleMatcher->add_key_value_matcher(); + keyValue->mutable_key_matcher()->set_key(KeyId::STATE); + + unordered_map<int, long> intMap; + unordered_map<int, string> strMap; + unordered_map<int, float> floatMap; + unordered_map<int, bool> boolMap; + + keyValue->set_lt_int(10); + intMap[KeyId::STATE] = 11; + EXPECT_FALSE(LogEntryMatcherManager::matches(matcher, TagId::WAKELOCK, intMap, strMap, + floatMap, boolMap)); + intMap[KeyId::STATE] = 10; + EXPECT_FALSE(LogEntryMatcherManager::matches(matcher, TagId::WAKELOCK, intMap, strMap, + floatMap, boolMap)); + intMap[KeyId::STATE] = 9; + EXPECT_TRUE(LogEntryMatcherManager::matches(matcher, TagId::WAKELOCK, intMap, strMap, + floatMap, boolMap)); + + keyValue->set_gt_int(10); + intMap[KeyId::STATE] = 11; + EXPECT_TRUE(LogEntryMatcherManager::matches(matcher, TagId::WAKELOCK, intMap, strMap, + floatMap, boolMap)); + intMap[KeyId::STATE] = 10; + EXPECT_FALSE(LogEntryMatcherManager::matches(matcher, TagId::WAKELOCK, intMap, strMap, + floatMap, boolMap)); + intMap[KeyId::STATE] = 9; + EXPECT_FALSE(LogEntryMatcherManager::matches(matcher, TagId::WAKELOCK, intMap, strMap, + floatMap, boolMap)); +} + +TEST(LogEntryMatcherTest, TestIntWithEqualityComparisonMatcher) { + // Set up the matcher + LogEntryMatcher matcher; + auto simpleMatcher = matcher.mutable_simple_log_entry_matcher(); + simpleMatcher->add_tag(TagId::WAKELOCK); + auto keyValue = simpleMatcher->add_key_value_matcher(); + keyValue->mutable_key_matcher()->set_key(KeyId::STATE); + + unordered_map<int, long> intMap; + unordered_map<int, string> strMap; + unordered_map<int, float> floatMap; + unordered_map<int, bool> boolMap; + + keyValue->set_lte_int(10); + intMap[KeyId::STATE] = 11; + EXPECT_FALSE(LogEntryMatcherManager::matches(matcher, TagId::WAKELOCK, intMap, strMap, + floatMap, boolMap)); + intMap[KeyId::STATE] = 10; + EXPECT_TRUE(LogEntryMatcherManager::matches(matcher, TagId::WAKELOCK, intMap, strMap, + floatMap, boolMap)); + intMap[KeyId::STATE] = 9; + EXPECT_TRUE(LogEntryMatcherManager::matches(matcher, TagId::WAKELOCK, intMap, strMap, + floatMap, boolMap)); + + keyValue->set_gte_int(10); + intMap[KeyId::STATE] = 11; + EXPECT_TRUE(LogEntryMatcherManager::matches(matcher, TagId::WAKELOCK, intMap, strMap, + floatMap, boolMap)); + intMap[KeyId::STATE] = 10; + EXPECT_TRUE(LogEntryMatcherManager::matches(matcher, TagId::WAKELOCK, intMap, strMap, + floatMap, boolMap)); + intMap[KeyId::STATE] = 9; + EXPECT_FALSE(LogEntryMatcherManager::matches(matcher, TagId::WAKELOCK, intMap, strMap, + floatMap, boolMap)); +} + +TEST(LogEntryMatcherTest, TestFloatComparisonMatcher) { + // Set up the matcher + LogEntryMatcher matcher; + auto simpleMatcher = matcher.mutable_simple_log_entry_matcher(); + simpleMatcher->add_tag(TagId::WAKELOCK); + auto keyValue = simpleMatcher->add_key_value_matcher(); + keyValue->mutable_key_matcher()->set_key(KeyId::STATE); + + unordered_map<int, long> intMap; + unordered_map<int, string> strMap; + unordered_map<int, float> floatMap; + unordered_map<int, bool> boolMap; + + keyValue->set_lt_float(10.0); + floatMap[KeyId::STATE] = 10.1; + EXPECT_FALSE(LogEntryMatcherManager::matches(matcher, TagId::WAKELOCK, intMap, strMap, + floatMap, boolMap)); + floatMap[KeyId::STATE] = 9.9; + EXPECT_TRUE(LogEntryMatcherManager::matches(matcher, TagId::WAKELOCK, intMap, strMap, + floatMap, boolMap)); + + keyValue->set_gt_float(10.0); + floatMap[KeyId::STATE] = 10.1; + EXPECT_TRUE(LogEntryMatcherManager::matches(matcher, TagId::WAKELOCK, intMap, strMap, + floatMap, boolMap)); + floatMap[KeyId::STATE] = 9.9; + EXPECT_FALSE(LogEntryMatcherManager::matches(matcher, TagId::WAKELOCK, intMap, strMap, + floatMap, boolMap)); +} + +// Helper for the composite matchers. +void addSimpleMatcher(SimpleLogEntryMatcher* simpleMatcher, TagId tag, KeyId key, int val) { + simpleMatcher->add_tag(tag); + auto keyValue = simpleMatcher->add_key_value_matcher(); + keyValue->mutable_key_matcher()->set_key(key); + keyValue->set_eq_int(val); +} + +TEST(LogEntryMatcherTest, TestAndMatcher) { + // Set up the matcher + LogEntryMatcher matcher; + auto combination = matcher.mutable_combination(); + combination->set_operation(LogicalOperation::AND); + + addSimpleMatcher(combination->add_matcher()->mutable_simple_log_entry_matcher(), TagId::WAKELOCK, KeyId::STATE, 3); + addSimpleMatcher(combination->add_matcher()->mutable_simple_log_entry_matcher(), TagId::WAKELOCK, KeyId::PACKAGE_VERSION, 4); + + unordered_map<int, long> intMap; + unordered_map<int, string> strMap; + unordered_map<int, float> floatMap; + unordered_map<int, bool> boolMap; + + intMap[1003] = 4; + EXPECT_FALSE(LogEntryMatcherManager::matches(matcher, TagId::WAKELOCK, intMap, strMap, floatMap, boolMap)); + intMap.clear(); + intMap[1] = 3; + EXPECT_FALSE(LogEntryMatcherManager::matches(matcher, TagId::WAKELOCK, intMap, strMap, floatMap, boolMap)); + intMap.clear(); + intMap[1] = 3; + intMap[1003] = 4; + EXPECT_TRUE(LogEntryMatcherManager::matches(matcher, TagId::WAKELOCK, intMap, strMap, floatMap, boolMap)); +} + +TEST(LogEntryMatcherTest, TestOrMatcher) { + // Set up the matcher + LogEntryMatcher matcher; + auto combination = matcher.mutable_combination(); + combination->set_operation(LogicalOperation::OR); + + addSimpleMatcher(combination->add_matcher()->mutable_simple_log_entry_matcher(), + TagId::WAKELOCK, KeyId::STATE, 3); + addSimpleMatcher(combination->add_matcher()->mutable_simple_log_entry_matcher(), + TagId::WAKELOCK, KeyId::PACKAGE_VERSION, 4); + + unordered_map<int, long> intMap; + unordered_map<int, string> strMap; + unordered_map<int, float> floatMap; + unordered_map<int, bool> boolMap; + + // Don't set any key-value pairs. + EXPECT_FALSE(LogEntryMatcherManager::matches(matcher, TagId::WAKELOCK, intMap, strMap, floatMap, + boolMap)); + intMap[1003] = 4; + EXPECT_TRUE(LogEntryMatcherManager::matches(matcher, TagId::WAKELOCK, intMap, strMap, floatMap, + boolMap)); + intMap.clear(); + intMap[1] = 3; + EXPECT_TRUE(LogEntryMatcherManager::matches(matcher, TagId::WAKELOCK, intMap, strMap, floatMap, + boolMap)); + intMap.clear(); + intMap[1] = 3; + intMap[1003] = 4; + EXPECT_TRUE(LogEntryMatcherManager::matches(matcher, TagId::WAKELOCK, intMap, strMap, floatMap, + boolMap)); +} + +TEST(LogEntryMatcherTest, TestNotMatcher) { + // Set up the matcher + LogEntryMatcher matcher; + auto combination = matcher.mutable_combination(); + combination->set_operation(LogicalOperation::NOT); + + // Define first simpleMatcher + addSimpleMatcher(combination->add_matcher()->mutable_simple_log_entry_matcher(), + TagId::WAKELOCK, KeyId::STATE, 3); + + unordered_map<int, long> intMap; + unordered_map<int, string> strMap; + unordered_map<int, float> floatMap; + unordered_map<int, bool> boolMap; + + // Don't set any key-value pairs. + intMap[KeyId::STATE] = 3; + EXPECT_FALSE(LogEntryMatcherManager::matches(matcher, TagId::WAKELOCK, intMap, strMap, floatMap, + boolMap)); +} + +TEST(LogEntryMatcherTest, TestNANDMatcher) { + // Set up the matcher + LogEntryMatcher matcher; + auto combination = matcher.mutable_combination(); + combination->set_operation(LogicalOperation::NAND); + + addSimpleMatcher(combination->add_matcher()->mutable_simple_log_entry_matcher(), + TagId::WAKELOCK, KeyId::STATE, 3); + addSimpleMatcher(combination->add_matcher()->mutable_simple_log_entry_matcher(), + TagId::WAKELOCK, KeyId::PACKAGE_VERSION, 4); + + unordered_map<int, long> intMap; + unordered_map<int, string> strMap; + unordered_map<int, float> floatMap; + unordered_map<int, bool> boolMap; + + // Don't set any key-value pairs. + EXPECT_TRUE(LogEntryMatcherManager::matches(matcher, TagId::WAKELOCK, intMap, strMap, floatMap, + boolMap)); + intMap[KeyId::STATE] = 3; + EXPECT_TRUE(LogEntryMatcherManager::matches(matcher, TagId::WAKELOCK, intMap, strMap, floatMap, + boolMap)); + intMap[KeyId::PACKAGE_VERSION] = 4; + EXPECT_FALSE(LogEntryMatcherManager::matches(matcher, TagId::WAKELOCK, intMap, strMap, floatMap, + boolMap)); +} + +TEST(LogEntryMatcherTest, TestNORMatcher) { + // Set up the matcher + LogEntryMatcher matcher; + auto combination = matcher.mutable_combination(); + combination->set_operation(LogicalOperation::NOR); + + addSimpleMatcher(combination->add_matcher()->mutable_simple_log_entry_matcher(), + TagId::WAKELOCK, KeyId::STATE, 3); + addSimpleMatcher(combination->add_matcher()->mutable_simple_log_entry_matcher(), + TagId::WAKELOCK, KeyId::PACKAGE_VERSION, 4); + + unordered_map<int, long> intMap; + unordered_map<int, string> strMap; + unordered_map<int, float> floatMap; + unordered_map<int, bool> boolMap; + + // Don't set any key-value pairs. + EXPECT_TRUE(LogEntryMatcherManager::matches(matcher, TagId::WAKELOCK, intMap, strMap, floatMap, + boolMap)); + intMap[KeyId::STATE] = 3; + EXPECT_FALSE(LogEntryMatcherManager::matches(matcher, TagId::WAKELOCK, intMap, strMap, floatMap, + boolMap)); + intMap[KeyId::PACKAGE_VERSION] = 4; + EXPECT_FALSE(LogEntryMatcherManager::matches(matcher, TagId::WAKELOCK, intMap, strMap, floatMap, + boolMap)); +} + +// Tests that a NOT on top of AND is the same as NAND +TEST(LogEntryMatcherTest, TestMultipleLayerMatcher) { + LogEntryMatcher matcher; + auto not_combination = matcher.mutable_combination(); + not_combination->set_operation(LogicalOperation::NOT); + + // Now add the AND + auto combination = not_combination->add_matcher()->mutable_combination(); + combination->set_operation(LogicalOperation::AND); + addSimpleMatcher(combination->add_matcher()->mutable_simple_log_entry_matcher(), + TagId::WAKELOCK, KeyId::STATE, 3); + addSimpleMatcher(combination->add_matcher()->mutable_simple_log_entry_matcher(), + TagId::WAKELOCK, KeyId::PACKAGE_VERSION, 4); + + unordered_map<int, long> intMap; + unordered_map<int, string> strMap; + unordered_map<int, float> floatMap; + unordered_map<int, bool> boolMap; + + // Don't set any key-value pairs. + EXPECT_TRUE(LogEntryMatcherManager::matches(matcher, TagId::WAKELOCK, intMap, strMap, floatMap, + boolMap)); + intMap[KeyId::STATE] = 3; + EXPECT_TRUE(LogEntryMatcherManager::matches(matcher, TagId::WAKELOCK, intMap, strMap, floatMap, + boolMap)); + intMap[KeyId::PACKAGE_VERSION] = 4; + EXPECT_FALSE(LogEntryMatcherManager::matches(matcher, TagId::WAKELOCK, intMap, strMap, floatMap, + boolMap)); +} +#else + GTEST_LOG_(INFO) << "This test does nothing.\n"; +#endif diff --git a/config/compiled-classes-phone b/config/compiled-classes-phone index df68f14efec9..42e6ecf79229 100644 --- a/config/compiled-classes-phone +++ b/config/compiled-classes-phone @@ -5022,8 +5022,6 @@ android.widget.RemoteViews$AsyncApplyTask android.widget.RemoteViews$BitmapCache android.widget.RemoteViews$BitmapReflectionAction android.widget.RemoteViews$LayoutParamAction -android.widget.RemoteViews$MemoryUsageCounter -android.widget.RemoteViews$MutablePair android.widget.RemoteViews$OnClickHandler android.widget.RemoteViews$OnViewAppliedListener android.widget.RemoteViews$ReflectionAction @@ -5031,7 +5029,7 @@ android.widget.RemoteViews$RemoteView android.widget.RemoteViews$RemoteViewsContextWrapper android.widget.RemoteViews$RunnableAction android.widget.RemoteViews$RuntimeAction -android.widget.RemoteViews$SetDrawableParameters +android.widget.RemoteViews$SetDrawableTint android.widget.RemoteViews$SetOnClickPendingIntent android.widget.RemoteViews$SetOnClickPendingIntent$1 android.widget.RemoteViews$ViewGroupAction diff --git a/config/preloaded-classes b/config/preloaded-classes index 337d7a0ad8bb..c0819a98a64c 100644 --- a/config/preloaded-classes +++ b/config/preloaded-classes @@ -2723,13 +2723,11 @@ android.widget.RemoteViews$3 android.widget.RemoteViews$Action android.widget.RemoteViews$BitmapCache android.widget.RemoteViews$LayoutParamAction -android.widget.RemoteViews$MemoryUsageCounter -android.widget.RemoteViews$MutablePair android.widget.RemoteViews$OnClickHandler android.widget.RemoteViews$ReflectionAction android.widget.RemoteViews$RemoteView android.widget.RemoteViews$RuntimeAction -android.widget.RemoteViews$SetDrawableParameters +android.widget.RemoteViews$SetDrawableTint android.widget.RemoteViewsAdapter$RemoteAdapterConnectionCallback android.widget.RtlSpacingHelper android.widget.ScrollBarDrawable diff --git a/core/java/android/animation/AnimatorSet.java b/core/java/android/animation/AnimatorSet.java index 00d6657efd0d..1a2dc5cde4e5 100644 --- a/core/java/android/animation/AnimatorSet.java +++ b/core/java/android/animation/AnimatorSet.java @@ -843,7 +843,7 @@ public final class AnimatorSet extends Animator implements AnimationHandler.Anim // Assumes forward playing from here on. for (int i = 0; i < mEvents.size(); i++) { AnimationEvent event = mEvents.get(i); - if (event.getTime() > currentPlayTime) { + if (event.getTime() > currentPlayTime || event.getTime() == DURATION_INFINITE) { break; } @@ -1264,7 +1264,8 @@ public final class AnimatorSet extends Animator implements AnimationHandler.Anim } else { for (int i = mLastEventId + 1; i < size; i++) { AnimationEvent event = mEvents.get(i); - if (event.getTime() <= currentPlayTime) { + // TODO: need a function that accounts for infinite duration to compare time + if (event.getTime() != DURATION_INFINITE && event.getTime() <= currentPlayTime) { latestId = i; } } diff --git a/core/java/android/app/KeyguardManager.java b/core/java/android/app/KeyguardManager.java index 76643d603304..54f74b15c501 100644 --- a/core/java/android/app/KeyguardManager.java +++ b/core/java/android/app/KeyguardManager.java @@ -174,7 +174,7 @@ public class KeyguardManager { */ public Intent createConfirmFactoryResetCredentialIntent( CharSequence title, CharSequence description, CharSequence alternateButtonLabel) { - if (!LockPatternUtils.frpCredentialEnabled()) { + if (!LockPatternUtils.frpCredentialEnabled(mContext)) { Log.w(TAG, "Factory reset credentials not supported."); return null; } diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java index 60f4ed01805c..fee7d6c8ba2b 100644 --- a/core/java/android/app/Notification.java +++ b/core/java/android/app/Notification.java @@ -3839,8 +3839,8 @@ public class Notification implements Parcelable contentView.setImageViewBitmap(R.id.profile_badge, profileBadge); contentView.setViewVisibility(R.id.profile_badge, View.VISIBLE); if (isColorized()) { - contentView.setDrawableParameters(R.id.profile_badge, false, -1, - getPrimaryTextColor(), PorterDuff.Mode.SRC_ATOP, -1); + contentView.setDrawableTint(R.id.profile_badge, false, + getPrimaryTextColor(), PorterDuff.Mode.SRC_ATOP); } } } @@ -4130,18 +4130,14 @@ public class Notification implements Parcelable if (action != null) { int contrastColor = resolveContrastColor(); - contentView.setDrawableParameters(R.id.reply_icon_action, + contentView.setDrawableTint(R.id.reply_icon_action, true /* targetBackground */, - -1, - contrastColor, - PorterDuff.Mode.SRC_ATOP, -1); + contrastColor, PorterDuff.Mode.SRC_ATOP); int iconColor = NotificationColorUtil.isColorLight(contrastColor) ? Color.BLACK : Color.WHITE; - contentView.setDrawableParameters(R.id.reply_icon_action, + contentView.setDrawableTint(R.id.reply_icon_action, false /* targetBackground */, - -1, - iconColor, - PorterDuff.Mode.SRC_ATOP, -1); + iconColor, PorterDuff.Mode.SRC_ATOP); contentView.setOnClickPendingIntent(R.id.right_icon, action.actionIntent); contentView.setOnClickPendingIntent(R.id.reply_icon_action, @@ -4185,8 +4181,8 @@ public class Notification implements Parcelable private void bindExpandButton(RemoteViews contentView) { int color = getPrimaryHighlightColor(); - contentView.setDrawableParameters(R.id.expand_button, false, -1, color, - PorterDuff.Mode.SRC_ATOP, -1); + contentView.setDrawableTint(R.id.expand_button, false, color, + PorterDuff.Mode.SRC_ATOP); contentView.setInt(R.id.notification_header, "setOriginalNotificationColor", color); } @@ -4293,8 +4289,7 @@ public class Notification implements Parcelable mN.mSmallIcon = Icon.createWithResource(mContext, mN.icon); } contentView.setImageViewIcon(R.id.icon, mN.mSmallIcon); - contentView.setDrawableParameters(R.id.icon, false /* targetBackground */, - -1 /* alpha */, -1 /* colorFilter */, null /* mode */, mN.iconLevel); + contentView.setInt(R.id.icon, "setImageLevel", mN.iconLevel); processSmallIconColor(mN.mSmallIcon, contentView, ambient); } @@ -4684,8 +4679,8 @@ public class Notification implements Parcelable bgColor = mContext.getColor(oddAction ? R.color.notification_action_list : R.color.notification_action_list_dark); } - button.setDrawableParameters(R.id.button_holder, true, -1, bgColor, - PorterDuff.Mode.SRC_ATOP, -1); + button.setDrawableTint(R.id.button_holder, true, + bgColor, PorterDuff.Mode.SRC_ATOP); CharSequence title = action.title; ColorStateList[] outResultColor = null; if (isLegacy()) { @@ -4818,8 +4813,8 @@ public class Notification implements Parcelable boolean colorable = !isLegacy() || getColorUtil().isGrayscaleIcon(mContext, smallIcon); int color = ambient ? resolveAmbientColor() : getPrimaryHighlightColor(); if (colorable) { - contentView.setDrawableParameters(R.id.icon, false, -1, color, - PorterDuff.Mode.SRC_ATOP, -1); + contentView.setDrawableTint(R.id.icon, false, color, + PorterDuff.Mode.SRC_ATOP); } contentView.setInt(R.id.notification_header, "setOriginalIconColor", @@ -4835,8 +4830,8 @@ public class Notification implements Parcelable if (largeIcon != null && isLegacy() && getColorUtil().isGrayscaleIcon(mContext, largeIcon)) { // resolve color will fall back to the default when legacy - contentView.setDrawableParameters(R.id.icon, false, -1, resolveContrastColor(), - PorterDuff.Mode.SRC_ATOP, -1); + contentView.setDrawableTint(R.id.icon, false, resolveContrastColor(), + PorterDuff.Mode.SRC_ATOP); } } @@ -6750,8 +6745,8 @@ public class Notification implements Parcelable : NotificationColorUtil.resolveColor(mBuilder.mContext, Notification.COLOR_DEFAULT); - button.setDrawableParameters(R.id.action0, false, -1, tintColor, - PorterDuff.Mode.SRC_ATOP, -1); + button.setDrawableTint(R.id.action0, false, tintColor, + PorterDuff.Mode.SRC_ATOP); if (!tombstone) { button.setOnClickPendingIntent(R.id.action0, action.actionIntent); } diff --git a/core/java/android/app/NotificationManager.java b/core/java/android/app/NotificationManager.java index 8fa7d6c3b4f7..eb52cb7f9508 100644 --- a/core/java/android/app/NotificationManager.java +++ b/core/java/android/app/NotificationManager.java @@ -41,6 +41,7 @@ import android.provider.Settings.Global; import android.service.notification.StatusBarNotification; import android.service.notification.ZenModeConfig; import android.util.Log; +import android.util.proto.ProtoOutputStream; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; @@ -1061,6 +1062,27 @@ public class NotificationManager { + "]"; } + /** @hide */ + public void toProto(ProtoOutputStream proto, long fieldId) { + final long pToken = proto.start(fieldId); + + bitwiseToProtoEnum(proto, PolicyProto.PRIORITY_CATEGORIES, priorityCategories); + proto.write(PolicyProto.PRIORITY_CALL_SENDER, priorityCallSenders); + proto.write(PolicyProto.PRIORITY_MESSAGE_SENDER, priorityMessageSenders); + bitwiseToProtoEnum( + proto, PolicyProto.SUPPRESSED_VISUAL_EFFECTS, suppressedVisualEffects); + + proto.end(pToken); + } + + private static void bitwiseToProtoEnum(ProtoOutputStream proto, long fieldId, int data) { + for (int i = 1; data > 0; ++i, data >>>= 1) { + if ((data & 1) == 1) { + proto.write(fieldId, i); + } + } + } + public static String suppressedEffectsToString(int effects) { if (effects <= 0) return ""; final StringBuilder sb = new StringBuilder(); diff --git a/core/java/android/app/StatusBarManager.java b/core/java/android/app/StatusBarManager.java index fe7afed8de13..80144bd7971b 100644 --- a/core/java/android/app/StatusBarManager.java +++ b/core/java/android/app/StatusBarManager.java @@ -70,14 +70,15 @@ public class StatusBarManager { * Setting this flag disables quick settings completely, but does not disable expanding the * notification shade. */ - public static final int DISABLE2_QUICK_SETTINGS = 0x00000001; + public static final int DISABLE2_QUICK_SETTINGS = 1; + public static final int DISABLE2_SYSTEM_ICONS = 1 << 1; public static final int DISABLE2_NONE = 0x00000000; - public static final int DISABLE2_MASK = DISABLE2_QUICK_SETTINGS; + public static final int DISABLE2_MASK = DISABLE2_QUICK_SETTINGS | DISABLE2_SYSTEM_ICONS; @IntDef(flag = true, - value = {DISABLE2_NONE, DISABLE2_MASK, DISABLE2_QUICK_SETTINGS}) + value = {DISABLE2_NONE, DISABLE2_MASK, DISABLE2_QUICK_SETTINGS, DISABLE2_SYSTEM_ICONS}) @Retention(RetentionPolicy.SOURCE) public @interface Disable2Flags {} diff --git a/core/java/android/app/timezone/RulesUpdaterContract.java b/core/java/android/app/timezone/RulesUpdaterContract.java index 2a22eadd28f2..74ed658875ab 100644 --- a/core/java/android/app/timezone/RulesUpdaterContract.java +++ b/core/java/android/app/timezone/RulesUpdaterContract.java @@ -83,8 +83,7 @@ public final class RulesUpdaterContract { Intent intent = createUpdaterIntent(updaterAppPackageName); intent.putExtra(EXTRA_CHECK_TOKEN, checkTokenBytes); context.sendBroadcastAsUser( - intent, - UserHandle.of(UserHandle.myUserId()), + intent, UserHandle.SYSTEM, RulesUpdaterContract.UPDATE_TIME_ZONE_RULES_PERMISSION); } } diff --git a/core/java/android/bluetooth/BluetoothAdapter.java b/core/java/android/bluetooth/BluetoothAdapter.java index 70591d4d0587..84765f6d7280 100644 --- a/core/java/android/bluetooth/BluetoothAdapter.java +++ b/core/java/android/bluetooth/BluetoothAdapter.java @@ -1134,6 +1134,29 @@ public final class BluetoothAdapter { } /** + * Sets the {@link BluetoothClass} Bluetooth Class of Device (CoD) of + * the local Bluetooth adapter. + * + * @param bluetoothClass {@link BluetoothClass} to set the local Bluetooth adapter to. + * @return true if successful, false if unsuccessful. + * + * @hide + */ + @RequiresPermission(Manifest.permission.BLUETOOTH_PRIVILEGED) + public boolean setBluetoothClass(BluetoothClass bluetoothClass) { + if (getState() != STATE_ON) return false; + try { + mServiceLock.readLock().lock(); + if (mService != null) return mService.setBluetoothClass(bluetoothClass); + } catch (RemoteException e) { + Log.e(TAG, "", e); + } finally { + mServiceLock.readLock().unlock(); + } + return false; + } + + /** * Get the current Bluetooth scan mode of the local Bluetooth adapter. * <p>The Bluetooth scan mode determines if the local adapter is * connectable and/or discoverable from remote Bluetooth devices. diff --git a/core/java/android/bluetooth/BluetoothClass.java b/core/java/android/bluetooth/BluetoothClass.java index 57e4abb12987..f22ea6e88e04 100755 --- a/core/java/android/bluetooth/BluetoothClass.java +++ b/core/java/android/bluetooth/BluetoothClass.java @@ -19,6 +19,10 @@ package android.bluetooth; import android.os.Parcel; import android.os.Parcelable; +import java.nio.ByteBuffer; +import java.nio.ByteOrder; +import java.util.Arrays; + /** * Represents a Bluetooth class, which describes general characteristics * and capabilities of a device. For example, a Bluetooth class will @@ -275,6 +279,48 @@ public final class BluetoothClass implements Parcelable { return (mClass & Device.BITMASK); } + /** + * Return the Bluetooth Class of Device (CoD) value including the + * {@link BluetoothClass.Service}, {@link BluetoothClass.Device.Major} and + * minor device fields. + * + * <p>This value is an integer representation of Bluetooth CoD as in + * Bluetooth specification. + * + * @see <a href="Bluetooth CoD">https://www.bluetooth.com/specifications/assigned-numbers/baseband</a> + * + * @hide + */ + public int getClassOfDevice() { + return mClass; + } + + /** + * Return the Bluetooth Class of Device (CoD) value including the + * {@link BluetoothClass.Service}, {@link BluetoothClass.Device.Major} and + * minor device fields. + * + * <p>This value is a byte array representation of Bluetooth CoD as in + * Bluetooth specification. + * + * <p>Bluetooth COD information is 3 bytes, but stored as an int. Hence the + * MSB is useless and needs to be thrown away. The lower 3 bytes are + * converted into a byte array MSB to LSB. Hence, using BIG_ENDIAN. + * + * @see <a href="Bluetooth CoD">https://www.bluetooth.com/specifications/assigned-numbers/baseband</a> + * + * @hide + */ + public byte[] getClassOfDeviceBytes() { + byte[] bytes = ByteBuffer.allocate(4) + .order(ByteOrder.BIG_ENDIAN) + .putInt(mClass) + .array(); + + // Discard the top byte + return Arrays.copyOfRange(bytes, 1, bytes.length); + } + /** @hide */ public static final int PROFILE_HEADSET = 0; /** @hide */ diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java index 03e4dfe829de..693921d2d7e0 100644 --- a/core/java/android/content/Context.java +++ b/core/java/android/content/Context.java @@ -3034,6 +3034,9 @@ public abstract class Context { * <dt> {@link #CONNECTIVITY_SERVICE} ("connection") * <dd> A {@link android.net.ConnectivityManager ConnectivityManager} for * handling management of network connections. + * <dt> {@link #IPSEC_SERVICE} ("ipsec") + * <dd> A {@link android.net.IpSecManager IpSecManager} for managing IPSec on + * sockets and networks. * <dt> {@link #WIFI_SERVICE} ("wifi") * <dd> A {@link android.net.wifi.WifiManager WifiManager} for management of Wi-Fi * connectivity. On releases before NYC, it should only be obtained from an application @@ -3378,7 +3381,6 @@ public abstract class Context { * {@link android.net.IpSecManager} for encrypting Sockets or Networks with * IPSec. * - * @hide * @see #getSystemService */ public static final String IPSEC_SERVICE = "ipsec"; diff --git a/core/java/android/content/pm/ActivityInfo.java b/core/java/android/content/pm/ActivityInfo.java index cd8201f8fb89..41667c4c3ce3 100644 --- a/core/java/android/content/pm/ActivityInfo.java +++ b/core/java/android/content/pm/ActivityInfo.java @@ -1217,7 +1217,7 @@ public class ActivityInfo extends ComponentInfo implements Parcelable { * @hide */ public static String screenOrientationToString(int orientation) { - switch(orientation) { + switch (orientation) { case SCREEN_ORIENTATION_UNSET: return "SCREEN_ORIENTATION_UNSET"; case SCREEN_ORIENTATION_UNSPECIFIED: @@ -1257,6 +1257,22 @@ public class ActivityInfo extends ComponentInfo implements Parcelable { } } + /** + * @hide + */ + public static String colorModeToString(@ColorMode int colorMode) { + switch (colorMode) { + case COLOR_MODE_DEFAULT: + return "COLOR_MODE_DEFAULT"; + case COLOR_MODE_WIDE_COLOR_GAMUT: + return "COLOR_MODE_WIDE_COLOR_GAMUT"; + case COLOR_MODE_HDR: + return "COLOR_MODE_HDR"; + default: + return Integer.toString(colorMode); + } + } + public static final Parcelable.Creator<ActivityInfo> CREATOR = new Parcelable.Creator<ActivityInfo>() { public ActivityInfo createFromParcel(Parcel source) { diff --git a/core/java/android/hardware/LegacySensorManager.java b/core/java/android/hardware/LegacySensorManager.java index f5cf3f74bc38..098121dfeffd 100644 --- a/core/java/android/hardware/LegacySensorManager.java +++ b/core/java/android/hardware/LegacySensorManager.java @@ -204,7 +204,7 @@ final class LegacySensorManager { } private static final class LegacyListener implements SensorEventListener { - private float mValues[] = new float[6]; + private float[] mValues = new float[6]; private SensorListener mTarget; private int mSensors; private final LmsFilter mYawfilter = new LmsFilter(); @@ -256,7 +256,7 @@ final class LegacySensorManager { } public void onSensorChanged(SensorEvent event) { - final float v[] = mValues; + final float[] v = mValues; v[0] = event.values[0]; v[1] = event.values[1]; v[2] = event.values[2]; @@ -264,10 +264,10 @@ final class LegacySensorManager { int legacyType = getLegacySensorType(type); mapSensorDataToWindow(legacyType, v, LegacySensorManager.getRotation()); if (type == Sensor.TYPE_ORIENTATION) { - if ((mSensors & SensorManager.SENSOR_ORIENTATION_RAW)!=0) { + if ((mSensors & SensorManager.SENSOR_ORIENTATION_RAW) != 0) { mTarget.onSensorChanged(SensorManager.SENSOR_ORIENTATION_RAW, v); } - if ((mSensors & SensorManager.SENSOR_ORIENTATION)!=0) { + if ((mSensors & SensorManager.SENSOR_ORIENTATION) != 0) { v[0] = mYawfilter.filter(event.timestamp, v[0]); mTarget.onSensorChanged(SensorManager.SENSOR_ORIENTATION, v); } @@ -317,7 +317,7 @@ final class LegacySensorManager { switch (sensor) { case SensorManager.SENSOR_ACCELEROMETER: case SensorManager.SENSOR_MAGNETIC_FIELD: - values[0] =-y; + values[0] = -y; values[1] = x; values[2] = z; break; @@ -337,15 +337,15 @@ final class LegacySensorManager { switch (sensor) { case SensorManager.SENSOR_ACCELEROMETER: case SensorManager.SENSOR_MAGNETIC_FIELD: - values[0] =-x; - values[1] =-y; + values[0] = -x; + values[1] = -y; values[2] = z; break; case SensorManager.SENSOR_ORIENTATION: case SensorManager.SENSOR_ORIENTATION_RAW: values[0] = (x >= 180) ? (x - 180) : (x + 180); - values[1] =-y; - values[2] =-z; + values[1] = -y; + values[2] = -z; break; } } @@ -369,10 +369,11 @@ final class LegacySensorManager { private static final class LmsFilter { private static final int SENSORS_RATE_MS = 20; private static final int COUNT = 12; - private static final float PREDICTION_RATIO = 1.0f/3.0f; - private static final float PREDICTION_TIME = (SENSORS_RATE_MS*COUNT/1000.0f)*PREDICTION_RATIO; - private float mV[] = new float[COUNT*2]; - private long mT[] = new long[COUNT*2]; + private static final float PREDICTION_RATIO = 1.0f / 3.0f; + private static final float PREDICTION_TIME = + (SENSORS_RATE_MS * COUNT / 1000.0f) * PREDICTION_RATIO; + private float[] mV = new float[COUNT * 2]; + private long[] mT = new long[COUNT * 2]; private int mIndex; public LmsFilter() { @@ -383,9 +384,9 @@ final class LegacySensorManager { float v = in; final float ns = 1.0f / 1000000000.0f; float v1 = mV[mIndex]; - if ((v-v1) > 180) { + if ((v - v1) > 180) { v -= 360; - } else if ((v1-v) > 180) { + } else if ((v1 - v) > 180) { v += 360; } /* Manage the circular buffer, we write the data twice spaced @@ -393,40 +394,43 @@ final class LegacySensorManager { * when it's full */ mIndex++; - if (mIndex >= COUNT*2) + if (mIndex >= COUNT * 2) { mIndex = COUNT; + } mV[mIndex] = v; mT[mIndex] = time; - mV[mIndex-COUNT] = v; - mT[mIndex-COUNT] = time; + mV[mIndex - COUNT] = v; + mT[mIndex - COUNT] = time; float A, B, C, D, E; float a, b; int i; A = B = C = D = E = 0; - for (i=0 ; i<COUNT-1 ; i++) { + for (i = 0; i < COUNT - 1; i++) { final int j = mIndex - 1 - i; final float Z = mV[j]; - final float T = (mT[j]/2 + mT[j+1]/2 - time)*ns; - float dT = (mT[j] - mT[j+1])*ns; + final float T = (mT[j] / 2 + mT[j + 1] / 2 - time) * ns; + float dT = (mT[j] - mT[j + 1]) * ns; dT *= dT; - A += Z*dT; - B += T*(T*dT); - C += (T*dT); - D += Z*(T*dT); + A += Z * dT; + B += T * (T * dT); + C += (T * dT); + D += Z * (T * dT); E += dT; } - b = (A*B + C*D) / (E*B + C*C); - a = (E*b - A) / C; - float f = b + PREDICTION_TIME*a; + b = (A * B + C * D) / (E * B + C * C); + a = (E * b - A) / C; + float f = b + PREDICTION_TIME * a; // Normalize f *= (1.0f / 360.0f); - if (((f>=0)?f:-f) >= 0.5f) - f = f - (float)Math.ceil(f + 0.5f) + 1.0f; - if (f < 0) + if (((f >= 0) ? f : -f) >= 0.5f) { + f = f - (float) Math.ceil(f + 0.5f) + 1.0f; + } + if (f < 0) { f += 1.0f; + } f *= 360.0f; return f; } diff --git a/core/java/android/hardware/Sensor.java b/core/java/android/hardware/Sensor.java index f02e4849e7da..7fb0c89e7f92 100644 --- a/core/java/android/hardware/Sensor.java +++ b/core/java/android/hardware/Sensor.java @@ -794,12 +794,12 @@ public final class Sensor { 1, // SENSOR_TYPE_PICK_UP_GESTURE 1, // SENSOR_TYPE_WRIST_TILT_GESTURE 1, // SENSOR_TYPE_DEVICE_ORIENTATION - 16,// SENSOR_TYPE_POSE_6DOF + 16, // SENSOR_TYPE_POSE_6DOF 1, // SENSOR_TYPE_STATIONARY_DETECT 1, // SENSOR_TYPE_MOTION_DETECT 1, // SENSOR_TYPE_HEART_BEAT 2, // SENSOR_TYPE_DYNAMIC_SENSOR_META - 16,// skip over additional sensor info type + 16, // skip over additional sensor info type 1, // SENSOR_TYPE_LOW_LATENCY_OFFBODY_DETECT 6, // SENSOR_TYPE_ACCELEROMETER_UNCALIBRATED }; @@ -857,8 +857,8 @@ public final class Sensor { static int getMaxLengthValuesArray(Sensor sensor, int sdkLevel) { // RotationVector length has changed to 3 to 5 for API level 18 // Set it to 3 for backward compatibility. - if (sensor.mType == Sensor.TYPE_ROTATION_VECTOR && - sdkLevel <= Build.VERSION_CODES.JELLY_BEAN_MR1) { + if (sensor.mType == Sensor.TYPE_ROTATION_VECTOR + && sdkLevel <= Build.VERSION_CODES.JELLY_BEAN_MR1) { return 3; } int offset = sensor.mType; @@ -1033,9 +1033,9 @@ public final class Sensor { * Returns true if the sensor is a wake-up sensor. * <p> * <b>Application Processor Power modes</b> <p> - * Application Processor(AP), is the processor on which applications run. When no wake lock is held - * and the user is not interacting with the device, this processor can enter a “Suspend” mode, - * reducing the power consumption by 10 times or more. + * Application Processor(AP), is the processor on which applications run. When no wake lock is + * held and the user is not interacting with the device, this processor can enter a “Suspend” + * mode, reducing the power consumption by 10 times or more. * </p> * <p> * <b>Non-wake-up sensors</b> <p> @@ -1232,6 +1232,6 @@ public final class Sensor { */ private void setUuid(long msb, long lsb) { // TODO(b/29547335): Rename this method to setId. - mId = (int)msb; + mId = (int) msb; } } diff --git a/core/java/android/hardware/SensorAdditionalInfo.java b/core/java/android/hardware/SensorAdditionalInfo.java index 0c6a41511181..7c876cfcb80a 100644 --- a/core/java/android/hardware/SensorAdditionalInfo.java +++ b/core/java/android/hardware/SensorAdditionalInfo.java @@ -200,7 +200,7 @@ public class SensorAdditionalInfo { public static final int TYPE_DEBUG_INFO = 0x40000000; SensorAdditionalInfo( - Sensor aSensor, int aType, int aSerial, int [] aIntValues, float [] aFloatValues) { + Sensor aSensor, int aType, int aSerial, int[] aIntValues, float[] aFloatValues) { sensor = aSensor; type = aType; serial = aSerial; @@ -222,10 +222,10 @@ public class SensorAdditionalInfo { null, new float[] { strength, declination, inclination}); } /** @hide */ - public static SensorAdditionalInfo createCustomInfo(Sensor aSensor, int type, float [] data) { + public static SensorAdditionalInfo createCustomInfo(Sensor aSensor, int type, float[] data) { if (type < TYPE_CUSTOM_INFO || type >= TYPE_DEBUG_INFO || aSensor == null) { - throw new IllegalArgumentException("invalid parameter(s): type: " + type + - "; sensor: " + aSensor); + throw new IllegalArgumentException( + "invalid parameter(s): type: " + type + "; sensor: " + aSensor); } return new SensorAdditionalInfo(aSensor, type, 0, null, data); diff --git a/core/java/android/hardware/SensorEvent.java b/core/java/android/hardware/SensorEvent.java index c0bca97e12b7..bbd04a31f8c8 100644 --- a/core/java/android/hardware/SensorEvent.java +++ b/core/java/android/hardware/SensorEvent.java @@ -207,8 +207,8 @@ public class SensorEvent { * timestamp = event.timestamp; * float[] deltaRotationMatrix = new float[9]; * SensorManager.getRotationMatrixFromVector(deltaRotationMatrix, deltaRotationVector); - * // User code should concatenate the delta rotation we computed with the current rotation - * // in order to get the updated rotation. + * // User code should concatenate the delta rotation we computed with the current + * // rotation in order to get the updated rotation. * // rotationCurrent = rotationCurrent * deltaRotationMatrix; * } * </pre> @@ -244,21 +244,22 @@ public class SensorEvent { * <h4>{@link android.hardware.Sensor#TYPE_GRAVITY Sensor.TYPE_GRAVITY}:</h4> * <p>A three dimensional vector indicating the direction and magnitude of gravity. Units * are m/s^2. The coordinate system is the same as is used by the acceleration sensor.</p> - * <p><b>Note:</b> When the device is at rest, the output of the gravity sensor should be identical - * to that of the accelerometer.</p> - * - * <h4>{@link android.hardware.Sensor#TYPE_LINEAR_ACCELERATION Sensor.TYPE_LINEAR_ACCELERATION}:</h4> - * A three dimensional vector indicating acceleration along each device axis, not including - * gravity. All values have units of m/s^2. The coordinate system is the same as is used by the - * acceleration sensor. + * <p><b>Note:</b> When the device is at rest, the output of the gravity sensor should be + * identical to that of the accelerometer.</p> + * + * <h4> + * {@link android.hardware.Sensor#TYPE_LINEAR_ACCELERATION Sensor.TYPE_LINEAR_ACCELERATION}: + * </h4> A three dimensional vector indicating acceleration along each device axis, not + * including gravity. All values have units of m/s^2. The coordinate system is the same as is + * used by the acceleration sensor. * <p>The output of the accelerometer, gravity and linear-acceleration sensors must obey the * following relation:</p> - * <p><ul>acceleration = gravity + linear-acceleration</ul></p> + * <p><ul>acceleration = gravity + linear-acceleration</ul></p> * * <h4>{@link android.hardware.Sensor#TYPE_ROTATION_VECTOR Sensor.TYPE_ROTATION_VECTOR}:</h4> - * <p>The rotation vector represents the orientation of the device as a combination of an <i>angle</i> - * and an <i>axis</i>, in which the device has rotated through an angle θ around an axis - * <x, y, z>.</p> + * <p>The rotation vector represents the orientation of the device as a combination of an + * <i>angle</i> and an <i>axis</i>, in which the device has rotated through an angle θ + * around an axis <x, y, z>.</p> * <p>The three elements of the rotation vector are * <x*sin(θ/2), y*sin(θ/2), z*sin(θ/2)>, such that the magnitude of the rotation * vector is equal to sin(θ/2), and the direction of the rotation vector is equal to the diff --git a/core/java/android/hardware/SensorListener.java b/core/java/android/hardware/SensorListener.java index c71e968d2713..e2033b6dc105 100644 --- a/core/java/android/hardware/SensorListener.java +++ b/core/java/android/hardware/SensorListener.java @@ -19,8 +19,8 @@ package android.hardware; /** * Used for receiving notifications from the SensorManager when * sensor values have changed. - * - * @deprecated Use + * + * @deprecated Use * {@link android.hardware.SensorEventListener SensorEventListener} instead. */ @Deprecated @@ -36,7 +36,7 @@ public interface SensorListener { * <p><u>Definition of the coordinate system used below.</u><p> * <p>The X axis refers to the screen's horizontal axis * (the small edge in portrait mode, the long edge in landscape mode) and - * points to the right. + * points to the right. * <p>The Y axis refers to the screen's vertical axis and points towards * the top of the screen (the origin is in the lower-left corner). * <p>The Z axis points toward the sky when the device is lying on its back @@ -44,18 +44,18 @@ public interface SensorListener { * <p> <b>IMPORTANT NOTE:</b> The axis <b><u>are swapped</u></b> when the * device's screen orientation changes. To access the unswapped values, * use indices 3, 4 and 5 in values[]. - * + * * <p>{@link android.hardware.SensorManager#SENSOR_ORIENTATION SENSOR_ORIENTATION}, * {@link android.hardware.SensorManager#SENSOR_ORIENTATION_RAW SENSOR_ORIENTATION_RAW}:<p> * All values are angles in degrees. - * + * * <p>values[0]: Azimuth, rotation around the Z axis (0<=azimuth<360). * 0 = North, 90 = East, 180 = South, 270 = West - * + * * <p>values[1]: Pitch, rotation around X axis (-180<=pitch<=180), with positive * values when the z-axis moves toward the y-axis. * - * <p>values[2]: Roll, rotation around Y axis (-90<=roll<=90), with positive values + * <p>values[2]: Roll, rotation around Y axis (-90<=roll<=90), with positive values * when the z-axis moves toward the x-axis. * * <p>Note that this definition of yaw, pitch and roll is different from the @@ -64,17 +64,17 @@ public interface SensorListener { * * <p>{@link android.hardware.SensorManager#SENSOR_ACCELEROMETER SENSOR_ACCELEROMETER}:<p> * All values are in SI units (m/s^2) and measure contact forces. - * - * <p>values[0]: force applied by the device on the x-axis - * <p>values[1]: force applied by the device on the y-axis + * + * <p>values[0]: force applied by the device on the x-axis + * <p>values[1]: force applied by the device on the y-axis * <p>values[2]: force applied by the device on the z-axis - * + * * <p><u>Examples</u>: * <li>When the device is pushed on its left side toward the right, the * x acceleration value is negative (the device applies a reaction force * to the push toward the left)</li> - * - * <li>When the device lies flat on a table, the acceleration value is + * + * <li>When the device lies flat on a table, the acceleration value is * {@link android.hardware.SensorManager#STANDARD_GRAVITY -STANDARD_GRAVITY}, * which correspond to the force the device applies on the table in reaction * to gravity.</li> @@ -83,7 +83,7 @@ public interface SensorListener { * All values are in micro-Tesla (uT) and measure the ambient magnetic * field in the X, Y and -Z axis. * <p><b><u>Note:</u></b> the magnetic field's Z axis is inverted. - * + * * @param sensor The ID of the sensor being monitored * @param values The new values for the sensor. */ @@ -97,5 +97,5 @@ public interface SensorListener { * @param sensor The ID of the sensor being monitored * @param accuracy The new accuracy of this sensor. */ - public void onAccuracyChanged(int sensor, int accuracy); + public void onAccuracyChanged(int sensor, int accuracy); } diff --git a/core/java/android/hardware/SensorManager.java b/core/java/android/hardware/SensorManager.java index e1cd451ba2a8..35aaf78bc3c2 100644 --- a/core/java/android/hardware/SensorManager.java +++ b/core/java/android/hardware/SensorManager.java @@ -83,7 +83,7 @@ public abstract class SensorManager { /** @hide */ protected static final String TAG = "SensorManager"; - private static final float[] mTempMatrix = new float[16]; + private static final float[] sTempMatrix = new float[16]; // Cached lists of sensors by type. Guarded by mSensorListByType. private final SparseArray<List<Sensor>> mSensorListByType = @@ -188,7 +188,7 @@ public abstract class SensorManager { * @deprecated use {@link android.hardware.Sensor Sensor} instead. */ @Deprecated - public static final int SENSOR_MAX = ((SENSOR_ALL + 1)>>1); + public static final int SENSOR_MAX = ((SENSOR_ALL + 1) >> 1); /** @@ -425,8 +425,9 @@ public abstract class SensorManager { } else { list = new ArrayList<Sensor>(); for (Sensor i : fullList) { - if (i.getType() == type) + if (i.getType() == type) { list.add(i); + } } } list = Collections.unmodifiableList(list); @@ -461,8 +462,9 @@ public abstract class SensorManager { } else { List<Sensor> list = new ArrayList(); for (Sensor i : fullList) { - if (i.getType() == type) + if (i.getType() == type) { list.add(i); + } } return Collections.unmodifiableList(list); } @@ -490,10 +492,11 @@ public abstract class SensorManager { // For the following sensor types, return a wake-up sensor. These types are by default // defined as wake-up sensors. For the rest of the SDK defined sensor types return a // non_wake-up version. - if (type == Sensor.TYPE_PROXIMITY || type == Sensor.TYPE_SIGNIFICANT_MOTION || - type == Sensor.TYPE_TILT_DETECTOR || type == Sensor.TYPE_WAKE_GESTURE || - type == Sensor.TYPE_GLANCE_GESTURE || type == Sensor.TYPE_PICK_UP_GESTURE || - type == Sensor.TYPE_WRIST_TILT_GESTURE || type == Sensor.TYPE_DYNAMIC_SENSOR_META) { + if (type == Sensor.TYPE_PROXIMITY || type == Sensor.TYPE_SIGNIFICANT_MOTION + || type == Sensor.TYPE_TILT_DETECTOR || type == Sensor.TYPE_WAKE_GESTURE + || type == Sensor.TYPE_GLANCE_GESTURE || type == Sensor.TYPE_PICK_UP_GESTURE + || type == Sensor.TYPE_WRIST_TILT_GESTURE + || type == Sensor.TYPE_DYNAMIC_SENSOR_META) { wakeUpSensor = true; } @@ -509,12 +512,12 @@ public abstract class SensorManager { * <p> * For example, * <ul> - * <li>getDefaultSensor({@link Sensor#TYPE_ACCELEROMETER}, true) returns a wake-up accelerometer - * sensor if it exists. </li> - * <li>getDefaultSensor({@link Sensor#TYPE_PROXIMITY}, false) returns a non wake-up proximity - * sensor if it exists. </li> - * <li>getDefaultSensor({@link Sensor#TYPE_PROXIMITY}, true) returns a wake-up proximity sensor - * which is the same as the Sensor returned by {@link #getDefaultSensor(int)}. </li> + * <li>getDefaultSensor({@link Sensor#TYPE_ACCELEROMETER}, true) returns a wake-up + * accelerometer sensor if it exists. </li> + * <li>getDefaultSensor({@link Sensor#TYPE_PROXIMITY}, false) returns a non wake-up + * proximity sensor if it exists. </li> + * <li>getDefaultSensor({@link Sensor#TYPE_PROXIMITY}, true) returns a wake-up proximity + * sensor which is the same as the Sensor returned by {@link #getDefaultSensor(int)}. </li> * </ul> * </p> * <p class="note"> @@ -532,8 +535,9 @@ public abstract class SensorManager { public Sensor getDefaultSensor(int type, boolean wakeUp) { List<Sensor> l = getSensorList(type); for (Sensor sensor : l) { - if (sensor.isWakeUpSensor() == wakeUp) + if (sensor.isWakeUpSensor() == wakeUp) { return sensor; + } } return null; } @@ -842,8 +846,8 @@ public abstract class SensorManager { * @return <code>true</code> if the sensor is supported and successfully enabled. * @see #registerListener(SensorEventListener, Sensor, int, int) */ - public boolean registerListener(SensorEventListener listener, Sensor sensor, int samplingPeriodUs, - int maxReportLatencyUs, Handler handler) { + public boolean registerListener(SensorEventListener listener, Sensor sensor, + int samplingPeriodUs, int maxReportLatencyUs, Handler handler) { int delayUs = getDelay(samplingPeriodUs); return registerListenerImpl(listener, sensor, delayUs, handler, maxReportLatencyUs, 0); } @@ -953,7 +957,7 @@ public abstract class SensorManager { * Used for receiving notifications from the SensorManager when dynamic sensors are connected or * disconnected. */ - public static abstract class DynamicSensorCallback { + public abstract static class DynamicSensorCallback { /** * Called when there is a dynamic sensor being connected to the system. * @@ -1180,7 +1184,7 @@ public abstract class SensorManager { float Ay = gravity[1]; float Az = gravity[2]; - final float normsqA = (Ax*Ax + Ay*Ay + Az*Az); + final float normsqA = (Ax * Ax + Ay * Ay + Az * Az); final float g = 9.81f; final float freeFallGravitySquared = 0.01f * g * g; if (normsqA < freeFallGravitySquared) { @@ -1191,10 +1195,10 @@ public abstract class SensorManager { final float Ex = geomagnetic[0]; final float Ey = geomagnetic[1]; final float Ez = geomagnetic[2]; - float Hx = Ey*Az - Ez*Ay; - float Hy = Ez*Ax - Ex*Az; - float Hz = Ex*Ay - Ey*Ax; - final float normH = (float)Math.sqrt(Hx*Hx + Hy*Hy + Hz*Hz); + float Hx = Ey * Az - Ez * Ay; + float Hy = Ez * Ax - Ex * Az; + float Hz = Ex * Ay - Ey * Ax; + final float normH = (float) Math.sqrt(Hx * Hx + Hy * Hy + Hz * Hz); if (normH < 0.1f) { // device is close to free fall (or in space?), or close to @@ -1205,13 +1209,13 @@ public abstract class SensorManager { Hx *= invH; Hy *= invH; Hz *= invH; - final float invA = 1.0f / (float)Math.sqrt(Ax*Ax + Ay*Ay + Az*Az); + final float invA = 1.0f / (float) Math.sqrt(Ax * Ax + Ay * Ay + Az * Az); Ax *= invA; Ay *= invA; Az *= invA; - final float Mx = Ay*Hz - Az*Hy; - final float My = Az*Hx - Ax*Hz; - final float Mz = Ax*Hy - Ay*Hx; + final float Mx = Ay * Hz - Az * Hy; + final float My = Az * Hx - Ax * Hz; + final float Mz = Ax * Hy - Ay * Hx; if (R != null) { if (R.length == 9) { R[0] = Hx; R[1] = Hy; R[2] = Hz; @@ -1228,17 +1232,17 @@ public abstract class SensorManager { // compute the inclination matrix by projecting the geomagnetic // vector onto the Z (gravity) and X (horizontal component // of geomagnetic vector) axes. - final float invE = 1.0f / (float)Math.sqrt(Ex*Ex + Ey*Ey + Ez*Ez); - final float c = (Ex*Mx + Ey*My + Ez*Mz) * invE; - final float s = (Ex*Ax + Ey*Ay + Ez*Az) * invE; + final float invE = 1.0f / (float) Math.sqrt(Ex * Ex + Ey * Ey + Ez * Ez); + final float c = (Ex * Mx + Ey * My + Ez * Mz) * invE; + final float s = (Ex * Ax + Ey * Ay + Ez * Az) * invE; if (I.length == 9) { I[0] = 1; I[1] = 0; I[2] = 0; I[3] = 0; I[4] = c; I[5] = s; - I[6] = 0; I[7] =-s; I[8] = c; + I[6] = 0; I[7] = -s; I[8] = c; } else if (I.length == 16) { I[0] = 1; I[1] = 0; I[2] = 0; I[4] = 0; I[5] = c; I[6] = s; - I[8] = 0; I[9] =-s; I[10]= c; + I[8] = 0; I[9] = -s; I[10] = c; I[3] = I[7] = I[11] = I[12] = I[13] = I[14] = 0; I[15] = 1; } @@ -1262,9 +1266,9 @@ public abstract class SensorManager { */ public static float getInclination(float[] I) { if (I.length == 9) { - return (float)Math.atan2(I[5], I[4]); + return (float) Math.atan2(I[5], I[4]); } else { - return (float)Math.atan2(I[6], I[5]); + return (float) Math.atan2(I[6], I[5]); } } @@ -1343,17 +1347,16 @@ public abstract class SensorManager { * @see #getRotationMatrix(float[], float[], float[], float[]) */ - public static boolean remapCoordinateSystem(float[] inR, int X, int Y, - float[] outR) - { + public static boolean remapCoordinateSystem(float[] inR, int X, int Y, float[] outR) { if (inR == outR) { - final float[] temp = mTempMatrix; - synchronized(temp) { + final float[] temp = sTempMatrix; + synchronized (temp) { // we don't expect to have a lot of contention if (remapCoordinateSystemImpl(inR, X, Y, temp)) { final int size = outR.length; - for (int i=0 ; i<size ; i++) + for (int i = 0; i < size; i++) { outR[i] = temp[i]; + } return true; } } @@ -1361,9 +1364,7 @@ public abstract class SensorManager { return remapCoordinateSystemImpl(inR, X, Y, outR); } - private static boolean remapCoordinateSystemImpl(float[] inR, int X, int Y, - float[] outR) - { + private static boolean remapCoordinateSystemImpl(float[] inR, int X, int Y, float[] outR) { /* * X and Y define a rotation matrix 'r': * @@ -1376,14 +1377,18 @@ public abstract class SensorManager { */ final int length = outR.length; - if (inR.length != length) + if (inR.length != length) { return false; // invalid parameter - if ((X & 0x7C)!=0 || (Y & 0x7C)!=0) + } + if ((X & 0x7C) != 0 || (Y & 0x7C) != 0) { return false; // invalid parameter - if (((X & 0x3)==0) || ((Y & 0x3)==0)) + } + if (((X & 0x3) == 0) || ((Y & 0x3) == 0)) { return false; // no axis specified - if ((X & 0x3) == (Y & 0x3)) + } + if ((X & 0x3) == (Y & 0x3)) { return false; // same axis specified + } // Z is "the other" axis, its sign is either +/- sign(X)*sign(Y) // this can be calculated by exclusive-or'ing X and Y; except for @@ -1391,28 +1396,29 @@ public abstract class SensorManager { int Z = X ^ Y; // extract the axis (remove the sign), offset in the range 0 to 2. - final int x = (X & 0x3)-1; - final int y = (Y & 0x3)-1; - final int z = (Z & 0x3)-1; + final int x = (X & 0x3) - 1; + final int y = (Y & 0x3) - 1; + final int z = (Z & 0x3) - 1; // compute the sign of Z (whether it needs to be inverted) - final int axis_y = (z+1)%3; - final int axis_z = (z+2)%3; - if (((x^axis_y)|(y^axis_z)) != 0) + final int axis_y = (z + 1) % 3; + final int axis_z = (z + 2) % 3; + if (((x ^ axis_y) | (y ^ axis_z)) != 0) { Z ^= 0x80; + } - final boolean sx = (X>=0x80); - final boolean sy = (Y>=0x80); - final boolean sz = (Z>=0x80); + final boolean sx = (X >= 0x80); + final boolean sy = (Y >= 0x80); + final boolean sz = (Z >= 0x80); // Perform R * r, in avoiding actual muls and adds. - final int rowLength = ((length==16)?4:3); - for (int j=0 ; j<3 ; j++) { - final int offset = j*rowLength; - for (int i=0 ; i<3 ; i++) { - if (x==i) outR[offset+i] = sx ? -inR[offset+0] : inR[offset+0]; - if (y==i) outR[offset+i] = sy ? -inR[offset+1] : inR[offset+1]; - if (z==i) outR[offset+i] = sz ? -inR[offset+2] : inR[offset+2]; + final int rowLength = ((length == 16) ? 4 : 3); + for (int j = 0; j < 3; j++) { + final int offset = j * rowLength; + for (int i = 0; i < 3; i++) { + if (x == i) outR[offset + i] = sx ? -inR[offset + 0] : inR[offset + 0]; + if (y == i) outR[offset + i] = sy ? -inR[offset + 1] : inR[offset + 1]; + if (z == i) outR[offset + i] = sz ? -inR[offset + 2] : inR[offset + 2]; } } if (length == 16) { @@ -1466,7 +1472,7 @@ public abstract class SensorManager { * @see #getRotationMatrix(float[], float[], float[], float[]) * @see GeomagneticField */ - public static float[] getOrientation(float[] R, float values[]) { + public static float[] getOrientation(float[] R, float[] values) { /* * 4x4 (length=16) case: * / R[ 0] R[ 1] R[ 2] 0 \ @@ -1481,13 +1487,13 @@ public abstract class SensorManager { * */ if (R.length == 9) { - values[0] = (float)Math.atan2(R[1], R[4]); - values[1] = (float)Math.asin(-R[7]); - values[2] = (float)Math.atan2(-R[6], R[8]); + values[0] = (float) Math.atan2(R[1], R[4]); + values[1] = (float) Math.asin(-R[7]); + values[2] = (float) Math.atan2(-R[6], R[8]); } else { - values[0] = (float)Math.atan2(R[1], R[5]); - values[1] = (float)Math.asin(-R[9]); - values[2] = (float)Math.atan2(-R[8], R[10]); + values[0] = (float) Math.atan2(R[1], R[5]); + values[1] = (float) Math.asin(-R[9]); + values[2] = (float) Math.atan2(-R[8], R[10]); } return values; @@ -1524,7 +1530,7 @@ public abstract class SensorManager { */ public static float getAltitude(float p0, float p) { final float coef = 1.0f / 5.255f; - return 44330.0f * (1.0f - (float)Math.pow(p/p0, coef)); + return 44330.0f * (1.0f - (float) Math.pow(p / p0, coef)); } /** Helper function to compute the angle change between two rotation matrices. @@ -1557,12 +1563,13 @@ public abstract class SensorManager { * (in radians) is stored */ - public static void getAngleChange( float[] angleChange, float[] R, float[] prevR) { - float rd1=0,rd4=0, rd6=0,rd7=0, rd8=0; - float ri0=0,ri1=0,ri2=0,ri3=0,ri4=0,ri5=0,ri6=0,ri7=0,ri8=0; - float pri0=0, pri1=0, pri2=0, pri3=0, pri4=0, pri5=0, pri6=0, pri7=0, pri8=0; + public static void getAngleChange(float[] angleChange, float[] R, float[] prevR) { + float rd1 = 0, rd4 = 0, rd6 = 0, rd7 = 0, rd8 = 0; + float ri0 = 0, ri1 = 0, ri2 = 0, ri3 = 0, ri4 = 0, ri5 = 0, ri6 = 0, ri7 = 0, ri8 = 0; + float pri0 = 0, pri1 = 0, pri2 = 0, pri3 = 0, pri4 = 0; + float pri5 = 0, pri6 = 0, pri7 = 0, pri8 = 0; - if(R.length == 9) { + if (R.length == 9) { ri0 = R[0]; ri1 = R[1]; ri2 = R[2]; @@ -1572,7 +1579,7 @@ public abstract class SensorManager { ri6 = R[6]; ri7 = R[7]; ri8 = R[8]; - } else if(R.length == 16) { + } else if (R.length == 16) { ri0 = R[0]; ri1 = R[1]; ri2 = R[2]; @@ -1584,7 +1591,7 @@ public abstract class SensorManager { ri8 = R[10]; } - if(prevR.length == 9) { + if (prevR.length == 9) { pri0 = prevR[0]; pri1 = prevR[1]; pri2 = prevR[2]; @@ -1594,7 +1601,7 @@ public abstract class SensorManager { pri6 = prevR[6]; pri7 = prevR[7]; pri8 = prevR[8]; - } else if(prevR.length == 16) { + } else if (prevR.length == 16) { pri0 = prevR[0]; pri1 = prevR[1]; pri2 = prevR[2]; @@ -1615,9 +1622,9 @@ public abstract class SensorManager { rd7 = pri2 * ri1 + pri5 * ri4 + pri8 * ri7; //rd[2][1] rd8 = pri2 * ri2 + pri5 * ri5 + pri8 * ri8; //rd[2][2] - angleChange[0] = (float)Math.atan2(rd1, rd4); - angleChange[1] = (float)Math.asin(-rd7); - angleChange[2] = (float)Math.atan2(-rd6, rd8); + angleChange[0] = (float) Math.atan2(rd1, rd4); + angleChange[1] = (float) Math.asin(-rd7); + angleChange[2] = (float) Math.atan2(-rd6, rd8); } @@ -1650,8 +1657,8 @@ public abstract class SensorManager { if (rotationVector.length >= 4) { q0 = rotationVector[3]; } else { - q0 = 1 - q1*q1 - q2*q2 - q3*q3; - q0 = (q0 > 0) ? (float)Math.sqrt(q0) : 0; + q0 = 1 - q1 * q1 - q2 * q2 - q3 * q3; + q0 = (q0 > 0) ? (float) Math.sqrt(q0) : 0; } float sq_q1 = 2 * q1 * q1; @@ -1664,7 +1671,7 @@ public abstract class SensorManager { float q2_q3 = 2 * q2 * q3; float q1_q0 = 2 * q1 * q0; - if(R.length == 9) { + if (R.length == 9) { R[0] = 1 - sq_q2 - sq_q3; R[1] = q1_q2 - q3_q0; R[2] = q1_q3 + q2_q0; @@ -1707,8 +1714,8 @@ public abstract class SensorManager { if (rv.length >= 4) { Q[0] = rv[3]; } else { - Q[0] = 1 - rv[0]*rv[0] - rv[1]*rv[1] - rv[2]*rv[2]; - Q[0] = (Q[0] > 0) ? (float)Math.sqrt(Q[0]) : 0; + Q[0] = 1 - rv[0] * rv[0] - rv[1] * rv[1] - rv[2] * rv[2]; + Q[0] = (Q[0] > 0) ? (float) Math.sqrt(Q[0]) : 0; } Q[1] = rv[0]; Q[2] = rv[1]; @@ -1800,7 +1807,7 @@ public abstract class SensorManager { */ @SystemApi public boolean initDataInjection(boolean enable) { - return initDataInjectionImpl(enable); + return initDataInjectionImpl(enable); } /** @@ -1846,9 +1853,9 @@ public abstract class SensorManager { } int expectedNumValues = Sensor.getMaxLengthValuesArray(sensor, Build.VERSION_CODES.M); if (values.length != expectedNumValues) { - throw new IllegalArgumentException ("Wrong number of values for sensor " + - sensor.getName() + " actual=" + values.length + " expected=" + - expectedNumValues); + throw new IllegalArgumentException("Wrong number of values for sensor " + + sensor.getName() + " actual=" + values.length + " expected=" + + expectedNumValues); } if (accuracy < SENSOR_STATUS_NO_CONTACT || accuracy > SENSOR_STATUS_ACCURACY_HIGH) { throw new IllegalArgumentException("Invalid sensor accuracy"); diff --git a/core/java/android/hardware/SystemSensorManager.java b/core/java/android/hardware/SystemSensorManager.java index 607788d3effc..1174cb6a2692 100644 --- a/core/java/android/hardware/SystemSensorManager.java +++ b/core/java/android/hardware/SystemSensorManager.java @@ -28,10 +28,11 @@ import android.util.Log; import android.util.SparseArray; import android.util.SparseBooleanArray; import android.util.SparseIntArray; -import dalvik.system.CloseGuard; import com.android.internal.annotations.GuardedBy; +import dalvik.system.CloseGuard; + import java.io.IOException; import java.io.UncheckedIOException; import java.lang.ref.WeakReference; @@ -40,7 +41,6 @@ import java.util.HashMap; import java.util.List; import java.util.Map; - /** * Sensor manager implementation that communicates with the built-in * system sensors. @@ -101,7 +101,7 @@ public class SystemSensorManager extends SensorManager { /** {@hide} */ public SystemSensorManager(Context context, Looper mainLooper) { - synchronized(sLock) { + synchronized (sLock) { if (!sNativeClassInited) { sNativeClassInited = true; nativeClassInit(); @@ -114,7 +114,7 @@ public class SystemSensorManager extends SensorManager { mNativeInstance = nativeCreate(context.getOpPackageName()); // initialize the sensor list - for (int index = 0;;++index) { + for (int index = 0;; ++index) { Sensor sensor = new Sensor(); if (!nativeGetSensorAtIndex(mNativeInstance, sensor, index)) break; mFullSensorsList.add(sensor); @@ -157,9 +157,9 @@ public class SystemSensorManager extends SensorManager { return false; } if (mSensorListeners.size() >= MAX_LISTENER_COUNT) { - throw new IllegalStateException("register failed, " + - "the sensor listeners size has exceeded the maximum limit " + - MAX_LISTENER_COUNT); + throw new IllegalStateException("register failed, " + + "the sensor listeners size has exceeded the maximum limit " + + MAX_LISTENER_COUNT); } // Invariants to preserve: @@ -170,9 +170,10 @@ public class SystemSensorManager extends SensorManager { SensorEventQueue queue = mSensorListeners.get(listener); if (queue == null) { Looper looper = (handler != null) ? handler.getLooper() : mMainLooper; - final String fullClassName = listener.getClass().getEnclosingClass() != null ? - listener.getClass().getEnclosingClass().getName() : - listener.getClass().getName(); + final String fullClassName = + listener.getClass().getEnclosingClass() != null + ? listener.getClass().getEnclosingClass().getName() + : listener.getClass().getName(); queue = new SensorEventQueue(listener, looper, this, fullClassName); if (!queue.addSensor(sensor, delayUs, maxBatchReportLatencyUs)) { queue.dispose(); @@ -221,17 +222,18 @@ public class SystemSensorManager extends SensorManager { if (sensor.getReportingMode() != Sensor.REPORTING_MODE_ONE_SHOT) return false; if (mTriggerListeners.size() >= MAX_LISTENER_COUNT) { - throw new IllegalStateException("request failed, " + - "the trigger listeners size has exceeded the maximum limit " + - MAX_LISTENER_COUNT); + throw new IllegalStateException("request failed, " + + "the trigger listeners size has exceeded the maximum limit " + + MAX_LISTENER_COUNT); } synchronized (mTriggerListeners) { TriggerEventQueue queue = mTriggerListeners.get(listener); if (queue == null) { - final String fullClassName = listener.getClass().getEnclosingClass() != null ? - listener.getClass().getEnclosingClass().getName() : - listener.getClass().getName(); + final String fullClassName = + listener.getClass().getEnclosingClass() != null + ? listener.getClass().getEnclosingClass().getName() + : listener.getClass().getName(); queue = new TriggerEventQueue(listener, mMainLooper, this, fullClassName); if (!queue.addSensor(sensor, 0, 0)) { queue.dispose(); @@ -336,27 +338,27 @@ public class SystemSensorManager extends SensorManager { mHandleToSensor.remove(sensor.getHandle()); if (sensor.getReportingMode() == Sensor.REPORTING_MODE_ONE_SHOT) { - synchronized(mTriggerListeners) { + synchronized (mTriggerListeners) { HashMap<TriggerEventListener, TriggerEventQueue> triggerListeners = - new HashMap<TriggerEventListener, TriggerEventQueue>(mTriggerListeners); + new HashMap<TriggerEventListener, TriggerEventQueue>(mTriggerListeners); - for (TriggerEventListener l: triggerListeners.keySet()) { - if (DEBUG_DYNAMIC_SENSOR){ - Log.i(TAG, "removed trigger listener" + l.toString() + - " due to sensor disconnection"); + for (TriggerEventListener l : triggerListeners.keySet()) { + if (DEBUG_DYNAMIC_SENSOR) { + Log.i(TAG, "removed trigger listener" + l.toString() + + " due to sensor disconnection"); } cancelTriggerSensorImpl(l, sensor, true); } } } else { - synchronized(mSensorListeners) { + synchronized (mSensorListeners) { HashMap<SensorEventListener, SensorEventQueue> sensorListeners = - new HashMap<SensorEventListener, SensorEventQueue>(mSensorListeners); + new HashMap<SensorEventListener, SensorEventQueue>(mSensorListeners); for (SensorEventListener l: sensorListeners.keySet()) { - if (DEBUG_DYNAMIC_SENSOR){ - Log.i(TAG, "removed event listener" + l.toString() + - " due to sensor disconnection"); + if (DEBUG_DYNAMIC_SENSOR) { + Log.i(TAG, "removed event listener" + l.toString() + + " due to sensor disconnection"); } unregisterListenerImpl(l, sensor); } @@ -365,7 +367,7 @@ public class SystemSensorManager extends SensorManager { } private void updateDynamicSensorList() { - synchronized(mFullDynamicSensorsList) { + synchronized (mFullDynamicSensorsList) { if (mDynamicSensorListDirty) { List<Sensor> list = new ArrayList<>(); nativeGetDynamicSensors(mNativeInstance, list); @@ -488,15 +490,15 @@ public class SystemSensorManager extends SensorManager { int i = 0, j = 0; while (true) { - if (j < oldList.size() && ( i >= newList.size() || - newList.get(i).getHandle() > oldList.get(j).getHandle()) ) { + if (j < oldList.size() && (i >= newList.size() + || newList.get(i).getHandle() > oldList.get(j).getHandle())) { changed = true; if (removed != null) { removed.add(oldList.get(j)); } ++j; - } else if (i < newList.size() && ( j >= oldList.size() || - newList.get(i).getHandle() < oldList.get(j).getHandle())) { + } else if (i < newList.size() && (j >= oldList.size() + || newList.get(i).getHandle() < oldList.get(j).getHandle())) { changed = true; if (added != null) { added.add(newList.get(i)); @@ -505,8 +507,8 @@ public class SystemSensorManager extends SensorManager { updated.add(newList.get(i)); } ++i; - } else if (i < newList.size() && j < oldList.size() && - newList.get(i).getHandle() == oldList.get(j).getHandle()) { + } else if (i < newList.size() && j < oldList.size() + && newList.get(i).getHandle() == oldList.get(j).getHandle()) { if (updated != null) { updated.add(oldList.get(j)); } @@ -623,7 +625,7 @@ public class SystemSensorManager extends SensorManager { * associated with any listener and there is one InjectEventQueue associated with a * SensorManager instance. */ - private static abstract class BaseEventQueue { + private abstract static class BaseEventQueue { private static native long nativeInitBaseEventQueue(long nativeManager, WeakReference<BaseEventQueue> eventQWeak, MessageQueue msgQ, String packageName, int mode, String opPackageName); @@ -633,9 +635,9 @@ public class SystemSensorManager extends SensorManager { private static native void nativeDestroySensorEventQueue(long eventQ); private static native int nativeFlushSensor(long eventQ); private static native int nativeInjectSensorData(long eventQ, int handle, - float[] values,int accuracy, long timestamp); + float[] values, int accuracy, long timestamp); - private long nSensorEventQueue; + private long mNativeSensorEventQueue; private final SparseBooleanArray mActiveSensors = new SparseBooleanArray(); protected final SparseIntArray mSensorAccuracies = new SparseIntArray(); private final CloseGuard mCloseGuard = CloseGuard.get(); @@ -646,7 +648,7 @@ public class SystemSensorManager extends SensorManager { BaseEventQueue(Looper looper, SystemSensorManager manager, int mode, String packageName) { if (packageName == null) packageName = ""; - nSensorEventQueue = nativeInitBaseEventQueue(manager.mNativeInstance, + mNativeSensorEventQueue = nativeInitBaseEventQueue(manager.mNativeInstance, new WeakReference<>(this), looper.getQueue(), packageName, mode, manager.mContext.getOpPackageName()); mCloseGuard.open("dispose"); @@ -668,17 +670,17 @@ public class SystemSensorManager extends SensorManager { addSensorEvent(sensor); if (enableSensor(sensor, delayUs, maxBatchReportLatencyUs) != 0) { // Try continuous mode if batching fails. - if (maxBatchReportLatencyUs == 0 || - maxBatchReportLatencyUs > 0 && enableSensor(sensor, delayUs, 0) != 0) { - removeSensor(sensor, false); - return false; + if (maxBatchReportLatencyUs == 0 + || maxBatchReportLatencyUs > 0 && enableSensor(sensor, delayUs, 0) != 0) { + removeSensor(sensor, false); + return false; } } return true; } public boolean removeAllSensors() { - for (int i=0 ; i<mActiveSensors.size(); i++) { + for (int i = 0; i < mActiveSensors.size(); i++) { if (mActiveSensors.valueAt(i) == true) { int handle = mActiveSensors.keyAt(i); Sensor sensor = mManager.mHandleToSensor.get(handle); @@ -706,8 +708,8 @@ public class SystemSensorManager extends SensorManager { } public int flush() { - if (nSensorEventQueue == 0) throw new NullPointerException(); - return nativeFlushSensor(nSensorEventQueue); + if (mNativeSensorEventQueue == 0) throw new NullPointerException(); + return nativeFlushSensor(mNativeSensorEventQueue); } public boolean hasSensors() { @@ -731,29 +733,30 @@ public class SystemSensorManager extends SensorManager { } mCloseGuard.close(); } - if (nSensorEventQueue != 0) { - nativeDestroySensorEventQueue(nSensorEventQueue); - nSensorEventQueue = 0; + if (mNativeSensorEventQueue != 0) { + nativeDestroySensorEventQueue(mNativeSensorEventQueue); + mNativeSensorEventQueue = 0; } } private int enableSensor( Sensor sensor, int rateUs, int maxBatchReportLatencyUs) { - if (nSensorEventQueue == 0) throw new NullPointerException(); + if (mNativeSensorEventQueue == 0) throw new NullPointerException(); if (sensor == null) throw new NullPointerException(); - return nativeEnableSensor(nSensorEventQueue, sensor.getHandle(), rateUs, + return nativeEnableSensor(mNativeSensorEventQueue, sensor.getHandle(), rateUs, maxBatchReportLatencyUs); } protected int injectSensorDataBase(int handle, float[] values, int accuracy, long timestamp) { - return nativeInjectSensorData(nSensorEventQueue, handle, values, accuracy, timestamp); + return nativeInjectSensorData( + mNativeSensorEventQueue, handle, values, accuracy, timestamp); } private int disableSensor(Sensor sensor) { - if (nSensorEventQueue == 0) throw new NullPointerException(); + if (mNativeSensorEventQueue == 0) throw new NullPointerException(); if (sensor == null) throw new NullPointerException(); - return nativeDisableSensor(nSensorEventQueue, sensor.getHandle()); + return nativeDisableSensor(mNativeSensorEventQueue, sensor.getHandle()); } protected abstract void dispatchSensorEvent(int handle, float[] values, int accuracy, long timestamp); @@ -840,7 +843,7 @@ public class SystemSensorManager extends SensorManager { // sensor disconnected return; } - ((SensorEventListener2)mListener).onFlushCompleted(sensor); + ((SensorEventListener2) mListener).onFlushCompleted(sensor); } return; } @@ -858,7 +861,7 @@ public class SystemSensorManager extends SensorManager { } SensorAdditionalInfo info = new SensorAdditionalInfo(sensor, type, serial, intValues, floatValues); - ((SensorEventCallback)mListener).onSensorAdditionalInfo(info); + ((SensorEventCallback) mListener).onSensorAdditionalInfo(info); } } } @@ -930,8 +933,8 @@ public class SystemSensorManager extends SensorManager { super(looper, manager, OPERATING_MODE_DATA_INJECTION, packageName); } - int injectSensorData(int handle, float[] values,int accuracy, long timestamp) { - return injectSensorDataBase(handle, values, accuracy, timestamp); + int injectSensorData(int handle, float[] values, int accuracy, long timestamp) { + return injectSensorDataBase(handle, values, accuracy, timestamp); } @SuppressWarnings("unused") @@ -959,6 +962,7 @@ public class SystemSensorManager extends SensorManager { int handle = -1; if (parameter.sensor != null) handle = parameter.sensor.getHandle(); return nativeSetOperationParameter( - mNativeInstance, handle, parameter.type, parameter.floatValues, parameter.intValues) == 0; + mNativeInstance, handle, + parameter.type, parameter.floatValues, parameter.intValues) == 0; } } diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java index 744ee8ed0e74..d7ecc81ffdba 100644 --- a/core/java/android/net/ConnectivityManager.java +++ b/core/java/android/net/ConnectivityManager.java @@ -2078,16 +2078,30 @@ public class ConnectivityManager { * {@code ro.tether.denied} system property, Settings.TETHER_SUPPORTED or * due to device configuration. * + * <p>If this app does not have permission to use this API, it will always + * return false rather than throw an exception.</p> + * + * <p>If the device has a hotspot provisioning app, the caller is required to hold the + * {@link android.Manifest.permission.TETHER_PRIVILEGED} permission.</p> + * + * <p>Otherwise, this method requires the caller to hold the ability to modify system + * settings as determined by {@link android.provider.Settings.System#canWrite}.</p> + * * @return a boolean - {@code true} indicating Tethering is supported. * * {@hide} */ @SystemApi - @RequiresPermission(android.Manifest.permission.TETHER_PRIVILEGED) + @RequiresPermission(anyOf = {android.Manifest.permission.TETHER_PRIVILEGED, + android.Manifest.permission.WRITE_SETTINGS}) public boolean isTetheringSupported() { + String pkgName = mContext.getOpPackageName(); try { - String pkgName = mContext.getOpPackageName(); return mService.isTetheringSupported(pkgName); + } catch (SecurityException e) { + // This API is not available to this caller, but for backward-compatibility + // this will just return false instead of throwing. + return false; } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } diff --git a/core/java/android/net/IpSecAlgorithm.java b/core/java/android/net/IpSecAlgorithm.java index 5ae340036147..ead406c20c93 100644 --- a/core/java/android/net/IpSecAlgorithm.java +++ b/core/java/android/net/IpSecAlgorithm.java @@ -19,15 +19,15 @@ import android.annotation.StringDef; import android.os.Build; import android.os.Parcel; import android.os.Parcelable; + import com.android.internal.util.HexDump; + import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; /** * IpSecAlgorithm specifies a single algorithm that can be applied to an IpSec Transform. Refer to * RFC 4301. - * - * @hide */ public final class IpSecAlgorithm implements Parcelable { diff --git a/core/java/android/net/IpSecManager.java b/core/java/android/net/IpSecManager.java index 2f791e151b08..d7908c8ceef8 100644 --- a/core/java/android/net/IpSecManager.java +++ b/core/java/android/net/IpSecManager.java @@ -25,7 +25,9 @@ import android.os.ParcelFileDescriptor; import android.os.RemoteException; import android.util.AndroidException; import android.util.Log; + import dalvik.system.CloseGuard; + import java.io.FileDescriptor; import java.io.IOException; import java.net.DatagramSocket; @@ -36,7 +38,9 @@ import java.net.Socket; * This class contains methods for managing IPsec sessions, which will perform kernel-space * encryption and decryption of socket or Network traffic. * - * @hide + * <p>An IpSecManager may be obtained by calling {@link + * android.content.Context#getSystemService(String) Context#getSystemService(String)} with {@link + * android.content.Context#IPSEC_SERVICE Context#IPSEC_SERVICE} */ @SystemService(Context.IPSEC_SERVICE) public final class IpSecManager { diff --git a/core/java/android/net/IpSecTransform.java b/core/java/android/net/IpSecTransform.java index cfbac58bbd1f..62fd65b9c176 100644 --- a/core/java/android/net/IpSecTransform.java +++ b/core/java/android/net/IpSecTransform.java @@ -26,9 +26,12 @@ import android.os.IBinder; import android.os.RemoteException; import android.os.ServiceManager; import android.util.Log; + import com.android.internal.annotations.VisibleForTesting; import com.android.internal.util.Preconditions; + import dalvik.system.CloseGuard; + import java.io.IOException; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; @@ -43,8 +46,6 @@ import java.net.InetAddress; * * <p>An IpSecTransform may either represent a tunnel mode transform that operates on a wide array * of traffic or may represent a transport mode transform operating on a Socket or Sockets. - * - * @hide */ public final class IpSecTransform implements AutoCloseable { private static final String TAG = "IpSecTransform"; diff --git a/core/java/android/os/Binder.java b/core/java/android/os/Binder.java index 0df6361d4224..e9e695bbdf10 100644 --- a/core/java/android/os/Binder.java +++ b/core/java/android/os/Binder.java @@ -23,7 +23,6 @@ import android.util.Log; import android.util.Slog; import com.android.internal.util.FastPrintWriter; -import com.android.internal.util.FunctionalUtils; import com.android.internal.util.FunctionalUtils.ThrowingRunnable; import com.android.internal.util.FunctionalUtils.ThrowingSupplier; @@ -202,7 +201,7 @@ public class Binder implements IBinder { * then its own pid is returned. */ public static final native int getCallingPid(); - + /** * Return the Linux uid assigned to the process that sent you the * current transaction that is being processed. This uid can be used with @@ -335,7 +334,7 @@ public class Binder implements IBinder { * it needs to. */ public static final native void flushPendingCommands(); - + /** * Add the calling thread to the IPC thread pool. This function does * not return until the current process is exiting. @@ -372,7 +371,7 @@ public class Binder implements IBinder { } } } - + /** * Convenience method for associating a specific interface with the Binder. * After calling, queryLocalInterface() will be implemented for you @@ -383,7 +382,7 @@ public class Binder implements IBinder { mOwner = owner; mDescriptor = descriptor; } - + /** * Default implementation returns an empty interface name. */ @@ -408,7 +407,7 @@ public class Binder implements IBinder { public boolean isBinderAlive() { return true; } - + /** * Use information supplied to attachInterface() to return the * associated IInterface if it matches the requested @@ -630,7 +629,7 @@ public class Binder implements IBinder { } return r; } - + /** * Local implementation is a no-op. */ @@ -643,7 +642,7 @@ public class Binder implements IBinder { public boolean unlinkToDeath(@NonNull DeathRecipient recipient, int flags) { return true; } - + protected void finalize() throws Throwable { try { destroyBinder(); @@ -730,7 +729,15 @@ public class Binder implements IBinder { } } +/** + * Java proxy for a native IBinder object. + * Allocated and constructed by the native javaObjectforIBinder function. Never allocated + * directly from Java code. + */ final class BinderProxy implements IBinder { + // See android_util_Binder.cpp for the native half of this. + // TODO: Consider using NativeAllocationRegistry instead of finalization. + // Assume the process-wide default value when created volatile boolean mWarnOnBlocking = Binder.sWarnOnBlocking; @@ -789,7 +796,7 @@ final class BinderProxy implements IBinder { reply.recycle(); } } - + public void dumpAsync(FileDescriptor fd, String[] args) throws RemoteException { Parcel data = Parcel.obtain(); Parcel reply = Parcel.obtain(); @@ -826,7 +833,7 @@ final class BinderProxy implements IBinder { BinderProxy() { mSelf = new WeakReference(this); } - + @Override protected void finalize() throws Throwable { try { @@ -835,9 +842,9 @@ final class BinderProxy implements IBinder { super.finalize(); } } - + private native final void destroy(); - + private static final void sendDeathNotice(DeathRecipient recipient) { if (false) Log.v("JavaBinder", "sendDeathNotice to " + recipient); try { @@ -848,8 +855,20 @@ final class BinderProxy implements IBinder { exc); } } - + + // This WeakReference to "this" is used only by native code to "attach" to the + // native IBinder object. + // Using WeakGlobalRefs instead currently appears unsafe, in that they can yield a + // non-null value after the BinderProxy is enqueued for finalization. + // Used only once immediately after construction. + // TODO: Consider making the extra native-to-java call to compute this on the fly. final private WeakReference mSelf; + + // Native pointer to the wrapped native IBinder object. Counted as strong reference. private long mObject; + + // Native pointer to native DeathRecipientList. Counted as strong reference. + // Basically owned by the JavaProxy object. Reference counted only because DeathRecipients + // hold a weak reference that can be temporarily promoted. private long mOrgue; } diff --git a/core/java/android/os/INetworkManagementService.aidl b/core/java/android/os/INetworkManagementService.aidl index 05627160cc3a..a474b47c4297 100644 --- a/core/java/android/os/INetworkManagementService.aidl +++ b/core/java/android/os/INetworkManagementService.aidl @@ -104,11 +104,6 @@ interface INetworkManagementService void setIPv6AddrGenMode(String iface, int mode); /** - * Enables or enables IPv6 ND offload. - */ - void setInterfaceIpv6NdOffload(String iface, boolean enable); - - /** * Add the specified route to the interface. */ void addRoute(int netId, in RouteInfo route); diff --git a/core/java/android/os/IServiceManager.java b/core/java/android/os/IServiceManager.java index 7b11c283d1e1..87c65ecc540b 100644 --- a/core/java/android/os/IServiceManager.java +++ b/core/java/android/os/IServiceManager.java @@ -18,12 +18,12 @@ package android.os; /** * Basic interface for finding and publishing system services. - * + * * An implementation of this interface is usually published as the * global context object, which can be retrieved via * BinderNative.getContextObject(). An easy way to retrieve this * is with the static method BnServiceManager.getDefault(). - * + * * @hide */ public interface IServiceManager extends IInterface @@ -33,33 +33,33 @@ public interface IServiceManager extends IInterface * service manager. Blocks for a few seconds waiting for it to be * published if it does not already exist. */ - public IBinder getService(String name) throws RemoteException; - + IBinder getService(String name) throws RemoteException; + /** * Retrieve an existing service called @a name from the * service manager. Non-blocking. */ - public IBinder checkService(String name) throws RemoteException; + IBinder checkService(String name) throws RemoteException; /** * Place a new @a service called @a name into the service * manager. */ - public void addService(String name, IBinder service, boolean allowIsolated) + void addService(String name, IBinder service, boolean allowIsolated, int dumpPriority) throws RemoteException; /** * Return a list of all currently running services. */ - public String[] listServices() throws RemoteException; + String[] listServices(int dumpPriority) throws RemoteException; /** * Assign a permission controller to the service manager. After set, this * interface is checked before any services are added. */ - public void setPermissionController(IPermissionController controller) + void setPermissionController(IPermissionController controller) throws RemoteException; - + static final String descriptor = "android.os.IServiceManager"; int GET_SERVICE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION; @@ -68,4 +68,13 @@ public interface IServiceManager extends IInterface int LIST_SERVICES_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+3; int CHECK_SERVICES_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+4; int SET_PERMISSION_CONTROLLER_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+5; + + /* + * Must update values in IServiceManager.h + */ + int DUMP_PRIORITY_CRITICAL = 1 << 0; + int DUMP_PRIORITY_HIGH = 1 << 1; + int DUMP_PRIORITY_NORMAL = 1 << 2; + int DUMP_PRIORITY_ALL = DUMP_PRIORITY_CRITICAL | DUMP_PRIORITY_HIGH + | DUMP_PRIORITY_NORMAL; } diff --git a/core/java/android/os/PowerManager.java b/core/java/android/os/PowerManager.java index 960c9f5cf22c..3726f47093b9 100644 --- a/core/java/android/os/PowerManager.java +++ b/core/java/android/os/PowerManager.java @@ -443,6 +443,20 @@ public final class PowerManager { public static final String SHUTDOWN_USER_REQUESTED = "userrequested"; /** + * The value to pass as the 'reason' argument to android_reboot() when battery temperature + * is too high. + * @hide + */ + public static final String SHUTDOWN_BATTERY_THERMAL_STATE = "thermal,battery"; + + /** + * The value to pass as the 'reason' argument to android_reboot() when device is running + * critically low on battery. + * @hide + */ + public static final String SHUTDOWN_LOW_BATTERY = "battery"; + + /** * @hide */ @Retention(RetentionPolicy.SOURCE) @@ -451,7 +465,9 @@ public final class PowerManager { SHUTDOWN_REASON_SHUTDOWN, SHUTDOWN_REASON_REBOOT, SHUTDOWN_REASON_USER_REQUESTED, - SHUTDOWN_REASON_THERMAL_SHUTDOWN + SHUTDOWN_REASON_THERMAL_SHUTDOWN, + SHUTDOWN_REASON_LOW_BATTERY, + SHUTDOWN_REASON_BATTERY_THERMAL }) public @interface ShutdownReason {} @@ -485,6 +501,18 @@ public final class PowerManager { */ public static final int SHUTDOWN_REASON_THERMAL_SHUTDOWN = 4; + /** + * constant for shutdown reason being low battery. + * @hide + */ + public static final int SHUTDOWN_REASON_LOW_BATTERY = 5; + + /** + * constant for shutdown reason being critical battery thermal state. + * @hide + */ + public static final int SHUTDOWN_REASON_BATTERY_THERMAL = 6; + final Context mContext; final IPowerManager mService; final Handler mHandler; diff --git a/core/java/android/os/ServiceManager.java b/core/java/android/os/ServiceManager.java index e11494d5cd41..f41848fad74a 100644 --- a/core/java/android/os/ServiceManager.java +++ b/core/java/android/os/ServiceManager.java @@ -26,7 +26,6 @@ import java.util.Map; /** @hide */ public final class ServiceManager { private static final String TAG = "ServiceManager"; - private static IServiceManager sServiceManager; private static HashMap<String, IBinder> sCache = new HashMap<String, IBinder>(); @@ -43,7 +42,7 @@ public final class ServiceManager { /** * Returns a reference to a service with the given name. - * + * * @param name the name of the service to get * @return a reference to the service, or <code>null</code> if the service doesn't exist */ @@ -79,35 +78,46 @@ public final class ServiceManager { /** * Place a new @a service called @a name into the service * manager. - * + * * @param name the name of the new service * @param service the service object */ public static void addService(String name, IBinder service) { - try { - getIServiceManager().addService(name, service, false); - } catch (RemoteException e) { - Log.e(TAG, "error in addService", e); - } + addService(name, service, false, IServiceManager.DUMP_PRIORITY_NORMAL); } /** * Place a new @a service called @a name into the service * manager. - * + * * @param name the name of the new service * @param service the service object * @param allowIsolated set to true to allow isolated sandboxed processes * to access this service */ public static void addService(String name, IBinder service, boolean allowIsolated) { + addService(name, service, allowIsolated, IServiceManager.DUMP_PRIORITY_NORMAL); + } + + /** + * Place a new @a service called @a name into the service + * manager. + * + * @param name the name of the new service + * @param service the service object + * @param allowIsolated set to true to allow isolated sandboxed processes + * @param dumpPriority supported dump priority levels as a bitmask + * to access this service + */ + public static void addService(String name, IBinder service, boolean allowIsolated, + int dumpPriority) { try { - getIServiceManager().addService(name, service, allowIsolated); + getIServiceManager().addService(name, service, allowIsolated, dumpPriority); } catch (RemoteException e) { Log.e(TAG, "error in addService", e); } } - + /** * Retrieve an existing service called @a name from the * service manager. Non-blocking. @@ -133,7 +143,7 @@ public final class ServiceManager { */ public static String[] listServices() { try { - return getIServiceManager().listServices(); + return getIServiceManager().listServices(IServiceManager.DUMP_PRIORITY_ALL); } catch (RemoteException e) { Log.e(TAG, "error in listServices", e); return null; @@ -144,7 +154,7 @@ public final class ServiceManager { * This is only intended to be called when the process is first being brought * up and bound by the activity manager. There is only one thread in the process * at that time, so no locking is done. - * + * * @param cache the cache of service references * @hide */ diff --git a/core/java/android/os/ServiceManagerNative.java b/core/java/android/os/ServiceManagerNative.java index be244264875e..589b8c492ab3 100644 --- a/core/java/android/os/ServiceManagerNative.java +++ b/core/java/android/os/ServiceManagerNative.java @@ -40,63 +40,65 @@ public abstract class ServiceManagerNative extends Binder implements IServiceMan if (in != null) { return in; } - + return new ServiceManagerProxy(obj); } - + public ServiceManagerNative() { attachInterface(this, descriptor); } - + public boolean onTransact(int code, Parcel data, Parcel reply, int flags) { try { switch (code) { - case IServiceManager.GET_SERVICE_TRANSACTION: { - data.enforceInterface(IServiceManager.descriptor); - String name = data.readString(); - IBinder service = getService(name); - reply.writeStrongBinder(service); - return true; - } - - case IServiceManager.CHECK_SERVICE_TRANSACTION: { - data.enforceInterface(IServiceManager.descriptor); - String name = data.readString(); - IBinder service = checkService(name); - reply.writeStrongBinder(service); - return true; - } - - case IServiceManager.ADD_SERVICE_TRANSACTION: { - data.enforceInterface(IServiceManager.descriptor); - String name = data.readString(); - IBinder service = data.readStrongBinder(); - boolean allowIsolated = data.readInt() != 0; - addService(name, service, allowIsolated); - return true; - } - - case IServiceManager.LIST_SERVICES_TRANSACTION: { - data.enforceInterface(IServiceManager.descriptor); - String[] list = listServices(); - reply.writeStringArray(list); - return true; - } - - case IServiceManager.SET_PERMISSION_CONTROLLER_TRANSACTION: { - data.enforceInterface(IServiceManager.descriptor); - IPermissionController controller - = IPermissionController.Stub.asInterface( - data.readStrongBinder()); - setPermissionController(controller); - return true; - } + case IServiceManager.GET_SERVICE_TRANSACTION: { + data.enforceInterface(IServiceManager.descriptor); + String name = data.readString(); + IBinder service = getService(name); + reply.writeStrongBinder(service); + return true; + } + + case IServiceManager.CHECK_SERVICE_TRANSACTION: { + data.enforceInterface(IServiceManager.descriptor); + String name = data.readString(); + IBinder service = checkService(name); + reply.writeStrongBinder(service); + return true; + } + + case IServiceManager.ADD_SERVICE_TRANSACTION: { + data.enforceInterface(IServiceManager.descriptor); + String name = data.readString(); + IBinder service = data.readStrongBinder(); + boolean allowIsolated = data.readInt() != 0; + int dumpPriority = data.readInt(); + addService(name, service, allowIsolated, dumpPriority); + return true; + } + + case IServiceManager.LIST_SERVICES_TRANSACTION: { + data.enforceInterface(IServiceManager.descriptor); + int dumpPriority = data.readInt(); + String[] list = listServices(dumpPriority); + reply.writeStringArray(list); + return true; + } + + case IServiceManager.SET_PERMISSION_CONTROLLER_TRANSACTION: { + data.enforceInterface(IServiceManager.descriptor); + IPermissionController controller = + IPermissionController.Stub.asInterface( + data.readStrongBinder()); + setPermissionController(controller); + return true; + } } } catch (RemoteException e) { } - + return false; } @@ -110,11 +112,11 @@ class ServiceManagerProxy implements IServiceManager { public ServiceManagerProxy(IBinder remote) { mRemote = remote; } - + public IBinder asBinder() { return mRemote; } - + public IBinder getService(String name) throws RemoteException { Parcel data = Parcel.obtain(); Parcel reply = Parcel.obtain(); @@ -139,7 +141,7 @@ class ServiceManagerProxy implements IServiceManager { return binder; } - public void addService(String name, IBinder service, boolean allowIsolated) + public void addService(String name, IBinder service, boolean allowIsolated, int dumpPriority) throws RemoteException { Parcel data = Parcel.obtain(); Parcel reply = Parcel.obtain(); @@ -147,12 +149,13 @@ class ServiceManagerProxy implements IServiceManager { data.writeString(name); data.writeStrongBinder(service); data.writeInt(allowIsolated ? 1 : 0); + data.writeInt(dumpPriority); mRemote.transact(ADD_SERVICE_TRANSACTION, data, reply, 0); reply.recycle(); data.recycle(); } - - public String[] listServices() throws RemoteException { + + public String[] listServices(int dumpPriority) throws RemoteException { ArrayList<String> services = new ArrayList<String>(); int n = 0; while (true) { @@ -160,6 +163,7 @@ class ServiceManagerProxy implements IServiceManager { Parcel reply = Parcel.obtain(); data.writeInterfaceToken(IServiceManager.descriptor); data.writeInt(n); + data.writeInt(dumpPriority); n++; try { boolean res = mRemote.transact(LIST_SERVICES_TRANSACTION, data, reply, 0); diff --git a/core/java/android/service/autofill/AutofillService.java b/core/java/android/service/autofill/AutofillService.java index 3e08dcf2b919..045c83304097 100644 --- a/core/java/android/service/autofill/AutofillService.java +++ b/core/java/android/service/autofill/AutofillService.java @@ -305,7 +305,7 @@ import com.android.internal.os.SomeArgs; * <li>Use the {@link android.app.assist.AssistStructure.ViewNode#getWebDomain()} to get the * source of the document. * <li>Get the canonical domain using the - * <a href="https://publicsuffix.org/>Public Suffix List</a> (see example below). + * <a href="https://publicsuffix.org/">Public Suffix List</a> (see example below). * <li>Use <a href="https://developers.google.com/digital-asset-links/">Digital Asset Links</a> * to obtain the package name and certificate fingerprint of the package corresponding to * the canonical domain. diff --git a/core/java/android/text/Layout.java b/core/java/android/text/Layout.java index 25f791bc8cc6..c3b2a16cc986 100644 --- a/core/java/android/text/Layout.java +++ b/core/java/android/text/Layout.java @@ -1915,8 +1915,7 @@ public abstract class Layout { return margin; } - /* package */ - static float measurePara(TextPaint paint, CharSequence text, int start, int end, + private static float measurePara(TextPaint paint, CharSequence text, int start, int end, TextDirectionHeuristic textDir) { MeasuredText mt = MeasuredText.obtain(); TextLine tl = TextLine.obtain(); diff --git a/core/java/android/text/StaticLayout.java b/core/java/android/text/StaticLayout.java index 3303b54e462b..8e0ad6352081 100644 --- a/core/java/android/text/StaticLayout.java +++ b/core/java/android/text/StaticLayout.java @@ -101,6 +101,7 @@ public class StaticLayout extends Layout { b.mBreakStrategy = Layout.BREAK_STRATEGY_SIMPLE; b.mHyphenationFrequency = Layout.HYPHENATION_FREQUENCY_NONE; b.mJustificationMode = Layout.JUSTIFICATION_MODE_NONE; + b.mLocales = null; b.mMeasuredText = MeasuredText.obtain(); return b; @@ -117,6 +118,9 @@ public class StaticLayout extends Layout { b.mMeasuredText = null; b.mLeftIndents = null; b.mRightIndents = null; + b.mLocales = null; + b.mLeftPaddings = null; + b.mRightPaddings = null; nFinishBuilder(b.mNativePtr); sPool.release(b); } @@ -128,6 +132,8 @@ public class StaticLayout extends Layout { mPaint = null; mLeftIndents = null; mRightIndents = null; + mLeftPaddings = null; + mRightPaddings = null; mMeasuredText.finish(); } @@ -356,6 +362,28 @@ public class StaticLayout extends Layout { } /** + * Set available paddings to draw overhanging text on. Arguments are arrays holding the + * amount of padding available, one per line, measured in pixels. For lines past the last + * element in the array, the last element repeats. + * + * The individual padding amounts should be non-negative. The result of passing negative + * paddings is undefined. + * + * @param leftPaddings array of amounts of available padding for left margin, in pixels + * @param rightPaddings array of amounts of available padding for right margin, in pixels + * @return this builder, useful for chaining + * + * @hide + */ + @NonNull + public Builder setAvailablePaddings(@Nullable int[] leftPaddings, + @Nullable int[] rightPaddings) { + mLeftPaddings = leftPaddings; + mRightPaddings = rightPaddings; + return this; + } + + /** * Set paragraph justification mode. The default value is * {@link Layout#JUSTIFICATION_MODE_NONE}. If the last line is too short for justification, * the last line will be displayed with the alignment set by {@link #setAlignment}. @@ -401,7 +429,6 @@ public class StaticLayout extends Layout { * future). * * Then, for each run within the paragraph: - * - setLocales (this must be done at least for the first run, optional afterwards) * - one of the following, depending on the type of run: * + addStyleRun (a text run, to be measured in native code) * + addMeasuredRun (a run already measured in Java, passed into native code) @@ -413,16 +440,21 @@ public class StaticLayout extends Layout { * After all paragraphs, call finish() to release expensive buffers. */ - private void setLocales(LocaleList locales) { + /* package */ float addStyleRun(TextPaint paint, int start, int end, boolean isRtl) { + final LocaleList locales = paint.getTextLocales(); + final String languageTags; + long[] hyphenators; if (!locales.equals(mLocales)) { - nSetLocales(mNativePtr, locales.toLanguageTags(), getHyphenators(locales)); - mLocales = locales; + languageTags = locales.toLanguageTags(); + hyphenators = getHyphenators(locales); + } else { + // passing null means keep current locale. + // TODO: move locale change detection to native. + languageTags = null; + hyphenators = null; } - } - - /* package */ float addStyleRun(TextPaint paint, int start, int end, boolean isRtl) { - setLocales(paint.getTextLocales()); - return nAddStyleRun(mNativePtr, paint.getNativeInstance(), start, end, isRtl); + return nAddStyleRun(mNativePtr, paint.getNativeInstance(), start, end, isRtl, + languageTags, hyphenators); } /* package */ void addMeasuredRun(int start, int end, float[] widths) { @@ -478,6 +510,8 @@ public class StaticLayout extends Layout { private int mHyphenationFrequency; @Nullable private int[] mLeftIndents; @Nullable private int[] mRightIndents; + @Nullable private int[] mLeftPaddings; + @Nullable private int[] mRightPaddings; private int mJustificationMode; private boolean mAddLastLineLineSpacing; @@ -638,6 +672,8 @@ public class StaticLayout extends Layout { mLeftIndents = b.mLeftIndents; mRightIndents = b.mRightIndents; + mLeftPaddings = b.mLeftPaddings; + mRightPaddings = b.mRightPaddings; setJustificationMode(b.mJustificationMode); generate(b, b.mIncludePad, b.mIncludePad); @@ -662,7 +698,6 @@ public class StaticLayout extends Layout { // store fontMetrics per span range // must be a multiple of 4 (and > 0) (store top, bottom, ascent, and descent per range) int[] fmCache = new int[4 * 4]; - b.setLocales(paint.getTextLocales()); mLineCount = 0; mEllipsized = false; @@ -780,7 +815,10 @@ public class StaticLayout extends Layout { firstWidth, firstWidthLineCount, restWidth, variableTabStops, TAB_INCREMENT, b.mBreakStrategy, b.mHyphenationFrequency, // TODO: Support more justification mode, e.g. letter spacing, stretching. - b.mJustificationMode != Layout.JUSTIFICATION_MODE_NONE, indents, mLineCount); + b.mJustificationMode != Layout.JUSTIFICATION_MODE_NONE, + // TODO: indents and paddings don't need to get passed to native code for every + // paragraph. Pass them to native code just once. + indents, mLeftPaddings, mRightPaddings, mLineCount); // measurement has to be done before performing line breaking // but we don't want to recompute fontmetrics or span ranges the @@ -1494,20 +1532,20 @@ public class StaticLayout extends Layout { /* package */ static native long nLoadHyphenator(ByteBuffer buf, int offset, int minPrefix, int minSuffix); - private static native void nSetLocales(long nativePtr, String locales, - long[] nativeHyphenators); - // Set up paragraph text and settings; done as one big method to minimize jni crossings private static native void nSetupParagraph( - @NonNull long nativePtr, @NonNull char[] text, @IntRange(from = 0) int length, + /* non zero */ long nativePtr, @NonNull char[] text, @IntRange(from = 0) int length, @FloatRange(from = 0.0f) float firstWidth, @IntRange(from = 0) int firstWidthLineCount, @FloatRange(from = 0.0f) float restWidth, @Nullable int[] variableTabStops, int defaultTabStop, @BreakStrategy int breakStrategy, @HyphenationFrequency int hyphenationFrequency, boolean isJustified, - @Nullable int[] indents, @IntRange(from = 0) int indentsOffset); + @Nullable int[] indents, @Nullable int[] leftPaddings, @Nullable int[] rightPaddings, + @IntRange(from = 0) int indentsOffset); - private static native float nAddStyleRun(long nativePtr, long nativePaint, int start, int end, - boolean isRtl); + private static native float nAddStyleRun( + /* non zero */ long nativePtr, /* non zero */ long nativePaint, + @IntRange(from = 0) int start, @IntRange(from = 0) int end, boolean isRtl, + @Nullable String languageTags, @Nullable long[] hyphenators); private static native void nAddMeasuredRun(long nativePtr, int start, int end, float[] widths); @@ -1590,4 +1628,6 @@ public class StaticLayout extends Layout { @Nullable private int[] mLeftIndents; @Nullable private int[] mRightIndents; + @Nullable private int[] mLeftPaddings; + @Nullable private int[] mRightPaddings; } diff --git a/core/java/android/transition/TransitionUtils.java b/core/java/android/transition/TransitionUtils.java index 4951237e5cc9..3af7e5d3eaa4 100644 --- a/core/java/android/transition/TransitionUtils.java +++ b/core/java/android/transition/TransitionUtils.java @@ -159,11 +159,14 @@ public class TransitionUtils { * @return A bitmap of the given view or null if bounds has no width or height. */ public static Bitmap createViewBitmap(View view, Matrix matrix, RectF bounds) { + if (!view.isAttachedToWindow()) { + return null; + } Bitmap bitmap = null; int bitmapWidth = Math.round(bounds.width()); int bitmapHeight = Math.round(bounds.height()); if (bitmapWidth > 0 && bitmapHeight > 0) { - float scale = Math.min(1f, ((float)MAX_IMAGE_SIZE) / (bitmapWidth * bitmapHeight)); + float scale = Math.min(1f, ((float) MAX_IMAGE_SIZE) / (bitmapWidth * bitmapHeight)); bitmapWidth *= scale; bitmapHeight *= scale; matrix.postTranslate(-bounds.left, -bounds.top); diff --git a/core/java/android/view/Gravity.java b/core/java/android/view/Gravity.java index 324a1ae3e606..232ff2551433 100644 --- a/core/java/android/view/Gravity.java +++ b/core/java/android/view/Gravity.java @@ -440,4 +440,57 @@ public class Gravity } return result; } + + /** + * @hide + */ + public static String toString(int gravity) { + final StringBuilder result = new StringBuilder(); + if ((gravity & FILL) != 0) { + result.append("FILL").append(' '); + } else { + if ((gravity & FILL_VERTICAL) != 0) { + result.append("FILL_VERTICAL").append(' '); + } else { + if ((gravity & TOP) != 0) { + result.append("TOP").append(' '); + } + if ((gravity & BOTTOM) != 0) { + result.append("BOTTOM").append(' '); + } + } + if ((gravity & FILL_HORIZONTAL) != 0) { + result.append("FILL_HORIZONTAL").append(' '); + } else { + if ((gravity & START) != 0) { + result.append("START").append(' '); + } else if ((gravity & LEFT) != 0) { + result.append("LEFT").append(' '); + } + if ((gravity & END) != 0) { + result.append("END").append(' '); + } else if ((gravity & RIGHT) != 0) { + result.append("RIGHT").append(' '); + } + } + } + if ((gravity & CENTER) != 0) { + result.append("CENTER").append(' '); + } else { + if ((gravity & CENTER_VERTICAL) != 0) { + result.append("CENTER_VERTICAL").append(' '); + } + if ((gravity & CENTER_HORIZONTAL) != 0) { + result.append("CENTER_HORIZONTAL").append(' '); + } + } + if ((gravity & DISPLAY_CLIP_VERTICAL) != 0) { + result.append("DISPLAY_CLIP_VERTICAL").append(' '); + } + if ((gravity & DISPLAY_CLIP_VERTICAL) != 0) { + result.append("DISPLAY_CLIP_VERTICAL").append(' '); + } + result.deleteCharAt(result.length() - 1); + return result.toString(); + } } diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java index 1556297a4cec..3f710a80f1c2 100644 --- a/core/java/android/view/View.java +++ b/core/java/android/view/View.java @@ -3742,15 +3742,90 @@ public class View implements Drawable.Callback, KeyEvent.Callback, * @hide */ @ViewDebug.ExportedProperty(flagMapping = { - @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_LOW_PROFILE, - equals = SYSTEM_UI_FLAG_LOW_PROFILE, - name = "SYSTEM_UI_FLAG_LOW_PROFILE", outputIf = true), - @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_HIDE_NAVIGATION, - equals = SYSTEM_UI_FLAG_HIDE_NAVIGATION, - name = "SYSTEM_UI_FLAG_HIDE_NAVIGATION", outputIf = true), - @ViewDebug.FlagToString(mask = PUBLIC_STATUS_BAR_VISIBILITY_MASK, - equals = SYSTEM_UI_FLAG_VISIBLE, - name = "SYSTEM_UI_FLAG_VISIBLE", outputIf = true) + @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_LOW_PROFILE, + equals = SYSTEM_UI_FLAG_LOW_PROFILE, + name = "LOW_PROFILE"), + @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_HIDE_NAVIGATION, + equals = SYSTEM_UI_FLAG_HIDE_NAVIGATION, + name = "HIDE_NAVIGATION"), + @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_FULLSCREEN, + equals = SYSTEM_UI_FLAG_FULLSCREEN, + name = "FULLSCREEN"), + @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_LAYOUT_STABLE, + equals = SYSTEM_UI_FLAG_LAYOUT_STABLE, + name = "LAYOUT_STABLE"), + @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION, + equals = SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION, + name = "LAYOUT_HIDE_NAVIGATION"), + @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN, + equals = SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN, + name = "LAYOUT_FULLSCREEN"), + @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_IMMERSIVE, + equals = SYSTEM_UI_FLAG_IMMERSIVE, + name = "IMMERSIVE"), + @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_IMMERSIVE_STICKY, + equals = SYSTEM_UI_FLAG_IMMERSIVE_STICKY, + name = "IMMERSIVE_STICKY"), + @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_LIGHT_STATUS_BAR, + equals = SYSTEM_UI_FLAG_LIGHT_STATUS_BAR, + name = "LIGHT_STATUS_BAR"), + @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR, + equals = SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR, + name = "LIGHT_NAVIGATION_BAR"), + @ViewDebug.FlagToString(mask = STATUS_BAR_DISABLE_EXPAND, + equals = STATUS_BAR_DISABLE_EXPAND, + name = "STATUS_BAR_DISABLE_EXPAND"), + @ViewDebug.FlagToString(mask = STATUS_BAR_DISABLE_NOTIFICATION_ICONS, + equals = STATUS_BAR_DISABLE_NOTIFICATION_ICONS, + name = "STATUS_BAR_DISABLE_NOTIFICATION_ICONS"), + @ViewDebug.FlagToString(mask = STATUS_BAR_DISABLE_NOTIFICATION_ALERTS, + equals = STATUS_BAR_DISABLE_NOTIFICATION_ALERTS, + name = "STATUS_BAR_DISABLE_NOTIFICATION_ALERTS"), + @ViewDebug.FlagToString(mask = STATUS_BAR_DISABLE_NOTIFICATION_TICKER, + equals = STATUS_BAR_DISABLE_NOTIFICATION_TICKER, + name = "STATUS_BAR_DISABLE_NOTIFICATION_TICKER"), + @ViewDebug.FlagToString(mask = STATUS_BAR_DISABLE_SYSTEM_INFO, + equals = STATUS_BAR_DISABLE_SYSTEM_INFO, + name = "STATUS_BAR_DISABLE_SYSTEM_INFO"), + @ViewDebug.FlagToString(mask = STATUS_BAR_DISABLE_HOME, + equals = STATUS_BAR_DISABLE_HOME, + name = "STATUS_BAR_DISABLE_HOME"), + @ViewDebug.FlagToString(mask = STATUS_BAR_DISABLE_BACK, + equals = STATUS_BAR_DISABLE_BACK, + name = "STATUS_BAR_DISABLE_BACK"), + @ViewDebug.FlagToString(mask = STATUS_BAR_DISABLE_CLOCK, + equals = STATUS_BAR_DISABLE_CLOCK, + name = "STATUS_BAR_DISABLE_CLOCK"), + @ViewDebug.FlagToString(mask = STATUS_BAR_DISABLE_RECENT, + equals = STATUS_BAR_DISABLE_RECENT, + name = "STATUS_BAR_DISABLE_RECENT"), + @ViewDebug.FlagToString(mask = STATUS_BAR_DISABLE_SEARCH, + equals = STATUS_BAR_DISABLE_SEARCH, + name = "STATUS_BAR_DISABLE_SEARCH"), + @ViewDebug.FlagToString(mask = STATUS_BAR_TRANSIENT, + equals = STATUS_BAR_TRANSIENT, + name = "STATUS_BAR_TRANSIENT"), + @ViewDebug.FlagToString(mask = NAVIGATION_BAR_TRANSIENT, + equals = NAVIGATION_BAR_TRANSIENT, + name = "NAVIGATION_BAR_TRANSIENT"), + @ViewDebug.FlagToString(mask = STATUS_BAR_UNHIDE, + equals = STATUS_BAR_UNHIDE, + name = "STATUS_BAR_UNHIDE"), + @ViewDebug.FlagToString(mask = NAVIGATION_BAR_UNHIDE, + equals = NAVIGATION_BAR_UNHIDE, + name = "NAVIGATION_BAR_UNHIDE"), + @ViewDebug.FlagToString(mask = STATUS_BAR_TRANSLUCENT, + equals = STATUS_BAR_TRANSLUCENT, + name = "STATUS_BAR_TRANSLUCENT"), + @ViewDebug.FlagToString(mask = NAVIGATION_BAR_TRANSLUCENT, + equals = NAVIGATION_BAR_TRANSLUCENT, + name = "NAVIGATION_BAR_TRANSLUCENT"), + @ViewDebug.FlagToString(mask = NAVIGATION_BAR_TRANSPARENT, + equals = NAVIGATION_BAR_TRANSPARENT, + name = "NAVIGATION_BAR_TRANSPARENT"), + @ViewDebug.FlagToString(mask = STATUS_BAR_TRANSPARENT, + equals = STATUS_BAR_TRANSPARENT, + name = "STATUS_BAR_TRANSPARENT") }, formatToHexString = true) int mSystemUiVisibility; diff --git a/core/java/android/view/ViewDebug.java b/core/java/android/view/ViewDebug.java index 66c05785d6a9..3427cffe93f6 100644 --- a/core/java/android/view/ViewDebug.java +++ b/core/java/android/view/ViewDebug.java @@ -1375,6 +1375,79 @@ public class ViewDebug { } } + /** + * Converts an integer from a field that is mapped with {@link IntToString} to its string + * representation. + * + * @param clazz The class the field is defined on. + * @param field The field on which the {@link ExportedProperty} is defined on. + * @param integer The value to convert. + * @return The value converted into its string representation. + * @hide + */ + public static String intToString(Class<?> clazz, String field, int integer) { + final IntToString[] mapping = getMapping(clazz, field); + if (mapping == null) { + return Integer.toString(integer); + } + final int count = mapping.length; + for (int j = 0; j < count; j++) { + final IntToString map = mapping[j]; + if (map.from() == integer) { + return map.to(); + } + } + return Integer.toString(integer); + } + + /** + * Converts a set of flags from a field that is mapped with {@link FlagToString} to its string + * representation. + * + * @param clazz The class the field is defined on. + * @param field The field on which the {@link ExportedProperty} is defined on. + * @param flags The flags to convert. + * @return The flags converted into their string representations. + * @hide + */ + public static String flagsToString(Class<?> clazz, String field, int flags) { + final FlagToString[] mapping = getFlagMapping(clazz, field); + if (mapping == null) { + return Integer.toHexString(flags); + } + final StringBuilder result = new StringBuilder(); + final int count = mapping.length; + for (int j = 0; j < count; j++) { + final FlagToString flagMapping = mapping[j]; + final boolean ifTrue = flagMapping.outputIf(); + final int maskResult = flags & flagMapping.mask(); + final boolean test = maskResult == flagMapping.equals(); + if (test && ifTrue) { + final String name = flagMapping.name(); + result.append(name).append(' '); + } + } + result.deleteCharAt(result.length() - 1); + return result.toString(); + } + + private static FlagToString[] getFlagMapping(Class<?> clazz, String field) { + try { + return clazz.getDeclaredField(field).getAnnotation(ExportedProperty.class) + .flagMapping(); + } catch (NoSuchFieldException e) { + return null; + } + } + + private static IntToString[] getMapping(Class<?> clazz, String field) { + try { + return clazz.getDeclaredField(field).getAnnotation(ExportedProperty.class).mapping(); + } catch (NoSuchFieldException e) { + return null; + } + } + private static void exportUnrolledArray(Context context, BufferedWriter out, ExportedProperty property, int[] array, String prefix, String suffix) throws IOException { diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java index 415aad54ee78..d988d664027f 100644 --- a/core/java/android/view/ViewRootImpl.java +++ b/core/java/android/view/ViewRootImpl.java @@ -7714,7 +7714,7 @@ public final class ViewRootImpl implements ViewParent, public void onAccessibilityStateChanged(boolean enabled) { if (enabled) { ensureConnection(); - if (mAttachInfo.mHasWindowFocus) { + if (mAttachInfo.mHasWindowFocus && (mView != null)) { mView.sendAccessibilityEvent(AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED); View focusedView = mView.findFocus(); if (focusedView != null && focusedView != mView) { diff --git a/core/java/android/view/WindowManager.java b/core/java/android/view/WindowManager.java index e56a82ffabd2..c29a1daf11ff 100644 --- a/core/java/android/view/WindowManager.java +++ b/core/java/android/view/WindowManager.java @@ -16,6 +16,8 @@ package android.view; +import static android.content.pm.ActivityInfo.COLOR_MODE_DEFAULT; + import android.Manifest.permission; import android.annotation.IntDef; import android.annotation.NonNull; @@ -268,93 +270,93 @@ public interface WindowManager extends ViewManager { */ @ViewDebug.ExportedProperty(mapping = { @ViewDebug.IntToString(from = TYPE_BASE_APPLICATION, - to = "TYPE_BASE_APPLICATION"), + to = "BASE_APPLICATION"), @ViewDebug.IntToString(from = TYPE_APPLICATION, - to = "TYPE_APPLICATION"), + to = "APPLICATION"), @ViewDebug.IntToString(from = TYPE_APPLICATION_STARTING, - to = "TYPE_APPLICATION_STARTING"), + to = "APPLICATION_STARTING"), @ViewDebug.IntToString(from = TYPE_DRAWN_APPLICATION, - to = "TYPE_DRAWN_APPLICATION"), + to = "DRAWN_APPLICATION"), @ViewDebug.IntToString(from = TYPE_APPLICATION_PANEL, - to = "TYPE_APPLICATION_PANEL"), + to = "APPLICATION_PANEL"), @ViewDebug.IntToString(from = TYPE_APPLICATION_MEDIA, - to = "TYPE_APPLICATION_MEDIA"), + to = "APPLICATION_MEDIA"), @ViewDebug.IntToString(from = TYPE_APPLICATION_SUB_PANEL, - to = "TYPE_APPLICATION_SUB_PANEL"), + to = "APPLICATION_SUB_PANEL"), @ViewDebug.IntToString(from = TYPE_APPLICATION_ABOVE_SUB_PANEL, - to = "TYPE_APPLICATION_ABOVE_SUB_PANEL"), + to = "APPLICATION_ABOVE_SUB_PANEL"), @ViewDebug.IntToString(from = TYPE_APPLICATION_ATTACHED_DIALOG, - to = "TYPE_APPLICATION_ATTACHED_DIALOG"), + to = "APPLICATION_ATTACHED_DIALOG"), @ViewDebug.IntToString(from = TYPE_APPLICATION_MEDIA_OVERLAY, - to = "TYPE_APPLICATION_MEDIA_OVERLAY"), + to = "APPLICATION_MEDIA_OVERLAY"), @ViewDebug.IntToString(from = TYPE_STATUS_BAR, - to = "TYPE_STATUS_BAR"), + to = "STATUS_BAR"), @ViewDebug.IntToString(from = TYPE_SEARCH_BAR, - to = "TYPE_SEARCH_BAR"), + to = "SEARCH_BAR"), @ViewDebug.IntToString(from = TYPE_PHONE, - to = "TYPE_PHONE"), + to = "PHONE"), @ViewDebug.IntToString(from = TYPE_SYSTEM_ALERT, - to = "TYPE_SYSTEM_ALERT"), + to = "SYSTEM_ALERT"), @ViewDebug.IntToString(from = TYPE_TOAST, - to = "TYPE_TOAST"), + to = "TOAST"), @ViewDebug.IntToString(from = TYPE_SYSTEM_OVERLAY, - to = "TYPE_SYSTEM_OVERLAY"), + to = "SYSTEM_OVERLAY"), @ViewDebug.IntToString(from = TYPE_PRIORITY_PHONE, - to = "TYPE_PRIORITY_PHONE"), + to = "PRIORITY_PHONE"), @ViewDebug.IntToString(from = TYPE_SYSTEM_DIALOG, - to = "TYPE_SYSTEM_DIALOG"), + to = "SYSTEM_DIALOG"), @ViewDebug.IntToString(from = TYPE_KEYGUARD_DIALOG, - to = "TYPE_KEYGUARD_DIALOG"), + to = "KEYGUARD_DIALOG"), @ViewDebug.IntToString(from = TYPE_SYSTEM_ERROR, - to = "TYPE_SYSTEM_ERROR"), + to = "SYSTEM_ERROR"), @ViewDebug.IntToString(from = TYPE_INPUT_METHOD, - to = "TYPE_INPUT_METHOD"), + to = "INPUT_METHOD"), @ViewDebug.IntToString(from = TYPE_INPUT_METHOD_DIALOG, - to = "TYPE_INPUT_METHOD_DIALOG"), + to = "INPUT_METHOD_DIALOG"), @ViewDebug.IntToString(from = TYPE_WALLPAPER, - to = "TYPE_WALLPAPER"), + to = "WALLPAPER"), @ViewDebug.IntToString(from = TYPE_STATUS_BAR_PANEL, - to = "TYPE_STATUS_BAR_PANEL"), + to = "STATUS_BAR_PANEL"), @ViewDebug.IntToString(from = TYPE_SECURE_SYSTEM_OVERLAY, - to = "TYPE_SECURE_SYSTEM_OVERLAY"), + to = "SECURE_SYSTEM_OVERLAY"), @ViewDebug.IntToString(from = TYPE_DRAG, - to = "TYPE_DRAG"), + to = "DRAG"), @ViewDebug.IntToString(from = TYPE_STATUS_BAR_SUB_PANEL, - to = "TYPE_STATUS_BAR_SUB_PANEL"), + to = "STATUS_BAR_SUB_PANEL"), @ViewDebug.IntToString(from = TYPE_POINTER, - to = "TYPE_POINTER"), + to = "POINTER"), @ViewDebug.IntToString(from = TYPE_NAVIGATION_BAR, - to = "TYPE_NAVIGATION_BAR"), + to = "NAVIGATION_BAR"), @ViewDebug.IntToString(from = TYPE_VOLUME_OVERLAY, - to = "TYPE_VOLUME_OVERLAY"), + to = "VOLUME_OVERLAY"), @ViewDebug.IntToString(from = TYPE_BOOT_PROGRESS, - to = "TYPE_BOOT_PROGRESS"), + to = "BOOT_PROGRESS"), @ViewDebug.IntToString(from = TYPE_INPUT_CONSUMER, - to = "TYPE_INPUT_CONSUMER"), + to = "INPUT_CONSUMER"), @ViewDebug.IntToString(from = TYPE_DREAM, - to = "TYPE_DREAM"), + to = "DREAM"), @ViewDebug.IntToString(from = TYPE_NAVIGATION_BAR_PANEL, - to = "TYPE_NAVIGATION_BAR_PANEL"), + to = "NAVIGATION_BAR_PANEL"), @ViewDebug.IntToString(from = TYPE_DISPLAY_OVERLAY, - to = "TYPE_DISPLAY_OVERLAY"), + to = "DISPLAY_OVERLAY"), @ViewDebug.IntToString(from = TYPE_MAGNIFICATION_OVERLAY, - to = "TYPE_MAGNIFICATION_OVERLAY"), + to = "MAGNIFICATION_OVERLAY"), @ViewDebug.IntToString(from = TYPE_PRESENTATION, - to = "TYPE_PRESENTATION"), + to = "PRESENTATION"), @ViewDebug.IntToString(from = TYPE_PRIVATE_PRESENTATION, - to = "TYPE_PRIVATE_PRESENTATION"), + to = "PRIVATE_PRESENTATION"), @ViewDebug.IntToString(from = TYPE_VOICE_INTERACTION, - to = "TYPE_VOICE_INTERACTION"), + to = "VOICE_INTERACTION"), @ViewDebug.IntToString(from = TYPE_VOICE_INTERACTION_STARTING, - to = "TYPE_VOICE_INTERACTION_STARTING"), + to = "VOICE_INTERACTION_STARTING"), @ViewDebug.IntToString(from = TYPE_DOCK_DIVIDER, - to = "TYPE_DOCK_DIVIDER"), + to = "DOCK_DIVIDER"), @ViewDebug.IntToString(from = TYPE_QS_DIALOG, - to = "TYPE_QS_DIALOG"), + to = "QS_DIALOG"), @ViewDebug.IntToString(from = TYPE_SCREENSHOT, - to = "TYPE_SCREENSHOT"), + to = "SCREENSHOT"), @ViewDebug.IntToString(from = TYPE_APPLICATION_OVERLAY, - to = "TYPE_APPLICATION_OVERLAY") + to = "APPLICATION_OVERLAY") }) public int type; @@ -1198,63 +1200,69 @@ public interface WindowManager extends ViewManager { */ @ViewDebug.ExportedProperty(flagMapping = { @ViewDebug.FlagToString(mask = FLAG_ALLOW_LOCK_WHILE_SCREEN_ON, equals = FLAG_ALLOW_LOCK_WHILE_SCREEN_ON, - name = "FLAG_ALLOW_LOCK_WHILE_SCREEN_ON"), + name = "ALLOW_LOCK_WHILE_SCREEN_ON"), @ViewDebug.FlagToString(mask = FLAG_DIM_BEHIND, equals = FLAG_DIM_BEHIND, - name = "FLAG_DIM_BEHIND"), + name = "DIM_BEHIND"), @ViewDebug.FlagToString(mask = FLAG_BLUR_BEHIND, equals = FLAG_BLUR_BEHIND, - name = "FLAG_BLUR_BEHIND"), + name = "BLUR_BEHIND"), @ViewDebug.FlagToString(mask = FLAG_NOT_FOCUSABLE, equals = FLAG_NOT_FOCUSABLE, - name = "FLAG_NOT_FOCUSABLE"), + name = "NOT_FOCUSABLE"), @ViewDebug.FlagToString(mask = FLAG_NOT_TOUCHABLE, equals = FLAG_NOT_TOUCHABLE, - name = "FLAG_NOT_TOUCHABLE"), + name = "NOT_TOUCHABLE"), @ViewDebug.FlagToString(mask = FLAG_NOT_TOUCH_MODAL, equals = FLAG_NOT_TOUCH_MODAL, - name = "FLAG_NOT_TOUCH_MODAL"), + name = "NOT_TOUCH_MODAL"), @ViewDebug.FlagToString(mask = FLAG_TOUCHABLE_WHEN_WAKING, equals = FLAG_TOUCHABLE_WHEN_WAKING, - name = "FLAG_TOUCHABLE_WHEN_WAKING"), + name = "TOUCHABLE_WHEN_WAKING"), @ViewDebug.FlagToString(mask = FLAG_KEEP_SCREEN_ON, equals = FLAG_KEEP_SCREEN_ON, - name = "FLAG_KEEP_SCREEN_ON"), + name = "KEEP_SCREEN_ON"), @ViewDebug.FlagToString(mask = FLAG_LAYOUT_IN_SCREEN, equals = FLAG_LAYOUT_IN_SCREEN, - name = "FLAG_LAYOUT_IN_SCREEN"), + name = "LAYOUT_IN_SCREEN"), @ViewDebug.FlagToString(mask = FLAG_LAYOUT_NO_LIMITS, equals = FLAG_LAYOUT_NO_LIMITS, - name = "FLAG_LAYOUT_NO_LIMITS"), + name = "LAYOUT_NO_LIMITS"), @ViewDebug.FlagToString(mask = FLAG_FULLSCREEN, equals = FLAG_FULLSCREEN, - name = "FLAG_FULLSCREEN"), + name = "FULLSCREEN"), @ViewDebug.FlagToString(mask = FLAG_FORCE_NOT_FULLSCREEN, equals = FLAG_FORCE_NOT_FULLSCREEN, - name = "FLAG_FORCE_NOT_FULLSCREEN"), + name = "FORCE_NOT_FULLSCREEN"), @ViewDebug.FlagToString(mask = FLAG_DITHER, equals = FLAG_DITHER, - name = "FLAG_DITHER"), + name = "DITHER"), @ViewDebug.FlagToString(mask = FLAG_SECURE, equals = FLAG_SECURE, - name = "FLAG_SECURE"), + name = "SECURE"), @ViewDebug.FlagToString(mask = FLAG_SCALED, equals = FLAG_SCALED, - name = "FLAG_SCALED"), + name = "SCALED"), @ViewDebug.FlagToString(mask = FLAG_IGNORE_CHEEK_PRESSES, equals = FLAG_IGNORE_CHEEK_PRESSES, - name = "FLAG_IGNORE_CHEEK_PRESSES"), + name = "IGNORE_CHEEK_PRESSES"), @ViewDebug.FlagToString(mask = FLAG_LAYOUT_INSET_DECOR, equals = FLAG_LAYOUT_INSET_DECOR, - name = "FLAG_LAYOUT_INSET_DECOR"), + name = "LAYOUT_INSET_DECOR"), @ViewDebug.FlagToString(mask = FLAG_ALT_FOCUSABLE_IM, equals = FLAG_ALT_FOCUSABLE_IM, - name = "FLAG_ALT_FOCUSABLE_IM"), + name = "ALT_FOCUSABLE_IM"), @ViewDebug.FlagToString(mask = FLAG_WATCH_OUTSIDE_TOUCH, equals = FLAG_WATCH_OUTSIDE_TOUCH, - name = "FLAG_WATCH_OUTSIDE_TOUCH"), + name = "WATCH_OUTSIDE_TOUCH"), @ViewDebug.FlagToString(mask = FLAG_SHOW_WHEN_LOCKED, equals = FLAG_SHOW_WHEN_LOCKED, - name = "FLAG_SHOW_WHEN_LOCKED"), + name = "SHOW_WHEN_LOCKED"), @ViewDebug.FlagToString(mask = FLAG_SHOW_WALLPAPER, equals = FLAG_SHOW_WALLPAPER, - name = "FLAG_SHOW_WALLPAPER"), + name = "SHOW_WALLPAPER"), @ViewDebug.FlagToString(mask = FLAG_TURN_SCREEN_ON, equals = FLAG_TURN_SCREEN_ON, - name = "FLAG_TURN_SCREEN_ON"), + name = "TURN_SCREEN_ON"), @ViewDebug.FlagToString(mask = FLAG_DISMISS_KEYGUARD, equals = FLAG_DISMISS_KEYGUARD, - name = "FLAG_DISMISS_KEYGUARD"), + name = "DISMISS_KEYGUARD"), @ViewDebug.FlagToString(mask = FLAG_SPLIT_TOUCH, equals = FLAG_SPLIT_TOUCH, - name = "FLAG_SPLIT_TOUCH"), + name = "SPLIT_TOUCH"), @ViewDebug.FlagToString(mask = FLAG_HARDWARE_ACCELERATED, equals = FLAG_HARDWARE_ACCELERATED, - name = "FLAG_HARDWARE_ACCELERATED"), - @ViewDebug.FlagToString(mask = FLAG_LOCAL_FOCUS_MODE, equals = FLAG_LOCAL_FOCUS_MODE, - name = "FLAG_LOCAL_FOCUS_MODE"), + name = "HARDWARE_ACCELERATED"), + @ViewDebug.FlagToString(mask = FLAG_LAYOUT_IN_OVERSCAN, equals = FLAG_LAYOUT_IN_OVERSCAN, + name = "LOCAL_FOCUS_MODE"), @ViewDebug.FlagToString(mask = FLAG_TRANSLUCENT_STATUS, equals = FLAG_TRANSLUCENT_STATUS, - name = "FLAG_TRANSLUCENT_STATUS"), + name = "TRANSLUCENT_STATUS"), @ViewDebug.FlagToString(mask = FLAG_TRANSLUCENT_NAVIGATION, equals = FLAG_TRANSLUCENT_NAVIGATION, - name = "FLAG_TRANSLUCENT_NAVIGATION"), + name = "TRANSLUCENT_NAVIGATION"), + @ViewDebug.FlagToString(mask = FLAG_LOCAL_FOCUS_MODE, equals = FLAG_LOCAL_FOCUS_MODE, + name = "LOCAL_FOCUS_MODE"), + @ViewDebug.FlagToString(mask = FLAG_SLIPPERY, equals = FLAG_SLIPPERY, + name = "FLAG_SLIPPERY"), + @ViewDebug.FlagToString(mask = FLAG_LAYOUT_ATTACHED_IN_DECOR, equals = FLAG_LAYOUT_ATTACHED_IN_DECOR, + name = "FLAG_LAYOUT_ATTACHED_IN_DECOR"), @ViewDebug.FlagToString(mask = FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS, equals = FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS, - name = "FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS") + name = "DRAWS_SYSTEM_BAR_BACKGROUNDS") }, formatToHexString = true) public int flags; @@ -1438,6 +1446,88 @@ public interface WindowManager extends ViewManager { * Control flags that are private to the platform. * @hide */ + @ViewDebug.ExportedProperty(flagMapping = { + @ViewDebug.FlagToString( + mask = PRIVATE_FLAG_FAKE_HARDWARE_ACCELERATED, + equals = PRIVATE_FLAG_FAKE_HARDWARE_ACCELERATED, + name = "FAKE_HARDWARE_ACCELERATED"), + @ViewDebug.FlagToString( + mask = PRIVATE_FLAG_FORCE_HARDWARE_ACCELERATED, + equals = PRIVATE_FLAG_FORCE_HARDWARE_ACCELERATED, + name = "FORCE_HARDWARE_ACCELERATED"), + @ViewDebug.FlagToString( + mask = PRIVATE_FLAG_WANTS_OFFSET_NOTIFICATIONS, + equals = PRIVATE_FLAG_WANTS_OFFSET_NOTIFICATIONS, + name = "WANTS_OFFSET_NOTIFICATIONS"), + @ViewDebug.FlagToString( + mask = PRIVATE_FLAG_SHOW_FOR_ALL_USERS, + equals = PRIVATE_FLAG_SHOW_FOR_ALL_USERS, + name = "SHOW_FOR_ALL_USERS"), + @ViewDebug.FlagToString( + mask = PRIVATE_FLAG_NO_MOVE_ANIMATION, + equals = PRIVATE_FLAG_NO_MOVE_ANIMATION, + name = "NO_MOVE_ANIMATION"), + @ViewDebug.FlagToString( + mask = PRIVATE_FLAG_COMPATIBLE_WINDOW, + equals = PRIVATE_FLAG_COMPATIBLE_WINDOW, + name = "COMPATIBLE_WINDOW"), + @ViewDebug.FlagToString( + mask = PRIVATE_FLAG_SYSTEM_ERROR, + equals = PRIVATE_FLAG_SYSTEM_ERROR, + name = "SYSTEM_ERROR"), + @ViewDebug.FlagToString( + mask = PRIVATE_FLAG_INHERIT_TRANSLUCENT_DECOR, + equals = PRIVATE_FLAG_INHERIT_TRANSLUCENT_DECOR, + name = "INHERIT_TRANSLUCENT_DECOR"), + @ViewDebug.FlagToString( + mask = PRIVATE_FLAG_KEYGUARD, + equals = PRIVATE_FLAG_KEYGUARD, + name = "KEYGUARD"), + @ViewDebug.FlagToString( + mask = PRIVATE_FLAG_DISABLE_WALLPAPER_TOUCH_EVENTS, + equals = PRIVATE_FLAG_DISABLE_WALLPAPER_TOUCH_EVENTS, + name = "DISABLE_WALLPAPER_TOUCH_EVENTS"), + @ViewDebug.FlagToString( + mask = PRIVATE_FLAG_FORCE_STATUS_BAR_VISIBLE_TRANSPARENT, + equals = PRIVATE_FLAG_FORCE_STATUS_BAR_VISIBLE_TRANSPARENT, + name = "FORCE_STATUS_BAR_VISIBLE_TRANSPARENT"), + @ViewDebug.FlagToString( + mask = PRIVATE_FLAG_PRESERVE_GEOMETRY, + equals = PRIVATE_FLAG_PRESERVE_GEOMETRY, + name = "PRESERVE_GEOMETRY"), + @ViewDebug.FlagToString( + mask = PRIVATE_FLAG_FORCE_DECOR_VIEW_VISIBILITY, + equals = PRIVATE_FLAG_FORCE_DECOR_VIEW_VISIBILITY, + name = "FORCE_DECOR_VIEW_VISIBILITY"), + @ViewDebug.FlagToString( + mask = PRIVATE_FLAG_WILL_NOT_REPLACE_ON_RELAUNCH, + equals = PRIVATE_FLAG_WILL_NOT_REPLACE_ON_RELAUNCH, + name = "WILL_NOT_REPLACE_ON_RELAUNCH"), + @ViewDebug.FlagToString( + mask = PRIVATE_FLAG_LAYOUT_CHILD_WINDOW_IN_PARENT_FRAME, + equals = PRIVATE_FLAG_LAYOUT_CHILD_WINDOW_IN_PARENT_FRAME, + name = "LAYOUT_CHILD_WINDOW_IN_PARENT_FRAME"), + @ViewDebug.FlagToString( + mask = PRIVATE_FLAG_FORCE_DRAW_STATUS_BAR_BACKGROUND, + equals = PRIVATE_FLAG_FORCE_DRAW_STATUS_BAR_BACKGROUND, + name = "FORCE_DRAW_STATUS_BAR_BACKGROUND"), + @ViewDebug.FlagToString( + mask = PRIVATE_FLAG_SUSTAINED_PERFORMANCE_MODE, + equals = PRIVATE_FLAG_SUSTAINED_PERFORMANCE_MODE, + name = "SUSTAINED_PERFORMANCE_MODE"), + @ViewDebug.FlagToString( + mask = PRIVATE_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS, + equals = PRIVATE_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS, + name = "HIDE_NON_SYSTEM_OVERLAY_WINDOWS"), + @ViewDebug.FlagToString( + mask = PRIVATE_FLAG_IS_ROUNDED_CORNERS_OVERLAY, + equals = PRIVATE_FLAG_IS_ROUNDED_CORNERS_OVERLAY, + name = "IS_ROUNDED_CORNERS_OVERLAY"), + @ViewDebug.FlagToString( + mask = PRIVATE_FLAG_ACQUIRES_SLEEP_TOKEN, + equals = PRIVATE_FLAG_ACQUIRES_SLEEP_TOKEN, + name = "ACQUIRES_SLEEP_TOKEN") + }) @TestApi public int privateFlags; @@ -1977,7 +2067,7 @@ public interface WindowManager extends ViewManager { * @hide */ @ActivityInfo.ColorMode - private int mColorMode = ActivityInfo.COLOR_MODE_DEFAULT; + private int mColorMode = COLOR_MODE_DEFAULT; public LayoutParams() { super(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT); @@ -2442,9 +2532,15 @@ public interface WindowManager extends ViewManager { @Override public String toString() { + return toString(""); + } + + /** + * @hide + */ + public String toString(String prefix) { StringBuilder sb = new StringBuilder(256); - sb.append("WM.LayoutParams{"); - sb.append("("); + sb.append("{("); sb.append(x); sb.append(','); sb.append(y); @@ -2464,26 +2560,19 @@ public interface WindowManager extends ViewManager { sb.append(verticalMargin); } if (gravity != 0) { - sb.append(" gr=#"); - sb.append(Integer.toHexString(gravity)); + sb.append(" gr="); + sb.append(Gravity.toString(gravity)); } if (softInputMode != 0) { - sb.append(" sim=#"); - sb.append(Integer.toHexString(softInputMode)); + sb.append(" sim={"); + sb.append(softInputModeToString(softInputMode)); + sb.append('}'); } sb.append(" ty="); - sb.append(type); - sb.append(" fl=#"); - sb.append(Integer.toHexString(flags)); - if (privateFlags != 0) { - if ((privateFlags & PRIVATE_FLAG_COMPATIBLE_WINDOW) != 0) { - sb.append(" compatible=true"); - } - sb.append(" pfl=0x").append(Integer.toHexString(privateFlags)); - } + sb.append(ViewDebug.intToString(LayoutParams.class, "type", type)); if (format != PixelFormat.OPAQUE) { sb.append(" fmt="); - sb.append(format); + sb.append(PixelFormat.formatToString(format)); } if (windowAnimations != 0) { sb.append(" wanim=0x"); @@ -2491,7 +2580,7 @@ public interface WindowManager extends ViewManager { } if (screenOrientation != ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED) { sb.append(" or="); - sb.append(screenOrientation); + sb.append(ActivityInfo.screenOrientationToString(screenOrientation)); } if (alpha != 1.0f) { sb.append(" alpha="); @@ -2507,7 +2596,7 @@ public interface WindowManager extends ViewManager { } if (rotationAnimation != ROTATION_ANIMATION_ROTATE) { sb.append(" rotAnim="); - sb.append(rotationAnimation); + sb.append(rotationAnimationToString(rotationAnimation)); } if (preferredRefreshRate != 0) { sb.append(" preferredRefreshRate="); @@ -2517,20 +2606,12 @@ public interface WindowManager extends ViewManager { sb.append(" preferredDisplayMode="); sb.append(preferredDisplayModeId); } - if (systemUiVisibility != 0) { - sb.append(" sysui=0x"); - sb.append(Integer.toHexString(systemUiVisibility)); - } - if (subtreeSystemUiVisibility != 0) { - sb.append(" vsysui=0x"); - sb.append(Integer.toHexString(subtreeSystemUiVisibility)); - } if (hasSystemUiListeners) { sb.append(" sysuil="); sb.append(hasSystemUiListeners); } if (inputFeatures != 0) { - sb.append(" if=0x").append(Integer.toHexString(inputFeatures)); + sb.append(" if=").append(inputFeatureToString(inputFeatures)); } if (userActivityTimeout >= 0) { sb.append(" userActivityTimeout=").append(userActivityTimeout); @@ -2546,11 +2627,30 @@ public interface WindowManager extends ViewManager { sb.append(" (!preservePreviousSurfaceInsets)"); } } - if (needsMenuKey != NEEDS_MENU_UNSET) { - sb.append(" needsMenuKey="); - sb.append(needsMenuKey); + if (needsMenuKey == NEEDS_MENU_SET_TRUE) { + sb.append(" needsMenuKey"); + } + if (mColorMode != COLOR_MODE_DEFAULT) { + sb.append(" colorMode=").append(ActivityInfo.colorModeToString(mColorMode)); + } + sb.append(System.lineSeparator()); + sb.append(prefix).append(" fl=").append( + ViewDebug.flagsToString(LayoutParams.class, "flags", flags)); + if (privateFlags != 0) { + sb.append(System.lineSeparator()); + sb.append(prefix).append(" pfl=").append(ViewDebug.flagsToString( + LayoutParams.class, "privateFlags", privateFlags)); + } + if (systemUiVisibility != 0) { + sb.append(System.lineSeparator()); + sb.append(prefix).append(" sysui=").append(ViewDebug.flagsToString( + View.class, "mSystemUiVisibility", systemUiVisibility)); + } + if (subtreeSystemUiVisibility != 0) { + sb.append(System.lineSeparator()); + sb.append(prefix).append(" vsysui=").append(ViewDebug.flagsToString( + View.class, "mSystemUiVisibility", subtreeSystemUiVisibility)); } - sb.append(" colorMode=").append(mColorMode); sb.append('}'); return sb.toString(); } @@ -2634,5 +2734,88 @@ public interface WindowManager extends ViewManager { && width == WindowManager.LayoutParams.MATCH_PARENT && height == WindowManager.LayoutParams.MATCH_PARENT; } + + private static String softInputModeToString(@SoftInputModeFlags int softInputMode) { + final StringBuilder result = new StringBuilder(); + final int state = softInputMode & SOFT_INPUT_MASK_STATE; + if (state != 0) { + result.append("state="); + switch (state) { + case SOFT_INPUT_STATE_UNCHANGED: + result.append("unchanged"); + break; + case SOFT_INPUT_STATE_HIDDEN: + result.append("hidden"); + break; + case SOFT_INPUT_STATE_ALWAYS_HIDDEN: + result.append("always_hidden"); + break; + case SOFT_INPUT_STATE_VISIBLE: + result.append("visible"); + break; + case SOFT_INPUT_STATE_ALWAYS_VISIBLE: + result.append("always_visible"); + break; + default: + result.append(state); + break; + } + result.append(' '); + } + final int adjust = softInputMode & SOFT_INPUT_MASK_ADJUST; + if (adjust != 0) { + result.append("adjust="); + switch (adjust) { + case SOFT_INPUT_ADJUST_RESIZE: + result.append("resize"); + break; + case SOFT_INPUT_ADJUST_PAN: + result.append("pan"); + break; + case SOFT_INPUT_ADJUST_NOTHING: + result.append("nothing"); + break; + default: + result.append(adjust); + break; + } + result.append(' '); + } + if ((softInputMode & SOFT_INPUT_IS_FORWARD_NAVIGATION) != 0) { + result.append("forwardNavigation").append(' '); + } + result.deleteCharAt(result.length() - 1); + return result.toString(); + } + + private static String rotationAnimationToString(int rotationAnimation) { + switch (rotationAnimation) { + case ROTATION_ANIMATION_UNSPECIFIED: + return "UNSPECIFIED"; + case ROTATION_ANIMATION_ROTATE: + return "ROTATE"; + case ROTATION_ANIMATION_CROSSFADE: + return "CROSSFADE"; + case ROTATION_ANIMATION_JUMPCUT: + return "JUMPCUT"; + case ROTATION_ANIMATION_SEAMLESS: + return "SEAMLESS"; + default: + return Integer.toString(rotationAnimation); + } + } + + private static String inputFeatureToString(int inputFeature) { + switch (inputFeature) { + case INPUT_FEATURE_DISABLE_POINTER_GESTURES: + return "DISABLE_POINTER_GESTURES"; + case INPUT_FEATURE_NO_INPUT_CHANNEL: + return "NO_INPUT_CHANNEL"; + case INPUT_FEATURE_DISABLE_USER_ACTIVITY: + return "DISABLE_USER_ACTIVITY"; + default: + return Integer.toString(inputFeature); + } + } } } diff --git a/core/java/android/view/autofill/AutofillPopupWindow.java b/core/java/android/view/autofill/AutofillPopupWindow.java index 5f476380b1c3..b4688bb1d48b 100644 --- a/core/java/android/view/autofill/AutofillPopupWindow.java +++ b/core/java/android/view/autofill/AutofillPopupWindow.java @@ -47,6 +47,19 @@ public class AutofillPopupWindow extends PopupWindow { private final WindowPresenter mWindowPresenter; private WindowManager.LayoutParams mWindowLayoutParams; + private final View.OnAttachStateChangeListener mOnAttachStateChangeListener = + new View.OnAttachStateChangeListener() { + @Override + public void onViewAttachedToWindow(View v) { + /* ignore - handled by the super class */ + } + + @Override + public void onViewDetachedFromWindow(View v) { + dismiss(); + } + }; + /** * Creates a popup window with a presenter owning the window and responsible for * showing/hiding/updating the backing window. This can be useful of the window is @@ -208,7 +221,21 @@ public class AutofillPopupWindow extends PopupWindow { p.packageName = anchor.getContext().getPackageName(); mWindowPresenter.show(p, getTransitionEpicenter(), isLayoutInsetDecor(), anchor.getLayoutDirection()); - return; + } + + @Override + protected void attachToAnchor(View anchor, int xoff, int yoff, int gravity) { + super.attachToAnchor(anchor, xoff, yoff, gravity); + anchor.addOnAttachStateChangeListener(mOnAttachStateChangeListener); + } + + @Override + protected void detachFromAnchor() { + final View anchor = getAnchor(); + if (anchor != null) { + anchor.removeOnAttachStateChangeListener(mOnAttachStateChangeListener); + } + super.detachFromAnchor(); } @Override diff --git a/core/java/android/view/textclassifier/logging/SmartSelectionEventTracker.java b/core/java/android/view/textclassifier/logging/SmartSelectionEventTracker.java index 8d88ba60da54..83af19bbd328 100644 --- a/core/java/android/view/textclassifier/logging/SmartSelectionEventTracker.java +++ b/core/java/android/view/textclassifier/logging/SmartSelectionEventTracker.java @@ -581,6 +581,7 @@ public final class SmartSelectionEventTracker { case ActionType.SMART_SHARE: // fall through case ActionType.DRAG: // fall through case ActionType.ABANDON: // fall through + case ActionType.OTHER: // fall through return true; default: return false; diff --git a/core/java/android/webkit/CacheManager.java b/core/java/android/webkit/CacheManager.java index b8394203c61f..fc76029a8bef 100644 --- a/core/java/android/webkit/CacheManager.java +++ b/core/java/android/webkit/CacheManager.java @@ -16,13 +16,14 @@ package android.webkit; +import android.annotation.Nullable; + import java.io.File; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.util.Map; - /** * Manages the HTTP cache used by an application's {@link WebView} instances. * @deprecated Access to the HTTP cache will be removed in a future release. @@ -233,6 +234,7 @@ public final class CacheManager { * @deprecated This method no longer has any effect and always returns {@code null}. */ @Deprecated + @Nullable public static File getCacheFileBaseDir() { return null; } @@ -287,6 +289,7 @@ public final class CacheManager { * @deprecated This method no longer has any effect and always returns {@code null}. */ @Deprecated + @Nullable public static CacheResult getCacheFile(String url, Map<String, String> headers) { return null; diff --git a/core/java/android/webkit/ClientCertRequest.java b/core/java/android/webkit/ClientCertRequest.java index de17534b959b..0fc47f1ed0ff 100644 --- a/core/java/android/webkit/ClientCertRequest.java +++ b/core/java/android/webkit/ClientCertRequest.java @@ -16,6 +16,8 @@ package android.webkit; +import android.annotation.Nullable; + import java.security.Principal; import java.security.PrivateKey; import java.security.cert.X509Certificate; @@ -42,14 +44,16 @@ public abstract class ClientCertRequest { public ClientCertRequest() { } /** - * Returns the acceptable types of asymmetric keys (can be {@code null}). + * Returns the acceptable types of asymmetric keys. */ + @Nullable public abstract String[] getKeyTypes(); /** * Returns the acceptable certificate issuers for the certificate - * matching the private key (can be {@code null}). + * matching the private key. */ + @Nullable public abstract Principal[] getPrincipals(); /** diff --git a/core/java/android/webkit/CookieManager.java b/core/java/android/webkit/CookieManager.java index 89892930ea89..ae6a2fd787d7 100644 --- a/core/java/android/webkit/CookieManager.java +++ b/core/java/android/webkit/CookieManager.java @@ -16,6 +16,7 @@ package android.webkit; +import android.annotation.Nullable; import android.annotation.SystemApi; import android.net.WebAddress; @@ -116,7 +117,8 @@ public abstract class CookieManager { * HTTP response header * @param callback a callback to be executed when the cookie has been set */ - public abstract void setCookie(String url, String value, ValueCallback<Boolean> callback); + public abstract void setCookie(String url, String value, @Nullable ValueCallback<Boolean> + callback); /** * Gets the cookies for the given URL. @@ -175,7 +177,7 @@ public abstract class CookieManager { * method from a thread without a Looper. * @param callback a callback which is executed when the session cookies have been removed */ - public abstract void removeSessionCookies(ValueCallback<Boolean> callback); + public abstract void removeSessionCookies(@Nullable ValueCallback<Boolean> callback); /** * Removes all cookies. @@ -197,7 +199,7 @@ public abstract class CookieManager { * method from a thread without a Looper. * @param callback a callback which is executed when the cookies have been removed */ - public abstract void removeAllCookies(ValueCallback<Boolean> callback); + public abstract void removeAllCookies(@Nullable ValueCallback<Boolean> callback); /** * Gets whether there are stored cookies. diff --git a/core/java/android/webkit/FindActionModeCallback.java b/core/java/android/webkit/FindActionModeCallback.java index 71f85d70e30d..6a8c256f0ae2 100644 --- a/core/java/android/webkit/FindActionModeCallback.java +++ b/core/java/android/webkit/FindActionModeCallback.java @@ -16,6 +16,7 @@ package android.webkit; +import android.annotation.NonNull; import android.annotation.SystemApi; import android.content.Context; import android.content.res.Resources; @@ -87,10 +88,12 @@ public class FindActionModeCallback implements ActionMode.Callback, TextWatcher, mMatchesFound = false; } - /* - * Set the WebView to search. Must be non null. + /** + * Set the WebView to search. + * + * @param webView an implementation of WebView */ - public void setWebView(WebView webView) { + public void setWebView(@NonNull WebView webView) { if (null == webView) { throw new AssertionError("WebView supplied to " + "FindActionModeCallback cannot be null"); diff --git a/core/java/android/webkit/MimeTypeMap.java b/core/java/android/webkit/MimeTypeMap.java index e172c02e2466..39874e82ec03 100644 --- a/core/java/android/webkit/MimeTypeMap.java +++ b/core/java/android/webkit/MimeTypeMap.java @@ -16,6 +16,7 @@ package android.webkit; +import android.annotation.Nullable; import android.text.TextUtils; import libcore.net.MimeUtils; @@ -86,6 +87,7 @@ public class MimeTypeMap { * @param extension A file extension without the leading '.' * @return The MIME type for the given extension or {@code null} iff there is none. */ + @Nullable public String getMimeTypeFromExtension(String extension) { return MimeUtils.guessMimeTypeFromExtension(extension); } @@ -111,6 +113,7 @@ public class MimeTypeMap { * @param mimeType A MIME type (i.e. text/plain) * @return The extension for the given MIME type or {@code null} iff there is none. */ + @Nullable public String getExtensionFromMimeType(String mimeType) { return MimeUtils.guessExtensionFromMimeType(mimeType); } @@ -125,7 +128,7 @@ public class MimeTypeMap { * @param contentDisposition Content-disposition header given by the server. * @return The MIME type that should be used for this data. */ - /* package */ String remapGenericMimeType(String mimeType, String url, + /* package */ String remapGenericMimeType(@Nullable String mimeType, String url, String contentDisposition) { // If we have one of "generic" MIME types, try to deduce // the right MIME type from the file extension (if any): diff --git a/core/java/android/webkit/ServiceWorkerClient.java b/core/java/android/webkit/ServiceWorkerClient.java index b4964fd2fea0..d6e8f36ce101 100644 --- a/core/java/android/webkit/ServiceWorkerClient.java +++ b/core/java/android/webkit/ServiceWorkerClient.java @@ -16,6 +16,8 @@ package android.webkit; +import android.annotation.Nullable; + /** * Base class for clients to capture Service Worker related callbacks, * see {@link ServiceWorkerController} for usage example. @@ -37,6 +39,7 @@ public class ServiceWorkerClient { * resource itself. * @see WebViewClient#shouldInterceptRequest(WebView, WebResourceRequest) */ + @Nullable public WebResourceResponse shouldInterceptRequest(WebResourceRequest request) { return null; } diff --git a/core/java/android/webkit/TokenBindingService.java b/core/java/android/webkit/TokenBindingService.java index 43565c23355d..b37e1b8962c5 100644 --- a/core/java/android/webkit/TokenBindingService.java +++ b/core/java/android/webkit/TokenBindingService.java @@ -16,6 +16,8 @@ package android.webkit; +import android.annotation.NonNull; +import android.annotation.Nullable; import android.annotation.SystemApi; import android.net.Uri; @@ -84,31 +86,30 @@ public abstract class TokenBindingService { * The user can pass {@code null} if any algorithm is acceptable. * * @param origin The origin for the server. - * @param algorithm The list of algorithms. Can be {@code null}. An - * IllegalArgumentException is thrown if array is empty. + * @param algorithm The list of algorithms. An IllegalArgumentException is thrown if array is + * empty. * @param callback The callback that will be called when key is available. - * Cannot be {@code null}. */ public abstract void getKey(Uri origin, - String[] algorithm, - ValueCallback<TokenBindingKey> callback); + @Nullable String[] algorithm, + @NonNull ValueCallback<TokenBindingKey> callback); /** * Deletes specified key (for use when associated cookie is cleared). * * @param origin The origin of the server. * @param callback The callback that will be called when key is deleted. The * callback parameter (Boolean) will indicate if operation is - * successful or if failed. The callback can be {@code null}. + * successful or if failed. */ public abstract void deleteKey(Uri origin, - ValueCallback<Boolean> callback); + @Nullable ValueCallback<Boolean> callback); /** * Deletes all the keys (for use when cookies are cleared). * * @param callback The callback that will be called when keys are deleted. * The callback parameter (Boolean) will indicate if operation is - * successful or if failed. The callback can be {@code null}. + * successful or if failed. */ - public abstract void deleteAllKeys(ValueCallback<Boolean> callback); + public abstract void deleteAllKeys(@Nullable ValueCallback<Boolean> callback); } diff --git a/core/java/android/webkit/URLUtil.java b/core/java/android/webkit/URLUtil.java index c8bfb77992f1..1956df341eb6 100644 --- a/core/java/android/webkit/URLUtil.java +++ b/core/java/android/webkit/URLUtil.java @@ -16,6 +16,7 @@ package android.webkit; +import android.annotation.Nullable; import android.net.ParseException; import android.net.Uri; import android.net.WebAddress; @@ -300,8 +301,8 @@ public final class URLUtil { */ public static final String guessFileName( String url, - String contentDisposition, - String mimeType) { + @Nullable String contentDisposition, + @Nullable String mimeType) { String filename = null; String extension = null; diff --git a/core/java/android/webkit/UrlInterceptHandler.java b/core/java/android/webkit/UrlInterceptHandler.java index aa5c6dc76753..0a6e51f7f3bd 100644 --- a/core/java/android/webkit/UrlInterceptHandler.java +++ b/core/java/android/webkit/UrlInterceptHandler.java @@ -16,6 +16,7 @@ package android.webkit; +import android.annotation.Nullable; import android.webkit.CacheManager.CacheResult; import android.webkit.PluginData; @@ -35,14 +36,15 @@ public interface UrlInterceptHandler { * not interested. * * @param url URL string. - * @param headers The headers associated with the request. May be {@code null}. + * @param headers The headers associated with the request. * @return The CacheResult containing the surrogate response. * * @hide * @deprecated Do not use, this interface is deprecated. */ @Deprecated - public CacheResult service(String url, Map<String, String> headers); + @Nullable + CacheResult service(String url, @Nullable Map<String, String> headers); /** * Given an URL, returns the PluginData which contains the @@ -50,12 +52,13 @@ public interface UrlInterceptHandler { * not interested. * * @param url URL string. - * @param headers The headers associated with the request. May be {@code null}. + * @param headers The headers associated with the request. * @return The PluginData containing the surrogate response. * * @hide * @deprecated Do not use, this interface is deprecated. */ @Deprecated - public PluginData getPluginData(String url, Map<String, String> headers); + @Nullable + PluginData getPluginData(String url, @Nullable Map<String, String> headers); } diff --git a/core/java/android/webkit/UrlInterceptRegistry.java b/core/java/android/webkit/UrlInterceptRegistry.java index 67af2ad015c7..700d6d9332d6 100644 --- a/core/java/android/webkit/UrlInterceptRegistry.java +++ b/core/java/android/webkit/UrlInterceptRegistry.java @@ -16,6 +16,7 @@ package android.webkit; +import android.annotation.Nullable; import android.webkit.CacheManager.CacheResult; import android.webkit.PluginData; import android.webkit.UrlInterceptHandler; @@ -121,6 +122,7 @@ public final class UrlInterceptRegistry { * deprecated, so is this class. */ @Deprecated + @Nullable public static synchronized CacheResult getSurrogate( String url, Map<String, String> headers) { if (urlInterceptDisabled()) { @@ -149,6 +151,7 @@ public final class UrlInterceptRegistry { * deprecated, so is this class. */ @Deprecated + @Nullable public static synchronized PluginData getPluginData( String url, Map<String, String> headers) { if (urlInterceptDisabled()) { diff --git a/core/java/android/webkit/WebBackForwardList.java b/core/java/android/webkit/WebBackForwardList.java index 3349b06538d1..0c34e3c16ac6 100644 --- a/core/java/android/webkit/WebBackForwardList.java +++ b/core/java/android/webkit/WebBackForwardList.java @@ -16,6 +16,8 @@ package android.webkit; +import android.annotation.Nullable; + import java.io.Serializable; /** @@ -29,6 +31,7 @@ public abstract class WebBackForwardList implements Cloneable, Serializable { * empty. * @return The current history item. */ + @Nullable public abstract WebHistoryItem getCurrentItem(); /** diff --git a/core/java/android/webkit/WebChromeClient.java b/core/java/android/webkit/WebChromeClient.java index 742daa9180eb..4aa1c4a6daff 100644 --- a/core/java/android/webkit/WebChromeClient.java +++ b/core/java/android/webkit/WebChromeClient.java @@ -16,6 +16,7 @@ package android.webkit; +import android.annotation.Nullable; import android.annotation.SystemApi; import android.content.Intent; import android.content.pm.ActivityInfo; @@ -383,6 +384,7 @@ public class WebChromeClient { * @return Bitmap The image to use as a default poster, or {@code null} if no such image is * available. */ + @Nullable public Bitmap getDefaultVideoPoster() { return null; } @@ -394,6 +396,7 @@ public class WebChromeClient { * * @return View The View to be displayed whilst the video is loading. */ + @Nullable public View getVideoLoadingProgressView() { return null; } @@ -452,6 +455,7 @@ public class WebChromeClient { * @return the Uris of selected file(s) or {@code null} if the resultCode indicates * activity canceled or any other error. */ + @Nullable public static Uri[] parseResult(int resultCode, Intent data) { return WebViewFactory.getProvider().getStatics().parseFileChooserResult(resultCode, data); } @@ -477,14 +481,16 @@ public class WebChromeClient { public abstract boolean isCaptureEnabled(); /** - * Returns the title to use for this file selector, or null. If {@code null} a default - * title should be used. + * Returns the title to use for this file selector. If {@code null} a default title should + * be used. */ + @Nullable public abstract CharSequence getTitle(); /** * The file name of a default selection if specified, or {@code null}. */ + @Nullable public abstract String getFilenameHint(); /** diff --git a/core/java/android/webkit/WebHistoryItem.java b/core/java/android/webkit/WebHistoryItem.java index 1591833eee96..74db039e015d 100644 --- a/core/java/android/webkit/WebHistoryItem.java +++ b/core/java/android/webkit/WebHistoryItem.java @@ -16,6 +16,7 @@ package android.webkit; +import android.annotation.Nullable; import android.annotation.SystemApi; import android.graphics.Bitmap; @@ -70,6 +71,7 @@ public abstract class WebHistoryItem implements Cloneable { * Note: The VM ensures 32-bit atomic read/write operations so we don't have * to synchronize this method. */ + @Nullable public abstract Bitmap getFavicon(); /** diff --git a/core/java/android/webkit/WebMessage.java b/core/java/android/webkit/WebMessage.java index 7fe66dc84e10..bfc00e7a0145 100644 --- a/core/java/android/webkit/WebMessage.java +++ b/core/java/android/webkit/WebMessage.java @@ -16,6 +16,8 @@ package android.webkit; +import android.annotation.Nullable; + /** * The Java representation of the HTML5 PostMessage event. See * https://html.spec.whatwg.org/multipage/comms.html#the-messageevent-interfaces @@ -56,6 +58,7 @@ public class WebMessage { * Returns the ports that are sent with the message, or {@code null} if no port * is sent. */ + @Nullable public WebMessagePort[] getPorts() { return mPorts; } diff --git a/core/java/android/webkit/WebResourceResponse.java b/core/java/android/webkit/WebResourceResponse.java index 80c43c147dbe..7bc7b07d2fc1 100644 --- a/core/java/android/webkit/WebResourceResponse.java +++ b/core/java/android/webkit/WebResourceResponse.java @@ -16,12 +16,13 @@ package android.webkit; +import android.annotation.NonNull; +import android.annotation.SystemApi; + import java.io.InputStream; import java.io.StringBufferInputStream; import java.util.Map; -import android.annotation.SystemApi; - /** * Encapsulates a resource response. Applications can return an instance of this * class from {@link WebViewClient#shouldInterceptRequest} to provide a custom @@ -63,15 +64,15 @@ public class WebResourceResponse { * @param encoding the resource response's encoding * @param statusCode the status code needs to be in the ranges [100, 299], [400, 599]. * Causing a redirect by specifying a 3xx code is not supported. - * @param reasonPhrase the phrase describing the status code, for example "OK". Must be non-null - * and not empty. + * @param reasonPhrase the phrase describing the status code, for example "OK". Must be + * non-empty. * @param responseHeaders the resource response's headers represented as a mapping of header * name -> header value. * @param data the input stream that provides the resource response's data. Must not be a * StringBufferInputStream. */ public WebResourceResponse(String mimeType, String encoding, int statusCode, - String reasonPhrase, Map<String, String> responseHeaders, InputStream data) { + @NonNull String reasonPhrase, Map<String, String> responseHeaders, InputStream data) { this(mimeType, encoding, data); setStatusCodeAndReasonPhrase(statusCode, reasonPhrase); setResponseHeaders(responseHeaders); @@ -121,10 +122,10 @@ public class WebResourceResponse { * * @param statusCode the status code needs to be in the ranges [100, 299], [400, 599]. * Causing a redirect by specifying a 3xx code is not supported. - * @param reasonPhrase the phrase describing the status code, for example "OK". Must be non-null - * and not empty. + * @param reasonPhrase the phrase describing the status code, for example "OK". Must be + * non-empty. */ - public void setStatusCodeAndReasonPhrase(int statusCode, String reasonPhrase) { + public void setStatusCodeAndReasonPhrase(int statusCode, @NonNull String reasonPhrase) { checkImmutable(); if (statusCode < 100) throw new IllegalArgumentException("statusCode can't be less than 100."); diff --git a/core/java/android/webkit/WebSettings.java b/core/java/android/webkit/WebSettings.java index 22d8561dac46..203de9c2e7e0 100644 --- a/core/java/android/webkit/WebSettings.java +++ b/core/java/android/webkit/WebSettings.java @@ -17,6 +17,7 @@ package android.webkit; import android.annotation.IntDef; +import android.annotation.Nullable; import android.annotation.SystemApi; import android.content.Context; @@ -1238,7 +1239,7 @@ public abstract class WebSettings { * * @param ua new user-agent string */ - public abstract void setUserAgentString(String ua); + public abstract void setUserAgentString(@Nullable String ua); /** * Gets the WebView's user-agent string. diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java index 3a4bfd686333..077a901898d4 100644 --- a/core/java/android/webkit/WebView.java +++ b/core/java/android/webkit/WebView.java @@ -438,7 +438,7 @@ public class WebView extends AbsoluteLayout * @deprecated Deprecated due to internal changes. */ @Deprecated - public void onNewPicture(WebView view, Picture picture); + void onNewPicture(WebView view, @Nullable Picture picture); } public static class HitTestResult { @@ -529,6 +529,7 @@ public class WebView extends AbsoluteLayout * * @return additional type-dependant information about the result */ + @Nullable public String getExtra() { return mExtra; } @@ -717,6 +718,7 @@ public class WebView extends AbsoluteLayout * * @return the SSL certificate for the main top-level page */ + @Nullable public SslCertificate getCertificate() { checkThread(); return mProvider.getCertificate(); @@ -785,6 +787,7 @@ public class WebView extends AbsoluteLayout * @deprecated Use {@link WebViewDatabase#getHttpAuthUsernamePassword} instead */ @Deprecated + @Nullable public String[] getHttpAuthUsernamePassword(String host, String realm) { checkThread(); return mProvider.getHttpAuthUsernamePassword(host, realm); @@ -853,9 +856,10 @@ public class WebView extends AbsoluteLayout * called. * * @param outState the Bundle to store this WebView's state - * @return the same copy of the back/forward list used to save the state. If - * saveState fails, the returned list will be {@code null}. + * @return the same copy of the back/forward list used to save the state, {@code null} if the + * method fails. */ + @Nullable public WebBackForwardList saveState(Bundle outState) { checkThread(); return mProvider.saveState(outState); @@ -906,6 +910,7 @@ public class WebView extends AbsoluteLayout * @param inState the incoming Bundle of state * @return the restored back/forward list or {@code null} if restoreState failed */ + @Nullable public WebBackForwardList restoreState(Bundle inState) { checkThread(); return mProvider.restoreState(inState); @@ -985,10 +990,11 @@ public class WebView extends AbsoluteLayout * always overrides that specified in the HTML or XML document itself. * * @param data a String of data in the given encoding - * @param mimeType the MIME type of the data, e.g. 'text/html' + * @param mimeType the MIMEType of the data, e.g. 'text/html'. If {@code null}, + * defaults to 'text/html'. * @param encoding the encoding of the data */ - public void loadData(String data, String mimeType, String encoding) { + public void loadData(String data, @Nullable String mimeType, @Nullable String encoding) { checkThread(); mProvider.loadData(data, mimeType, encoding); } @@ -1022,8 +1028,8 @@ public class WebView extends AbsoluteLayout * @param historyUrl the URL to use as the history entry. If {@code null} defaults * to 'about:blank'. If non-null, this must be a valid URL. */ - public void loadDataWithBaseURL(String baseUrl, String data, - String mimeType, String encoding, String historyUrl) { + public void loadDataWithBaseURL(@Nullable String baseUrl, String data, + @Nullable String mimeType, @Nullable String encoding, @Nullable String historyUrl) { checkThread(); mProvider.loadDataWithBaseURL(baseUrl, data, mimeType, encoding, historyUrl); } @@ -1045,7 +1051,7 @@ public class WebView extends AbsoluteLayout * completes with the result of the execution (if any). * May be {@code null} if no notification of the result is required. */ - public void evaluateJavascript(String script, ValueCallback<String> resultCallback) { + public void evaluateJavascript(String script, @Nullable ValueCallback<String> resultCallback) { checkThread(); mProvider.evaluateJavaScript(script, resultCallback); } @@ -1072,7 +1078,8 @@ public class WebView extends AbsoluteLayout * under which the file was saved, or {@code null} if saving the * file failed. */ - public void saveWebArchive(String basename, boolean autoname, ValueCallback<String> callback) { + public void saveWebArchive(String basename, boolean autoname, @Nullable ValueCallback<String> + callback) { checkThread(); mProvider.saveWebArchive(basename, autoname, callback); } @@ -1395,7 +1402,7 @@ public class WebView extends AbsoluteLayout * returns the anchor's href attribute. "title" returns the * anchor's text. "src" returns the image's src attribute. */ - public void requestFocusNodeHref(Message hrefMsg) { + public void requestFocusNodeHref(@Nullable Message hrefMsg) { checkThread(); mProvider.requestFocusNodeHref(hrefMsg); } @@ -1615,10 +1622,9 @@ public class WebView extends AbsoluteLayout * shared by all the WebViews that are created by the embedder application. * * @param onCleared A runnable to be invoked when client certs are cleared. - * The embedder can pass {@code null} if not interested in the - * callback. The runnable will be called in UI thread. + * The runnable will be called in UI thread. */ - public static void clearClientCertPreferences(Runnable onCleared) { + public static void clearClientCertPreferences(@Nullable Runnable onCleared) { getFactory().getStatics().clearClientCertPreferences(onCleared); } @@ -1640,7 +1646,8 @@ public class WebView extends AbsoluteLayout * @param callback will be called on the UI thread with {@code true} if initialization is * successful, {@code false} otherwise. */ - public static void startSafeBrowsing(Context context, ValueCallback<Boolean> callback) { + public static void startSafeBrowsing(Context context, + @Nullable ValueCallback<Boolean> callback) { getFactory().getStatics().initSafeBrowsing(context, callback); } @@ -1764,7 +1771,7 @@ public class WebView extends AbsoluteLayout * provides a more robust solution. */ @Deprecated - public boolean showFindDialog(String text, boolean showIme) { + public boolean showFindDialog(@Nullable String text, boolean showIme) { checkThread(); return mProvider.showFindDialog(text, showIme); } @@ -1791,6 +1798,7 @@ public class WebView extends AbsoluteLayout * @param addr the string to search for addresses * @return the address, or if no address is found, {@code null} */ + @Nullable public static String findAddress(String addr) { // TODO: Rewrite this in Java so it is not needed to start up chromium // Could also be deprecated @@ -1891,6 +1899,7 @@ public class WebView extends AbsoluteLayout * @return the WebChromeClient, or {@code null} if not yet set * @see #setWebChromeClient */ + @Nullable public WebChromeClient getWebChromeClient() { checkThread(); return mProvider.getWebChromeClient(); @@ -1973,7 +1982,7 @@ public class WebView extends AbsoluteLayout * * @param name the name used to expose the object in JavaScript */ - public void removeJavascriptInterface(String name) { + public void removeJavascriptInterface(@NonNull String name) { checkThread(); mProvider.removeJavascriptInterface(name); } @@ -2956,6 +2965,7 @@ public class WebView extends AbsoluteLayout * next time the app starts and loads WebView it will use the new WebView package instead. * @return the current WebView package, or {@code null} if there is none. */ + @Nullable public static PackageInfo getCurrentWebViewPackage() { PackageInfo webviewPackage = WebViewFactory.getLoadedPackageInfo(); if (webviewPackage != null) { diff --git a/core/java/android/webkit/WebViewClient.java b/core/java/android/webkit/WebViewClient.java index af7026d9f16a..c5b64eb89f44 100644 --- a/core/java/android/webkit/WebViewClient.java +++ b/core/java/android/webkit/WebViewClient.java @@ -17,6 +17,7 @@ package android.webkit; import android.annotation.IntDef; +import android.annotation.Nullable; import android.graphics.Bitmap; import android.net.http.SslError; import android.os.Message; @@ -167,6 +168,7 @@ public class WebViewClient { * shouldInterceptRequest(WebView, WebResourceRequest)} instead. */ @Deprecated + @Nullable public WebResourceResponse shouldInterceptRequest(WebView view, String url) { return null; @@ -191,6 +193,7 @@ public class WebViewClient { * response information or {@code null} if the WebView should load the * resource itself. */ + @Nullable public WebResourceResponse shouldInterceptRequest(WebView view, WebResourceRequest request) { return shouldInterceptRequest(view, request.getUrl().toString()); @@ -496,7 +499,7 @@ public class WebViewClient { * @param args Authenticator specific arguments used to log in the user. */ public void onReceivedLoginRequest(WebView view, String realm, - String account, String args) { + @Nullable String account, String args) { } /** diff --git a/core/java/android/webkit/WebViewDatabase.java b/core/java/android/webkit/WebViewDatabase.java index de75d5d0feea..f6166c58a4c9 100644 --- a/core/java/android/webkit/WebViewDatabase.java +++ b/core/java/android/webkit/WebViewDatabase.java @@ -16,6 +16,7 @@ package android.webkit; +import android.annotation.Nullable; import android.content.Context; /** @@ -135,6 +136,7 @@ public abstract class WebViewDatabase { * @see #hasHttpAuthUsernamePassword * @see #clearHttpAuthUsernamePassword */ + @Nullable public abstract String[] getHttpAuthUsernamePassword(String host, String realm); /** diff --git a/core/java/android/widget/PopupWindow.java b/core/java/android/widget/PopupWindow.java index bf25915df211..23ebadb3806a 100644 --- a/core/java/android/widget/PopupWindow.java +++ b/core/java/android/widget/PopupWindow.java @@ -2296,8 +2296,8 @@ public class PopupWindow { } /** @hide */ - protected final void detachFromAnchor() { - final View anchor = mAnchor != null ? mAnchor.get() : null; + protected void detachFromAnchor() { + final View anchor = getAnchor(); if (anchor != null) { final ViewTreeObserver vto = anchor.getViewTreeObserver(); vto.removeOnScrollChangedListener(mOnScrollChangedListener); @@ -2316,7 +2316,7 @@ public class PopupWindow { } /** @hide */ - protected final void attachToAnchor(View anchor, int xoff, int yoff, int gravity) { + protected void attachToAnchor(View anchor, int xoff, int yoff, int gravity) { detachFromAnchor(); final ViewTreeObserver vto = anchor.getViewTreeObserver(); @@ -2339,6 +2339,11 @@ public class PopupWindow { mAnchoredGravity = gravity; } + /** @hide */ + protected @Nullable View getAnchor() { + return mAnchor != null ? mAnchor.get() : null; + } + private void alignToAnchor() { final View anchor = mAnchor != null ? mAnchor.get() : null; if (anchor != null && anchor.isAttachedToWindow() && hasDecorView()) { diff --git a/core/java/android/widget/RemoteViews.java b/core/java/android/widget/RemoteViews.java index 1653afd1ac0f..1b26f8e2fd9f 100644 --- a/core/java/android/widget/RemoteViews.java +++ b/core/java/android/widget/RemoteViews.java @@ -20,6 +20,7 @@ import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED; import android.annotation.ColorInt; import android.annotation.DimenRes; +import android.annotation.NonNull; import android.app.ActivityOptions; import android.app.ActivityThread; import android.app.Application; @@ -108,9 +109,9 @@ public class RemoteViews implements Parcelable, Filter { // The unique identifiers for each custom {@link Action}. private static final int SET_ON_CLICK_PENDING_INTENT_TAG = 1; private static final int REFLECTION_ACTION_TAG = 2; - private static final int SET_DRAWABLE_PARAMETERS_TAG = 3; + private static final int SET_DRAWABLE_TINT_TAG = 3; private static final int VIEW_GROUP_ACTION_ADD_TAG = 4; - private static final int SET_REFLECTION_ACTION_WITHOUT_PARAMS_TAG = 5; + private static final int VIEW_CONTENT_NAVIGATION_TAG = 5; private static final int SET_EMPTY_VIEW_ACTION_TAG = 6; private static final int VIEW_GROUP_ACTION_REMOVE_TAG = 7; private static final int SET_PENDING_INTENT_TEMPLATE_TAG = 8; @@ -121,7 +122,6 @@ public class RemoteViews implements Parcelable, Filter { private static final int TEXT_VIEW_SIZE_ACTION_TAG = 13; private static final int VIEW_PADDING_ACTION_TAG = 14; private static final int SET_REMOTE_VIEW_ADAPTER_LIST_TAG = 15; - private static final int TEXT_VIEW_DRAWABLE_COLOR_FILTER_ACTION_TAG = 17; private static final int SET_REMOTE_INPUTS_ACTION_TAG = 18; private static final int LAYOUT_PARAM_ACTION_TAG = 19; private static final int OVERRIDE_TEXT_COLORS_TAG = 20; @@ -389,10 +389,10 @@ public class RemoteViews implements Parcelable, Filter { return MERGE_REPLACE; } - public abstract String getActionName(); + public abstract int getActionTag(); public String getUniqueKey() { - return (getActionName() + viewId); + return (getActionTag() + "_" + viewId); } /** @@ -424,8 +424,8 @@ public class RemoteViews implements Parcelable, Filter { */ private static abstract class RuntimeAction extends Action { @Override - public final String getActionName() { - return "RuntimeAction"; + public final int getActionTag() { + return 0; } @Override @@ -514,7 +514,6 @@ public class RemoteViews implements Parcelable, Filter { } private class SetEmptyView extends Action { - int viewId; int emptyViewId; SetEmptyView(int viewId, int emptyViewId) { @@ -528,7 +527,6 @@ public class RemoteViews implements Parcelable, Filter { } public void writeToParcel(Parcel out, int flags) { - out.writeInt(SET_EMPTY_VIEW_ACTION_TAG); out.writeInt(this.viewId); out.writeInt(this.emptyViewId); } @@ -546,8 +544,9 @@ public class RemoteViews implements Parcelable, Filter { adapterView.setEmptyView(emptyView); } - public String getActionName() { - return "SetEmptyView"; + @Override + public int getActionTag() { + return SET_EMPTY_VIEW_ACTION_TAG; } } @@ -559,13 +558,12 @@ public class RemoteViews implements Parcelable, Filter { public SetOnClickFillInIntent(Parcel parcel) { viewId = parcel.readInt(); - fillInIntent = Intent.CREATOR.createFromParcel(parcel); + fillInIntent = parcel.readTypedObject(Intent.CREATOR); } public void writeToParcel(Parcel dest, int flags) { - dest.writeInt(SET_ON_CLICK_FILL_IN_INTENT_TAG); dest.writeInt(viewId); - fillInIntent.writeToParcel(dest, 0 /* no flags */); + dest.writeTypedObject(fillInIntent, 0 /* no flags */); } @Override @@ -624,8 +622,9 @@ public class RemoteViews implements Parcelable, Filter { } } - public String getActionName() { - return "SetOnClickFillInIntent"; + @Override + public int getActionTag() { + return SET_ON_CLICK_FILL_IN_INTENT_TAG; } Intent fillInIntent; @@ -643,9 +642,8 @@ public class RemoteViews implements Parcelable, Filter { } public void writeToParcel(Parcel dest, int flags) { - dest.writeInt(SET_PENDING_INTENT_TEMPLATE_TAG); dest.writeInt(viewId); - pendingIntentTemplate.writeToParcel(dest, 0 /* no flags */); + PendingIntent.writePendingIntentOrNullToParcel(pendingIntentTemplate, dest); } @Override @@ -699,8 +697,9 @@ public class RemoteViews implements Parcelable, Filter { } } - public String getActionName() { - return "SetPendingIntentTemplate"; + @Override + public int getActionTag() { + return SET_PENDING_INTENT_TEMPLATE_TAG; } PendingIntent pendingIntentTemplate; @@ -716,30 +715,13 @@ public class RemoteViews implements Parcelable, Filter { public SetRemoteViewsAdapterList(Parcel parcel) { viewId = parcel.readInt(); viewTypeCount = parcel.readInt(); - int count = parcel.readInt(); - list = new ArrayList<RemoteViews>(); - - for (int i = 0; i < count; i++) { - RemoteViews rv = RemoteViews.CREATOR.createFromParcel(parcel); - list.add(rv); - } + list = parcel.createTypedArrayList(RemoteViews.CREATOR); } public void writeToParcel(Parcel dest, int flags) { - dest.writeInt(SET_REMOTE_VIEW_ADAPTER_LIST_TAG); dest.writeInt(viewId); dest.writeInt(viewTypeCount); - - if (list == null || list.size() == 0) { - dest.writeInt(0); - } else { - int count = list.size(); - dest.writeInt(count); - for (int i = 0; i < count; i++) { - RemoteViews rv = list.get(i); - rv.writeToParcel(dest, flags); - } - } + dest.writeTypedList(list, flags); } @Override @@ -779,8 +761,9 @@ public class RemoteViews implements Parcelable, Filter { } } - public String getActionName() { - return "SetRemoteViewsAdapterList"; + @Override + public int getActionTag() { + return SET_REMOTE_VIEW_ADAPTER_LIST_TAG; } int viewTypeCount; @@ -795,13 +778,12 @@ public class RemoteViews implements Parcelable, Filter { public SetRemoteViewsAdapterIntent(Parcel parcel) { viewId = parcel.readInt(); - intent = Intent.CREATOR.createFromParcel(parcel); + intent = parcel.readTypedObject(Intent.CREATOR); } public void writeToParcel(Parcel dest, int flags) { - dest.writeInt(SET_REMOTE_VIEW_ADAPTER_INTENT_TAG); dest.writeInt(viewId); - intent.writeToParcel(dest, flags); + dest.writeTypedObject(intent, flags); } @Override @@ -845,8 +827,9 @@ public class RemoteViews implements Parcelable, Filter { return copy; } - public String getActionName() { - return "SetRemoteViewsAdapterIntent"; + @Override + public int getActionTag() { + return SET_REMOTE_VIEW_ADAPTER_INTENT_TAG; } Intent intent; @@ -866,22 +849,12 @@ public class RemoteViews implements Parcelable, Filter { public SetOnClickPendingIntent(Parcel parcel) { viewId = parcel.readInt(); - - // We check a flag to determine if the parcel contains a PendingIntent. - if (parcel.readInt() != 0) { - pendingIntent = PendingIntent.readPendingIntentOrNullFromParcel(parcel); - } + pendingIntent = PendingIntent.readPendingIntentOrNullFromParcel(parcel); } public void writeToParcel(Parcel dest, int flags) { - dest.writeInt(SET_ON_CLICK_PENDING_INTENT_TAG); dest.writeInt(viewId); - - // We use a flag to indicate whether the parcel contains a valid object. - dest.writeInt(pendingIntent != null ? 1 : 0); - if (pendingIntent != null) { - pendingIntent.writeToParcel(dest, 0 /* no flags */); - } + PendingIntent.writePendingIntentOrNullToParcel(pendingIntent, dest); } @Override @@ -922,8 +895,9 @@ public class RemoteViews implements Parcelable, Filter { target.setOnClickListener(listener); } - public String getActionName() { - return "SetOnClickPendingIntent"; + @Override + public int getActionTag() { + return SET_ON_CLICK_PENDING_INTENT_TAG; } PendingIntent pendingIntent; @@ -1012,55 +986,37 @@ public class RemoteViews implements Parcelable, Filter { } /** - * Equivalent to calling a combination of {@link Drawable#setAlpha(int)}, + * Equivalent to calling * {@link Drawable#setColorFilter(int, android.graphics.PorterDuff.Mode)}, - * and/or {@link Drawable#setLevel(int)} on the {@link Drawable} of a given view. + * on the {@link Drawable} of a given view. * <p> - * These operations will be performed on the {@link Drawable} returned by the + * The operation will be performed on the {@link Drawable} returned by the * target {@link View#getBackground()} by default. If targetBackground is false, * we assume the target is an {@link ImageView} and try applying the operations * to {@link ImageView#getDrawable()}. * <p> - * You can omit specific calls by marking their values with null or -1. */ - private class SetDrawableParameters extends Action { - public SetDrawableParameters(int id, boolean targetBackground, int alpha, - int colorFilter, PorterDuff.Mode mode, int level) { + private class SetDrawableTint extends Action { + SetDrawableTint(int id, boolean targetBackground, + int colorFilter, @NonNull PorterDuff.Mode mode) { this.viewId = id; this.targetBackground = targetBackground; - this.alpha = alpha; this.colorFilter = colorFilter; this.filterMode = mode; - this.level = level; } - public SetDrawableParameters(Parcel parcel) { + SetDrawableTint(Parcel parcel) { viewId = parcel.readInt(); targetBackground = parcel.readInt() != 0; - alpha = parcel.readInt(); colorFilter = parcel.readInt(); - boolean hasMode = parcel.readInt() != 0; - if (hasMode) { - filterMode = PorterDuff.Mode.valueOf(parcel.readString()); - } else { - filterMode = null; - } - level = parcel.readInt(); + filterMode = PorterDuff.intToMode(parcel.readInt()); } public void writeToParcel(Parcel dest, int flags) { - dest.writeInt(SET_DRAWABLE_PARAMETERS_TAG); dest.writeInt(viewId); dest.writeInt(targetBackground ? 1 : 0); - dest.writeInt(alpha); dest.writeInt(colorFilter); - if (filterMode != null) { - dest.writeInt(1); - dest.writeString(filterMode.toString()); - } else { - dest.writeInt(0); - } - dest.writeInt(level); + dest.writeInt(PorterDuff.modeToInt(filterMode)); } @Override @@ -1078,47 +1034,36 @@ public class RemoteViews implements Parcelable, Filter { } if (targetDrawable != null) { - // Perform modifications only if values are set correctly - if (alpha != -1) { - targetDrawable.mutate().setAlpha(alpha); - } - if (filterMode != null) { - targetDrawable.mutate().setColorFilter(colorFilter, filterMode); - } - if (level != -1) { - targetDrawable.mutate().setLevel(level); - } + targetDrawable.mutate().setColorFilter(colorFilter, filterMode); } } - public String getActionName() { - return "SetDrawableParameters"; + @Override + public int getActionTag() { + return SET_DRAWABLE_TINT_TAG; } boolean targetBackground; - int alpha; int colorFilter; PorterDuff.Mode filterMode; - int level; } - private final class ReflectionActionWithoutParams extends Action { - final String methodName; + private final class ViewContentNavigation extends Action { + final boolean mNext; - ReflectionActionWithoutParams(int viewId, String methodName) { + ViewContentNavigation(int viewId, boolean next) { this.viewId = viewId; - this.methodName = methodName; + this.mNext = next; } - ReflectionActionWithoutParams(Parcel in) { + ViewContentNavigation(Parcel in) { this.viewId = in.readInt(); - this.methodName = in.readString(); + this.mNext = in.readBoolean(); } public void writeToParcel(Parcel out, int flags) { - out.writeInt(SET_REFLECTION_ACTION_WITHOUT_PARAMS_TAG); out.writeInt(this.viewId); - out.writeString(this.methodName); + out.writeBoolean(this.mNext); } @Override @@ -1127,23 +1072,20 @@ public class RemoteViews implements Parcelable, Filter { if (view == null) return; try { - getMethod(view, this.methodName, null, false /* async */).invoke(view); + getMethod(view, + mNext ? "showNext" : "showPrevious", null, false /* async */).invoke(view); } catch (Throwable ex) { throw new ActionException(ex); } } public int mergeBehavior() { - // we don't need to build up showNext or showPrevious calls - if (methodName.equals("showNext") || methodName.equals("showPrevious")) { - return MERGE_IGNORE; - } else { - return MERGE_REPLACE; - } + return MERGE_IGNORE; } - public String getActionName() { - return "ReflectionActionWithoutParams"; + @Override + public int getActionTag() { + return VIEW_CONTENT_NAVIGATION_TAG; } } @@ -1157,12 +1099,7 @@ public class RemoteViews implements Parcelable, Filter { } public BitmapCache(Parcel source) { - int count = source.readInt(); - mBitmaps = new ArrayList<>(count); - for (int i = 0; i < count; i++) { - Bitmap b = Bitmap.CREATOR.createFromParcel(source); - mBitmaps.add(b); - } + mBitmaps = source.createTypedArrayList(Bitmap.CREATOR); } public int getBitmapId(Bitmap b) { @@ -1188,11 +1125,7 @@ public class RemoteViews implements Parcelable, Filter { } public void writeBitmapsToParcel(Parcel dest, int flags) { - int count = mBitmaps.size(); - dest.writeInt(count); - for (int i = 0; i < count; i++) { - mBitmaps.get(i).writeToParcel(dest, flags); - } + dest.writeTypedList(mBitmaps, flags); } public int getBitmapMemory() { @@ -1228,7 +1161,6 @@ public class RemoteViews implements Parcelable, Filter { @Override public void writeToParcel(Parcel dest, int flags) { - dest.writeInt(BITMAP_REFLECTION_ACTION_TAG); dest.writeInt(viewId); dest.writeString(methodName); dest.writeInt(bitmapId); @@ -1247,8 +1179,9 @@ public class RemoteViews implements Parcelable, Filter { bitmapId = bitmapCache.getBitmapId(bitmap); } - public String getActionName() { - return "BitmapReflectionAction"; + @Override + public int getActionTag() { + return BITMAP_REFLECTION_ACTION_TAG; } } @@ -1300,7 +1233,7 @@ public class RemoteViews implements Parcelable, Filter { // written to the parcel. switch (this.type) { case BOOLEAN: - this.value = in.readInt() != 0; + this.value = in.readBoolean(); break; case BYTE: this.value = in.readByte(); @@ -1330,39 +1263,28 @@ public class RemoteViews implements Parcelable, Filter { this.value = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(in); break; case URI: - if (in.readInt() != 0) { - this.value = Uri.CREATOR.createFromParcel(in); - } + this.value = in.readTypedObject(Uri.CREATOR); break; case BITMAP: - if (in.readInt() != 0) { - this.value = Bitmap.CREATOR.createFromParcel(in); - } + this.value = in.readTypedObject(Bitmap.CREATOR); break; case BUNDLE: this.value = in.readBundle(); break; case INTENT: - if (in.readInt() != 0) { - this.value = Intent.CREATOR.createFromParcel(in); - } + this.value = in.readTypedObject(Intent.CREATOR); break; case COLOR_STATE_LIST: - if (in.readInt() != 0) { - this.value = ColorStateList.CREATOR.createFromParcel(in); - } + this.value = in.readTypedObject(ColorStateList.CREATOR); break; case ICON: - if (in.readInt() != 0) { - this.value = Icon.CREATOR.createFromParcel(in); - } + this.value = in.readTypedObject(Icon.CREATOR); default: break; } } public void writeToParcel(Parcel out, int flags) { - out.writeInt(REFLECTION_ACTION_TAG); out.writeInt(this.viewId); out.writeString(this.methodName); out.writeInt(this.type); @@ -1376,7 +1298,7 @@ public class RemoteViews implements Parcelable, Filter { // we have written a valid value to the parcel. switch (this.type) { case BOOLEAN: - out.writeInt((Boolean) this.value ? 1 : 0); + out.writeBoolean((Boolean) this.value); break; case BYTE: out.writeByte((Byte) this.value); @@ -1413,10 +1335,7 @@ public class RemoteViews implements Parcelable, Filter { case INTENT: case COLOR_STATE_LIST: case ICON: - out.writeInt(this.value != null ? 1 : 0); - if (this.value != null) { - ((Parcelable) this.value).writeToParcel(out, flags); - } + out.writeTypedObject((Parcelable) this.value, flags); break; default: break; @@ -1522,10 +1441,16 @@ public class RemoteViews implements Parcelable, Filter { } } - public String getActionName() { + @Override + public int getActionTag() { + return REFLECTION_ACTION_TAG; + } + + @Override + public String getUniqueKey() { // Each type of reflection action corresponds to a setter, so each should be seen as // unique from the standpoint of merging. - return "ReflectionAction" + this.methodName + this.type; + return super.getUniqueKey() + this.methodName + this.type; } @Override @@ -1587,7 +1512,6 @@ public class RemoteViews implements Parcelable, Filter { } public void writeToParcel(Parcel dest, int flags) { - dest.writeInt(VIEW_GROUP_ACTION_ADD_TAG); dest.writeInt(viewId); dest.writeInt(mIndex); mNestedViews.writeToParcel(dest, flags); @@ -1662,10 +1586,9 @@ public class RemoteViews implements Parcelable, Filter { return mNestedViews.prefersAsyncApply(); } - @Override - public String getActionName() { - return "ViewGroupActionAdd"; + public int getActionTag() { + return VIEW_GROUP_ACTION_ADD_TAG; } } @@ -1697,7 +1620,6 @@ public class RemoteViews implements Parcelable, Filter { } public void writeToParcel(Parcel dest, int flags) { - dest.writeInt(VIEW_GROUP_ACTION_REMOVE_TAG); dest.writeInt(viewId); dest.writeInt(mViewIdToKeep); } @@ -1763,8 +1685,8 @@ public class RemoteViews implements Parcelable, Filter { } @Override - public String getActionName() { - return "ViewGroupActionRemove"; + public int getActionTag() { + return VIEW_GROUP_ACTION_REMOVE_TAG; } @Override @@ -1804,18 +1726,10 @@ public class RemoteViews implements Parcelable, Filter { isRelative = (parcel.readInt() != 0); useIcons = (parcel.readInt() != 0); if (useIcons) { - if (parcel.readInt() != 0) { - i1 = Icon.CREATOR.createFromParcel(parcel); - } - if (parcel.readInt() != 0) { - i2 = Icon.CREATOR.createFromParcel(parcel); - } - if (parcel.readInt() != 0) { - i3 = Icon.CREATOR.createFromParcel(parcel); - } - if (parcel.readInt() != 0) { - i4 = Icon.CREATOR.createFromParcel(parcel); - } + i1 = parcel.readTypedObject(Icon.CREATOR); + i2 = parcel.readTypedObject(Icon.CREATOR); + i3 = parcel.readTypedObject(Icon.CREATOR); + i4 = parcel.readTypedObject(Icon.CREATOR); } else { d1 = parcel.readInt(); d2 = parcel.readInt(); @@ -1825,35 +1739,14 @@ public class RemoteViews implements Parcelable, Filter { } public void writeToParcel(Parcel dest, int flags) { - dest.writeInt(TEXT_VIEW_DRAWABLE_ACTION_TAG); dest.writeInt(viewId); dest.writeInt(isRelative ? 1 : 0); dest.writeInt(useIcons ? 1 : 0); if (useIcons) { - if (i1 != null) { - dest.writeInt(1); - i1.writeToParcel(dest, 0); - } else { - dest.writeInt(0); - } - if (i2 != null) { - dest.writeInt(1); - i2.writeToParcel(dest, 0); - } else { - dest.writeInt(0); - } - if (i3 != null) { - dest.writeInt(1); - i3.writeToParcel(dest, 0); - } else { - dest.writeInt(0); - } - if (i4 != null) { - dest.writeInt(1); - i4.writeToParcel(dest, 0); - } else { - dest.writeInt(0); - } + dest.writeTypedObject(i1, 0); + dest.writeTypedObject(i2, 0); + dest.writeTypedObject(i3, 0); + dest.writeTypedObject(i4, 0); } else { dest.writeInt(d1); dest.writeInt(d2); @@ -1924,8 +1817,9 @@ public class RemoteViews implements Parcelable, Filter { return useIcons; } - public String getActionName() { - return "TextViewDrawableAction"; + @Override + public int getActionTag() { + return TEXT_VIEW_DRAWABLE_ACTION_TAG; } boolean isRelative = false; @@ -1954,7 +1848,6 @@ public class RemoteViews implements Parcelable, Filter { } public void writeToParcel(Parcel dest, int flags) { - dest.writeInt(TEXT_VIEW_SIZE_ACTION_TAG); dest.writeInt(viewId); dest.writeInt(units); dest.writeFloat(size); @@ -1967,8 +1860,9 @@ public class RemoteViews implements Parcelable, Filter { target.setTextSize(units, size); } - public String getActionName() { - return "TextViewSizeAction"; + @Override + public int getActionTag() { + return TEXT_VIEW_SIZE_ACTION_TAG; } int units; @@ -1996,7 +1890,6 @@ public class RemoteViews implements Parcelable, Filter { } public void writeToParcel(Parcel dest, int flags) { - dest.writeInt(VIEW_PADDING_ACTION_TAG); dest.writeInt(viewId); dest.writeInt(left); dest.writeInt(top); @@ -2011,8 +1904,9 @@ public class RemoteViews implements Parcelable, Filter { target.setPadding(left, top, right, bottom); } - public String getActionName() { - return "ViewPaddingAction"; + @Override + public int getActionTag() { + return VIEW_PADDING_ACTION_TAG; } int left, top, right, bottom; @@ -2029,6 +1923,9 @@ public class RemoteViews implements Parcelable, Filter { public static final int LAYOUT_WIDTH = 2; public static final int LAYOUT_MARGIN_BOTTOM_DIMEN = 3; + final int mProperty; + final int mValue; + /** * @param viewId ID of the view alter * @param property which layout parameter to alter @@ -2036,21 +1933,20 @@ public class RemoteViews implements Parcelable, Filter { */ public LayoutParamAction(int viewId, int property, int value) { this.viewId = viewId; - this.property = property; - this.value = value; + this.mProperty = property; + this.mValue = value; } public LayoutParamAction(Parcel parcel) { viewId = parcel.readInt(); - property = parcel.readInt(); - value = parcel.readInt(); + mProperty = parcel.readInt(); + mValue = parcel.readInt(); } public void writeToParcel(Parcel dest, int flags) { - dest.writeInt(LAYOUT_PARAM_ACTION_TAG); dest.writeInt(viewId); - dest.writeInt(property); - dest.writeInt(value); + dest.writeInt(mProperty); + dest.writeInt(mValue); } @Override @@ -2063,27 +1959,27 @@ public class RemoteViews implements Parcelable, Filter { if (layoutParams == null) { return; } - switch (property) { + switch (mProperty) { case LAYOUT_MARGIN_END_DIMEN: if (layoutParams instanceof ViewGroup.MarginLayoutParams) { - int resolved = resolveDimenPixelOffset(target, value); + int resolved = resolveDimenPixelOffset(target, mValue); ((ViewGroup.MarginLayoutParams) layoutParams).setMarginEnd(resolved); target.setLayoutParams(layoutParams); } break; case LAYOUT_MARGIN_BOTTOM_DIMEN: if (layoutParams instanceof ViewGroup.MarginLayoutParams) { - int resolved = resolveDimenPixelOffset(target, value); + int resolved = resolveDimenPixelOffset(target, mValue); ((ViewGroup.MarginLayoutParams) layoutParams).bottomMargin = resolved; target.setLayoutParams(layoutParams); } break; case LAYOUT_WIDTH: - layoutParams.width = value; + layoutParams.width = mValue; target.setLayoutParams(layoutParams); break; default: - throw new IllegalArgumentException("Unknown property " + property); + throw new IllegalArgumentException("Unknown property " + mProperty); } } @@ -2094,79 +1990,15 @@ public class RemoteViews implements Parcelable, Filter { return target.getContext().getResources().getDimensionPixelOffset(value); } - public String getActionName() { - return "LayoutParamAction" + property + "."; - } - - int property; - int value; - } - - /** - * Helper action to set a color filter on a compound drawable on a TextView. Supports relative - * (s/t/e/b) or cardinal (l/t/r/b) arrangement. - */ - private class TextViewDrawableColorFilterAction extends Action { - public TextViewDrawableColorFilterAction(int viewId, boolean isRelative, int index, - int color, PorterDuff.Mode mode) { - this.viewId = viewId; - this.isRelative = isRelative; - this.index = index; - this.color = color; - this.mode = mode; - } - - public TextViewDrawableColorFilterAction(Parcel parcel) { - viewId = parcel.readInt(); - isRelative = (parcel.readInt() != 0); - index = parcel.readInt(); - color = parcel.readInt(); - mode = readPorterDuffMode(parcel); - } - - private PorterDuff.Mode readPorterDuffMode(Parcel parcel) { - int mode = parcel.readInt(); - if (mode >= 0 && mode < PorterDuff.Mode.values().length) { - return PorterDuff.Mode.values()[mode]; - } else { - return PorterDuff.Mode.CLEAR; - } - } - - public void writeToParcel(Parcel dest, int flags) { - dest.writeInt(TEXT_VIEW_DRAWABLE_COLOR_FILTER_ACTION_TAG); - dest.writeInt(viewId); - dest.writeInt(isRelative ? 1 : 0); - dest.writeInt(index); - dest.writeInt(color); - dest.writeInt(mode.ordinal()); - } - @Override - public void apply(View root, ViewGroup rootParent, OnClickHandler handler) { - final TextView target = root.findViewById(viewId); - if (target == null) return; - Drawable[] drawables = isRelative - ? target.getCompoundDrawablesRelative() - : target.getCompoundDrawables(); - if (index < 0 || index >= 4) { - throw new IllegalStateException("index must be in range [0, 3]."); - } - Drawable d = drawables[index]; - if (d != null) { - d.mutate(); - d.setColorFilter(color, mode); - } + public int getActionTag() { + return LAYOUT_PARAM_ACTION_TAG; } - public String getActionName() { - return "TextViewDrawableColorFilterAction"; + @Override + public String getUniqueKey() { + return super.getUniqueKey() + mProperty; } - - final boolean isRelative; - final int index; - final int color; - final PorterDuff.Mode mode; } /** @@ -2185,7 +2017,6 @@ public class RemoteViews implements Parcelable, Filter { } public void writeToParcel(Parcel dest, int flags) { - dest.writeInt(SET_REMOTE_INPUTS_ACTION_TAG); dest.writeInt(viewId); dest.writeTypedArray(remoteInputs, flags); } @@ -2198,8 +2029,9 @@ public class RemoteViews implements Parcelable, Filter { target.setTagInternal(R.id.remote_input_tag, remoteInputs); } - public String getActionName() { - return "SetRemoteInputsAction"; + @Override + public int getActionTag() { + return SET_REMOTE_INPUTS_ACTION_TAG; } final Parcelable[] remoteInputs; @@ -2221,7 +2053,6 @@ public class RemoteViews implements Parcelable, Filter { } public void writeToParcel(Parcel dest, int flags) { - dest.writeInt(OVERRIDE_TEXT_COLORS_TAG); dest.writeInt(textColor); } @@ -2246,8 +2077,9 @@ public class RemoteViews implements Parcelable, Filter { } } - public String getActionName() { - return "OverrideTextColorsAction"; + @Override + public int getActionTag() { + return OVERRIDE_TEXT_COLORS_TAG; } } @@ -2340,7 +2172,7 @@ public class RemoteViews implements Parcelable, Filter { if (src.mActions != null) { Parcel p = Parcel.obtain(); - writeActionsToParcel(p); + src.writeActionsToParcel(p); p.setDataPosition(0); // Since src is already in memory, we do not care about stack overflow as it has // already been read once. @@ -2411,16 +2243,16 @@ public class RemoteViews implements Parcelable, Filter { switch (tag) { case SET_ON_CLICK_PENDING_INTENT_TAG: return new SetOnClickPendingIntent(parcel); - case SET_DRAWABLE_PARAMETERS_TAG: - return new SetDrawableParameters(parcel); + case SET_DRAWABLE_TINT_TAG: + return new SetDrawableTint(parcel); case REFLECTION_ACTION_TAG: return new ReflectionAction(parcel); case VIEW_GROUP_ACTION_ADD_TAG: return new ViewGroupActionAdd(parcel, mBitmapCache, mApplication, depth); case VIEW_GROUP_ACTION_REMOVE_TAG: return new ViewGroupActionRemove(parcel); - case SET_REFLECTION_ACTION_WITHOUT_PARAMS_TAG: - return new ReflectionActionWithoutParams(parcel); + case VIEW_CONTENT_NAVIGATION_TAG: + return new ViewContentNavigation(parcel); case SET_EMPTY_VIEW_ACTION_TAG: return new SetEmptyView(parcel); case SET_PENDING_INTENT_TEMPLATE_TAG: @@ -2439,8 +2271,6 @@ public class RemoteViews implements Parcelable, Filter { return new BitmapReflectionAction(parcel); case SET_REMOTE_VIEW_ADAPTER_LIST_TAG: return new SetRemoteViewsAdapterList(parcel); - case TEXT_VIEW_DRAWABLE_COLOR_FILTER_ACTION_TAG: - return new TextViewDrawableColorFilterAction(parcel); case SET_REMOTE_INPUTS_ACTION_TAG: return new SetRemoteInputsAction(parcel); case LAYOUT_PARAM_ACTION_TAG: @@ -2597,7 +2427,7 @@ public class RemoteViews implements Parcelable, Filter { * @param viewId The id of the view on which to call {@link AdapterViewAnimator#showNext()} */ public void showNext(int viewId) { - addAction(new ReflectionActionWithoutParams(viewId, "showNext")); + addAction(new ViewContentNavigation(viewId, true /* next */)); } /** @@ -2606,7 +2436,7 @@ public class RemoteViews implements Parcelable, Filter { * @param viewId The id of the view on which to call {@link AdapterViewAnimator#showPrevious()} */ public void showPrevious(int viewId) { - addAction(new ReflectionActionWithoutParams(viewId, "showPrevious")); + addAction(new ViewContentNavigation(viewId, false /* next */)); } /** @@ -2680,28 +2510,6 @@ public class RemoteViews implements Parcelable, Filter { } /** - * Equivalent to applying a color filter on one of the drawables in - * {@link android.widget.TextView#getCompoundDrawablesRelative()}. - * - * @param viewId The id of the view whose text should change. - * @param index The index of the drawable in the array of - * {@link android.widget.TextView#getCompoundDrawablesRelative()} to set the color - * filter on. Must be in [0, 3]. - * @param color The color of the color filter. See - * {@link Drawable#setColorFilter(int, android.graphics.PorterDuff.Mode)}. - * @param mode The mode of the color filter. See - * {@link Drawable#setColorFilter(int, android.graphics.PorterDuff.Mode)}. - * @hide - */ - public void setTextViewCompoundDrawablesRelativeColorFilter(int viewId, - int index, int color, PorterDuff.Mode mode) { - if (index < 0 || index >= 4) { - throw new IllegalArgumentException("index must be in range [0, 3]."); - } - addAction(new TextViewDrawableColorFilterAction(viewId, true, index, color, mode)); - } - - /** * Equivalent to calling {@link * TextView#setCompoundDrawablesWithIntrinsicBounds(Drawable, Drawable, Drawable, Drawable)} * using the drawables yielded by {@link Icon#loadDrawable(Context)}. @@ -2898,12 +2706,10 @@ public class RemoteViews implements Parcelable, Filter { /** * @hide - * Equivalent to calling a combination of {@link Drawable#setAlpha(int)}, + * Equivalent to calling * {@link Drawable#setColorFilter(int, android.graphics.PorterDuff.Mode)}, - * and/or {@link Drawable#setLevel(int)} on the {@link Drawable} of a given - * view. + * on the {@link Drawable} of a given view. * <p> - * You can omit specific calls by marking their values with null or -1. * * @param viewId The id of the view that contains the target * {@link Drawable} @@ -2912,20 +2718,15 @@ public class RemoteViews implements Parcelable, Filter { * {@link android.view.View#getBackground()}. Otherwise, assume * the target view is an {@link ImageView} and apply them to * {@link ImageView#getDrawable()}. - * @param alpha Specify an alpha value for the drawable, or -1 to leave - * unchanged. * @param colorFilter Specify a color for a * {@link android.graphics.ColorFilter} for this drawable. This will be ignored if * {@code mode} is {@code null}. * @param mode Specify a PorterDuff mode for this drawable, or null to leave * unchanged. - * @param level Specify the level for the drawable, or -1 to leave - * unchanged. */ - public void setDrawableParameters(int viewId, boolean targetBackground, int alpha, - int colorFilter, PorterDuff.Mode mode, int level) { - addAction(new SetDrawableParameters(viewId, targetBackground, alpha, - colorFilter, mode, level)); + public void setDrawableTint(int viewId, boolean targetBackground, + int colorFilter, @NonNull PorterDuff.Mode mode) { + addAction(new SetDrawableTint(viewId, targetBackground, colorFilter, mode)); } /** @@ -3717,6 +3518,7 @@ public class RemoteViews implements Parcelable, Filter { parcel.writeInt(count); for (int i = 0; i < count; i++) { Action a = mActions.get(i); + parcel.writeInt(a.getActionTag()); a.writeToParcel(parcel, a.hasSameAppInfo(mApplication) ? PARCELABLE_ELIDE_DUPLICATES : 0); } diff --git a/core/java/android/widget/SelectionActionModeHelper.java b/core/java/android/widget/SelectionActionModeHelper.java index 36dc3308a721..c7f22e6e8465 100644 --- a/core/java/android/widget/SelectionActionModeHelper.java +++ b/core/java/android/widget/SelectionActionModeHelper.java @@ -58,6 +58,8 @@ import java.util.regex.Pattern; @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE) public final class SelectionActionModeHelper { + private static final String LOG_TAG = "SelectActionModeHelper"; + /** * Maximum time (in milliseconds) to wait for a result before timing out. */ @@ -83,7 +85,8 @@ public final class SelectionActionModeHelper { mEditor = Preconditions.checkNotNull(editor); mTextView = mEditor.getTextView(); mTextClassificationHelper = new TextClassificationHelper( - mTextView.getTextClassifier(), mTextView.getText(), + mTextView.getTextClassifier(), + getText(mTextView), 0, 1, mTextView.getTextLocales()); mSelectionTracker = new SelectionTracker(mTextView); @@ -97,7 +100,7 @@ public final class SelectionActionModeHelper { public void startActionModeAsync(boolean adjustSelection) { mSelectionTracker.onOriginalSelection( - mTextView.getText(), + getText(mTextView), mTextView.getSelectionStart(), mTextView.getSelectionEnd(), mTextView.isTextEditable()); @@ -195,7 +198,7 @@ public final class SelectionActionModeHelper { } private void startActionMode(@Nullable SelectionResult result) { - final CharSequence text = mTextView.getText(); + final CharSequence text = getText(mTextView); if (result != null && text instanceof Spannable) { Selection.setSelection((Spannable) text, result.mStart, result.mEnd); mTextClassification = result.mClassification; @@ -356,7 +359,9 @@ public final class SelectionActionModeHelper { } private void resetTextClassificationHelper() { - mTextClassificationHelper.reset(mTextView.getTextClassifier(), mTextView.getText(), + mTextClassificationHelper.reset( + mTextView.getTextClassifier(), + getText(mTextView), mTextView.getSelectionStart(), mTextView.getSelectionEnd(), mTextView.getTextLocales()); } @@ -382,6 +387,7 @@ public final class SelectionActionModeHelper { private int mSelectionStart; private int mSelectionEnd; private boolean mAllowReset; + private final LogAbandonRunnable mDelayedLogAbandon = new LogAbandonRunnable(); SelectionTracker(TextView textView) { mTextView = Preconditions.checkNotNull(textView); @@ -393,6 +399,10 @@ public final class SelectionActionModeHelper { */ public void onOriginalSelection( CharSequence text, int selectionStart, int selectionEnd, boolean editableText) { + // If we abandoned a selection and created a new one very shortly after, we may still + // have a pending request to log ABANDON, which we flush here. + mDelayedLogAbandon.flush(); + mOriginalStart = mSelectionStart = selectionStart; mOriginalEnd = mSelectionEnd = selectionEnd; mAllowReset = false; @@ -433,12 +443,7 @@ public final class SelectionActionModeHelper { public void onSelectionDestroyed() { mAllowReset = false; // Wait a few ms to see if the selection was destroyed because of a text change event. - mTextView.postDelayed(() -> { - mLogger.logSelectionAction( - mSelectionStart, mSelectionEnd, - SelectionEvent.ActionType.ABANDON, null /* classification */); - mSelectionStart = mSelectionEnd = -1; - }, 100 /* ms */); + mDelayedLogAbandon.schedule(100 /* ms */); } /** @@ -465,7 +470,7 @@ public final class SelectionActionModeHelper { if (isSelectionStarted() && mAllowReset && textIndex >= mSelectionStart && textIndex <= mSelectionEnd - && textView.getText() instanceof Spannable) { + && getText(textView) instanceof Spannable) { mAllowReset = false; boolean selected = editor.selectCurrentWord(); if (selected) { @@ -495,6 +500,38 @@ public final class SelectionActionModeHelper { private boolean isSelectionStarted() { return mSelectionStart >= 0 && mSelectionEnd >= 0 && mSelectionStart != mSelectionEnd; } + + /** A helper for keeping track of pending abandon logging requests. */ + private final class LogAbandonRunnable implements Runnable { + private boolean mIsPending; + + /** Schedules an abandon to be logged with the given delay. Flush if necessary. */ + void schedule(int delayMillis) { + if (mIsPending) { + Log.e(LOG_TAG, "Force flushing abandon due to new scheduling request"); + flush(); + } + mIsPending = true; + mTextView.postDelayed(this, delayMillis); + } + + /** If there is a pending log request, execute it now. */ + void flush() { + mTextView.removeCallbacks(this); + run(); + } + + @Override + public void run() { + if (mIsPending) { + mLogger.logSelectionAction( + mSelectionStart, mSelectionEnd, + SelectionEvent.ActionType.ABANDON, null /* classification */); + mSelectionStart = mSelectionEnd = -1; + mIsPending = false; + } + } + } } // TODO: Write tests @@ -689,7 +726,7 @@ public final class SelectionActionModeHelper { mSelectionResultSupplier = Preconditions.checkNotNull(selectionResultSupplier); mSelectionResultCallback = Preconditions.checkNotNull(selectionResultCallback); // Make a copy of the original text. - mOriginalText = mTextView.getText().toString(); + mOriginalText = getText(mTextView).toString(); } @Override @@ -705,7 +742,7 @@ public final class SelectionActionModeHelper { @Override @UiThread protected void onPostExecute(SelectionResult result) { - result = TextUtils.equals(mOriginalText, mTextView.getText()) ? result : null; + result = TextUtils.equals(mOriginalText, getText(mTextView)) ? result : null; mSelectionResultCallback.accept(result); } @@ -854,4 +891,14 @@ public final class SelectionActionModeHelper { return SelectionEvent.ActionType.OTHER; } } + + private static CharSequence getText(TextView textView) { + // Extracts the textView's text. + // TODO: Investigate why/when TextView.getText() is null. + final CharSequence text = textView.getText(); + if (text != null) { + return text; + } + return ""; + } } diff --git a/core/java/com/android/internal/app/ChooserActivity.java b/core/java/com/android/internal/app/ChooserActivity.java index 2cab009f7354..eb639bd98d49 100644 --- a/core/java/com/android/internal/app/ChooserActivity.java +++ b/core/java/com/android/internal/app/ChooserActivity.java @@ -1450,11 +1450,16 @@ public class ChooserActivity extends ResolverActivity { getFirstRowPosition(rowPosition + 1)); int serviceSpacing = holder.row.getContext().getResources() .getDimensionPixelSize(R.dimen.chooser_service_spacing); - int top = rowPosition == 0 ? serviceSpacing : 0; - if (nextStartType != ChooserListAdapter.TARGET_SERVICE) { - setVertPadding(holder, top, serviceSpacing); + if (rowPosition == 0 && nextStartType != ChooserListAdapter.TARGET_SERVICE) { + // if the row is the only row for target service + setVertPadding(holder, 0, 0); } else { - setVertPadding(holder, top, 0); + int top = rowPosition == 0 ? serviceSpacing : 0; + if (nextStartType != ChooserListAdapter.TARGET_SERVICE) { + setVertPadding(holder, top, serviceSpacing); + } else { + setVertPadding(holder, top, 0); + } } } else { holder.row.setBackgroundColor(Color.TRANSPARENT); diff --git a/core/java/com/android/internal/app/ShutdownActivity.java b/core/java/com/android/internal/app/ShutdownActivity.java index 745d28f367a3..f81e83836e18 100644 --- a/core/java/com/android/internal/app/ShutdownActivity.java +++ b/core/java/com/android/internal/app/ShutdownActivity.java @@ -41,6 +41,9 @@ public class ShutdownActivity extends Activity { mReboot = Intent.ACTION_REBOOT.equals(intent.getAction()); mConfirm = intent.getBooleanExtra(Intent.EXTRA_KEY_CONFIRM, false); mUserRequested = intent.getBooleanExtra(Intent.EXTRA_USER_REQUESTED_SHUTDOWN, false); + final String reason = mUserRequested + ? PowerManager.SHUTDOWN_USER_REQUESTED + : intent.getStringExtra(Intent.EXTRA_REASON); Slog.i(TAG, "onCreate(): confirm=" + mConfirm); Thread thr = new Thread("ShutdownActivity") { @@ -52,9 +55,7 @@ public class ShutdownActivity extends Activity { if (mReboot) { pm.reboot(mConfirm, null, false); } else { - pm.shutdown(mConfirm, - mUserRequested ? PowerManager.SHUTDOWN_USER_REQUESTED : null, - false); + pm.shutdown(mConfirm, reason, false); } } catch (RemoteException e) { } diff --git a/core/java/com/android/internal/util/RingBuffer.java b/core/java/com/android/internal/util/RingBuffer.java new file mode 100644 index 000000000000..ad84353f23a9 --- /dev/null +++ b/core/java/com/android/internal/util/RingBuffer.java @@ -0,0 +1,67 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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.internal.util; + +import static com.android.internal.util.Preconditions.checkArgumentPositive; + +import java.lang.reflect.Array; +import java.util.Arrays; + +/** + * A simple ring buffer structure with bounded capacity backed by an array. + * Events can always be added at the logical end of the buffer. If the buffer is + * full, oldest events are dropped when new events are added. + * {@hide} + */ +public class RingBuffer<T> { + + // Array for storing events. + private final T[] mBuffer; + // Cursor keeping track of the logical end of the array. This cursor never + // wraps and instead keeps track of the total number of append() operations. + private long mCursor = 0; + + public RingBuffer(Class<T> c, int capacity) { + checkArgumentPositive(capacity, "A RingBuffer cannot have 0 capacity"); + // Java cannot create generic arrays without a runtime hint. + mBuffer = (T[]) Array.newInstance(c, capacity); + } + + public int size() { + return (int) Math.min(mBuffer.length, (long) mCursor); + } + + public void append(T t) { + mBuffer[indexOf(mCursor++)] = t; + } + + public T[] toArray() { + // Only generic way to create a T[] from another T[] + T[] out = Arrays.copyOf(mBuffer, size(), (Class<T[]>) mBuffer.getClass()); + // Reverse iteration from youngest event to oldest event. + long inCursor = mCursor - 1; + int outIdx = out.length - 1; + while (outIdx >= 0) { + out[outIdx--] = (T) mBuffer[indexOf(inCursor--)]; + } + return out; + } + + private int indexOf(long cursor) { + return (int) Math.abs(cursor % mBuffer.length); + } +} diff --git a/core/java/com/android/internal/widget/LockPatternUtils.java b/core/java/com/android/internal/widget/LockPatternUtils.java index b8ef82b8c1d9..4be6b28ad95c 100644 --- a/core/java/com/android/internal/widget/LockPatternUtils.java +++ b/core/java/com/android/internal/widget/LockPatternUtils.java @@ -303,7 +303,7 @@ public class LockPatternUtils { } public void reportFailedPasswordAttempt(int userId) { - if (userId == USER_FRP && frpCredentialEnabled()) { + if (userId == USER_FRP && frpCredentialEnabled(mContext)) { return; } getDevicePolicyManager().reportFailedPasswordAttempt(userId); @@ -311,7 +311,7 @@ public class LockPatternUtils { } public void reportSuccessfulPasswordAttempt(int userId) { - if (userId == USER_FRP && frpCredentialEnabled()) { + if (userId == USER_FRP && frpCredentialEnabled(mContext)) { return; } getDevicePolicyManager().reportSuccessfulPasswordAttempt(userId); @@ -319,21 +319,21 @@ public class LockPatternUtils { } public void reportPasswordLockout(int timeoutMs, int userId) { - if (userId == USER_FRP && frpCredentialEnabled()) { + if (userId == USER_FRP && frpCredentialEnabled(mContext)) { return; } getTrustManager().reportUnlockLockout(timeoutMs, userId); } public int getCurrentFailedPasswordAttempts(int userId) { - if (userId == USER_FRP && frpCredentialEnabled()) { + if (userId == USER_FRP && frpCredentialEnabled(mContext)) { return 0; } return getDevicePolicyManager().getCurrentFailedPasswordAttempts(userId); } public int getMaximumFailedPasswordsForWipe(int userId) { - if (userId == USER_FRP && frpCredentialEnabled()) { + if (userId == USER_FRP && frpCredentialEnabled(mContext)) { return 0; } return getDevicePolicyManager().getMaximumFailedPasswordsForWipe( @@ -1774,11 +1774,12 @@ public class LockPatternUtils { return getLong(SYNTHETIC_PASSWORD_ENABLED_KEY, 0, UserHandle.USER_SYSTEM) != 0; } - public static boolean userOwnsFrpCredential(UserInfo info) { - return info != null && info.isPrimary() && info.isAdmin() && frpCredentialEnabled(); + public static boolean userOwnsFrpCredential(Context context, UserInfo info) { + return info != null && info.isPrimary() && info.isAdmin() && frpCredentialEnabled(context); } - public static boolean frpCredentialEnabled() { - return FRP_CREDENTIAL_ENABLED; + public static boolean frpCredentialEnabled(Context context) { + return FRP_CREDENTIAL_ENABLED && context.getResources().getBoolean( + com.android.internal.R.bool.config_enableCredentialFactoryResetProtection); } } diff --git a/core/jni/Android.bp b/core/jni/Android.bp index d63e22c189f8..016c0c8e37df 100644 --- a/core/jni/Android.bp +++ b/core/jni/Android.bp @@ -239,7 +239,6 @@ cc_library_shared { "libinput", "libcamera_client", "libcamera_metadata", - "libskia", "libsqlite", "libEGL", "libGLESv1_CM", diff --git a/core/jni/android/graphics/FontFamily.cpp b/core/jni/android/graphics/FontFamily.cpp index 0ba27f61d3a0..c6801bf613fa 100644 --- a/core/jni/android/graphics/FontFamily.cpp +++ b/core/jni/android/graphics/FontFamily.cpp @@ -97,21 +97,21 @@ static void FontFamily_unref(jlong familyPtr) { static bool addSkTypeface(NativeFamilyBuilder* builder, sk_sp<SkData>&& data, int ttcIndex, jint givenWeight, jint givenItalic) { - uirenderer::FatVector<SkFontMgr::FontParameters::Axis, 2> skiaAxes; + uirenderer::FatVector<SkFontArguments::Axis, 2> skiaAxes; for (const auto& axis : builder->axes) { - skiaAxes.emplace_back(SkFontMgr::FontParameters::Axis{axis.axisTag, axis.value}); + skiaAxes.emplace_back(SkFontArguments::Axis{axis.axisTag, axis.value}); } const size_t fontSize = data->size(); const void* fontPtr = data->data(); std::unique_ptr<SkStreamAsset> fontData(new SkMemoryStream(std::move(data))); - SkFontMgr::FontParameters params; + SkFontArguments params; params.setCollectionIndex(ttcIndex); params.setAxes(skiaAxes.data(), skiaAxes.size()); sk_sp<SkFontMgr> fm(SkFontMgr::RefDefault()); - sk_sp<SkTypeface> face(fm->createFromStream(fontData.release(), params)); + sk_sp<SkTypeface> face(fm->makeFromStream(std::move(fontData), params)); if (face == NULL) { ALOGE("addFont failed to create font, invalid request"); builder->axes.clear(); diff --git a/core/jni/android/graphics/FontUtils.cpp b/core/jni/android/graphics/FontUtils.cpp index 3bcf0c7fb354..0cf61b9ade89 100644 --- a/core/jni/android/graphics/FontUtils.cpp +++ b/core/jni/android/graphics/FontUtils.cpp @@ -16,7 +16,7 @@ #include "FontUtils.h" -#include "JNIHelp.h" +#include <nativehelper/JNIHelp.h> #include <core_jni_helpers.h> namespace android { diff --git a/core/jni/android/graphics/GraphicBuffer.cpp b/core/jni/android/graphics/GraphicBuffer.cpp index 1017cba01705..ae6fd38da319 100644 --- a/core/jni/android/graphics/GraphicBuffer.cpp +++ b/core/jni/android/graphics/GraphicBuffer.cpp @@ -17,7 +17,7 @@ #define LOG_TAG "GraphicBuffer" #include "jni.h" -#include "JNIHelp.h" +#include <nativehelper/JNIHelp.h> #include <inttypes.h> #include "android_os_Parcel.h" diff --git a/core/jni/android/graphics/pdf/PdfUtils.cpp b/core/jni/android/graphics/pdf/PdfUtils.cpp index dacca78c650a..36355ebbefc4 100644 --- a/core/jni/android/graphics/pdf/PdfUtils.cpp +++ b/core/jni/android/graphics/pdf/PdfUtils.cpp @@ -17,7 +17,7 @@ #include "PdfUtils.h" #include "jni.h" -#include "JNIHelp.h" +#include <nativehelper/JNIHelp.h> #include "fpdfview.h" diff --git a/core/jni/android_hardware_HardwareBuffer.cpp b/core/jni/android_hardware_HardwareBuffer.cpp index ba2345083661..8174a4184c83 100644 --- a/core/jni/android_hardware_HardwareBuffer.cpp +++ b/core/jni/android_hardware_HardwareBuffer.cpp @@ -17,7 +17,7 @@ #define LOG_TAG "HardwareBuffer" #include "jni.h" -#include "JNIHelp.h" +#include <nativehelper/JNIHelp.h> #include "android_os_Parcel.h" #include "android/graphics/GraphicsJNI.h" diff --git a/core/jni/android_hardware_display_DisplayViewport.cpp b/core/jni/android_hardware_display_DisplayViewport.cpp index 2d2837cc4a1c..23c3877e1200 100644 --- a/core/jni/android_hardware_display_DisplayViewport.cpp +++ b/core/jni/android_hardware_display_DisplayViewport.cpp @@ -16,7 +16,7 @@ #define LOG_TAG "DisplayViewport-JNI" -#include "JNIHelp.h" +#include <nativehelper/JNIHelp.h> #include "core_jni_helpers.h" #include <android_hardware_display_DisplayViewport.h> diff --git a/core/jni/android_os_SharedMemory.cpp b/core/jni/android_os_SharedMemory.cpp index 1d29908ad3df..f6e5c7a48c4c 100644 --- a/core/jni/android_os_SharedMemory.cpp +++ b/core/jni/android_os_SharedMemory.cpp @@ -20,7 +20,7 @@ #include <cutils/ashmem.h> #include <utils/Log.h> -#include "JNIHelp.h" +#include <nativehelper/JNIHelp.h> #include <nativehelper/JniConstants.h> #include <nativehelper/ScopedLocalRef.h> diff --git a/core/jni/android_text_StaticLayout.cpp b/core/jni/android_text_StaticLayout.cpp index 7442fa2d62dc..9afb7f3ed444 100644 --- a/core/jni/android_text_StaticLayout.cpp +++ b/core/jni/android_text_StaticLayout.cpp @@ -87,7 +87,8 @@ class JNILineBreakerLineWidth : public minikin::LineBreaker::LineWidthDelegate { static void nSetupParagraph(JNIEnv* env, jclass, jlong nativePtr, jcharArray text, jint length, jfloat firstWidth, jint firstWidthLineLimit, jfloat restWidth, jintArray variableTabStops, jint defaultTabStop, jint strategy, jint hyphenFrequency, - jboolean isJustified, jintArray indents, jint indentsOffset) { + jboolean isJustified, jintArray indents, jintArray leftPaddings, jintArray rightPaddings, + jint indentsOffset) { minikin::LineBreaker* b = reinterpret_cast<minikin::LineBreaker*>(nativePtr); b->resize(length); env->GetCharArrayRegion(text, 0, length, b->buffer()); @@ -187,24 +188,9 @@ static jlong nLoadHyphenator(JNIEnv* env, jclass, jobject buffer, jint offset, return reinterpret_cast<jlong>(hyphenator); } -static void nSetLocales(JNIEnv* env, jclass, jlong nativePtr, jstring javaLocaleNames, - jlongArray nativeHyphenators) { - minikin::LineBreaker* b = reinterpret_cast<minikin::LineBreaker*>(nativePtr); - - ScopedUtfChars localeNames(env, javaLocaleNames); - ScopedLongArrayRO hyphArr(env, nativeHyphenators); - const size_t numLocales = hyphArr.size(); - std::vector<minikin::Hyphenator*> hyphVec; - hyphVec.reserve(numLocales); - for (size_t i = 0; i < numLocales; i++) { - hyphVec.push_back(reinterpret_cast<minikin::Hyphenator*>(hyphArr[i])); - } - b->setLocales(localeNames.c_str(), hyphVec); -} - // Basically similar to Paint.getTextRunAdvances but with C++ interface static jfloat nAddStyleRun(JNIEnv* env, jclass, jlong nativePtr, jlong nativePaint, jint start, - jint end, jboolean isRtl) { + jint end, jboolean isRtl, jstring langTags, jlongArray hyphenators) { minikin::LineBreaker* b = reinterpret_cast<minikin::LineBreaker*>(nativePtr); Paint* paint = reinterpret_cast<Paint*>(nativePaint); const Typeface* typeface = paint->getAndroidTypeface(); @@ -212,8 +198,26 @@ static jfloat nAddStyleRun(JNIEnv* env, jclass, jlong nativePtr, jlong nativePai const Typeface* resolvedTypeface = Typeface::resolveDefault(typeface); minikin::FontStyle style = MinikinUtils::prepareMinikinPaint(&minikinPaint, paint, typeface); - return b->addStyleRun(&minikinPaint, resolvedTypeface->fFontCollection, style, start, end, - isRtl); + + std::vector<minikin::Hyphenator*> hyphVec; + const char* langTagStr; + if (langTags == nullptr) { + langTagStr = nullptr; // nullptr languageTag means keeping current locale + } else { + ScopedLongArrayRO hyphArr(env, hyphenators); + const size_t numLocales = hyphArr.size(); + hyphVec.reserve(numLocales); + for (size_t i = 0; i < numLocales; i++) { + hyphVec.push_back(reinterpret_cast<minikin::Hyphenator*>(hyphArr[i])); + } + langTagStr = env->GetStringUTFChars(langTags, nullptr); + } + float result = b->addStyleRun(&minikinPaint, resolvedTypeface->fFontCollection, style, start, + end, isRtl, langTagStr, hyphVec); + if (langTagStr != nullptr) { + env->ReleaseStringUTFChars(langTags, langTagStr); + } + return result; } // Accept width measurements for the run, passed in from Java @@ -221,7 +225,8 @@ static void nAddMeasuredRun(JNIEnv* env, jclass, jlong nativePtr, jint start, jint end, jfloatArray widths) { minikin::LineBreaker* b = reinterpret_cast<minikin::LineBreaker*>(nativePtr); env->GetFloatArrayRegion(widths, start, end - start, b->charWidths() + start); - b->addStyleRun(nullptr, nullptr, minikin::FontStyle{}, start, end, false); + b->addStyleRun(nullptr, nullptr, minikin::FontStyle{}, start, end, false, + nullptr /* keep current locale */, std::vector<minikin::Hyphenator*>()); } static void nAddReplacementRun(JNIEnv* env, jclass, jlong nativePtr, @@ -241,9 +246,8 @@ static const JNINativeMethod gMethods[] = { {"nFreeBuilder", "(J)V", (void*) nFreeBuilder}, {"nFinishBuilder", "(J)V", (void*) nFinishBuilder}, {"nLoadHyphenator", "(Ljava/nio/ByteBuffer;III)J", (void*) nLoadHyphenator}, - {"nSetLocales", "(JLjava/lang/String;[J)V", (void*) nSetLocales}, - {"nSetupParagraph", "(J[CIFIF[IIIIZ[II)V", (void*) nSetupParagraph}, - {"nAddStyleRun", "(JJIIZ)F", (void*) nAddStyleRun}, + {"nSetupParagraph", "(J[CIFIF[IIIIZ[I[I[II)V", (void*) nSetupParagraph}, + {"nAddStyleRun", "(JJIIZLjava/lang/String;[J)F", (void*) nAddStyleRun}, {"nAddMeasuredRun", "(JII[F)V", (void*) nAddMeasuredRun}, {"nAddReplacementRun", "(JIIF)V", (void*) nAddReplacementRun}, {"nGetWidths", "(J[F)V", (void*) nGetWidths}, diff --git a/core/jni/android_util_Binder.cpp b/core/jni/android_util_Binder.cpp index af5d12bd2510..7908c9d2b609 100644 --- a/core/jni/android_util_Binder.cpp +++ b/core/jni/android_util_Binder.cpp @@ -513,8 +513,8 @@ protected: private: JavaVM* const mVM; - jobject mObject; - jweak mObjectWeak; // will be a weak ref to the same VM-side DeathRecipient after binderDied() + jobject mObject; // Initial strong ref to Java-side DeathRecipient. Cleared on binderDied(). + jweak mObjectWeak; // weak ref to the same Java-side DeathRecipient after binderDied(). wp<DeathRecipientList> mList; }; @@ -586,7 +586,7 @@ static void proxy_cleanup(const void* id, void* obj, void* cleanupCookie) env->DeleteGlobalRef((jobject)obj); } -static Mutex mProxyLock; +static Mutex gProxyLock; jobject javaObjectForIBinder(JNIEnv* env, const sp<IBinder>& val) { @@ -601,7 +601,7 @@ jobject javaObjectForIBinder(JNIEnv* env, const sp<IBinder>& val) // For the rest of the function we will hold this lock, to serialize // looking/creation/destruction of Java proxies for native Binder proxies. - AutoMutex _l(mProxyLock); + AutoMutex _l(gProxyLock); // Someone else's... do we know about it? jobject object = (jobject)val->findObject(&gBinderProxyOffsets); @@ -1277,7 +1277,7 @@ static jboolean android_os_BinderProxy_unlinkToDeath(JNIEnv* env, jobject obj, static void android_os_BinderProxy_destroy(JNIEnv* env, jobject obj) { // Don't race with construction/initialization - AutoMutex _l(mProxyLock); + AutoMutex _l(gProxyLock); IBinder* b = (IBinder*) env->GetLongField(obj, gBinderProxyOffsets.mObject); diff --git a/core/proto/android/app/notificationmanager.proto b/core/proto/android/app/notificationmanager.proto new file mode 100644 index 000000000000..4dfd0cf469a7 --- /dev/null +++ b/core/proto/android/app/notificationmanager.proto @@ -0,0 +1,65 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +syntax = "proto3"; + +option java_package = "android.app"; +option java_multiple_files = true; + +package android.app; + +/** + * An android.app.NotificationMananger.Policy object. + */ +message PolicyProto { + enum Category { + CATEGORY_UNKNOWN = 0; + // Reminder notifications are prioritized. + REMINDERS = 1; + // Event notifications are prioritized. + EVENTS = 2; + // Message notifications are prioritized. + MESSAGES = 3; + // Calls are prioritized. + CALLS = 4; + // Calls from repeat callers are prioritized. + REPEAT_CALLERS = 5; + } + repeated Category priority_categories = 1; + + enum Sender { + // Any sender is prioritized. + ANY = 0; + // Saved contacts are prioritized. + CONTACTS = 1; + // Only starred contacts are prioritized. + STARRED = 2; + } + Sender priority_call_sender = 2; + Sender priority_message_sender = 3; + + enum SuppressedVisualEffect { + SVE_UNKNOWN = 0; + // Whether notifications suppressed by DND should not interrupt visually + // (e.g. with notification lights or by turning the screen on) when the + // screen is off. + SCREEN_OFF = 1; + // Whether notifications suppressed by DND should not interrupt visually + // when the screen is on (e.g. by peeking onto the screen). + SCREEN_ON = 2; + } + repeated SuppressedVisualEffect suppressed_visual_effects = 4; +} diff --git a/core/proto/android/os/incident.proto b/core/proto/android/os/incident.proto index bce10dc2e2fb..15c547f0196c 100644 --- a/core/proto/android/os/incident.proto +++ b/core/proto/android/os/incident.proto @@ -78,7 +78,10 @@ message IncidentProto { (section).type = SECTION_DUMPSYS, (section).args = "notification --proto" ]; - android.service.battery.BatteryServiceDumpProto battery = 3006; + android.service.battery.BatteryServiceDumpProto battery = 3006 [ + (section).type = SECTION_DUMPSYS, + (section).args = "battery --proto" + ]; android.service.diskstats.DiskStatsServiceDumpProto diskstats = 3007; android.service.pm.PackageServiceDumpProto package = 3008; android.service.power.PowerServiceDumpProto power = 3009; diff --git a/core/proto/android/service/diskstats.proto b/core/proto/android/service/diskstats.proto index 4d865264d19e..4057e45430fe 100644 --- a/core/proto/android/service/diskstats.proto +++ b/core/proto/android/service/diskstats.proto @@ -47,7 +47,7 @@ message DiskStatsServiceDumpProto { } message DiskStatsCachedValuesProto { - // Total app data size, in kilobytes + // Total app code size, in kilobytes int64 agg_apps_size = 1; // Total app cache size, in kilobytes int64 agg_apps_cache_size = 2; @@ -65,15 +65,19 @@ message DiskStatsCachedValuesProto { int64 other_size = 8; // Sizes of individual packages repeated DiskStatsAppSizesProto app_sizes = 9; + // Total app data size, in kilobytes + int64 agg_apps_data_size = 10; } message DiskStatsAppSizesProto { // Name of the package string package_name = 1; - // App's data size in kilobytes + // App's code size in kilobytes int64 app_size = 2; // App's cache size in kilobytes int64 cache_size = 3; + // App's data size in kilobytes + int64 app_data_size = 4; } message DiskStatsFreeSpaceProto { diff --git a/core/proto/android/service/notification.proto b/core/proto/android/service/notification.proto index a8482a1d6be6..05afe525c1eb 100644 --- a/core/proto/android/service/notification.proto +++ b/core/proto/android/service/notification.proto @@ -21,6 +21,7 @@ package android.service.notification; option java_multiple_files = true; option java_outer_classname = "NotificationServiceProto"; +import "frameworks/base/core/proto/android/app/notificationmanager.proto"; import "frameworks/base/core/proto/android/content/component_name.proto"; message NotificationServiceDumpProto { @@ -98,7 +99,7 @@ message ZenModeProto { repeated string enabled_active_conditions = 2; int32 suppressed_effects = 3; repeated string suppressors = 4; - string policy = 5; + android.app.PolicyProto policy = 5; } enum ZenMode { diff --git a/core/res/res/layout/notification_template_material_ambient.xml b/core/res/res/layout/notification_template_material_ambient.xml index 76b3528d26fe..ee5c758cc130 100644 --- a/core/res/res/layout/notification_template_material_ambient.xml +++ b/core/res/res/layout/notification_template_material_ambient.xml @@ -70,6 +70,8 @@ android:textSize="16sp" android:textColor="#eeffffff" android:layout_marginTop="4dp" + android:ellipsize="end" + android:maxLines="7" /> </LinearLayout> </LinearLayout> diff --git a/core/res/res/values-af/strings.xml b/core/res/res/values-af/strings.xml index c734cfa5786a..164b585de385 100644 --- a/core/res/res/values-af/strings.xml +++ b/core/res/res/values-af/strings.xml @@ -1421,11 +1421,9 @@ <string name="default_audio_route_name" product="tv" msgid="9158088547603019321">"TV"</string> <string name="default_audio_route_name" product="default" msgid="4239291273420140123">"Foon"</string> <string name="default_audio_route_name_dock_speakers" msgid="6240602982276591864">"Dokluidsprekers"</string> - <!-- no translation found for default_audio_route_name_hdmi (1486254205617081251) --> - <skip /> + <string name="default_audio_route_name_hdmi" msgid="1486254205617081251">"HDMI"</string> <string name="default_audio_route_name_headphones" msgid="8119971843803439110">"Oorfone"</string> - <!-- no translation found for default_audio_route_name_usb (1234984851352637769) --> - <skip /> + <string name="default_audio_route_name_usb" msgid="1234984851352637769">"USB"</string> <string name="default_audio_route_category_name" msgid="3722811174003886946">"Stelsel"</string> <string name="bluetooth_a2dp_audio_route_name" msgid="8575624030406771015">"Bluetooth-oudio"</string> <string name="wireless_display_route_description" msgid="9070346425023979651">"Draadlose skerm"</string> diff --git a/core/res/res/values-am/strings.xml b/core/res/res/values-am/strings.xml index 43c1dc48fdd4..9f3bcbbafed5 100644 --- a/core/res/res/values-am/strings.xml +++ b/core/res/res/values-am/strings.xml @@ -1421,11 +1421,9 @@ <string name="default_audio_route_name" product="tv" msgid="9158088547603019321">"ቴሌቪዥን"</string> <string name="default_audio_route_name" product="default" msgid="4239291273420140123">"ስልክ"</string> <string name="default_audio_route_name_dock_speakers" msgid="6240602982276591864">"የትከል ድምፅ ማጉያዎች"</string> - <!-- no translation found for default_audio_route_name_hdmi (1486254205617081251) --> - <skip /> + <string name="default_audio_route_name_hdmi" msgid="1486254205617081251">"ኤችዲኤምአይ"</string> <string name="default_audio_route_name_headphones" msgid="8119971843803439110">"የጆሮ ማዳመጫዎች"</string> - <!-- no translation found for default_audio_route_name_usb (1234984851352637769) --> - <skip /> + <string name="default_audio_route_name_usb" msgid="1234984851352637769">"ዩ ኤስ ቢ"</string> <string name="default_audio_route_category_name" msgid="3722811174003886946">"ስርዓት"</string> <string name="bluetooth_a2dp_audio_route_name" msgid="8575624030406771015">"የብሉቱዝ ድምጽ"</string> <string name="wireless_display_route_description" msgid="9070346425023979651">"ገመድ አልባ ማሳያ"</string> diff --git a/core/res/res/values-ar/strings.xml b/core/res/res/values-ar/strings.xml index d248428ac570..b3aa8bfb2000 100644 --- a/core/res/res/values-ar/strings.xml +++ b/core/res/res/values-ar/strings.xml @@ -1513,11 +1513,9 @@ <string name="default_audio_route_name" product="tv" msgid="9158088547603019321">"التلفزيون"</string> <string name="default_audio_route_name" product="default" msgid="4239291273420140123">"الهاتف"</string> <string name="default_audio_route_name_dock_speakers" msgid="6240602982276591864">"مكبرات صوت للإرساء"</string> - <!-- no translation found for default_audio_route_name_hdmi (1486254205617081251) --> - <skip /> + <string name="default_audio_route_name_hdmi" msgid="1486254205617081251">"HDMI"</string> <string name="default_audio_route_name_headphones" msgid="8119971843803439110">"سماعات رأس"</string> - <!-- no translation found for default_audio_route_name_usb (1234984851352637769) --> - <skip /> + <string name="default_audio_route_name_usb" msgid="1234984851352637769">"USB"</string> <string name="default_audio_route_category_name" msgid="3722811174003886946">"النظام"</string> <string name="bluetooth_a2dp_audio_route_name" msgid="8575624030406771015">"صوت بلوتوث"</string> <string name="wireless_display_route_description" msgid="9070346425023979651">"عرض شاشة لاسلكي"</string> diff --git a/core/res/res/values-az/strings.xml b/core/res/res/values-az/strings.xml index bd711bfb32ed..61e2c1e4139d 100644 --- a/core/res/res/values-az/strings.xml +++ b/core/res/res/values-az/strings.xml @@ -1421,11 +1421,9 @@ <string name="default_audio_route_name" product="tv" msgid="9158088547603019321">"TV"</string> <string name="default_audio_route_name" product="default" msgid="4239291273420140123">"Telefon"</string> <string name="default_audio_route_name_dock_speakers" msgid="6240602982276591864">"Dok spikerlər"</string> - <!-- no translation found for default_audio_route_name_hdmi (1486254205617081251) --> - <skip /> + <string name="default_audio_route_name_hdmi" msgid="1486254205617081251">"HDMI"</string> <string name="default_audio_route_name_headphones" msgid="8119971843803439110">"Qulaqlıq"</string> - <!-- no translation found for default_audio_route_name_usb (1234984851352637769) --> - <skip /> + <string name="default_audio_route_name_usb" msgid="1234984851352637769">"USB"</string> <string name="default_audio_route_category_name" msgid="3722811174003886946">"Sistem"</string> <string name="bluetooth_a2dp_audio_route_name" msgid="8575624030406771015">"Bluetooth audio"</string> <string name="wireless_display_route_description" msgid="9070346425023979651">"Simsiz ekran"</string> diff --git a/core/res/res/values-b+sr+Latn/strings.xml b/core/res/res/values-b+sr+Latn/strings.xml index 621185c02da9..f3c25d627f54 100644 --- a/core/res/res/values-b+sr+Latn/strings.xml +++ b/core/res/res/values-b+sr+Latn/strings.xml @@ -1444,11 +1444,9 @@ <string name="default_audio_route_name" product="tv" msgid="9158088547603019321">"TV"</string> <string name="default_audio_route_name" product="default" msgid="4239291273420140123">"Telefon"</string> <string name="default_audio_route_name_dock_speakers" msgid="6240602982276591864">"Zvučnici bazne stanice"</string> - <!-- no translation found for default_audio_route_name_hdmi (1486254205617081251) --> - <skip /> + <string name="default_audio_route_name_hdmi" msgid="1486254205617081251">"HDMI"</string> <string name="default_audio_route_name_headphones" msgid="8119971843803439110">"Slušalice"</string> - <!-- no translation found for default_audio_route_name_usb (1234984851352637769) --> - <skip /> + <string name="default_audio_route_name_usb" msgid="1234984851352637769">"USB"</string> <string name="default_audio_route_category_name" msgid="3722811174003886946">"Sistem"</string> <string name="bluetooth_a2dp_audio_route_name" msgid="8575624030406771015">"Bluetooth audio"</string> <string name="wireless_display_route_description" msgid="9070346425023979651">"Bežični ekran"</string> diff --git a/core/res/res/values-be/strings.xml b/core/res/res/values-be/strings.xml index d4808d06c17a..bba23aa76458 100644 --- a/core/res/res/values-be/strings.xml +++ b/core/res/res/values-be/strings.xml @@ -1467,11 +1467,9 @@ <string name="default_audio_route_name" product="tv" msgid="9158088547603019321">"ТБ"</string> <string name="default_audio_route_name" product="default" msgid="4239291273420140123">"Тэлефон"</string> <string name="default_audio_route_name_dock_speakers" msgid="6240602982276591864">"Дынамікі станцыi"</string> - <!-- no translation found for default_audio_route_name_hdmi (1486254205617081251) --> - <skip /> + <string name="default_audio_route_name_hdmi" msgid="1486254205617081251">"HDMI"</string> <string name="default_audio_route_name_headphones" msgid="8119971843803439110">"Навушнікі"</string> - <!-- no translation found for default_audio_route_name_usb (1234984851352637769) --> - <skip /> + <string name="default_audio_route_name_usb" msgid="1234984851352637769">"USB"</string> <string name="default_audio_route_category_name" msgid="3722811174003886946">"Сістэма"</string> <string name="bluetooth_a2dp_audio_route_name" msgid="8575624030406771015">"Bluetooth-аўдыё"</string> <string name="wireless_display_route_description" msgid="9070346425023979651">"Бесправадны дысплей"</string> diff --git a/core/res/res/values-bg/strings.xml b/core/res/res/values-bg/strings.xml index 70870ec296a3..5b9288810239 100644 --- a/core/res/res/values-bg/strings.xml +++ b/core/res/res/values-bg/strings.xml @@ -1421,11 +1421,9 @@ <string name="default_audio_route_name" product="tv" msgid="9158088547603019321">"Телевизор"</string> <string name="default_audio_route_name" product="default" msgid="4239291273420140123">"Телефон"</string> <string name="default_audio_route_name_dock_speakers" msgid="6240602982276591864">"Докинг станц.: Високогов."</string> - <!-- no translation found for default_audio_route_name_hdmi (1486254205617081251) --> - <skip /> + <string name="default_audio_route_name_hdmi" msgid="1486254205617081251">"HDMI"</string> <string name="default_audio_route_name_headphones" msgid="8119971843803439110">"Слушалки"</string> - <!-- no translation found for default_audio_route_name_usb (1234984851352637769) --> - <skip /> + <string name="default_audio_route_name_usb" msgid="1234984851352637769">"USB"</string> <string name="default_audio_route_category_name" msgid="3722811174003886946">"Система"</string> <string name="bluetooth_a2dp_audio_route_name" msgid="8575624030406771015">"Звук през Bluetooth"</string> <string name="wireless_display_route_description" msgid="9070346425023979651">"Безжичен дисплей"</string> diff --git a/core/res/res/values-bn/strings.xml b/core/res/res/values-bn/strings.xml index 49b2ccc50657..dff5ab608eec 100644 --- a/core/res/res/values-bn/strings.xml +++ b/core/res/res/values-bn/strings.xml @@ -1421,11 +1421,9 @@ <string name="default_audio_route_name" product="tv" msgid="9158088547603019321">"টিভি"</string> <string name="default_audio_route_name" product="default" msgid="4239291273420140123">"ফোন"</string> <string name="default_audio_route_name_dock_speakers" msgid="6240602982276591864">"ডক স্পিকার"</string> - <!-- no translation found for default_audio_route_name_hdmi (1486254205617081251) --> - <skip /> + <string name="default_audio_route_name_hdmi" msgid="1486254205617081251">"HDMI"</string> <string name="default_audio_route_name_headphones" msgid="8119971843803439110">"হেডফোন"</string> - <!-- no translation found for default_audio_route_name_usb (1234984851352637769) --> - <skip /> + <string name="default_audio_route_name_usb" msgid="1234984851352637769">"USB"</string> <string name="default_audio_route_category_name" msgid="3722811174003886946">"সিস্টেম"</string> <string name="bluetooth_a2dp_audio_route_name" msgid="8575624030406771015">"ব্লুটুথ অডিও"</string> <string name="wireless_display_route_description" msgid="9070346425023979651">"ওয়্যারলেস প্রদর্শন"</string> diff --git a/core/res/res/values-bs/strings.xml b/core/res/res/values-bs/strings.xml index 38601064f85a..d1bb0f9c2298 100644 --- a/core/res/res/values-bs/strings.xml +++ b/core/res/res/values-bs/strings.xml @@ -1446,11 +1446,9 @@ <string name="default_audio_route_name" product="tv" msgid="9158088547603019321">"TV"</string> <string name="default_audio_route_name" product="default" msgid="4239291273420140123">"Telefon"</string> <string name="default_audio_route_name_dock_speakers" msgid="6240602982276591864">"Zvučnici priključne stanice"</string> - <!-- no translation found for default_audio_route_name_hdmi (1486254205617081251) --> - <skip /> + <string name="default_audio_route_name_hdmi" msgid="1486254205617081251">"HDMI"</string> <string name="default_audio_route_name_headphones" msgid="8119971843803439110">"Slušalice"</string> - <!-- no translation found for default_audio_route_name_usb (1234984851352637769) --> - <skip /> + <string name="default_audio_route_name_usb" msgid="1234984851352637769">"USB"</string> <string name="default_audio_route_category_name" msgid="3722811174003886946">"Sistem"</string> <string name="bluetooth_a2dp_audio_route_name" msgid="8575624030406771015">"Bluetooth audio"</string> <string name="wireless_display_route_description" msgid="9070346425023979651">"Bežični prikaz"</string> diff --git a/core/res/res/values-ca/strings.xml b/core/res/res/values-ca/strings.xml index 3475891d108a..60018d93ad38 100644 --- a/core/res/res/values-ca/strings.xml +++ b/core/res/res/values-ca/strings.xml @@ -1421,11 +1421,9 @@ <string name="default_audio_route_name" product="tv" msgid="9158088547603019321">"Televisor"</string> <string name="default_audio_route_name" product="default" msgid="4239291273420140123">"Telèfon"</string> <string name="default_audio_route_name_dock_speakers" msgid="6240602982276591864">"Altaveus de la base"</string> - <!-- no translation found for default_audio_route_name_hdmi (1486254205617081251) --> - <skip /> + <string name="default_audio_route_name_hdmi" msgid="1486254205617081251">"HDMI"</string> <string name="default_audio_route_name_headphones" msgid="8119971843803439110">"Auriculars"</string> - <!-- no translation found for default_audio_route_name_usb (1234984851352637769) --> - <skip /> + <string name="default_audio_route_name_usb" msgid="1234984851352637769">"USB"</string> <string name="default_audio_route_category_name" msgid="3722811174003886946">"Sistema"</string> <string name="bluetooth_a2dp_audio_route_name" msgid="8575624030406771015">"Àudio per Bluetooth"</string> <string name="wireless_display_route_description" msgid="9070346425023979651">"Pantalla sense fil"</string> diff --git a/core/res/res/values-cs/strings.xml b/core/res/res/values-cs/strings.xml index 09e156d522e6..53ea5860d200 100644 --- a/core/res/res/values-cs/strings.xml +++ b/core/res/res/values-cs/strings.xml @@ -1467,11 +1467,9 @@ <string name="default_audio_route_name" product="tv" msgid="9158088547603019321">"Televize"</string> <string name="default_audio_route_name" product="default" msgid="4239291273420140123">"Telefon"</string> <string name="default_audio_route_name_dock_speakers" msgid="6240602982276591864">"Reproduktory doku"</string> - <!-- no translation found for default_audio_route_name_hdmi (1486254205617081251) --> - <skip /> + <string name="default_audio_route_name_hdmi" msgid="1486254205617081251">"HDMI"</string> <string name="default_audio_route_name_headphones" msgid="8119971843803439110">"Sluchátka"</string> - <!-- no translation found for default_audio_route_name_usb (1234984851352637769) --> - <skip /> + <string name="default_audio_route_name_usb" msgid="1234984851352637769">"USB"</string> <string name="default_audio_route_category_name" msgid="3722811174003886946">"Systém"</string> <string name="bluetooth_a2dp_audio_route_name" msgid="8575624030406771015">"Bluetooth Audio"</string> <string name="wireless_display_route_description" msgid="9070346425023979651">"Bezdrátový displej"</string> diff --git a/core/res/res/values-da/strings.xml b/core/res/res/values-da/strings.xml index 5ee109d21246..d6e400ba2da0 100644 --- a/core/res/res/values-da/strings.xml +++ b/core/res/res/values-da/strings.xml @@ -1421,11 +1421,9 @@ <string name="default_audio_route_name" product="tv" msgid="9158088547603019321">"Tv"</string> <string name="default_audio_route_name" product="default" msgid="4239291273420140123">"Telefon"</string> <string name="default_audio_route_name_dock_speakers" msgid="6240602982276591864">"Dockstationens højttalere"</string> - <!-- no translation found for default_audio_route_name_hdmi (1486254205617081251) --> - <skip /> + <string name="default_audio_route_name_hdmi" msgid="1486254205617081251">"HDMI"</string> <string name="default_audio_route_name_headphones" msgid="8119971843803439110">"Hovedtelefoner"</string> - <!-- no translation found for default_audio_route_name_usb (1234984851352637769) --> - <skip /> + <string name="default_audio_route_name_usb" msgid="1234984851352637769">"USB"</string> <string name="default_audio_route_category_name" msgid="3722811174003886946">"System"</string> <string name="bluetooth_a2dp_audio_route_name" msgid="8575624030406771015">"Bluetooth-lyd"</string> <string name="wireless_display_route_description" msgid="9070346425023979651">"Trådløs skærm"</string> diff --git a/core/res/res/values-de/strings.xml b/core/res/res/values-de/strings.xml index 3585d4cceeac..ff0fe95bf153 100644 --- a/core/res/res/values-de/strings.xml +++ b/core/res/res/values-de/strings.xml @@ -1421,11 +1421,9 @@ <string name="default_audio_route_name" product="tv" msgid="9158088547603019321">"TV"</string> <string name="default_audio_route_name" product="default" msgid="4239291273420140123">"Telefon"</string> <string name="default_audio_route_name_dock_speakers" msgid="6240602982276591864">"Dock-Lautsprecher"</string> - <!-- no translation found for default_audio_route_name_hdmi (1486254205617081251) --> - <skip /> + <string name="default_audio_route_name_hdmi" msgid="1486254205617081251">"HDMI"</string> <string name="default_audio_route_name_headphones" msgid="8119971843803439110">"Kopfhörer"</string> - <!-- no translation found for default_audio_route_name_usb (1234984851352637769) --> - <skip /> + <string name="default_audio_route_name_usb" msgid="1234984851352637769">"USB"</string> <string name="default_audio_route_category_name" msgid="3722811174003886946">"System"</string> <string name="bluetooth_a2dp_audio_route_name" msgid="8575624030406771015">"Bluetooth-Audio"</string> <string name="wireless_display_route_description" msgid="9070346425023979651">"Kabellose Übertragung (WiDi)"</string> diff --git a/core/res/res/values-el/strings.xml b/core/res/res/values-el/strings.xml index c20ba6ef4076..806d42496458 100644 --- a/core/res/res/values-el/strings.xml +++ b/core/res/res/values-el/strings.xml @@ -1421,11 +1421,9 @@ <string name="default_audio_route_name" product="tv" msgid="9158088547603019321">"Τηλεόραση"</string> <string name="default_audio_route_name" product="default" msgid="4239291273420140123">"Τηλέφωνο"</string> <string name="default_audio_route_name_dock_speakers" msgid="6240602982276591864">"Ηχεία βάσης σύνδεσης"</string> - <!-- no translation found for default_audio_route_name_hdmi (1486254205617081251) --> - <skip /> + <string name="default_audio_route_name_hdmi" msgid="1486254205617081251">"HDMI"</string> <string name="default_audio_route_name_headphones" msgid="8119971843803439110">"Ακουστικά"</string> - <!-- no translation found for default_audio_route_name_usb (1234984851352637769) --> - <skip /> + <string name="default_audio_route_name_usb" msgid="1234984851352637769">"USB"</string> <string name="default_audio_route_category_name" msgid="3722811174003886946">"Σύστημα"</string> <string name="bluetooth_a2dp_audio_route_name" msgid="8575624030406771015">"Ήχος Bluetooth"</string> <string name="wireless_display_route_description" msgid="9070346425023979651">"Ασύρματη οθόνη"</string> diff --git a/core/res/res/values-en-rAU/strings.xml b/core/res/res/values-en-rAU/strings.xml index afddfc4b9d04..8264a28035f3 100644 --- a/core/res/res/values-en-rAU/strings.xml +++ b/core/res/res/values-en-rAU/strings.xml @@ -1421,11 +1421,9 @@ <string name="default_audio_route_name" product="tv" msgid="9158088547603019321">"TV"</string> <string name="default_audio_route_name" product="default" msgid="4239291273420140123">"Phone"</string> <string name="default_audio_route_name_dock_speakers" msgid="6240602982276591864">"Dock speakers"</string> - <!-- no translation found for default_audio_route_name_hdmi (1486254205617081251) --> - <skip /> + <string name="default_audio_route_name_hdmi" msgid="1486254205617081251">"HDMI"</string> <string name="default_audio_route_name_headphones" msgid="8119971843803439110">"Headphones"</string> - <!-- no translation found for default_audio_route_name_usb (1234984851352637769) --> - <skip /> + <string name="default_audio_route_name_usb" msgid="1234984851352637769">"USB"</string> <string name="default_audio_route_category_name" msgid="3722811174003886946">"System"</string> <string name="bluetooth_a2dp_audio_route_name" msgid="8575624030406771015">"Bluetooth audio"</string> <string name="wireless_display_route_description" msgid="9070346425023979651">"Wireless display"</string> diff --git a/core/res/res/values-en-rCA/strings.xml b/core/res/res/values-en-rCA/strings.xml index afddfc4b9d04..8264a28035f3 100644 --- a/core/res/res/values-en-rCA/strings.xml +++ b/core/res/res/values-en-rCA/strings.xml @@ -1421,11 +1421,9 @@ <string name="default_audio_route_name" product="tv" msgid="9158088547603019321">"TV"</string> <string name="default_audio_route_name" product="default" msgid="4239291273420140123">"Phone"</string> <string name="default_audio_route_name_dock_speakers" msgid="6240602982276591864">"Dock speakers"</string> - <!-- no translation found for default_audio_route_name_hdmi (1486254205617081251) --> - <skip /> + <string name="default_audio_route_name_hdmi" msgid="1486254205617081251">"HDMI"</string> <string name="default_audio_route_name_headphones" msgid="8119971843803439110">"Headphones"</string> - <!-- no translation found for default_audio_route_name_usb (1234984851352637769) --> - <skip /> + <string name="default_audio_route_name_usb" msgid="1234984851352637769">"USB"</string> <string name="default_audio_route_category_name" msgid="3722811174003886946">"System"</string> <string name="bluetooth_a2dp_audio_route_name" msgid="8575624030406771015">"Bluetooth audio"</string> <string name="wireless_display_route_description" msgid="9070346425023979651">"Wireless display"</string> diff --git a/core/res/res/values-en-rGB/strings.xml b/core/res/res/values-en-rGB/strings.xml index afddfc4b9d04..8264a28035f3 100644 --- a/core/res/res/values-en-rGB/strings.xml +++ b/core/res/res/values-en-rGB/strings.xml @@ -1421,11 +1421,9 @@ <string name="default_audio_route_name" product="tv" msgid="9158088547603019321">"TV"</string> <string name="default_audio_route_name" product="default" msgid="4239291273420140123">"Phone"</string> <string name="default_audio_route_name_dock_speakers" msgid="6240602982276591864">"Dock speakers"</string> - <!-- no translation found for default_audio_route_name_hdmi (1486254205617081251) --> - <skip /> + <string name="default_audio_route_name_hdmi" msgid="1486254205617081251">"HDMI"</string> <string name="default_audio_route_name_headphones" msgid="8119971843803439110">"Headphones"</string> - <!-- no translation found for default_audio_route_name_usb (1234984851352637769) --> - <skip /> + <string name="default_audio_route_name_usb" msgid="1234984851352637769">"USB"</string> <string name="default_audio_route_category_name" msgid="3722811174003886946">"System"</string> <string name="bluetooth_a2dp_audio_route_name" msgid="8575624030406771015">"Bluetooth audio"</string> <string name="wireless_display_route_description" msgid="9070346425023979651">"Wireless display"</string> diff --git a/core/res/res/values-en-rIN/strings.xml b/core/res/res/values-en-rIN/strings.xml index afddfc4b9d04..8264a28035f3 100644 --- a/core/res/res/values-en-rIN/strings.xml +++ b/core/res/res/values-en-rIN/strings.xml @@ -1421,11 +1421,9 @@ <string name="default_audio_route_name" product="tv" msgid="9158088547603019321">"TV"</string> <string name="default_audio_route_name" product="default" msgid="4239291273420140123">"Phone"</string> <string name="default_audio_route_name_dock_speakers" msgid="6240602982276591864">"Dock speakers"</string> - <!-- no translation found for default_audio_route_name_hdmi (1486254205617081251) --> - <skip /> + <string name="default_audio_route_name_hdmi" msgid="1486254205617081251">"HDMI"</string> <string name="default_audio_route_name_headphones" msgid="8119971843803439110">"Headphones"</string> - <!-- no translation found for default_audio_route_name_usb (1234984851352637769) --> - <skip /> + <string name="default_audio_route_name_usb" msgid="1234984851352637769">"USB"</string> <string name="default_audio_route_category_name" msgid="3722811174003886946">"System"</string> <string name="bluetooth_a2dp_audio_route_name" msgid="8575624030406771015">"Bluetooth audio"</string> <string name="wireless_display_route_description" msgid="9070346425023979651">"Wireless display"</string> diff --git a/core/res/res/values-en-rXC/strings.xml b/core/res/res/values-en-rXC/strings.xml index e4a69ab1df9c..44fd405a8961 100644 --- a/core/res/res/values-en-rXC/strings.xml +++ b/core/res/res/values-en-rXC/strings.xml @@ -1421,11 +1421,9 @@ <string name="default_audio_route_name" product="tv" msgid="9158088547603019321">"TV"</string> <string name="default_audio_route_name" product="default" msgid="4239291273420140123">"Phone"</string> <string name="default_audio_route_name_dock_speakers" msgid="6240602982276591864">"Dock speakers"</string> - <!-- no translation found for default_audio_route_name_hdmi (1486254205617081251) --> - <skip /> + <string name="default_audio_route_name_hdmi" msgid="1486254205617081251">"HDMI"</string> <string name="default_audio_route_name_headphones" msgid="8119971843803439110">"Headphones"</string> - <!-- no translation found for default_audio_route_name_usb (1234984851352637769) --> - <skip /> + <string name="default_audio_route_name_usb" msgid="1234984851352637769">"USB"</string> <string name="default_audio_route_category_name" msgid="3722811174003886946">"System"</string> <string name="bluetooth_a2dp_audio_route_name" msgid="8575624030406771015">"Bluetooth audio"</string> <string name="wireless_display_route_description" msgid="9070346425023979651">"Wireless display"</string> diff --git a/core/res/res/values-es-rUS/strings.xml b/core/res/res/values-es-rUS/strings.xml index 02613635b2a3..e7a18eac324f 100644 --- a/core/res/res/values-es-rUS/strings.xml +++ b/core/res/res/values-es-rUS/strings.xml @@ -1421,11 +1421,9 @@ <string name="default_audio_route_name" product="tv" msgid="9158088547603019321">"TV"</string> <string name="default_audio_route_name" product="default" msgid="4239291273420140123">"Dispositivo"</string> <string name="default_audio_route_name_dock_speakers" msgid="6240602982276591864">"Altavoces del conector"</string> - <!-- no translation found for default_audio_route_name_hdmi (1486254205617081251) --> - <skip /> + <string name="default_audio_route_name_hdmi" msgid="1486254205617081251">"HDMI"</string> <string name="default_audio_route_name_headphones" msgid="8119971843803439110">"Auriculares"</string> - <!-- no translation found for default_audio_route_name_usb (1234984851352637769) --> - <skip /> + <string name="default_audio_route_name_usb" msgid="1234984851352637769">"USB"</string> <string name="default_audio_route_category_name" msgid="3722811174003886946">"Sistema"</string> <string name="bluetooth_a2dp_audio_route_name" msgid="8575624030406771015">"Audio Bluetooth"</string> <string name="wireless_display_route_description" msgid="9070346425023979651">"Pantalla inalámbrica"</string> diff --git a/core/res/res/values-es/strings.xml b/core/res/res/values-es/strings.xml index 6a5d3a9efcb6..820ab101ca23 100644 --- a/core/res/res/values-es/strings.xml +++ b/core/res/res/values-es/strings.xml @@ -1421,11 +1421,9 @@ <string name="default_audio_route_name" product="tv" msgid="9158088547603019321">"TV"</string> <string name="default_audio_route_name" product="default" msgid="4239291273420140123">"Teléfono"</string> <string name="default_audio_route_name_dock_speakers" msgid="6240602982276591864">"Altavoces de la base"</string> - <!-- no translation found for default_audio_route_name_hdmi (1486254205617081251) --> - <skip /> + <string name="default_audio_route_name_hdmi" msgid="1486254205617081251">"HDMI"</string> <string name="default_audio_route_name_headphones" msgid="8119971843803439110">"Auriculares"</string> - <!-- no translation found for default_audio_route_name_usb (1234984851352637769) --> - <skip /> + <string name="default_audio_route_name_usb" msgid="1234984851352637769">"USB"</string> <string name="default_audio_route_category_name" msgid="3722811174003886946">"Sistema"</string> <string name="bluetooth_a2dp_audio_route_name" msgid="8575624030406771015">"Audio Bluetooth"</string> <string name="wireless_display_route_description" msgid="9070346425023979651">"Pantalla inalámbrica"</string> diff --git a/core/res/res/values-et/strings.xml b/core/res/res/values-et/strings.xml index 267cd9ddc4e3..d6cf28e7b885 100644 --- a/core/res/res/values-et/strings.xml +++ b/core/res/res/values-et/strings.xml @@ -1421,11 +1421,9 @@ <string name="default_audio_route_name" product="tv" msgid="9158088547603019321">"Teler"</string> <string name="default_audio_route_name" product="default" msgid="4239291273420140123">"Telefon"</string> <string name="default_audio_route_name_dock_speakers" msgid="6240602982276591864">"Doki kõlarid"</string> - <!-- no translation found for default_audio_route_name_hdmi (1486254205617081251) --> - <skip /> + <string name="default_audio_route_name_hdmi" msgid="1486254205617081251">"HDMI"</string> <string name="default_audio_route_name_headphones" msgid="8119971843803439110">"Kõrvaklapid"</string> - <!-- no translation found for default_audio_route_name_usb (1234984851352637769) --> - <skip /> + <string name="default_audio_route_name_usb" msgid="1234984851352637769">"USB"</string> <string name="default_audio_route_category_name" msgid="3722811174003886946">"Süsteem"</string> <string name="bluetooth_a2dp_audio_route_name" msgid="8575624030406771015">"Bluetooth-heli"</string> <string name="wireless_display_route_description" msgid="9070346425023979651">"Juhtmeta ekraan"</string> diff --git a/core/res/res/values-eu/strings.xml b/core/res/res/values-eu/strings.xml index 20cefa886a71..f0414bb0bcac 100644 --- a/core/res/res/values-eu/strings.xml +++ b/core/res/res/values-eu/strings.xml @@ -1421,11 +1421,9 @@ <string name="default_audio_route_name" product="tv" msgid="9158088547603019321">"Telebista"</string> <string name="default_audio_route_name" product="default" msgid="4239291273420140123">"Telefonoa"</string> <string name="default_audio_route_name_dock_speakers" msgid="6240602982276591864">"Konektatu bozgorailuak oinarrira"</string> - <!-- no translation found for default_audio_route_name_hdmi (1486254205617081251) --> - <skip /> + <string name="default_audio_route_name_hdmi" msgid="1486254205617081251">"HDMI"</string> <string name="default_audio_route_name_headphones" msgid="8119971843803439110">"Aurikularrak"</string> - <!-- no translation found for default_audio_route_name_usb (1234984851352637769) --> - <skip /> + <string name="default_audio_route_name_usb" msgid="1234984851352637769">"USB"</string> <string name="default_audio_route_category_name" msgid="3722811174003886946">"Sistema"</string> <string name="bluetooth_a2dp_audio_route_name" msgid="8575624030406771015">"Bluetootharen audioa"</string> <string name="wireless_display_route_description" msgid="9070346425023979651">"Hari gabeko pantaila"</string> diff --git a/core/res/res/values-fa/strings.xml b/core/res/res/values-fa/strings.xml index 320ab80b7f46..9b974fe3ef06 100644 --- a/core/res/res/values-fa/strings.xml +++ b/core/res/res/values-fa/strings.xml @@ -1421,11 +1421,9 @@ <string name="default_audio_route_name" product="tv" msgid="9158088547603019321">"تلویزیون"</string> <string name="default_audio_route_name" product="default" msgid="4239291273420140123">"تلفن"</string> <string name="default_audio_route_name_dock_speakers" msgid="6240602982276591864">"بلندگوهای جایگاه"</string> - <!-- no translation found for default_audio_route_name_hdmi (1486254205617081251) --> - <skip /> + <string name="default_audio_route_name_hdmi" msgid="1486254205617081251">"HDMI"</string> <string name="default_audio_route_name_headphones" msgid="8119971843803439110">"هدفونها"</string> - <!-- no translation found for default_audio_route_name_usb (1234984851352637769) --> - <skip /> + <string name="default_audio_route_name_usb" msgid="1234984851352637769">"USB"</string> <string name="default_audio_route_category_name" msgid="3722811174003886946">"سیستم"</string> <string name="bluetooth_a2dp_audio_route_name" msgid="8575624030406771015">"بلوتوثهای صوتی"</string> <string name="wireless_display_route_description" msgid="9070346425023979651">"صفحه نمایش بیسیم"</string> diff --git a/core/res/res/values-fi/strings.xml b/core/res/res/values-fi/strings.xml index 62b0486d9c95..ed516766ef81 100644 --- a/core/res/res/values-fi/strings.xml +++ b/core/res/res/values-fi/strings.xml @@ -1130,7 +1130,7 @@ <string name="wifi_connect_alert_title" msgid="8455846016001810172">"Sallitaanko yhteys?"</string> <string name="wifi_connect_alert_message" msgid="6451273376815958922">"Sovellus %1$s yrittää yhdistää Wi-Fi-verkkoon %2$s."</string> <string name="wifi_connect_default_application" msgid="7143109390475484319">"Sovellus"</string> - <string name="wifi_p2p_dialog_title" msgid="97611782659324517">"Suora Wi-Fi-yhteys"</string> + <string name="wifi_p2p_dialog_title" msgid="97611782659324517">"Wi-Fi Direct"</string> <string name="wifi_p2p_turnon_message" msgid="2909250942299627244">"Käynnistä suora Wi-Fi-yhteys. Wi-Fi-asiakas/-hotspot poistetaan käytöstä."</string> <string name="wifi_p2p_failed_message" msgid="3763669677935623084">"Suoran Wi-Fi-yhteyden käynnistäminen epäonnistui."</string> <string name="wifi_p2p_enabled_notification_title" msgid="2068321881673734886">"Wi-Fi Direct on käytössä"</string> @@ -1421,11 +1421,9 @@ <string name="default_audio_route_name" product="tv" msgid="9158088547603019321">"Televisio"</string> <string name="default_audio_route_name" product="default" msgid="4239291273420140123">"Puhelin"</string> <string name="default_audio_route_name_dock_speakers" msgid="6240602982276591864">"Telineen kaiuttimet"</string> - <!-- no translation found for default_audio_route_name_hdmi (1486254205617081251) --> - <skip /> + <string name="default_audio_route_name_hdmi" msgid="1486254205617081251">"HDMI"</string> <string name="default_audio_route_name_headphones" msgid="8119971843803439110">"Kuulokkeet"</string> - <!-- no translation found for default_audio_route_name_usb (1234984851352637769) --> - <skip /> + <string name="default_audio_route_name_usb" msgid="1234984851352637769">"USB"</string> <string name="default_audio_route_category_name" msgid="3722811174003886946">"Järjestelmä"</string> <string name="bluetooth_a2dp_audio_route_name" msgid="8575624030406771015">"Bluetooth-ääni"</string> <string name="wireless_display_route_description" msgid="9070346425023979651">"Langaton näyttö"</string> diff --git a/core/res/res/values-fr-rCA/strings.xml b/core/res/res/values-fr-rCA/strings.xml index 90b31c89dec2..085c9d0ccfe4 100644 --- a/core/res/res/values-fr-rCA/strings.xml +++ b/core/res/res/values-fr-rCA/strings.xml @@ -253,7 +253,7 @@ <string name="foreground_service_apps_in_background" msgid="7175032677643332242">"<xliff:g id="NUMBER">%1$d</xliff:g> applications sollicitent la pile"</string> <string name="foreground_service_tap_for_details" msgid="372046743534354644">"Touchez pour afficher des détails sur l\'utilisation de la pile et des données"</string> <string name="foreground_service_multiple_separator" msgid="4021901567939866542">"<xliff:g id="LEFT_SIDE">%1$s</xliff:g>, <xliff:g id="RIGHT_SIDE">%2$s</xliff:g>"</string> - <string name="safeMode" msgid="2788228061547930246">"Mode sécurisé"</string> + <string name="safeMode" msgid="2788228061547930246">"Mode sans échec"</string> <string name="android_system_label" msgid="6577375335728551336">"Système Android"</string> <string name="user_owner_label" msgid="1119010402169916617">"Passer au profil personnel"</string> <string name="managed_profile_label" msgid="5289992269827577857">"Passer au profil professionnel"</string> @@ -1421,11 +1421,9 @@ <string name="default_audio_route_name" product="tv" msgid="9158088547603019321">"Télévision"</string> <string name="default_audio_route_name" product="default" msgid="4239291273420140123">"Téléphone"</string> <string name="default_audio_route_name_dock_speakers" msgid="6240602982276591864">"Haut-parleurs de la station d\'accueil"</string> - <!-- no translation found for default_audio_route_name_hdmi (1486254205617081251) --> - <skip /> + <string name="default_audio_route_name_hdmi" msgid="1486254205617081251">"HDMI"</string> <string name="default_audio_route_name_headphones" msgid="8119971843803439110">"Oreillettes"</string> - <!-- no translation found for default_audio_route_name_usb (1234984851352637769) --> - <skip /> + <string name="default_audio_route_name_usb" msgid="1234984851352637769">"USB"</string> <string name="default_audio_route_category_name" msgid="3722811174003886946">"Système"</string> <string name="bluetooth_a2dp_audio_route_name" msgid="8575624030406771015">"Audio Bluetooth"</string> <string name="wireless_display_route_description" msgid="9070346425023979651">"Affichage sans fil"</string> diff --git a/core/res/res/values-fr/strings.xml b/core/res/res/values-fr/strings.xml index e361500146f6..5a360a86b0b3 100644 --- a/core/res/res/values-fr/strings.xml +++ b/core/res/res/values-fr/strings.xml @@ -1421,11 +1421,9 @@ <string name="default_audio_route_name" product="tv" msgid="9158088547603019321">"Téléviseur"</string> <string name="default_audio_route_name" product="default" msgid="4239291273420140123">"Téléphone"</string> <string name="default_audio_route_name_dock_speakers" msgid="6240602982276591864">"Haut-parleurs de la station d\'accueil"</string> - <!-- no translation found for default_audio_route_name_hdmi (1486254205617081251) --> - <skip /> + <string name="default_audio_route_name_hdmi" msgid="1486254205617081251">"HDMI"</string> <string name="default_audio_route_name_headphones" msgid="8119971843803439110">"Écouteurs"</string> - <!-- no translation found for default_audio_route_name_usb (1234984851352637769) --> - <skip /> + <string name="default_audio_route_name_usb" msgid="1234984851352637769">"USB"</string> <string name="default_audio_route_category_name" msgid="3722811174003886946">"Système"</string> <string name="bluetooth_a2dp_audio_route_name" msgid="8575624030406771015">"Audio Bluetooth"</string> <string name="wireless_display_route_description" msgid="9070346425023979651">"Affichage sans fil"</string> diff --git a/core/res/res/values-gl/strings.xml b/core/res/res/values-gl/strings.xml index a24252ccb562..f17f10b261f3 100644 --- a/core/res/res/values-gl/strings.xml +++ b/core/res/res/values-gl/strings.xml @@ -1421,11 +1421,9 @@ <string name="default_audio_route_name" product="tv" msgid="9158088547603019321">"Televisión"</string> <string name="default_audio_route_name" product="default" msgid="4239291273420140123">"Teléfono"</string> <string name="default_audio_route_name_dock_speakers" msgid="6240602982276591864">"Conectar altofalantes á base"</string> - <!-- no translation found for default_audio_route_name_hdmi (1486254205617081251) --> - <skip /> + <string name="default_audio_route_name_hdmi" msgid="1486254205617081251">"HDMI"</string> <string name="default_audio_route_name_headphones" msgid="8119971843803439110">"Auriculares"</string> - <!-- no translation found for default_audio_route_name_usb (1234984851352637769) --> - <skip /> + <string name="default_audio_route_name_usb" msgid="1234984851352637769">"USB"</string> <string name="default_audio_route_category_name" msgid="3722811174003886946">"Sistema"</string> <string name="bluetooth_a2dp_audio_route_name" msgid="8575624030406771015">"Audio por Bluetooth"</string> <string name="wireless_display_route_description" msgid="9070346425023979651">"Visualización sen fíos"</string> diff --git a/core/res/res/values-gu/strings.xml b/core/res/res/values-gu/strings.xml index 3249e14b094e..4f2e29c806b3 100644 --- a/core/res/res/values-gu/strings.xml +++ b/core/res/res/values-gu/strings.xml @@ -1421,11 +1421,9 @@ <string name="default_audio_route_name" product="tv" msgid="9158088547603019321">"TV"</string> <string name="default_audio_route_name" product="default" msgid="4239291273420140123">"ફોન"</string> <string name="default_audio_route_name_dock_speakers" msgid="6240602982276591864">"સ્પીકર્સ ડૉક કરો"</string> - <!-- no translation found for default_audio_route_name_hdmi (1486254205617081251) --> - <skip /> + <string name="default_audio_route_name_hdmi" msgid="1486254205617081251">"HDMI"</string> <string name="default_audio_route_name_headphones" msgid="8119971843803439110">"હેડફોન"</string> - <!-- no translation found for default_audio_route_name_usb (1234984851352637769) --> - <skip /> + <string name="default_audio_route_name_usb" msgid="1234984851352637769">"USB"</string> <string name="default_audio_route_category_name" msgid="3722811174003886946">"સિસ્ટમ"</string> <string name="bluetooth_a2dp_audio_route_name" msgid="8575624030406771015">"બ્લૂટૂથ ઑડિઓ"</string> <string name="wireless_display_route_description" msgid="9070346425023979651">"વાયરલેસ ડિસ્પ્લે"</string> diff --git a/core/res/res/values-hi/strings.xml b/core/res/res/values-hi/strings.xml index 7c2c35c2cb70..a112be440b14 100644 --- a/core/res/res/values-hi/strings.xml +++ b/core/res/res/values-hi/strings.xml @@ -1421,11 +1421,9 @@ <string name="default_audio_route_name" product="tv" msgid="9158088547603019321">"टीवी"</string> <string name="default_audio_route_name" product="default" msgid="4239291273420140123">"फ़ोन"</string> <string name="default_audio_route_name_dock_speakers" msgid="6240602982276591864">"डॉक स्पीकर"</string> - <!-- no translation found for default_audio_route_name_hdmi (1486254205617081251) --> - <skip /> + <string name="default_audio_route_name_hdmi" msgid="1486254205617081251">"HDMI"</string> <string name="default_audio_route_name_headphones" msgid="8119971843803439110">"हेडफ़ोन"</string> - <!-- no translation found for default_audio_route_name_usb (1234984851352637769) --> - <skip /> + <string name="default_audio_route_name_usb" msgid="1234984851352637769">"USB"</string> <string name="default_audio_route_category_name" msgid="3722811174003886946">"सिस्टम"</string> <string name="bluetooth_a2dp_audio_route_name" msgid="8575624030406771015">"ब्लूटूथ ऑडियो"</string> <string name="wireless_display_route_description" msgid="9070346425023979651">"वायरलेस डिसप्ले"</string> diff --git a/core/res/res/values-hr/strings.xml b/core/res/res/values-hr/strings.xml index 8f74abc0208c..08a7697bf440 100644 --- a/core/res/res/values-hr/strings.xml +++ b/core/res/res/values-hr/strings.xml @@ -1444,11 +1444,9 @@ <string name="default_audio_route_name" product="tv" msgid="9158088547603019321">"Televizor"</string> <string name="default_audio_route_name" product="default" msgid="4239291273420140123">"Telefon"</string> <string name="default_audio_route_name_dock_speakers" msgid="6240602982276591864">"Zvučnici postolja"</string> - <!-- no translation found for default_audio_route_name_hdmi (1486254205617081251) --> - <skip /> + <string name="default_audio_route_name_hdmi" msgid="1486254205617081251">"HDMI"</string> <string name="default_audio_route_name_headphones" msgid="8119971843803439110">"Slušalice"</string> - <!-- no translation found for default_audio_route_name_usb (1234984851352637769) --> - <skip /> + <string name="default_audio_route_name_usb" msgid="1234984851352637769">"USB"</string> <string name="default_audio_route_category_name" msgid="3722811174003886946">"Sustav"</string> <string name="bluetooth_a2dp_audio_route_name" msgid="8575624030406771015">"Bluetooth zvuk"</string> <string name="wireless_display_route_description" msgid="9070346425023979651">"Bežični prikaz"</string> diff --git a/core/res/res/values-hu/strings.xml b/core/res/res/values-hu/strings.xml index 96d878cd0313..2cd1a10d6a8e 100644 --- a/core/res/res/values-hu/strings.xml +++ b/core/res/res/values-hu/strings.xml @@ -1421,11 +1421,9 @@ <string name="default_audio_route_name" product="tv" msgid="9158088547603019321">"TV"</string> <string name="default_audio_route_name" product="default" msgid="4239291273420140123">"Telefon"</string> <string name="default_audio_route_name_dock_speakers" msgid="6240602982276591864">"Dokkolóegység hangszórója"</string> - <!-- no translation found for default_audio_route_name_hdmi (1486254205617081251) --> - <skip /> + <string name="default_audio_route_name_hdmi" msgid="1486254205617081251">"HDMI"</string> <string name="default_audio_route_name_headphones" msgid="8119971843803439110">"Fejhallgató"</string> - <!-- no translation found for default_audio_route_name_usb (1234984851352637769) --> - <skip /> + <string name="default_audio_route_name_usb" msgid="1234984851352637769">"USB"</string> <string name="default_audio_route_category_name" msgid="3722811174003886946">"Rendszer"</string> <string name="bluetooth_a2dp_audio_route_name" msgid="8575624030406771015">"Bluetooth hang"</string> <string name="wireless_display_route_description" msgid="9070346425023979651">"Vezeték nélküli kijelző"</string> diff --git a/core/res/res/values-hy/strings.xml b/core/res/res/values-hy/strings.xml index b6649971afec..b27b257b24c0 100644 --- a/core/res/res/values-hy/strings.xml +++ b/core/res/res/values-hy/strings.xml @@ -1421,11 +1421,9 @@ <string name="default_audio_route_name" product="tv" msgid="9158088547603019321">"Հեռուստացույց"</string> <string name="default_audio_route_name" product="default" msgid="4239291273420140123">"Հեռախոս"</string> <string name="default_audio_route_name_dock_speakers" msgid="6240602982276591864">"Համակցված բարձրախոսներ"</string> - <!-- no translation found for default_audio_route_name_hdmi (1486254205617081251) --> - <skip /> + <string name="default_audio_route_name_hdmi" msgid="1486254205617081251">"HDMI"</string> <string name="default_audio_route_name_headphones" msgid="8119971843803439110">"Ականջակալներ"</string> - <!-- no translation found for default_audio_route_name_usb (1234984851352637769) --> - <skip /> + <string name="default_audio_route_name_usb" msgid="1234984851352637769">"USB"</string> <string name="default_audio_route_category_name" msgid="3722811174003886946">"Համակարգ"</string> <string name="bluetooth_a2dp_audio_route_name" msgid="8575624030406771015">"Bluetooth-ի աուդիո ֆայլ"</string> <string name="wireless_display_route_description" msgid="9070346425023979651">"Անլար էկրան"</string> diff --git a/core/res/res/values-in/strings.xml b/core/res/res/values-in/strings.xml index 0f210e9fc8d7..dda8877b3785 100644 --- a/core/res/res/values-in/strings.xml +++ b/core/res/res/values-in/strings.xml @@ -1421,11 +1421,9 @@ <string name="default_audio_route_name" product="tv" msgid="9158088547603019321">"TV"</string> <string name="default_audio_route_name" product="default" msgid="4239291273420140123">"Ponsel"</string> <string name="default_audio_route_name_dock_speakers" msgid="6240602982276591864">"Pengeras suara dok"</string> - <!-- no translation found for default_audio_route_name_hdmi (1486254205617081251) --> - <skip /> + <string name="default_audio_route_name_hdmi" msgid="1486254205617081251">"HDMI"</string> <string name="default_audio_route_name_headphones" msgid="8119971843803439110">"Headphone"</string> - <!-- no translation found for default_audio_route_name_usb (1234984851352637769) --> - <skip /> + <string name="default_audio_route_name_usb" msgid="1234984851352637769">"USB"</string> <string name="default_audio_route_category_name" msgid="3722811174003886946">"Sistem"</string> <string name="bluetooth_a2dp_audio_route_name" msgid="8575624030406771015">"Audio Bluetooth"</string> <string name="wireless_display_route_description" msgid="9070346425023979651">"Layar nirkabel"</string> diff --git a/core/res/res/values-is/strings.xml b/core/res/res/values-is/strings.xml index 3c256a9050f6..f72f0f640980 100644 --- a/core/res/res/values-is/strings.xml +++ b/core/res/res/values-is/strings.xml @@ -1421,11 +1421,9 @@ <string name="default_audio_route_name" product="tv" msgid="9158088547603019321">"Sjónvarp"</string> <string name="default_audio_route_name" product="default" msgid="4239291273420140123">"Sími"</string> <string name="default_audio_route_name_dock_speakers" msgid="6240602982276591864">"Dokkuhátalarar"</string> - <!-- no translation found for default_audio_route_name_hdmi (1486254205617081251) --> - <skip /> + <string name="default_audio_route_name_hdmi" msgid="1486254205617081251">"HDMI"</string> <string name="default_audio_route_name_headphones" msgid="8119971843803439110">"Heyrnartól"</string> - <!-- no translation found for default_audio_route_name_usb (1234984851352637769) --> - <skip /> + <string name="default_audio_route_name_usb" msgid="1234984851352637769">"USB"</string> <string name="default_audio_route_category_name" msgid="3722811174003886946">"Kerfi"</string> <string name="bluetooth_a2dp_audio_route_name" msgid="8575624030406771015">"Bluetooth-hljóð"</string> <string name="wireless_display_route_description" msgid="9070346425023979651">"Þráðlaus skjábirting"</string> diff --git a/core/res/res/values-it/strings.xml b/core/res/res/values-it/strings.xml index 147c10358221..e2c99e7d61d9 100644 --- a/core/res/res/values-it/strings.xml +++ b/core/res/res/values-it/strings.xml @@ -1421,11 +1421,9 @@ <string name="default_audio_route_name" product="tv" msgid="9158088547603019321">"TV"</string> <string name="default_audio_route_name" product="default" msgid="4239291273420140123">"Telefono"</string> <string name="default_audio_route_name_dock_speakers" msgid="6240602982276591864">"Altoparlanti dock"</string> - <!-- no translation found for default_audio_route_name_hdmi (1486254205617081251) --> - <skip /> + <string name="default_audio_route_name_hdmi" msgid="1486254205617081251">"HDMI"</string> <string name="default_audio_route_name_headphones" msgid="8119971843803439110">"Cuffie audio"</string> - <!-- no translation found for default_audio_route_name_usb (1234984851352637769) --> - <skip /> + <string name="default_audio_route_name_usb" msgid="1234984851352637769">"USB"</string> <string name="default_audio_route_category_name" msgid="3722811174003886946">"Sistema"</string> <string name="bluetooth_a2dp_audio_route_name" msgid="8575624030406771015">"Audio Bluetooth"</string> <string name="wireless_display_route_description" msgid="9070346425023979651">"Visualizzazione wireless"</string> diff --git a/core/res/res/values-iw/strings.xml b/core/res/res/values-iw/strings.xml index 67acb4f91f3f..1eb1e6625357 100644 --- a/core/res/res/values-iw/strings.xml +++ b/core/res/res/values-iw/strings.xml @@ -1467,11 +1467,9 @@ <string name="default_audio_route_name" product="tv" msgid="9158088547603019321">"טלוויזיה"</string> <string name="default_audio_route_name" product="default" msgid="4239291273420140123">"טלפון"</string> <string name="default_audio_route_name_dock_speakers" msgid="6240602982276591864">"רמקולים של מעגן"</string> - <!-- no translation found for default_audio_route_name_hdmi (1486254205617081251) --> - <skip /> + <string name="default_audio_route_name_hdmi" msgid="1486254205617081251">"HDMI"</string> <string name="default_audio_route_name_headphones" msgid="8119971843803439110">"אוזניות"</string> - <!-- no translation found for default_audio_route_name_usb (1234984851352637769) --> - <skip /> + <string name="default_audio_route_name_usb" msgid="1234984851352637769">"USB"</string> <string name="default_audio_route_category_name" msgid="3722811174003886946">"מערכת"</string> <string name="bluetooth_a2dp_audio_route_name" msgid="8575624030406771015">"אודיו Bluetooth"</string> <string name="wireless_display_route_description" msgid="9070346425023979651">"צג אלחוטי"</string> diff --git a/core/res/res/values-ja/strings.xml b/core/res/res/values-ja/strings.xml index de8c758a46f3..76caa1c7fc2f 100644 --- a/core/res/res/values-ja/strings.xml +++ b/core/res/res/values-ja/strings.xml @@ -1421,11 +1421,9 @@ <string name="default_audio_route_name" product="tv" msgid="9158088547603019321">"テレビ"</string> <string name="default_audio_route_name" product="default" msgid="4239291273420140123">"モバイル端末"</string> <string name="default_audio_route_name_dock_speakers" msgid="6240602982276591864">"ホルダーのスピーカー"</string> - <!-- no translation found for default_audio_route_name_hdmi (1486254205617081251) --> - <skip /> + <string name="default_audio_route_name_hdmi" msgid="1486254205617081251">"HDMI"</string> <string name="default_audio_route_name_headphones" msgid="8119971843803439110">"ヘッドホン"</string> - <!-- no translation found for default_audio_route_name_usb (1234984851352637769) --> - <skip /> + <string name="default_audio_route_name_usb" msgid="1234984851352637769">"USB"</string> <string name="default_audio_route_category_name" msgid="3722811174003886946">"システム"</string> <string name="bluetooth_a2dp_audio_route_name" msgid="8575624030406771015">"Bluetooth音声"</string> <string name="wireless_display_route_description" msgid="9070346425023979651">"ワイヤレスディスプレイ"</string> diff --git a/core/res/res/values-ka/strings.xml b/core/res/res/values-ka/strings.xml index 08bd6a4088e0..2149ded4fa16 100644 --- a/core/res/res/values-ka/strings.xml +++ b/core/res/res/values-ka/strings.xml @@ -1421,11 +1421,9 @@ <string name="default_audio_route_name" product="tv" msgid="9158088547603019321">"ტელევიზია"</string> <string name="default_audio_route_name" product="default" msgid="4239291273420140123">"ტელეფონი"</string> <string name="default_audio_route_name_dock_speakers" msgid="6240602982276591864">"სპიკერების მიმაგრება"</string> - <!-- no translation found for default_audio_route_name_hdmi (1486254205617081251) --> - <skip /> + <string name="default_audio_route_name_hdmi" msgid="1486254205617081251">"HDMI"</string> <string name="default_audio_route_name_headphones" msgid="8119971843803439110">"ყურსასმენები"</string> - <!-- no translation found for default_audio_route_name_usb (1234984851352637769) --> - <skip /> + <string name="default_audio_route_name_usb" msgid="1234984851352637769">"USB"</string> <string name="default_audio_route_category_name" msgid="3722811174003886946">"სისტემა"</string> <string name="bluetooth_a2dp_audio_route_name" msgid="8575624030406771015">"Bluetooth აუდიო"</string> <string name="wireless_display_route_description" msgid="9070346425023979651">"უსადენო ეკრანი"</string> diff --git a/core/res/res/values-kk/strings.xml b/core/res/res/values-kk/strings.xml index cd08c7ae1ff6..8e421de5e5b2 100644 --- a/core/res/res/values-kk/strings.xml +++ b/core/res/res/values-kk/strings.xml @@ -1421,11 +1421,9 @@ <string name="default_audio_route_name" product="tv" msgid="9158088547603019321">"ТД"</string> <string name="default_audio_route_name" product="default" msgid="4239291273420140123">"Телефон"</string> <string name="default_audio_route_name_dock_speakers" msgid="6240602982276591864">"Үндеткіштерді қондыру"</string> - <!-- no translation found for default_audio_route_name_hdmi (1486254205617081251) --> - <skip /> + <string name="default_audio_route_name_hdmi" msgid="1486254205617081251">"HDMI"</string> <string name="default_audio_route_name_headphones" msgid="8119971843803439110">"Құлақаспаптар"</string> - <!-- no translation found for default_audio_route_name_usb (1234984851352637769) --> - <skip /> + <string name="default_audio_route_name_usb" msgid="1234984851352637769">"USB"</string> <string name="default_audio_route_category_name" msgid="3722811174003886946">"Жүйе"</string> <string name="bluetooth_a2dp_audio_route_name" msgid="8575624030406771015">"Bluetooth aудио"</string> <string name="wireless_display_route_description" msgid="9070346425023979651">"Сымсыз дисплей"</string> diff --git a/core/res/res/values-km/strings.xml b/core/res/res/values-km/strings.xml index b8f982099c4b..910f42cf57ff 100644 --- a/core/res/res/values-km/strings.xml +++ b/core/res/res/values-km/strings.xml @@ -1423,11 +1423,9 @@ <string name="default_audio_route_name" product="tv" msgid="9158088547603019321">"ទូរទស្សន៍"</string> <string name="default_audio_route_name" product="default" msgid="4239291273420140123">"ទូរសព្ទ"</string> <string name="default_audio_route_name_dock_speakers" msgid="6240602982276591864">"ភ្ជាប់អូប៉ាល័រ"</string> - <!-- no translation found for default_audio_route_name_hdmi (1486254205617081251) --> - <skip /> + <string name="default_audio_route_name_hdmi" msgid="1486254205617081251">"HDMI"</string> <string name="default_audio_route_name_headphones" msgid="8119971843803439110">"កាស"</string> - <!-- no translation found for default_audio_route_name_usb (1234984851352637769) --> - <skip /> + <string name="default_audio_route_name_usb" msgid="1234984851352637769">"USB"</string> <string name="default_audio_route_category_name" msgid="3722811174003886946">"ប្រព័ន្ធ"</string> <string name="bluetooth_a2dp_audio_route_name" msgid="8575624030406771015">"សំឡេងប៊្លូធូស"</string> <string name="wireless_display_route_description" msgid="9070346425023979651">"បង្ហាញបណ្ដាញឥតខ្សែ"</string> diff --git a/core/res/res/values-kn/strings.xml b/core/res/res/values-kn/strings.xml index ea233f65f6ec..5db847f0909e 100644 --- a/core/res/res/values-kn/strings.xml +++ b/core/res/res/values-kn/strings.xml @@ -1421,11 +1421,9 @@ <string name="default_audio_route_name" product="tv" msgid="9158088547603019321">"ಟಿವಿ"</string> <string name="default_audio_route_name" product="default" msgid="4239291273420140123">"ಫೋನ್"</string> <string name="default_audio_route_name_dock_speakers" msgid="6240602982276591864">"ಡಾಕ್ ಸ್ಪೀಕರ್ಗಳು"</string> - <!-- no translation found for default_audio_route_name_hdmi (1486254205617081251) --> - <skip /> + <string name="default_audio_route_name_hdmi" msgid="1486254205617081251">"HDMI"</string> <string name="default_audio_route_name_headphones" msgid="8119971843803439110">"ಹೆಡ್ಫೋನ್ಗಳು"</string> - <!-- no translation found for default_audio_route_name_usb (1234984851352637769) --> - <skip /> + <string name="default_audio_route_name_usb" msgid="1234984851352637769">"USB"</string> <string name="default_audio_route_category_name" msgid="3722811174003886946">"ಸಿಸ್ಟಂ"</string> <string name="bluetooth_a2dp_audio_route_name" msgid="8575624030406771015">"ಬ್ಲೂಟೂತ್ ಆಡಿಯೊ"</string> <string name="wireless_display_route_description" msgid="9070346425023979651">"ವಯರ್ಲೆಸ್ ಪ್ರದರ್ಶನ"</string> diff --git a/core/res/res/values-ko/strings.xml b/core/res/res/values-ko/strings.xml index 411f12741887..ab31961399d3 100644 --- a/core/res/res/values-ko/strings.xml +++ b/core/res/res/values-ko/strings.xml @@ -358,11 +358,11 @@ <string name="permdesc_broadcastSticky" product="tablet" msgid="7749760494399915651">"앱이 브로드캐스트가 끝난 후에 남은 브로드캐스트를 보낼 수 있도록 허용합니다. 앱을 지나치게 사용하면 태블릿에서 메모리를 너무 많이 사용하도록 하여 속도를 저하시키거나 불안정하게 만들 수 있습니다."</string> <string name="permdesc_broadcastSticky" product="tv" msgid="6839285697565389467">"앱이 브로드캐스트가 끝난 후에도 흥미로운 브로드캐스트를 보낼 수 있도록 허용합니다. 이 기능을 과도하게 사용하면 메모리 사용량이 많아져 TV 속도가 저하되거나 성능이 불안정해질 수 있습니다."</string> <string name="permdesc_broadcastSticky" product="default" msgid="2825803764232445091">"앱이 브로드캐스트가 끝난 후에 남은 브로드캐스트를 보낼 수 있도록 허용합니다. 앱을 지나치게 사용하면 휴대전화에서 메모리를 너무 많이 사용하도록 하여 속도를 저하시키거나 불안정하게 만들 수 있습니다."</string> - <string name="permlab_readContacts" msgid="8348481131899886131">"주소록 읽기"</string> + <string name="permlab_readContacts" msgid="8348481131899886131">"연락처 읽기"</string> <string name="permdesc_readContacts" product="tablet" msgid="5294866856941149639">"특정인과 전화, 이메일 또는 기타 수단으로 연락한 빈도를 포함하여 사용자 태블릿에 저장된 연락처에 대한 데이터를 앱이 읽도록 허용합니다. 이 권한을 사용하면 앱이 연락처 데이터를 저장할 수 있으며, 악성 앱이 사용자 모르게 연락처 데이터를 공유할 수도 있습니다."</string> <string name="permdesc_readContacts" product="tv" msgid="1839238344654834087">"앱이 특정 연락처와 통화를 하거나 이메일을 주고받거나 다른 방법으로 연락한 횟수를 포함하여 TV에 저장된 연락처 관련 데이터를 읽을 수 있도록 허용합니다. 이 경우 앱이 연락처 데이터를 저장할 수 있으며 악성 앱이 사용자 몰래 연락처 데이터에 공유할 수도 있습니다."</string> <string name="permdesc_readContacts" product="default" msgid="8440654152457300662">"특정인과 전화, 이메일 또는 기타 수단으로 연락한 빈도를 포함하여 사용자 휴대전화에 저장된 연락처에 대한 데이터를 앱이 읽도록 허용합니다. 이 권한을 사용하면 앱이 연락처 데이터를 저장할 수 있으며, 악성 앱이 사용자 모르게 연락처 데이터를 공유할 수도 있습니다."</string> - <string name="permlab_writeContacts" msgid="5107492086416793544">"주소록 수정"</string> + <string name="permlab_writeContacts" msgid="5107492086416793544">"연락처 수정"</string> <string name="permdesc_writeContacts" product="tablet" msgid="897243932521953602">"특정인과 전화, 이메일 또는 기타 수단으로 연락한 빈도를 포함하여 사용자 태블릿에 저장된 연락처에 대한 데이터를 앱이 수정할 수 있도록 허용합니다. 이 권한을 사용하면 앱이 연락처 데이터를 삭제할 수 있습니다."</string> <string name="permdesc_writeContacts" product="tv" msgid="5438230957000018959">"앱이 특정 연락처와 통화를 하거나 이메일을 주고받거나 다른 수단으로 연락한 횟수를 포함하여 TV에 저장된 연락처 관련 데이터를 수정할 수 있도록 허용합니다. 이 경우 앱이 연락처 데이터를 삭제할 수 있습니다."</string> <string name="permdesc_writeContacts" product="default" msgid="589869224625163558">"특정인과 전화, 이메일 또는 기타 수단으로 연락한 빈도를 포함하여 사용자 휴대전화에 저장된 연락처에 대한 데이터를 앱이 수정할 수 있도록 허용합니다. 이 권한을 사용하면 앱이 연락처 데이터를 삭제할 수 있습니다."</string> @@ -1421,11 +1421,9 @@ <string name="default_audio_route_name" product="tv" msgid="9158088547603019321">"TV"</string> <string name="default_audio_route_name" product="default" msgid="4239291273420140123">"휴대전화"</string> <string name="default_audio_route_name_dock_speakers" msgid="6240602982276591864">"도크 스피커"</string> - <!-- no translation found for default_audio_route_name_hdmi (1486254205617081251) --> - <skip /> + <string name="default_audio_route_name_hdmi" msgid="1486254205617081251">"HDMI"</string> <string name="default_audio_route_name_headphones" msgid="8119971843803439110">"헤드폰"</string> - <!-- no translation found for default_audio_route_name_usb (1234984851352637769) --> - <skip /> + <string name="default_audio_route_name_usb" msgid="1234984851352637769">"USB"</string> <string name="default_audio_route_category_name" msgid="3722811174003886946">"시스템"</string> <string name="bluetooth_a2dp_audio_route_name" msgid="8575624030406771015">"블루투스 오디오"</string> <string name="wireless_display_route_description" msgid="9070346425023979651">"무선 디스플레이"</string> diff --git a/core/res/res/values-ky/strings.xml b/core/res/res/values-ky/strings.xml index ce9bab3e8ca5..25958bff8c8a 100644 --- a/core/res/res/values-ky/strings.xml +++ b/core/res/res/values-ky/strings.xml @@ -1422,11 +1422,9 @@ <string name="default_audio_route_name" product="tv" msgid="9158088547603019321">"Сыналгы"</string> <string name="default_audio_route_name" product="default" msgid="4239291273420140123">"Телефон"</string> <string name="default_audio_route_name_dock_speakers" msgid="6240602982276591864">"Аудио док бекет"</string> - <!-- no translation found for default_audio_route_name_hdmi (1486254205617081251) --> - <skip /> + <string name="default_audio_route_name_hdmi" msgid="1486254205617081251">"HDMI"</string> <string name="default_audio_route_name_headphones" msgid="8119971843803439110">"Кулакчын"</string> - <!-- no translation found for default_audio_route_name_usb (1234984851352637769) --> - <skip /> + <string name="default_audio_route_name_usb" msgid="1234984851352637769">"USB"</string> <string name="default_audio_route_category_name" msgid="3722811174003886946">"Тутум"</string> <string name="bluetooth_a2dp_audio_route_name" msgid="8575624030406771015">"Bluetooth аудио"</string> <string name="wireless_display_route_description" msgid="9070346425023979651">"Зымсыз дисплей"</string> diff --git a/core/res/res/values-lo/strings.xml b/core/res/res/values-lo/strings.xml index 2ebf450c4f84..8c6b80735a5c 100644 --- a/core/res/res/values-lo/strings.xml +++ b/core/res/res/values-lo/strings.xml @@ -1421,11 +1421,9 @@ <string name="default_audio_route_name" product="tv" msgid="9158088547603019321">"ໂທລະພາບ"</string> <string name="default_audio_route_name" product="default" msgid="4239291273420140123">"ໂທລະສັບ"</string> <string name="default_audio_route_name_dock_speakers" msgid="6240602982276591864">"ບ່ອນຕັ້ງລຳໂພງ"</string> - <!-- no translation found for default_audio_route_name_hdmi (1486254205617081251) --> - <skip /> + <string name="default_audio_route_name_hdmi" msgid="1486254205617081251">"HDMI"</string> <string name="default_audio_route_name_headphones" msgid="8119971843803439110">"ຫູຟັງ"</string> - <!-- no translation found for default_audio_route_name_usb (1234984851352637769) --> - <skip /> + <string name="default_audio_route_name_usb" msgid="1234984851352637769">"USB"</string> <string name="default_audio_route_category_name" msgid="3722811174003886946">"ລະບົບ"</string> <string name="bluetooth_a2dp_audio_route_name" msgid="8575624030406771015">"ສຽງ Bluetooth"</string> <string name="wireless_display_route_description" msgid="9070346425023979651">"ການສະແດງຜົນໄຮ້ສາຍ"</string> diff --git a/core/res/res/values-lt/strings.xml b/core/res/res/values-lt/strings.xml index e5a72092b1d1..3f6cddf98616 100644 --- a/core/res/res/values-lt/strings.xml +++ b/core/res/res/values-lt/strings.xml @@ -1467,11 +1467,9 @@ <string name="default_audio_route_name" product="tv" msgid="9158088547603019321">"TV"</string> <string name="default_audio_route_name" product="default" msgid="4239291273420140123">"Telefonas"</string> <string name="default_audio_route_name_dock_speakers" msgid="6240602982276591864">"Doko garsiakalbiai"</string> - <!-- no translation found for default_audio_route_name_hdmi (1486254205617081251) --> - <skip /> + <string name="default_audio_route_name_hdmi" msgid="1486254205617081251">"HDMI"</string> <string name="default_audio_route_name_headphones" msgid="8119971843803439110">"Ausinės"</string> - <!-- no translation found for default_audio_route_name_usb (1234984851352637769) --> - <skip /> + <string name="default_audio_route_name_usb" msgid="1234984851352637769">"USB"</string> <string name="default_audio_route_category_name" msgid="3722811174003886946">"Sistema"</string> <string name="bluetooth_a2dp_audio_route_name" msgid="8575624030406771015">"„Bluetooth“ garsas"</string> <string name="wireless_display_route_description" msgid="9070346425023979651">"Belaidis rodymas"</string> diff --git a/core/res/res/values-lv/strings.xml b/core/res/res/values-lv/strings.xml index 61c07566e30e..0afd3e773c86 100644 --- a/core/res/res/values-lv/strings.xml +++ b/core/res/res/values-lv/strings.xml @@ -1444,11 +1444,9 @@ <string name="default_audio_route_name" product="tv" msgid="9158088547603019321">"TV"</string> <string name="default_audio_route_name" product="default" msgid="4239291273420140123">"Tālrunis"</string> <string name="default_audio_route_name_dock_speakers" msgid="6240602982276591864">"Doka skaļruņi"</string> - <!-- no translation found for default_audio_route_name_hdmi (1486254205617081251) --> - <skip /> + <string name="default_audio_route_name_hdmi" msgid="1486254205617081251">"HDMI"</string> <string name="default_audio_route_name_headphones" msgid="8119971843803439110">"Austiņas"</string> - <!-- no translation found for default_audio_route_name_usb (1234984851352637769) --> - <skip /> + <string name="default_audio_route_name_usb" msgid="1234984851352637769">"USB"</string> <string name="default_audio_route_category_name" msgid="3722811174003886946">"Sistēma"</string> <string name="bluetooth_a2dp_audio_route_name" msgid="8575624030406771015">"Bluetooth audio"</string> <string name="wireless_display_route_description" msgid="9070346425023979651">"Bezvadu attēlošana"</string> diff --git a/core/res/res/values-mk/strings.xml b/core/res/res/values-mk/strings.xml index 6406ed1af1de..df755eab834e 100644 --- a/core/res/res/values-mk/strings.xml +++ b/core/res/res/values-mk/strings.xml @@ -1423,11 +1423,9 @@ <string name="default_audio_route_name" product="tv" msgid="9158088547603019321">"Телевизор"</string> <string name="default_audio_route_name" product="default" msgid="4239291273420140123">"Телефон"</string> <string name="default_audio_route_name_dock_speakers" msgid="6240602982276591864">"Приклучи звучници"</string> - <!-- no translation found for default_audio_route_name_hdmi (1486254205617081251) --> - <skip /> + <string name="default_audio_route_name_hdmi" msgid="1486254205617081251">"HDMI"</string> <string name="default_audio_route_name_headphones" msgid="8119971843803439110">"Слушалки"</string> - <!-- no translation found for default_audio_route_name_usb (1234984851352637769) --> - <skip /> + <string name="default_audio_route_name_usb" msgid="1234984851352637769">"USB"</string> <string name="default_audio_route_category_name" msgid="3722811174003886946">"Систем"</string> <string name="bluetooth_a2dp_audio_route_name" msgid="8575624030406771015">"Аудио на Bluetooth"</string> <string name="wireless_display_route_description" msgid="9070346425023979651">"Безжичен приказ"</string> diff --git a/core/res/res/values-ml/strings.xml b/core/res/res/values-ml/strings.xml index 2f9583ea01a7..488eba853431 100644 --- a/core/res/res/values-ml/strings.xml +++ b/core/res/res/values-ml/strings.xml @@ -1421,11 +1421,9 @@ <string name="default_audio_route_name" product="tv" msgid="9158088547603019321">"ടിവി"</string> <string name="default_audio_route_name" product="default" msgid="4239291273420140123">"ഫോണ്"</string> <string name="default_audio_route_name_dock_speakers" msgid="6240602982276591864">"ഡോക്ക് സ്പീക്കറുകൾ"</string> - <!-- no translation found for default_audio_route_name_hdmi (1486254205617081251) --> - <skip /> + <string name="default_audio_route_name_hdmi" msgid="1486254205617081251">"HDMI"</string> <string name="default_audio_route_name_headphones" msgid="8119971843803439110">"ഹെഡ്ഫോണുകൾ"</string> - <!-- no translation found for default_audio_route_name_usb (1234984851352637769) --> - <skip /> + <string name="default_audio_route_name_usb" msgid="1234984851352637769">"USB"</string> <string name="default_audio_route_category_name" msgid="3722811174003886946">"സിസ്റ്റം"</string> <string name="bluetooth_a2dp_audio_route_name" msgid="8575624030406771015">"ബ്ലൂടൂത്ത് ഓഡിയോ"</string> <string name="wireless_display_route_description" msgid="9070346425023979651">"വയർലെസ് ഡിസ്പ്ലേ"</string> diff --git a/core/res/res/values-mn/strings.xml b/core/res/res/values-mn/strings.xml index eab1e7ed1aa6..e58193216c4c 100644 --- a/core/res/res/values-mn/strings.xml +++ b/core/res/res/values-mn/strings.xml @@ -1421,11 +1421,9 @@ <string name="default_audio_route_name" product="tv" msgid="9158088547603019321">"Tелевиз"</string> <string name="default_audio_route_name" product="default" msgid="4239291273420140123">"Утас"</string> <string name="default_audio_route_name_dock_speakers" msgid="6240602982276591864">"Чанга яригчийг суулгах"</string> - <!-- no translation found for default_audio_route_name_hdmi (1486254205617081251) --> - <skip /> + <string name="default_audio_route_name_hdmi" msgid="1486254205617081251">"HDMI"</string> <string name="default_audio_route_name_headphones" msgid="8119971843803439110">"Чихэвч"</string> - <!-- no translation found for default_audio_route_name_usb (1234984851352637769) --> - <skip /> + <string name="default_audio_route_name_usb" msgid="1234984851352637769">"USB"</string> <string name="default_audio_route_category_name" msgid="3722811174003886946">"Систем"</string> <string name="bluetooth_a2dp_audio_route_name" msgid="8575624030406771015">"Bluetooth аудио"</string> <string name="wireless_display_route_description" msgid="9070346425023979651">"Утасгүй дэлгэц"</string> diff --git a/core/res/res/values-mr/strings.xml b/core/res/res/values-mr/strings.xml index f95df783790a..2cf3ec829845 100644 --- a/core/res/res/values-mr/strings.xml +++ b/core/res/res/values-mr/strings.xml @@ -1421,11 +1421,9 @@ <string name="default_audio_route_name" product="tv" msgid="9158088547603019321">"टीव्ही"</string> <string name="default_audio_route_name" product="default" msgid="4239291273420140123">"फोन"</string> <string name="default_audio_route_name_dock_speakers" msgid="6240602982276591864">"स्पीकर डॉक करा"</string> - <!-- no translation found for default_audio_route_name_hdmi (1486254205617081251) --> - <skip /> + <string name="default_audio_route_name_hdmi" msgid="1486254205617081251">"HDMI"</string> <string name="default_audio_route_name_headphones" msgid="8119971843803439110">"हेडफोन"</string> - <!-- no translation found for default_audio_route_name_usb (1234984851352637769) --> - <skip /> + <string name="default_audio_route_name_usb" msgid="1234984851352637769">"USB"</string> <string name="default_audio_route_category_name" msgid="3722811174003886946">"सिस्टम"</string> <string name="bluetooth_a2dp_audio_route_name" msgid="8575624030406771015">"ब्लूटूथ ऑडिओ"</string> <string name="wireless_display_route_description" msgid="9070346425023979651">"वायरलेस डिस्प्ले"</string> diff --git a/core/res/res/values-ms/strings.xml b/core/res/res/values-ms/strings.xml index e526246b1813..612bc0f7387c 100644 --- a/core/res/res/values-ms/strings.xml +++ b/core/res/res/values-ms/strings.xml @@ -1421,11 +1421,9 @@ <string name="default_audio_route_name" product="tv" msgid="9158088547603019321">"TV"</string> <string name="default_audio_route_name" product="default" msgid="4239291273420140123">"Telefon"</string> <string name="default_audio_route_name_dock_speakers" msgid="6240602982276591864">"Pembesar suara dok"</string> - <!-- no translation found for default_audio_route_name_hdmi (1486254205617081251) --> - <skip /> + <string name="default_audio_route_name_hdmi" msgid="1486254205617081251">"HDMI"</string> <string name="default_audio_route_name_headphones" msgid="8119971843803439110">"Fon kepala"</string> - <!-- no translation found for default_audio_route_name_usb (1234984851352637769) --> - <skip /> + <string name="default_audio_route_name_usb" msgid="1234984851352637769">"USB"</string> <string name="default_audio_route_category_name" msgid="3722811174003886946">"Sistem"</string> <string name="bluetooth_a2dp_audio_route_name" msgid="8575624030406771015">"Audio Bluetooth"</string> <string name="wireless_display_route_description" msgid="9070346425023979651">"Paparan wayarles"</string> diff --git a/core/res/res/values-my/strings.xml b/core/res/res/values-my/strings.xml index c8c95f0b09fe..7c2277865daf 100644 --- a/core/res/res/values-my/strings.xml +++ b/core/res/res/values-my/strings.xml @@ -1421,11 +1421,9 @@ <string name="default_audio_route_name" product="tv" msgid="9158088547603019321">"တီဗွီ"</string> <string name="default_audio_route_name" product="default" msgid="4239291273420140123">"ဖုန်း"</string> <string name="default_audio_route_name_dock_speakers" msgid="6240602982276591864">"အထိုင်ရှိသော စပီကာများ"</string> - <!-- no translation found for default_audio_route_name_hdmi (1486254205617081251) --> - <skip /> + <string name="default_audio_route_name_hdmi" msgid="1486254205617081251">"HDMI"</string> <string name="default_audio_route_name_headphones" msgid="8119971843803439110">"နားကြပ်"</string> - <!-- no translation found for default_audio_route_name_usb (1234984851352637769) --> - <skip /> + <string name="default_audio_route_name_usb" msgid="1234984851352637769">"USB"</string> <string name="default_audio_route_category_name" msgid="3722811174003886946">"စနစ်"</string> <string name="bluetooth_a2dp_audio_route_name" msgid="8575624030406771015">"ဘလူးတုသ် အသံ"</string> <string name="wireless_display_route_description" msgid="9070346425023979651">"ကြိုးမဲ့ပြသခြင်း"</string> diff --git a/core/res/res/values-nb/strings.xml b/core/res/res/values-nb/strings.xml index b8538942eb07..8b1f80435387 100644 --- a/core/res/res/values-nb/strings.xml +++ b/core/res/res/values-nb/strings.xml @@ -1421,11 +1421,9 @@ <string name="default_audio_route_name" product="tv" msgid="9158088547603019321">"Google TV"</string> <string name="default_audio_route_name" product="default" msgid="4239291273420140123">"Telefon"</string> <string name="default_audio_route_name_dock_speakers" msgid="6240602982276591864">"Dokkhøyttalere"</string> - <!-- no translation found for default_audio_route_name_hdmi (1486254205617081251) --> - <skip /> + <string name="default_audio_route_name_hdmi" msgid="1486254205617081251">"HDMI"</string> <string name="default_audio_route_name_headphones" msgid="8119971843803439110">"Hodetelefoner"</string> - <!-- no translation found for default_audio_route_name_usb (1234984851352637769) --> - <skip /> + <string name="default_audio_route_name_usb" msgid="1234984851352637769">"USB"</string> <string name="default_audio_route_category_name" msgid="3722811174003886946">"System"</string> <string name="bluetooth_a2dp_audio_route_name" msgid="8575624030406771015">"Bluetooth-lyd"</string> <string name="wireless_display_route_description" msgid="9070346425023979651">"Trådløs skjerm"</string> diff --git a/core/res/res/values-ne/strings.xml b/core/res/res/values-ne/strings.xml index 69eab151810e..a0f0065d7041 100644 --- a/core/res/res/values-ne/strings.xml +++ b/core/res/res/values-ne/strings.xml @@ -1427,11 +1427,9 @@ <string name="default_audio_route_name" product="tv" msgid="9158088547603019321">"TV"</string> <string name="default_audio_route_name" product="default" msgid="4239291273420140123">"फोन"</string> <string name="default_audio_route_name_dock_speakers" msgid="6240602982276591864">"डक स्पिकरहरू"</string> - <!-- no translation found for default_audio_route_name_hdmi (1486254205617081251) --> - <skip /> + <string name="default_audio_route_name_hdmi" msgid="1486254205617081251">"HDMI"</string> <string name="default_audio_route_name_headphones" msgid="8119971843803439110">"हेडफोनहरू"</string> - <!-- no translation found for default_audio_route_name_usb (1234984851352637769) --> - <skip /> + <string name="default_audio_route_name_usb" msgid="1234984851352637769">"USB"</string> <string name="default_audio_route_category_name" msgid="3722811174003886946">"प्रणाली"</string> <string name="bluetooth_a2dp_audio_route_name" msgid="8575624030406771015">"ब्लुटुथ अडियो"</string> <string name="wireless_display_route_description" msgid="9070346425023979651">"ताररहित प्रदर्शन"</string> diff --git a/core/res/res/values-nl/strings.xml b/core/res/res/values-nl/strings.xml index ed7a1dd6bbb2..39810e4ac052 100644 --- a/core/res/res/values-nl/strings.xml +++ b/core/res/res/values-nl/strings.xml @@ -1421,11 +1421,9 @@ <string name="default_audio_route_name" product="tv" msgid="9158088547603019321">"Tv"</string> <string name="default_audio_route_name" product="default" msgid="4239291273420140123">"Telefoon"</string> <string name="default_audio_route_name_dock_speakers" msgid="6240602982276591864">"Dockluidsprekers"</string> - <!-- no translation found for default_audio_route_name_hdmi (1486254205617081251) --> - <skip /> + <string name="default_audio_route_name_hdmi" msgid="1486254205617081251">"HDMI"</string> <string name="default_audio_route_name_headphones" msgid="8119971843803439110">"Hoofdtelefoon"</string> - <!-- no translation found for default_audio_route_name_usb (1234984851352637769) --> - <skip /> + <string name="default_audio_route_name_usb" msgid="1234984851352637769">"USB"</string> <string name="default_audio_route_category_name" msgid="3722811174003886946">"Systeem"</string> <string name="bluetooth_a2dp_audio_route_name" msgid="8575624030406771015">"Bluetooth-audio"</string> <string name="wireless_display_route_description" msgid="9070346425023979651">"Draadloze weergave"</string> diff --git a/core/res/res/values-pa/strings.xml b/core/res/res/values-pa/strings.xml index 11957f1524af..719eb97cc980 100644 --- a/core/res/res/values-pa/strings.xml +++ b/core/res/res/values-pa/strings.xml @@ -1421,11 +1421,9 @@ <string name="default_audio_route_name" product="tv" msgid="9158088547603019321">"TV"</string> <string name="default_audio_route_name" product="default" msgid="4239291273420140123">"ਫ਼ੋਨ ਕਰੋ"</string> <string name="default_audio_route_name_dock_speakers" msgid="6240602982276591864">"ਡੌਕ ਸਪੀਕਰਸ"</string> - <!-- no translation found for default_audio_route_name_hdmi (1486254205617081251) --> - <skip /> + <string name="default_audio_route_name_hdmi" msgid="1486254205617081251">"HDMI"</string> <string name="default_audio_route_name_headphones" msgid="8119971843803439110">"ਹੈੱਡਫ਼ੋਨ"</string> - <!-- no translation found for default_audio_route_name_usb (1234984851352637769) --> - <skip /> + <string name="default_audio_route_name_usb" msgid="1234984851352637769">"USB"</string> <string name="default_audio_route_category_name" msgid="3722811174003886946">"ਸਿਸਟਮ"</string> <string name="bluetooth_a2dp_audio_route_name" msgid="8575624030406771015">"Bluetooth ਆਡੀਓ"</string> <string name="wireless_display_route_description" msgid="9070346425023979651">"ਵਾਇਰਲੈੱਸ ਡਿਸਪਲੇ"</string> diff --git a/core/res/res/values-pl/strings.xml b/core/res/res/values-pl/strings.xml index 071b570499f0..7b349796d5c3 100644 --- a/core/res/res/values-pl/strings.xml +++ b/core/res/res/values-pl/strings.xml @@ -257,7 +257,7 @@ <string name="notification_channel_foreground_service" msgid="3931987440602669158">"Aplikacje zużywające baterię"</string> <string name="foreground_service_app_in_background" msgid="1060198778219731292">"Aplikacja <xliff:g id="APP_NAME">%1$s</xliff:g> zużywa baterię"</string> <string name="foreground_service_apps_in_background" msgid="7175032677643332242">"Liczba aplikacji zużywających baterię: <xliff:g id="NUMBER">%1$d</xliff:g>"</string> - <string name="foreground_service_tap_for_details" msgid="372046743534354644">"Kliknij, by wyświetlić szczegóły wykorzystania baterii i transmisji danych"</string> + <string name="foreground_service_tap_for_details" msgid="372046743534354644">"Kliknij, by wyświetlić szczegóły wykorzystania baterii i użycia danych"</string> <string name="foreground_service_multiple_separator" msgid="4021901567939866542">"<xliff:g id="LEFT_SIDE">%1$s</xliff:g>, <xliff:g id="RIGHT_SIDE">%2$s</xliff:g>"</string> <string name="safeMode" msgid="2788228061547930246">"Tryb awaryjny"</string> <string name="android_system_label" msgid="6577375335728551336">"System Android"</string> @@ -347,7 +347,7 @@ <string name="permlab_runInBackground" msgid="7365290743781858803">"działanie w tle"</string> <string name="permdesc_runInBackground" msgid="7370142232209999824">"Ta aplikacja może działać w tle. Bateria może się szybciej rozładowywać."</string> <string name="permlab_useDataInBackground" msgid="8694951340794341809">"transmisja danych w tle"</string> - <string name="permdesc_useDataInBackground" msgid="6049514223791806027">"Ta aplikacja może przesyłać i odbierać dane w tle. Transmisja danych może się zwiększyć."</string> + <string name="permdesc_useDataInBackground" msgid="6049514223791806027">"Ta aplikacja może przesyłać i odbierać dane w tle. Użycie danych może się zwiększyć."</string> <string name="permlab_persistentActivity" msgid="8841113627955563938">"sprawianie, że aplikacja jest cały czas uruchomiona"</string> <string name="permdesc_persistentActivity" product="tablet" msgid="8525189272329086137">"Pozwala aplikacji na trwałe zapisywanie swoich fragmentów w pamięci. Może to zmniejszyć ilość pamięci dostępnej dla innych aplikacji i spowolnić działanie tabletu."</string> <string name="permdesc_persistentActivity" product="tv" msgid="5086862529499103587">"Pozwala aplikacji zapewnić nieusuwalność swoich fragmentów z pamięci. Może to ograniczyć ilość pamięci dostępną dla innych aplikacji i spowalniać działanie telewizora."</string> @@ -1426,7 +1426,7 @@ <string name="storage_usb_drive_label" msgid="4501418548927759953">"Dysk USB (<xliff:g id="MANUFACTURER">%s</xliff:g>)"</string> <string name="storage_usb" msgid="3017954059538517278">"Nośnik USB"</string> <string name="extract_edit_menu_button" msgid="8940478730496610137">"Edytuj"</string> - <string name="data_usage_warning_title" msgid="3620440638180218181">"Alert transmisji danych"</string> + <string name="data_usage_warning_title" msgid="3620440638180218181">"Alert użycia danych"</string> <string name="data_usage_warning_body" msgid="6660692274311972007">"Kliknij, by wyświetlić użycie i ustawienia."</string> <string name="data_usage_3g_limit_title" msgid="4361523876818447683">"Osiągnięto limit danych 2G/3G"</string> <string name="data_usage_4g_limit_title" msgid="4609566827219442376">"Osiągnięto limit danych 4G"</string> @@ -1467,11 +1467,9 @@ <string name="default_audio_route_name" product="tv" msgid="9158088547603019321">"Telewizor"</string> <string name="default_audio_route_name" product="default" msgid="4239291273420140123">"Telefon"</string> <string name="default_audio_route_name_dock_speakers" msgid="6240602982276591864">"Głośniki stacji dokującej"</string> - <!-- no translation found for default_audio_route_name_hdmi (1486254205617081251) --> - <skip /> + <string name="default_audio_route_name_hdmi" msgid="1486254205617081251">"HDMI"</string> <string name="default_audio_route_name_headphones" msgid="8119971843803439110">"Słuchawki"</string> - <!-- no translation found for default_audio_route_name_usb (1234984851352637769) --> - <skip /> + <string name="default_audio_route_name_usb" msgid="1234984851352637769">"USB"</string> <string name="default_audio_route_category_name" msgid="3722811174003886946">"System"</string> <string name="bluetooth_a2dp_audio_route_name" msgid="8575624030406771015">"Dźwięk Bluetooth"</string> <string name="wireless_display_route_description" msgid="9070346425023979651">"Wyświetlacz bezprzewodowy"</string> diff --git a/core/res/res/values-pt-rBR/strings.xml b/core/res/res/values-pt-rBR/strings.xml index 8e3c99126ed4..276add6425be 100644 --- a/core/res/res/values-pt-rBR/strings.xml +++ b/core/res/res/values-pt-rBR/strings.xml @@ -1421,11 +1421,9 @@ <string name="default_audio_route_name" product="tv" msgid="9158088547603019321">"TV"</string> <string name="default_audio_route_name" product="default" msgid="4239291273420140123">"Telefone"</string> <string name="default_audio_route_name_dock_speakers" msgid="6240602982276591864">"Alto-falantes da dock"</string> - <!-- no translation found for default_audio_route_name_hdmi (1486254205617081251) --> - <skip /> + <string name="default_audio_route_name_hdmi" msgid="1486254205617081251">"HDMI"</string> <string name="default_audio_route_name_headphones" msgid="8119971843803439110">"Fones de ouvido"</string> - <!-- no translation found for default_audio_route_name_usb (1234984851352637769) --> - <skip /> + <string name="default_audio_route_name_usb" msgid="1234984851352637769">"USB"</string> <string name="default_audio_route_category_name" msgid="3722811174003886946">"Sistema"</string> <string name="bluetooth_a2dp_audio_route_name" msgid="8575624030406771015">"Áudio Bluetooth"</string> <string name="wireless_display_route_description" msgid="9070346425023979651">"Display sem fio"</string> diff --git a/core/res/res/values-pt-rPT/strings.xml b/core/res/res/values-pt-rPT/strings.xml index 1042165235fd..ac81366a6bd5 100644 --- a/core/res/res/values-pt-rPT/strings.xml +++ b/core/res/res/values-pt-rPT/strings.xml @@ -1421,11 +1421,9 @@ <string name="default_audio_route_name" product="tv" msgid="9158088547603019321">"TV"</string> <string name="default_audio_route_name" product="default" msgid="4239291273420140123">"Telemóvel"</string> <string name="default_audio_route_name_dock_speakers" msgid="6240602982276591864">"Altif. estação ancoragem"</string> - <!-- no translation found for default_audio_route_name_hdmi (1486254205617081251) --> - <skip /> + <string name="default_audio_route_name_hdmi" msgid="1486254205617081251">"HDMI"</string> <string name="default_audio_route_name_headphones" msgid="8119971843803439110">"Auscultadores"</string> - <!-- no translation found for default_audio_route_name_usb (1234984851352637769) --> - <skip /> + <string name="default_audio_route_name_usb" msgid="1234984851352637769">"USB"</string> <string name="default_audio_route_category_name" msgid="3722811174003886946">"Sistema"</string> <string name="bluetooth_a2dp_audio_route_name" msgid="8575624030406771015">"Áudio Bluetooth"</string> <string name="wireless_display_route_description" msgid="9070346425023979651">"Visualização sem fios"</string> diff --git a/core/res/res/values-pt/strings.xml b/core/res/res/values-pt/strings.xml index 8e3c99126ed4..276add6425be 100644 --- a/core/res/res/values-pt/strings.xml +++ b/core/res/res/values-pt/strings.xml @@ -1421,11 +1421,9 @@ <string name="default_audio_route_name" product="tv" msgid="9158088547603019321">"TV"</string> <string name="default_audio_route_name" product="default" msgid="4239291273420140123">"Telefone"</string> <string name="default_audio_route_name_dock_speakers" msgid="6240602982276591864">"Alto-falantes da dock"</string> - <!-- no translation found for default_audio_route_name_hdmi (1486254205617081251) --> - <skip /> + <string name="default_audio_route_name_hdmi" msgid="1486254205617081251">"HDMI"</string> <string name="default_audio_route_name_headphones" msgid="8119971843803439110">"Fones de ouvido"</string> - <!-- no translation found for default_audio_route_name_usb (1234984851352637769) --> - <skip /> + <string name="default_audio_route_name_usb" msgid="1234984851352637769">"USB"</string> <string name="default_audio_route_category_name" msgid="3722811174003886946">"Sistema"</string> <string name="bluetooth_a2dp_audio_route_name" msgid="8575624030406771015">"Áudio Bluetooth"</string> <string name="wireless_display_route_description" msgid="9070346425023979651">"Display sem fio"</string> diff --git a/core/res/res/values-ro/strings.xml b/core/res/res/values-ro/strings.xml index 1750066de566..6f310b3d0155 100644 --- a/core/res/res/values-ro/strings.xml +++ b/core/res/res/values-ro/strings.xml @@ -1444,11 +1444,9 @@ <string name="default_audio_route_name" product="tv" msgid="9158088547603019321">"TV"</string> <string name="default_audio_route_name" product="default" msgid="4239291273420140123">"Telefon"</string> <string name="default_audio_route_name_dock_speakers" msgid="6240602982276591864">"Difuz. dispozit. andocare"</string> - <!-- no translation found for default_audio_route_name_hdmi (1486254205617081251) --> - <skip /> + <string name="default_audio_route_name_hdmi" msgid="1486254205617081251">"HDMI"</string> <string name="default_audio_route_name_headphones" msgid="8119971843803439110">"Căști"</string> - <!-- no translation found for default_audio_route_name_usb (1234984851352637769) --> - <skip /> + <string name="default_audio_route_name_usb" msgid="1234984851352637769">"USB"</string> <string name="default_audio_route_category_name" msgid="3722811174003886946">"Sistem"</string> <string name="bluetooth_a2dp_audio_route_name" msgid="8575624030406771015">"Audio Bluetooth"</string> <string name="wireless_display_route_description" msgid="9070346425023979651">"Ecran wireless"</string> diff --git a/core/res/res/values-ru/strings.xml b/core/res/res/values-ru/strings.xml index b5cf23370048..1960663f0ab9 100644 --- a/core/res/res/values-ru/strings.xml +++ b/core/res/res/values-ru/strings.xml @@ -1467,11 +1467,9 @@ <string name="default_audio_route_name" product="tv" msgid="9158088547603019321">"Телевизор"</string> <string name="default_audio_route_name" product="default" msgid="4239291273420140123">"Телефон"</string> <string name="default_audio_route_name_dock_speakers" msgid="6240602982276591864">"Динамики док-станции"</string> - <!-- no translation found for default_audio_route_name_hdmi (1486254205617081251) --> - <skip /> + <string name="default_audio_route_name_hdmi" msgid="1486254205617081251">"HDMI"</string> <string name="default_audio_route_name_headphones" msgid="8119971843803439110">"Наушники"</string> - <!-- no translation found for default_audio_route_name_usb (1234984851352637769) --> - <skip /> + <string name="default_audio_route_name_usb" msgid="1234984851352637769">"USB"</string> <string name="default_audio_route_category_name" msgid="3722811174003886946">"Система"</string> <string name="bluetooth_a2dp_audio_route_name" msgid="8575624030406771015">"Воспроизведение звука через Bluetooth"</string> <string name="wireless_display_route_description" msgid="9070346425023979651">"Беспроводной монитор"</string> diff --git a/core/res/res/values-si/strings.xml b/core/res/res/values-si/strings.xml index 539064c0f7e2..63f2c50c0a78 100644 --- a/core/res/res/values-si/strings.xml +++ b/core/res/res/values-si/strings.xml @@ -1423,11 +1423,9 @@ <string name="default_audio_route_name" product="tv" msgid="9158088547603019321">"රූපවාහිනී"</string> <string name="default_audio_route_name" product="default" msgid="4239291273420140123">"දුරකථනය"</string> <string name="default_audio_route_name_dock_speakers" msgid="6240602982276591864">"නාදක ඩොක් කරන්න"</string> - <!-- no translation found for default_audio_route_name_hdmi (1486254205617081251) --> - <skip /> + <string name="default_audio_route_name_hdmi" msgid="1486254205617081251">"HDMI"</string> <string name="default_audio_route_name_headphones" msgid="8119971843803439110">"ඉස් බණු"</string> - <!-- no translation found for default_audio_route_name_usb (1234984851352637769) --> - <skip /> + <string name="default_audio_route_name_usb" msgid="1234984851352637769">"USB"</string> <string name="default_audio_route_category_name" msgid="3722811174003886946">"පද්ධතිය"</string> <string name="bluetooth_a2dp_audio_route_name" msgid="8575624030406771015">"බ්ලූටූත් ශ්රව්ය"</string> <string name="wireless_display_route_description" msgid="9070346425023979651">"නොරැහැන් සංදර්ශකය"</string> diff --git a/core/res/res/values-sk/strings.xml b/core/res/res/values-sk/strings.xml index be7664c78fbb..9f37618bfc8f 100644 --- a/core/res/res/values-sk/strings.xml +++ b/core/res/res/values-sk/strings.xml @@ -1467,11 +1467,9 @@ <string name="default_audio_route_name" product="tv" msgid="9158088547603019321">"Televízor"</string> <string name="default_audio_route_name" product="default" msgid="4239291273420140123">"Telefón"</string> <string name="default_audio_route_name_dock_speakers" msgid="6240602982276591864">"Reproduktory doku"</string> - <!-- no translation found for default_audio_route_name_hdmi (1486254205617081251) --> - <skip /> + <string name="default_audio_route_name_hdmi" msgid="1486254205617081251">"HDMI"</string> <string name="default_audio_route_name_headphones" msgid="8119971843803439110">"Slúchadlá"</string> - <!-- no translation found for default_audio_route_name_usb (1234984851352637769) --> - <skip /> + <string name="default_audio_route_name_usb" msgid="1234984851352637769">"USB"</string> <string name="default_audio_route_category_name" msgid="3722811174003886946">"Systém"</string> <string name="bluetooth_a2dp_audio_route_name" msgid="8575624030406771015">"Bluetooth audio"</string> <string name="wireless_display_route_description" msgid="9070346425023979651">"Bezdrôtové zobrazenie"</string> diff --git a/core/res/res/values-sl/strings.xml b/core/res/res/values-sl/strings.xml index aaa2432c2145..349e5b1901eb 100644 --- a/core/res/res/values-sl/strings.xml +++ b/core/res/res/values-sl/strings.xml @@ -1467,11 +1467,9 @@ <string name="default_audio_route_name" product="tv" msgid="9158088547603019321">"Televizor"</string> <string name="default_audio_route_name" product="default" msgid="4239291273420140123">"Telefon"</string> <string name="default_audio_route_name_dock_speakers" msgid="6240602982276591864">"Zvočniki stojala"</string> - <!-- no translation found for default_audio_route_name_hdmi (1486254205617081251) --> - <skip /> + <string name="default_audio_route_name_hdmi" msgid="1486254205617081251">"HDMI"</string> <string name="default_audio_route_name_headphones" msgid="8119971843803439110">"Slušalke"</string> - <!-- no translation found for default_audio_route_name_usb (1234984851352637769) --> - <skip /> + <string name="default_audio_route_name_usb" msgid="1234984851352637769">"USB"</string> <string name="default_audio_route_category_name" msgid="3722811174003886946">"Sistem"</string> <string name="bluetooth_a2dp_audio_route_name" msgid="8575624030406771015">"Zvok prek Bluetootha"</string> <string name="wireless_display_route_description" msgid="9070346425023979651">"Brezžični prikaz"</string> diff --git a/core/res/res/values-sq/strings.xml b/core/res/res/values-sq/strings.xml index 31c7c313c95f..f67c889e34e9 100644 --- a/core/res/res/values-sq/strings.xml +++ b/core/res/res/values-sq/strings.xml @@ -1421,11 +1421,9 @@ <string name="default_audio_route_name" product="tv" msgid="9158088547603019321">"Televizori"</string> <string name="default_audio_route_name" product="default" msgid="4239291273420140123">"Telefon"</string> <string name="default_audio_route_name_dock_speakers" msgid="6240602982276591864">"Altoparlantët e stacionit"</string> - <!-- no translation found for default_audio_route_name_hdmi (1486254205617081251) --> - <skip /> + <string name="default_audio_route_name_hdmi" msgid="1486254205617081251">"HDMI"</string> <string name="default_audio_route_name_headphones" msgid="8119971843803439110">"Kufjet"</string> - <!-- no translation found for default_audio_route_name_usb (1234984851352637769) --> - <skip /> + <string name="default_audio_route_name_usb" msgid="1234984851352637769">"USB"</string> <string name="default_audio_route_category_name" msgid="3722811174003886946">"Sistemi"</string> <string name="bluetooth_a2dp_audio_route_name" msgid="8575624030406771015">"Audioja e \"bluetooth-it\""</string> <string name="wireless_display_route_description" msgid="9070346425023979651">"Ekran pa tel"</string> diff --git a/core/res/res/values-sr/strings.xml b/core/res/res/values-sr/strings.xml index 5d25cf174509..579a60199e71 100644 --- a/core/res/res/values-sr/strings.xml +++ b/core/res/res/values-sr/strings.xml @@ -1444,11 +1444,9 @@ <string name="default_audio_route_name" product="tv" msgid="9158088547603019321">"ТВ"</string> <string name="default_audio_route_name" product="default" msgid="4239291273420140123">"Телефон"</string> <string name="default_audio_route_name_dock_speakers" msgid="6240602982276591864">"Звучници базне станице"</string> - <!-- no translation found for default_audio_route_name_hdmi (1486254205617081251) --> - <skip /> + <string name="default_audio_route_name_hdmi" msgid="1486254205617081251">"HDMI"</string> <string name="default_audio_route_name_headphones" msgid="8119971843803439110">"Слушалице"</string> - <!-- no translation found for default_audio_route_name_usb (1234984851352637769) --> - <skip /> + <string name="default_audio_route_name_usb" msgid="1234984851352637769">"USB"</string> <string name="default_audio_route_category_name" msgid="3722811174003886946">"Систем"</string> <string name="bluetooth_a2dp_audio_route_name" msgid="8575624030406771015">"Bluetooth аудио"</string> <string name="wireless_display_route_description" msgid="9070346425023979651">"Бежични екран"</string> diff --git a/core/res/res/values-sv/strings.xml b/core/res/res/values-sv/strings.xml index d0c857251963..619d498349bb 100644 --- a/core/res/res/values-sv/strings.xml +++ b/core/res/res/values-sv/strings.xml @@ -1421,11 +1421,9 @@ <string name="default_audio_route_name" product="tv" msgid="9158088547603019321">"TV"</string> <string name="default_audio_route_name" product="default" msgid="4239291273420140123">"Mobil"</string> <string name="default_audio_route_name_dock_speakers" msgid="6240602982276591864">"Dockningsstationens högtalare"</string> - <!-- no translation found for default_audio_route_name_hdmi (1486254205617081251) --> - <skip /> + <string name="default_audio_route_name_hdmi" msgid="1486254205617081251">"HDMI"</string> <string name="default_audio_route_name_headphones" msgid="8119971843803439110">"Hörlurar"</string> - <!-- no translation found for default_audio_route_name_usb (1234984851352637769) --> - <skip /> + <string name="default_audio_route_name_usb" msgid="1234984851352637769">"USB"</string> <string name="default_audio_route_category_name" msgid="3722811174003886946">"System"</string> <string name="bluetooth_a2dp_audio_route_name" msgid="8575624030406771015">"Bluetooth-ljud"</string> <string name="wireless_display_route_description" msgid="9070346425023979651">"Trådlös skärm"</string> diff --git a/core/res/res/values-sw/strings.xml b/core/res/res/values-sw/strings.xml index a28e14a59dc3..236e467c0db8 100644 --- a/core/res/res/values-sw/strings.xml +++ b/core/res/res/values-sw/strings.xml @@ -1419,11 +1419,9 @@ <string name="default_audio_route_name" product="tv" msgid="9158088547603019321">"Runinga"</string> <string name="default_audio_route_name" product="default" msgid="4239291273420140123">"Simu"</string> <string name="default_audio_route_name_dock_speakers" msgid="6240602982276591864">"Vipasa sauti vya kituo"</string> - <!-- no translation found for default_audio_route_name_hdmi (1486254205617081251) --> - <skip /> + <string name="default_audio_route_name_hdmi" msgid="1486254205617081251">"HDMI"</string> <string name="default_audio_route_name_headphones" msgid="8119971843803439110">"Vipokeasauti"</string> - <!-- no translation found for default_audio_route_name_usb (1234984851352637769) --> - <skip /> + <string name="default_audio_route_name_usb" msgid="1234984851352637769">"USB"</string> <string name="default_audio_route_category_name" msgid="3722811174003886946">"Mfumo"</string> <string name="bluetooth_a2dp_audio_route_name" msgid="8575624030406771015">"Sauti ya Bluetooth"</string> <string name="wireless_display_route_description" msgid="9070346425023979651">"Uonyeshaji usiotumia waya"</string> diff --git a/core/res/res/values-ta/strings.xml b/core/res/res/values-ta/strings.xml index 62f90539a0eb..9c81d0ec49bb 100644 --- a/core/res/res/values-ta/strings.xml +++ b/core/res/res/values-ta/strings.xml @@ -1421,11 +1421,9 @@ <string name="default_audio_route_name" product="tv" msgid="9158088547603019321">"டிவி"</string> <string name="default_audio_route_name" product="default" msgid="4239291273420140123">"ஃபோன்"</string> <string name="default_audio_route_name_dock_speakers" msgid="6240602982276591864">"மொபைல் வைக்கும் கருவியின் ஸ்பீக்கர்கள்"</string> - <!-- no translation found for default_audio_route_name_hdmi (1486254205617081251) --> - <skip /> + <string name="default_audio_route_name_hdmi" msgid="1486254205617081251">"HDMI"</string> <string name="default_audio_route_name_headphones" msgid="8119971843803439110">"ஹெட்ஃபோன்கள்"</string> - <!-- no translation found for default_audio_route_name_usb (1234984851352637769) --> - <skip /> + <string name="default_audio_route_name_usb" msgid="1234984851352637769">"USB"</string> <string name="default_audio_route_category_name" msgid="3722811174003886946">"சிஸ்டம்"</string> <string name="bluetooth_a2dp_audio_route_name" msgid="8575624030406771015">"புளூடூத் ஆடியோ"</string> <string name="wireless_display_route_description" msgid="9070346425023979651">"வயர்லெஸ் காட்சி"</string> diff --git a/core/res/res/values-te/strings.xml b/core/res/res/values-te/strings.xml index 95c055635f73..5b05a254d1fb 100644 --- a/core/res/res/values-te/strings.xml +++ b/core/res/res/values-te/strings.xml @@ -1421,11 +1421,9 @@ <string name="default_audio_route_name" product="tv" msgid="9158088547603019321">"టీవీ"</string> <string name="default_audio_route_name" product="default" msgid="4239291273420140123">"ఫోన్"</string> <string name="default_audio_route_name_dock_speakers" msgid="6240602982276591864">"డాక్ స్పీకర్లు"</string> - <!-- no translation found for default_audio_route_name_hdmi (1486254205617081251) --> - <skip /> + <string name="default_audio_route_name_hdmi" msgid="1486254205617081251">"HDMI"</string> <string name="default_audio_route_name_headphones" msgid="8119971843803439110">"హెడ్ఫోన్లు"</string> - <!-- no translation found for default_audio_route_name_usb (1234984851352637769) --> - <skip /> + <string name="default_audio_route_name_usb" msgid="1234984851352637769">"USB"</string> <string name="default_audio_route_category_name" msgid="3722811174003886946">"సిస్టమ్"</string> <string name="bluetooth_a2dp_audio_route_name" msgid="8575624030406771015">"బ్లూటూత్ ఆడియో"</string> <string name="wireless_display_route_description" msgid="9070346425023979651">"వైర్లెస్ డిస్ప్లే"</string> diff --git a/core/res/res/values-th/strings.xml b/core/res/res/values-th/strings.xml index 8b2db467860d..05a8b92a6286 100644 --- a/core/res/res/values-th/strings.xml +++ b/core/res/res/values-th/strings.xml @@ -1421,11 +1421,9 @@ <string name="default_audio_route_name" product="tv" msgid="9158088547603019321">"ทีวี"</string> <string name="default_audio_route_name" product="default" msgid="4239291273420140123">"โทรศัพท์"</string> <string name="default_audio_route_name_dock_speakers" msgid="6240602982276591864">"ลำโพงแท่นชาร์จ"</string> - <!-- no translation found for default_audio_route_name_hdmi (1486254205617081251) --> - <skip /> + <string name="default_audio_route_name_hdmi" msgid="1486254205617081251">"HDMI"</string> <string name="default_audio_route_name_headphones" msgid="8119971843803439110">"หูฟัง"</string> - <!-- no translation found for default_audio_route_name_usb (1234984851352637769) --> - <skip /> + <string name="default_audio_route_name_usb" msgid="1234984851352637769">"USB"</string> <string name="default_audio_route_category_name" msgid="3722811174003886946">"ระบบ"</string> <string name="bluetooth_a2dp_audio_route_name" msgid="8575624030406771015">"เสียงบลูทูธ"</string> <string name="wireless_display_route_description" msgid="9070346425023979651">"การแสดงผลแบบไร้สาย"</string> diff --git a/core/res/res/values-tl/strings.xml b/core/res/res/values-tl/strings.xml index 2e047c24ac7a..227a28749c2e 100644 --- a/core/res/res/values-tl/strings.xml +++ b/core/res/res/values-tl/strings.xml @@ -1421,11 +1421,9 @@ <string name="default_audio_route_name" product="tv" msgid="9158088547603019321">"TV"</string> <string name="default_audio_route_name" product="default" msgid="4239291273420140123">"Telepono"</string> <string name="default_audio_route_name_dock_speakers" msgid="6240602982276591864">"Mga speaker ng dock"</string> - <!-- no translation found for default_audio_route_name_hdmi (1486254205617081251) --> - <skip /> + <string name="default_audio_route_name_hdmi" msgid="1486254205617081251">"HDMI"</string> <string name="default_audio_route_name_headphones" msgid="8119971843803439110">"Mga Headphone"</string> - <!-- no translation found for default_audio_route_name_usb (1234984851352637769) --> - <skip /> + <string name="default_audio_route_name_usb" msgid="1234984851352637769">"USB"</string> <string name="default_audio_route_category_name" msgid="3722811174003886946">"System"</string> <string name="bluetooth_a2dp_audio_route_name" msgid="8575624030406771015">"Audio sa Bluetooth"</string> <string name="wireless_display_route_description" msgid="9070346425023979651">"Wireless display"</string> diff --git a/core/res/res/values-tr/strings.xml b/core/res/res/values-tr/strings.xml index 852471c13022..918d9d670da9 100644 --- a/core/res/res/values-tr/strings.xml +++ b/core/res/res/values-tr/strings.xml @@ -1421,11 +1421,9 @@ <string name="default_audio_route_name" product="tv" msgid="9158088547603019321">"TV"</string> <string name="default_audio_route_name" product="default" msgid="4239291273420140123">"Telefon"</string> <string name="default_audio_route_name_dock_speakers" msgid="6240602982276591864">"Yuva hoparlörleri"</string> - <!-- no translation found for default_audio_route_name_hdmi (1486254205617081251) --> - <skip /> + <string name="default_audio_route_name_hdmi" msgid="1486254205617081251">"HDMI"</string> <string name="default_audio_route_name_headphones" msgid="8119971843803439110">"Kulaklıklar"</string> - <!-- no translation found for default_audio_route_name_usb (1234984851352637769) --> - <skip /> + <string name="default_audio_route_name_usb" msgid="1234984851352637769">"USB"</string> <string name="default_audio_route_category_name" msgid="3722811174003886946">"Sistem"</string> <string name="bluetooth_a2dp_audio_route_name" msgid="8575624030406771015">"Bluetooth ses"</string> <string name="wireless_display_route_description" msgid="9070346425023979651">"Kablosuz ekran"</string> diff --git a/core/res/res/values-uk/strings.xml b/core/res/res/values-uk/strings.xml index 7d98b78fcbd3..08fdf012cc5f 100644 --- a/core/res/res/values-uk/strings.xml +++ b/core/res/res/values-uk/strings.xml @@ -1467,11 +1467,9 @@ <string name="default_audio_route_name" product="tv" msgid="9158088547603019321">"Телевізор"</string> <string name="default_audio_route_name" product="default" msgid="4239291273420140123">"Телефон"</string> <string name="default_audio_route_name_dock_speakers" msgid="6240602982276591864">"Динаміки док-станції"</string> - <!-- no translation found for default_audio_route_name_hdmi (1486254205617081251) --> - <skip /> + <string name="default_audio_route_name_hdmi" msgid="1486254205617081251">"HDMI"</string> <string name="default_audio_route_name_headphones" msgid="8119971843803439110">"Навушники"</string> - <!-- no translation found for default_audio_route_name_usb (1234984851352637769) --> - <skip /> + <string name="default_audio_route_name_usb" msgid="1234984851352637769">"USB"</string> <string name="default_audio_route_category_name" msgid="3722811174003886946">"Система"</string> <string name="bluetooth_a2dp_audio_route_name" msgid="8575624030406771015">"Аудіо Bluetooth"</string> <string name="wireless_display_route_description" msgid="9070346425023979651">"Бездротовий екран"</string> diff --git a/core/res/res/values-ur/strings.xml b/core/res/res/values-ur/strings.xml index 5198bb2f83e5..073f7a6948e0 100644 --- a/core/res/res/values-ur/strings.xml +++ b/core/res/res/values-ur/strings.xml @@ -1421,11 +1421,9 @@ <string name="default_audio_route_name" product="tv" msgid="9158088547603019321">"TV"</string> <string name="default_audio_route_name" product="default" msgid="4239291273420140123">"فون"</string> <string name="default_audio_route_name_dock_speakers" msgid="6240602982276591864">"ڈاک اسپیکرز"</string> - <!-- no translation found for default_audio_route_name_hdmi (1486254205617081251) --> - <skip /> + <string name="default_audio_route_name_hdmi" msgid="1486254205617081251">"HDMI"</string> <string name="default_audio_route_name_headphones" msgid="8119971843803439110">"ہیڈ فونز"</string> - <!-- no translation found for default_audio_route_name_usb (1234984851352637769) --> - <skip /> + <string name="default_audio_route_name_usb" msgid="1234984851352637769">"USB"</string> <string name="default_audio_route_category_name" msgid="3722811174003886946">"سسٹم"</string> <string name="bluetooth_a2dp_audio_route_name" msgid="8575624030406771015">"بلوٹوتھ آڈیو"</string> <string name="wireless_display_route_description" msgid="9070346425023979651">"وائرلیس ڈسپلے"</string> diff --git a/core/res/res/values-uz/strings.xml b/core/res/res/values-uz/strings.xml index bc30741250d9..2ad9bd1f02b4 100644 --- a/core/res/res/values-uz/strings.xml +++ b/core/res/res/values-uz/strings.xml @@ -1421,11 +1421,9 @@ <string name="default_audio_route_name" product="tv" msgid="9158088547603019321">"TV"</string> <string name="default_audio_route_name" product="default" msgid="4239291273420140123">"Telefon"</string> <string name="default_audio_route_name_dock_speakers" msgid="6240602982276591864">"Taglik karnaylar"</string> - <!-- no translation found for default_audio_route_name_hdmi (1486254205617081251) --> - <skip /> + <string name="default_audio_route_name_hdmi" msgid="1486254205617081251">"HDMI"</string> <string name="default_audio_route_name_headphones" msgid="8119971843803439110">"Quloq karnaychalari"</string> - <!-- no translation found for default_audio_route_name_usb (1234984851352637769) --> - <skip /> + <string name="default_audio_route_name_usb" msgid="1234984851352637769">"USB"</string> <string name="default_audio_route_category_name" msgid="3722811174003886946">"Tizim"</string> <string name="bluetooth_a2dp_audio_route_name" msgid="8575624030406771015">"Ovozni Bluetooth orqali chiqarish"</string> <string name="wireless_display_route_description" msgid="9070346425023979651">"Simsiz monitor"</string> diff --git a/core/res/res/values-vi/strings.xml b/core/res/res/values-vi/strings.xml index ea2c3af123e5..e585f77b50da 100644 --- a/core/res/res/values-vi/strings.xml +++ b/core/res/res/values-vi/strings.xml @@ -1421,11 +1421,9 @@ <string name="default_audio_route_name" product="tv" msgid="9158088547603019321">"TV"</string> <string name="default_audio_route_name" product="default" msgid="4239291273420140123">"Điện thoại"</string> <string name="default_audio_route_name_dock_speakers" msgid="6240602982276591864">"Loa đế"</string> - <!-- no translation found for default_audio_route_name_hdmi (1486254205617081251) --> - <skip /> + <string name="default_audio_route_name_hdmi" msgid="1486254205617081251">"HDMI"</string> <string name="default_audio_route_name_headphones" msgid="8119971843803439110">"Tai nghe"</string> - <!-- no translation found for default_audio_route_name_usb (1234984851352637769) --> - <skip /> + <string name="default_audio_route_name_usb" msgid="1234984851352637769">"USB"</string> <string name="default_audio_route_category_name" msgid="3722811174003886946">"Hệ thống"</string> <string name="bluetooth_a2dp_audio_route_name" msgid="8575624030406771015">"Âm thanh Bluetooth"</string> <string name="wireless_display_route_description" msgid="9070346425023979651">"Hiển thị không dây"</string> diff --git a/core/res/res/values-zh-rCN/strings.xml b/core/res/res/values-zh-rCN/strings.xml index f66faf690a6e..5f8d072c446e 100644 --- a/core/res/res/values-zh-rCN/strings.xml +++ b/core/res/res/values-zh-rCN/strings.xml @@ -1421,11 +1421,9 @@ <string name="default_audio_route_name" product="tv" msgid="9158088547603019321">"电视"</string> <string name="default_audio_route_name" product="default" msgid="4239291273420140123">"手机"</string> <string name="default_audio_route_name_dock_speakers" msgid="6240602982276591864">"基座扬声器"</string> - <!-- no translation found for default_audio_route_name_hdmi (1486254205617081251) --> - <skip /> + <string name="default_audio_route_name_hdmi" msgid="1486254205617081251">"HDMI"</string> <string name="default_audio_route_name_headphones" msgid="8119971843803439110">"耳机"</string> - <!-- no translation found for default_audio_route_name_usb (1234984851352637769) --> - <skip /> + <string name="default_audio_route_name_usb" msgid="1234984851352637769">"USB"</string> <string name="default_audio_route_category_name" msgid="3722811174003886946">"系统"</string> <string name="bluetooth_a2dp_audio_route_name" msgid="8575624030406771015">"蓝牙音频"</string> <string name="wireless_display_route_description" msgid="9070346425023979651">"无线显示"</string> diff --git a/core/res/res/values-zh-rHK/strings.xml b/core/res/res/values-zh-rHK/strings.xml index 52df581f377f..d4b3b394055b 100644 --- a/core/res/res/values-zh-rHK/strings.xml +++ b/core/res/res/values-zh-rHK/strings.xml @@ -1421,11 +1421,9 @@ <string name="default_audio_route_name" product="tv" msgid="9158088547603019321">"電視"</string> <string name="default_audio_route_name" product="default" msgid="4239291273420140123">"手機"</string> <string name="default_audio_route_name_dock_speakers" msgid="6240602982276591864">"插座喇叭"</string> - <!-- no translation found for default_audio_route_name_hdmi (1486254205617081251) --> - <skip /> + <string name="default_audio_route_name_hdmi" msgid="1486254205617081251">"HDMI"</string> <string name="default_audio_route_name_headphones" msgid="8119971843803439110">"耳機"</string> - <!-- no translation found for default_audio_route_name_usb (1234984851352637769) --> - <skip /> + <string name="default_audio_route_name_usb" msgid="1234984851352637769">"USB"</string> <string name="default_audio_route_category_name" msgid="3722811174003886946">"系統"</string> <string name="bluetooth_a2dp_audio_route_name" msgid="8575624030406771015">"藍牙音頻"</string> <string name="wireless_display_route_description" msgid="9070346425023979651">"無線螢幕分享"</string> diff --git a/core/res/res/values-zh-rTW/strings.xml b/core/res/res/values-zh-rTW/strings.xml index e7fa2f1abba3..de12340f6be5 100644 --- a/core/res/res/values-zh-rTW/strings.xml +++ b/core/res/res/values-zh-rTW/strings.xml @@ -1421,11 +1421,9 @@ <string name="default_audio_route_name" product="tv" msgid="9158088547603019321">"電視"</string> <string name="default_audio_route_name" product="default" msgid="4239291273420140123">"手機"</string> <string name="default_audio_route_name_dock_speakers" msgid="6240602982276591864">"座架喇叭"</string> - <!-- no translation found for default_audio_route_name_hdmi (1486254205617081251) --> - <skip /> + <string name="default_audio_route_name_hdmi" msgid="1486254205617081251">"HDMI"</string> <string name="default_audio_route_name_headphones" msgid="8119971843803439110">"耳機"</string> - <!-- no translation found for default_audio_route_name_usb (1234984851352637769) --> - <skip /> + <string name="default_audio_route_name_usb" msgid="1234984851352637769">"USB"</string> <string name="default_audio_route_category_name" msgid="3722811174003886946">"系統"</string> <string name="bluetooth_a2dp_audio_route_name" msgid="8575624030406771015">"藍牙音訊"</string> <string name="wireless_display_route_description" msgid="9070346425023979651">"無線螢幕分享"</string> diff --git a/core/res/res/values-zu/strings.xml b/core/res/res/values-zu/strings.xml index 0c986676cb4f..9178ed785ae1 100644 --- a/core/res/res/values-zu/strings.xml +++ b/core/res/res/values-zu/strings.xml @@ -1421,11 +1421,9 @@ <string name="default_audio_route_name" product="tv" msgid="9158088547603019321">"I-TV"</string> <string name="default_audio_route_name" product="default" msgid="4239291273420140123">"Ifoni"</string> <string name="default_audio_route_name_dock_speakers" msgid="6240602982276591864">"Izipikha ze-Dock"</string> - <!-- no translation found for default_audio_route_name_hdmi (1486254205617081251) --> - <skip /> + <string name="default_audio_route_name_hdmi" msgid="1486254205617081251">"HDMI"</string> <string name="default_audio_route_name_headphones" msgid="8119971843803439110">"Ama-headphone"</string> - <!-- no translation found for default_audio_route_name_usb (1234984851352637769) --> - <skip /> + <string name="default_audio_route_name_usb" msgid="1234984851352637769">"I-USB"</string> <string name="default_audio_route_category_name" msgid="3722811174003886946">"Isistimu"</string> <string name="bluetooth_a2dp_audio_route_name" msgid="8575624030406771015">"Umsindo we-Bluetooth"</string> <string name="wireless_display_route_description" msgid="9070346425023979651">"Ukubonisa okungenazintambo"</string> diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml index 07a11098999d..cd8f6eaaaa0a 100644 --- a/core/res/res/values/config.xml +++ b/core/res/res/values/config.xml @@ -1127,6 +1127,11 @@ <!-- Is the lock-screen disabled for new users by default --> <bool name="config_disableLockscreenByDefault">false</bool> + <!-- If true, enables verification of the lockscreen credential in the factory reset protection + flow. This should be true if gatekeeper / weaver credentials can still be checked after a + factory reset. --> + <bool name="config_enableCredentialFactoryResetProtection">true</bool> + <!-- Control the behavior when the user long presses the home button. 0 - Nothing 1 - Launch all apps intent diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml index 7416113b4e90..afcb35feaedd 100644 --- a/core/res/res/values/strings.xml +++ b/core/res/res/values/strings.xml @@ -2709,6 +2709,8 @@ <string name="yes">OK</string> <!-- Preference framework strings. --> <string name="no">Cancel</string> + <!-- Preference framework strings. --> + <string name="close">CLOSE</string> <!-- This is the generic "attention" string to be used in attention dialogs. Typically combined with setIconAttribute(android.R.attr.alertDialogIcon) (or setIcon(android.R.drawable.ic_dialog_alert) on legacy versions of the platform) --> @@ -2841,6 +2843,11 @@ <!-- [CHAR LIMIT=200] Compat mode dialog: hint to re-enable compat mode dialog. --> <string name="screen_compat_mode_hint">Re-enable this in System settings > Apps > Downloaded.</string> + <!-- Text of the alert that is displayed when a top application is killed by lmk. --> + <string name="top_app_killed_title">App isn\'t responding</string> + <!-- Top app killed by lmk dialog message. --> + <string name="top_app_killed_message"><xliff:g id="app_name">%1$s</xliff:g> may be using too much memory.</string> + <!-- [CHAR LIMIT=200] Unsupported display size dialog: message. Refers to "Display size" setting. --> <string name="unsupported_display_size_message"><xliff:g id="app_name">%1$s</xliff:g> does not support the current Display size setting and may behave unexpectedly.</string> <!-- [CHAR LIMIT=50] Unsupported display size dialog: check box label. --> diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml index 1877d421736f..96695538b7ce 100644 --- a/core/res/res/values/symbols.xml +++ b/core/res/res/values/symbols.xml @@ -1893,6 +1893,9 @@ <java-symbol type="string" name="anr_application_process" /> <java-symbol type="string" name="anr_process" /> <java-symbol type="string" name="anr_title" /> + <java-symbol type="string" name="top_app_killed_title" /> + <java-symbol type="string" name="top_app_killed_message" /> + <java-symbol type="string" name="close" /> <java-symbol type="string" name="car_mode_disable_notification_message" /> <java-symbol type="string" name="car_mode_disable_notification_title" /> <java-symbol type="string" name="chooser_wallpaper" /> @@ -3027,6 +3030,8 @@ <java-symbol type="string" name="foreground_service_tap_for_details" /> <java-symbol type="string" name="foreground_service_multiple_separator" /> + <java-symbol type="bool" name="config_enableCredentialFactoryResetProtection" /> + <!-- ETWS primary messages --> <java-symbol type="string" name="etws_primary_default_message_earthquake" /> <java-symbol type="string" name="etws_primary_default_message_tsunami" /> diff --git a/graphics/java/android/graphics/PixelFormat.java b/graphics/java/android/graphics/PixelFormat.java index f93886dcb06b..96d6eeece0a3 100644 --- a/graphics/java/android/graphics/PixelFormat.java +++ b/graphics/java/android/graphics/PixelFormat.java @@ -185,4 +185,52 @@ public class PixelFormat { return false; } + + /** + * @hide + */ + public static String formatToString(@Format int format) { + switch (format) { + case UNKNOWN: + return "UNKNOWN"; + case TRANSLUCENT: + return "TRANSLUCENT"; + case TRANSPARENT: + return "TRANSPARENT"; + case RGBA_8888: + return "RGBA_8888"; + case RGBX_8888: + return "RGBX_8888"; + case RGB_888: + return "RGB_888"; + case RGB_565: + return "RGB_565"; + case RGBA_5551: + return "RGBA_5551"; + case RGBA_4444: + return "RGBA_4444"; + case A_8: + return "A_8"; + case L_8: + return "L_8"; + case LA_88: + return "LA_88"; + case RGB_332: + return "RGB_332"; + case YCbCr_422_SP: + return "YCbCr_422_SP"; + case YCbCr_420_SP: + return "YCbCr_420_SP"; + case YCbCr_422_I: + return "YCbCr_422_I"; + case RGBA_F16: + return "RGBA_F16"; + case RGBA_1010102: + return "RGBA_1010102"; + case JPEG: + return "JPEG"; + default: + return Integer.toString(format); + } + } } diff --git a/graphics/java/android/graphics/Shader.java b/graphics/java/android/graphics/Shader.java index 0209cea4e2e5..40288f5ec8af 100644 --- a/graphics/java/android/graphics/Shader.java +++ b/graphics/java/android/graphics/Shader.java @@ -159,8 +159,10 @@ public class Shader { if (mNativeInstance == 0) { mNativeInstance = createNativeInstance(mLocalMatrix == null ? 0 : mLocalMatrix.native_instance); - mCleaner = NoImagePreloadHolder.sRegistry.registerNativeAllocation( - this, mNativeInstance); + if (mNativeInstance != 0) { + mCleaner = NoImagePreloadHolder.sRegistry.registerNativeAllocation( + this, mNativeInstance); + } } return mNativeInstance; } diff --git a/libs/androidfw/ApkAssets.cpp b/libs/androidfw/ApkAssets.cpp index a5b1d29dbf91..0e577d1c9e3c 100644 --- a/libs/androidfw/ApkAssets.cpp +++ b/libs/androidfw/ApkAssets.cpp @@ -30,6 +30,8 @@ namespace android { +ApkAssets::ApkAssets() : zip_handle_(nullptr, ::CloseArchive) {} + std::unique_ptr<const ApkAssets> ApkAssets::Load(const std::string& path, bool system) { return ApkAssets::LoadImpl(path, system, false /*load_as_shared_library*/); } diff --git a/libs/androidfw/AssetManager2.cpp b/libs/androidfw/AssetManager2.cpp index ab7e14de48fb..f1f2e2d1417e 100644 --- a/libs/androidfw/AssetManager2.cpp +++ b/libs/androidfw/AssetManager2.cpp @@ -902,26 +902,32 @@ bool Theme::SetTo(const Theme& o) { return true; } - if (asset_manager_ != o.asset_manager_) { - return false; - } - type_spec_flags_ = o.type_spec_flags_; + const bool copy_only_system = asset_manager_ != o.asset_manager_; + for (size_t p = 0; p < packages_.size(); p++) { const Package* package = o.packages_[p].get(); - if (package == nullptr) { + if (package == nullptr || (copy_only_system && p != 0x01)) { + // The other theme doesn't have this package, clear ours. packages_[p].reset(); continue; } + if (packages_[p] == nullptr) { + // The other theme has this package, but we don't. Make one. + packages_[p].reset(new Package()); + } + for (size_t t = 0; t < package->types.size(); t++) { const Type* type = package->types[t].get(); if (type == nullptr) { + // The other theme doesn't have this type, clear ours. packages_[p]->types[t].reset(); continue; } + // Create a new type and update it to theirs. const size_t type_alloc_size = sizeof(Type) + (type->entry_capacity * sizeof(Entry)); void* copied_data = malloc(type_alloc_size); memcpy(copied_data, type, type_alloc_size); diff --git a/libs/androidfw/include/androidfw/ApkAssets.h b/libs/androidfw/include/androidfw/ApkAssets.h index b7e66fb68be5..2e392d57b1c8 100644 --- a/libs/androidfw/include/androidfw/ApkAssets.h +++ b/libs/androidfw/include/androidfw/ApkAssets.h @@ -21,7 +21,6 @@ #include <string> #include "android-base/macros.h" -#include "ziparchive/zip_archive.h" #include "androidfw/Asset.h" #include "androidfw/LoadedArsc.h" @@ -52,14 +51,9 @@ class ApkAssets { static std::unique_ptr<const ApkAssets> LoadImpl(const std::string& path, bool system, bool load_as_shared_library); - ApkAssets() = default; + ApkAssets(); - struct ZipArchivePtrCloser { - void operator()(::ZipArchiveHandle handle) { ::CloseArchive(handle); } - }; - - using ZipArchivePtr = - std::unique_ptr<typename std::remove_pointer<::ZipArchiveHandle>::type, ZipArchivePtrCloser>; + using ZipArchivePtr = std::unique_ptr<void, void(*)(void*)>; ZipArchivePtr zip_handle_; std::string path_; diff --git a/libs/androidfw/include/androidfw/AssetManager2.h b/libs/androidfw/include/androidfw/AssetManager2.h index d2bc6ee45576..fd94144544a8 100644 --- a/libs/androidfw/include/androidfw/AssetManager2.h +++ b/libs/androidfw/include/androidfw/AssetManager2.h @@ -70,9 +70,8 @@ struct ResolvedBag { }; // AssetManager2 is the main entry point for accessing assets and resources. -// AssetManager2 provides caching of resources retrieved via the underlying -// ApkAssets. -class AssetManager2 : public ::AAssetManager { +// AssetManager2 provides caching of resources retrieved via the underlying ApkAssets. +class AssetManager2 { public: struct ResourceName { const char* package = nullptr; diff --git a/libs/androidfw/tests/Theme_test.cpp b/libs/androidfw/tests/Theme_test.cpp index dfff9c00922c..feb454e144e3 100644 --- a/libs/androidfw/tests/Theme_test.cpp +++ b/libs/androidfw/tests/Theme_test.cpp @@ -23,6 +23,7 @@ #include "data/lib_one/R.h" #include "data/libclient/R.h" #include "data/styles/R.h" +#include "data/system/R.h" namespace app = com::android::app; namespace lib_one = com::android::lib_one; @@ -33,6 +34,9 @@ namespace android { class ThemeTest : public ::testing::Test { public: void SetUp() override { + system_assets_ = ApkAssets::Load(GetTestDataPath() + "/system/system.apk", true /*system*/); + ASSERT_NE(nullptr, system_assets_); + style_assets_ = ApkAssets::Load(GetTestDataPath() + "/styles/styles.apk"); ASSERT_NE(nullptr, style_assets_); @@ -47,6 +51,7 @@ class ThemeTest : public ::testing::Test { } protected: + std::unique_ptr<const ApkAssets> system_assets_; std::unique_ptr<const ApkAssets> style_assets_; std::unique_ptr<const ApkAssets> libclient_assets_; std::unique_ptr<const ApkAssets> lib_one_assets_; @@ -262,20 +267,30 @@ TEST_F(ThemeTest, CopyThemeSameAssetManager) { EXPECT_EQ(static_cast<uint32_t>(ResTable_typeSpec::SPEC_PUBLIC), flags); } -TEST_F(ThemeTest, FailToCopyThemeWithDifferentAssetManager) { +TEST_F(ThemeTest, OnlyCopySystemThemeWhenAssetManagersDiffer) { AssetManager2 assetmanager_one; - assetmanager_one.SetApkAssets({style_assets_.get()}); + assetmanager_one.SetApkAssets({system_assets_.get(), style_assets_.get()}); AssetManager2 assetmanager_two; - assetmanager_two.SetApkAssets({style_assets_.get()}); + assetmanager_two.SetApkAssets({system_assets_.get(), style_assets_.get()}); auto theme_one = assetmanager_one.NewTheme(); ASSERT_TRUE(theme_one->ApplyStyle(app::R::style::StyleOne)); auto theme_two = assetmanager_two.NewTheme(); + ASSERT_TRUE(theme_two->ApplyStyle(R::style::Theme_One)); ASSERT_TRUE(theme_two->ApplyStyle(app::R::style::StyleTwo)); - EXPECT_FALSE(theme_one->SetTo(*theme_two)); + EXPECT_TRUE(theme_one->SetTo(*theme_two)); + + Res_value value; + uint32_t flags; + + // No app resources. + EXPECT_EQ(kInvalidCookie, theme_one->GetAttribute(app::R::attr::attr_one, &value, &flags)); + + // Only system. + EXPECT_NE(kInvalidCookie, theme_one->GetAttribute(R::attr::foreground, &value, &flags)); } } // namespace android diff --git a/libs/hwui/Android.bp b/libs/hwui/Android.bp index 770a57a5c445..124182f0336e 100644 --- a/libs/hwui/Android.bp +++ b/libs/hwui/Android.bp @@ -2,7 +2,7 @@ cc_defaults { name: "hwui_defaults", defaults: [ "hwui_static_deps", - + "skia_deps" //"hwui_bugreport_font_cache_usage", //"hwui_compile_for_perf", ], @@ -55,7 +55,6 @@ cc_defaults { "libEGL", "libGLESv2", "libvulkan", - "libskia", "libui", "libgui", "libprotobuf-cpp-lite", @@ -114,6 +113,9 @@ cc_defaults { cc_defaults { name: "libhwui_defaults", defaults: ["hwui_defaults"], + + whole_static_libs: ["libskia"], + srcs: [ "hwui/Bitmap.cpp", "font/CacheTexture.cpp", diff --git a/libs/hwui/AnimatorManager.cpp b/libs/hwui/AnimatorManager.cpp index f5bb821f4e23..69ead5890566 100644 --- a/libs/hwui/AnimatorManager.cpp +++ b/libs/hwui/AnimatorManager.cpp @@ -71,9 +71,11 @@ void AnimatorManager::setAnimationHandle(AnimationHandle* handle) { void AnimatorManager::pushStaging() { if (mNewAnimators.size()) { - LOG_ALWAYS_FATAL_IF(!mAnimationHandle, - "Trying to start new animators on %p (%s) without an animation handle!", - &mParent, mParent.getName()); + if (CC_UNLIKELY(!mAnimationHandle)) { + ALOGW("Trying to start new animators on %p (%s) without an animation handle!", + &mParent, mParent.getName()); + return; + } // Only add new animators that are not already in the mAnimators list for (auto& anim : mNewAnimators) { diff --git a/libs/hwui/hwui/MinikinSkia.cpp b/libs/hwui/hwui/MinikinSkia.cpp index 2b29542fb623..a5b4c42d68d2 100644 --- a/libs/hwui/hwui/MinikinSkia.cpp +++ b/libs/hwui/hwui/MinikinSkia.cpp @@ -104,14 +104,14 @@ const std::vector<minikin::FontVariation>& MinikinFontSkia::GetAxes() const { std::shared_ptr<minikin::MinikinFont> MinikinFontSkia::createFontWithVariation( const std::vector<minikin::FontVariation>& variations) const { - SkFontMgr::FontParameters params; + SkFontArguments params; int ttcIndex; - SkStreamAsset* stream = mTypeface->openStream(&ttcIndex); + std::unique_ptr<SkStreamAsset> stream(mTypeface->openStream(&ttcIndex)); LOG_ALWAYS_FATAL_IF(stream == nullptr, "openStream failed"); params.setCollectionIndex(ttcIndex); - std::vector<SkFontMgr::FontParameters::Axis> skAxes; + std::vector<SkFontArguments::Axis> skAxes; skAxes.resize(variations.size()); for (size_t i = 0; i < variations.size(); i++) { skAxes[i].fTag = variations[i].axisTag; @@ -119,7 +119,7 @@ std::shared_ptr<minikin::MinikinFont> MinikinFontSkia::createFontWithVariation( } params.setAxes(skAxes.data(), skAxes.size()); sk_sp<SkFontMgr> fm(SkFontMgr::RefDefault()); - sk_sp<SkTypeface> face(fm->createFromStream(stream, params)); + sk_sp<SkTypeface> face(fm->makeFromStream(std::move(stream), params)); return std::make_shared<MinikinFontSkia>(std::move(face), mFontData, mFontSize, ttcIndex, variations); diff --git a/libs/hwui/pipeline/skia/LayerDrawable.cpp b/libs/hwui/pipeline/skia/LayerDrawable.cpp index 17438e5e1cdc..5c6078d566b4 100644 --- a/libs/hwui/pipeline/skia/LayerDrawable.cpp +++ b/libs/hwui/pipeline/skia/LayerDrawable.cpp @@ -36,22 +36,18 @@ void LayerDrawable::onDraw(SkCanvas* canvas) { bool LayerDrawable::DrawLayer(GrContext* context, SkCanvas* canvas, Layer* layer) { // transform the matrix based on the layer - int saveCount = -1; - if (!layer->getTransform().isIdentity()) { - saveCount = canvas->save(); - SkMatrix transform; - layer->getTransform().copyTo(transform); - canvas->concat(transform); - } - + SkMatrix layerTransform; + layer->getTransform().copyTo(layerTransform); sk_sp<SkImage> layerImage; + int layerWidth = layer->getWidth(); + int layerHeight = layer->getHeight(); if (layer->getApi() == Layer::Api::OpenGL) { GlLayer* glLayer = static_cast<GlLayer*>(layer); GrGLTextureInfo externalTexture; externalTexture.fTarget = glLayer->getRenderTarget(); externalTexture.fID = glLayer->getTextureId(); - GrBackendTexture backendTexture(glLayer->getWidth(), glLayer->getHeight(), - kRGBA_8888_GrPixelConfig, externalTexture); + GrBackendTexture backendTexture(layerWidth, layerHeight, kRGBA_8888_GrPixelConfig, + externalTexture); layerImage = SkImage::MakeFromTexture(context, backendTexture, kTopLeft_GrSurfaceOrigin, kPremul_SkAlphaType, nullptr); } else { @@ -62,15 +58,29 @@ bool LayerDrawable::DrawLayer(GrContext* context, SkCanvas* canvas, Layer* layer } if (layerImage) { + SkMatrix textureMatrix; + layer->getTexTransform().copyTo(textureMatrix); + //TODO: after skia bug https://bugs.chromium.org/p/skia/issues/detail?id=7075 is fixed + // use bottom left origin and remove flipV and invert transformations. + SkMatrix flipV; + flipV.setAll(1, 0, 0, 0, -1, 1, 0, 0, 1); + textureMatrix.preConcat(flipV); + textureMatrix.preScale(1.0f/layerWidth, 1.0f/layerHeight); + textureMatrix.postScale(layerWidth, layerHeight); + SkMatrix textureMatrixInv; + if (!textureMatrix.invert(&textureMatrixInv)) { + textureMatrixInv = textureMatrix; + } + + SkMatrix matrix = SkMatrix::Concat(textureMatrixInv, layerTransform); + SkPaint paint; paint.setAlpha(layer->getAlpha()); paint.setBlendMode(layer->getMode()); paint.setColorFilter(sk_ref_sp(layer->getColorFilter())); - canvas->drawImage(layerImage, 0, 0, &paint); - } - // restore the original matrix - if (saveCount >= 0) { - canvas->restoreToCount(saveCount); + // draw image with a shader to avoid save/restore of the matrix + paint.setShader(layerImage->makeShader(&matrix)); + canvas->drawRect(SkRect::MakeWH(layerWidth, layerHeight), paint); } return layerImage; diff --git a/libs/hwui/tests/unit/TypefaceTests.cpp b/libs/hwui/tests/unit/TypefaceTests.cpp index 345cfd647b11..439d6906e526 100644 --- a/libs/hwui/tests/unit/TypefaceTests.cpp +++ b/libs/hwui/tests/unit/TypefaceTests.cpp @@ -52,7 +52,7 @@ std::shared_ptr<minikin::FontFamily> buildFamily(const char* fileName) { SkData::MakeWithProc(data, st.st_size, unmap, reinterpret_cast<void*>(st.st_size)); std::unique_ptr<SkStreamAsset> fontData(new SkMemoryStream(skData)); sk_sp<SkFontMgr> fm(SkFontMgr::RefDefault()); - sk_sp<SkTypeface> typeface(fm->createFromStream(fontData.release())); + sk_sp<SkTypeface> typeface(fm->makeFromStream(std::move(fontData))); LOG_ALWAYS_FATAL_IF(typeface == nullptr, "Failed to make typeface from %s", fileName); std::shared_ptr<minikin::MinikinFont> font = std::make_shared<MinikinFontSkia>( std::move(typeface), data, st.st_size, 0, std::vector<minikin::FontVariation>()); diff --git a/libs/input/Android.bp b/libs/input/Android.bp index 43107064332e..67682a06cb6a 100644 --- a/libs/input/Android.bp +++ b/libs/input/Android.bp @@ -24,7 +24,7 @@ cc_library_shared { "libcutils", "liblog", "libutils", - "libskia", + "libhwui", "libgui", "libui", "libinput", diff --git a/media/jni/Android.bp b/media/jni/Android.bp index 02667ca070a4..1d85c97239ac 100644 --- a/media/jni/Android.bp +++ b/media/jni/Android.bp @@ -38,7 +38,7 @@ cc_library_shared { "libmediametrics", "libmediadrm", "libmidi", - "libskia", + "libhwui", "libui", "liblog", "libcutils", diff --git a/media/jni/android_media_MediaDescrambler.cpp b/media/jni/android_media_MediaDescrambler.cpp index bee52188e798..e77e855ce53a 100644 --- a/media/jni/android_media_MediaDescrambler.cpp +++ b/media/jni/android_media_MediaDescrambler.cpp @@ -21,7 +21,7 @@ #include "android_media_MediaDescrambler.h" #include "android_runtime/AndroidRuntime.h" #include "android_os_HwRemoteBinder.h" -#include "JNIHelp.h" +#include <nativehelper/JNIHelp.h> #include <android/hardware/cas/native/1.0/BpHwDescrambler.h> #include <android/hardware/cas/native/1.0/BnHwDescrambler.h> diff --git a/media/jni/android_media_MediaExtractor.cpp b/media/jni/android_media_MediaExtractor.cpp index c9657b119bdb..d2fa8f5f4c2a 100644 --- a/media/jni/android_media_MediaExtractor.cpp +++ b/media/jni/android_media_MediaExtractor.cpp @@ -27,7 +27,7 @@ #include "android_runtime/Log.h" #include "android_util_Binder.h" #include "jni.h" -#include "JNIHelp.h" +#include <nativehelper/JNIHelp.h> #include <android/hardware/cas/1.0/BpHwCas.h> #include <android/hardware/cas/1.0/BnHwCas.h> diff --git a/media/jni/android_media_MediaMetricsJNI.cpp b/media/jni/android_media_MediaMetricsJNI.cpp index 8979cec2e864..38f7a7e25389 100644 --- a/media/jni/android_media_MediaMetricsJNI.cpp +++ b/media/jni/android_media_MediaMetricsJNI.cpp @@ -16,7 +16,7 @@ #include <android_runtime/AndroidRuntime.h> #include <jni.h> -#include <JNIHelp.h> +#include <nativehelper/JNIHelp.h> #include "android_media_MediaMetricsJNI.h" #include <media/MediaAnalyticsItem.h> diff --git a/media/jni/android_media_MediaMetricsJNI.h b/media/jni/android_media_MediaMetricsJNI.h index d1742121277b..16081b4af1cb 100644 --- a/media/jni/android_media_MediaMetricsJNI.h +++ b/media/jni/android_media_MediaMetricsJNI.h @@ -19,7 +19,7 @@ #include <android_runtime/AndroidRuntime.h> #include <jni.h> -#include <JNIHelp.h> +#include <nativehelper/JNIHelp.h> #include <media/MediaAnalyticsItem.h> namespace android { diff --git a/media/jni/android_media_MediaRecorder.cpp b/media/jni/android_media_MediaRecorder.cpp index ceab47888940..497684c61f1e 100644 --- a/media/jni/android_media_MediaRecorder.cpp +++ b/media/jni/android_media_MediaRecorder.cpp @@ -35,7 +35,7 @@ #include <nativehelper/ScopedUtfChars.h> #include "jni.h" -#include "JNIHelp.h" +#include <nativehelper/JNIHelp.h> #include "android_media_MediaMetricsJNI.h" #include "android_runtime/AndroidRuntime.h" diff --git a/native/graphics/jni/Android.mk b/native/graphics/jni/Android.mk index ec4b35aac9c3..7a40e62d4527 100644 --- a/native/graphics/jni/Android.mk +++ b/native/graphics/jni/Android.mk @@ -20,14 +20,11 @@ LOCAL_SRC_FILES:= \ LOCAL_SHARED_LIBRARIES := \ libandroid_runtime \ - libskia \ libui \ libandroidfw LOCAL_C_INCLUDES += \ - frameworks/base/native/include \ - frameworks/base/core/jni/android/graphics \ - frameworks/base/libs/hwui + frameworks/base/core/jni/android/graphics LOCAL_MODULE:= libjnigraphics diff --git a/packages/SettingsLib/res/values-hi/strings.xml b/packages/SettingsLib/res/values-hi/strings.xml index 7b0190377bb6..a900f2bae07b 100644 --- a/packages/SettingsLib/res/values-hi/strings.xml +++ b/packages/SettingsLib/res/values-hi/strings.xml @@ -45,7 +45,7 @@ <string name="available_via_carrier" msgid="1469036129740799053">"%1$s के ज़रिए उपलब्ध"</string> <string name="speed_label_very_slow" msgid="1867055264243608530">"अत्यधिक धीमी"</string> <string name="speed_label_slow" msgid="813109590815810235">"धीमी"</string> - <string name="speed_label_okay" msgid="2331665440671174858">"ठीक"</string> + <string name="speed_label_okay" msgid="2331665440671174858">"ठीक है"</string> <string name="speed_label_medium" msgid="3175763313268941953">"मध्यम"</string> <string name="speed_label_fast" msgid="7715732164050975057">"तेज़"</string> <string name="speed_label_very_fast" msgid="2265363430784523409">"अत्यधिक तेज़"</string> @@ -289,7 +289,7 @@ <string name="transition_animation_scale_title" msgid="387527540523595875">"संक्रमण एनिमेशन स्केल"</string> <string name="animator_duration_scale_title" msgid="3406722410819934083">"एनिमेटर अवधि स्केल"</string> <string name="overlay_display_devices_title" msgid="5364176287998398539">"द्वितीयक डिस्प्ले अनुरूपित करें"</string> - <string name="debug_applications_category" msgid="4206913653849771549">"ऐप्स"</string> + <string name="debug_applications_category" msgid="4206913653849771549">"ऐप"</string> <string name="immediately_destroy_activities" msgid="1579659389568133959">"गतिविधियों को न रखें"</string> <string name="immediately_destroy_activities_summary" msgid="3592221124808773368">"उपयोगकर्ता के छोड़ते ही हर गतिविधि को खत्म करें"</string> <string name="app_process_limit_title" msgid="4280600650253107163">"पृष्ठभूमि प्रक्रिया सीमा"</string> diff --git a/packages/SettingsLib/res/values-pa/strings.xml b/packages/SettingsLib/res/values-pa/strings.xml index 6e93e86992a9..bdd8927c51a0 100644 --- a/packages/SettingsLib/res/values-pa/strings.xml +++ b/packages/SettingsLib/res/values-pa/strings.xml @@ -331,7 +331,7 @@ <string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"ਤਬਦੀਲ ਕਰੋ ..."</string> <string name="convert_to_file_encryption_done" msgid="7859766358000523953">"ਫ਼ਾਈਲ ਪਹਿਲਾਂ ਤੋਂ ਇਨਕ੍ਰਿਪਟਡ ਹੈ"</string> <string name="title_convert_fbe" msgid="1263622876196444453">"ਫ਼ਾਈਲ ਆਧਾਰਿਤ ਇਨਕ੍ਰਿਪਸ਼ਨ ਵਿੱਚ ਤਬਦੀਲ ਕੀਤਾ ਜਾ ਰਿਹਾ ਹੈ"</string> - <string name="convert_to_fbe_warning" msgid="6139067817148865527">" ਡਾਟਾ ਪਾਰਟੀਸ਼ਨ ਦਾ ਫ਼ਾਈਲ ਆਧਾਰਿਤ ਇਨਕ੍ਰਿਪਸ਼ਨ ਵਿੱਚ ਰੁਪਾਂਤਰਣ ਕਰੋ\n !! ਚਿਤਾਵਨੀ !! ਇਹ ਤੁਹਾਡੇ ਸਾਰੇ ਡੈਟੇ ਨੂੰ ਮਿਟਾ ਦੇਵੇਗਾ\n ਇਹ ਵਿਸ਼ੇਸ਼ਤਾ ਪ੍ਰਯੋਗਿਕ ਹੈ, ਅਤੇ ਸ਼ਾਇਦ ਸਹੀ ਢੰਗ ਨਾਲ ਕੰਮ ਨਾ ਕਰੇ।\n ਜਾਰੀ ਰੱਖਣ ਲਈ \'ਮਿਟਾਓ ਅਤੇ ਰੁਪਾਂਤਰਣ ਕਰੋ...\' ਨੂੰ ਦਬਾਓ।"</string> + <string name="convert_to_fbe_warning" msgid="6139067817148865527">" ਡਾਟਾ ਪਾਰਟੀਸ਼ਨ ਦਾ ਫ਼ਾਈਲ ਆਧਾਰਿਤ ਇਨਕ੍ਰਿਪਸ਼ਨ ਵਿੱਚ ਰੁਪਾਂਤਰਣ ਕਰੋ\n !! ਚਿਤਾਵਨੀ !! ਇਹ ਤੁਹਾਡੇ ਸਾਰੇ ਡਾਟੇ ਨੂੰ ਮਿਟਾ ਦੇਵੇਗਾ\n ਇਹ ਵਿਸ਼ੇਸ਼ਤਾ ਪ੍ਰਯੋਗਿਕ ਹੈ, ਅਤੇ ਸ਼ਾਇਦ ਸਹੀ ਢੰਗ ਨਾਲ ਕੰਮ ਨਾ ਕਰੇ।\n ਜਾਰੀ ਰੱਖਣ ਲਈ \'ਮਿਟਾਓ ਅਤੇ ਰੁਪਾਂਤਰਣ ਕਰੋ...\' ਨੂੰ ਦਬਾਓ।"</string> <string name="button_convert_fbe" msgid="5152671181309826405">"ਮਿਟਾਓ ਅਤੇ ਰੁਪਾਂਤਰਣ ਕਰੋ..."</string> <string name="picture_color_mode" msgid="4560755008730283695">"ਤਸਵੀਰ ਰੰਗ ਮੋਡ"</string> <string name="picture_color_mode_desc" msgid="1141891467675548590">"sRGB ਵਰਤੋਂ ਕਰੋ"</string> diff --git a/packages/SettingsLib/res/values/strings.xml b/packages/SettingsLib/res/values/strings.xml index bd884a3c9729..fbfa7250083b 100644 --- a/packages/SettingsLib/res/values/strings.xml +++ b/packages/SettingsLib/res/values/strings.xml @@ -608,11 +608,6 @@ <string name="wait_for_debugger_summary">Debugged application waits for debugger to attach before executing</string> - <!-- UI debug setting: title for Telephonymonitor switch [CHAR LIMIT=50] --> - <string name="telephony_monitor_switch">Telephony Monitor</string> - <!-- UI debug setting: summary for switch of Telephonymonitor [CHAR LIMIT=500] --> - <string name="telephony_monitor_switch_summary">TelephonyMonitor will collect logs when it detects a problem with telephony/modem functionality and prompt notification to user to file a bug</string> - <!-- Preference category for input debugging development settings. [CHAR LIMIT=25] --> <string name="debug_input_category">Input</string> diff --git a/packages/SettingsLib/src/com/android/settingslib/applications/ApplicationsState.java b/packages/SettingsLib/src/com/android/settingslib/applications/ApplicationsState.java index 40c2b1f3b771..fa2499f6c144 100644 --- a/packages/SettingsLib/src/com/android/settingslib/applications/ApplicationsState.java +++ b/packages/SettingsLib/src/com/android/settingslib/applications/ApplicationsState.java @@ -52,6 +52,11 @@ import android.util.SparseArray; import com.android.internal.R; import com.android.internal.util.ArrayUtils; +import com.android.settingslib.core.lifecycle.Lifecycle; +import com.android.settingslib.core.lifecycle.LifecycleObserver; +import com.android.settingslib.core.lifecycle.events.OnDestroy; +import com.android.settingslib.core.lifecycle.events.OnPause; +import com.android.settingslib.core.lifecycle.events.OnResume; import java.io.File; import java.io.IOException; @@ -180,7 +185,11 @@ public class ApplicationsState { } public Session newSession(Callbacks callbacks) { - Session s = new Session(callbacks); + return newSession(callbacks, null); + } + + public Session newSession(Callbacks callbacks, Lifecycle lifecycle) { + Session s = new Session(callbacks, lifecycle); synchronized (mEntriesMap) { mSessions.add(s); } @@ -586,7 +595,7 @@ public class ApplicationsState { .replaceAll("").toLowerCase(); } - public class Session { + public class Session implements LifecycleObserver, OnPause, OnResume, OnDestroy { final Callbacks mCallbacks; boolean mResumed; @@ -600,11 +609,19 @@ public class ApplicationsState { ArrayList<AppEntry> mLastAppList; boolean mRebuildForeground; - Session(Callbacks callbacks) { + private final boolean mHasLifecycle; + + Session(Callbacks callbacks, Lifecycle lifecycle) { mCallbacks = callbacks; + if (lifecycle != null) { + lifecycle.addObserver(this); + mHasLifecycle = true; + } else { + mHasLifecycle = false; + } } - public void resume() { + public void onResume() { if (DEBUG_LOCKING) Log.v(TAG, "resume about to acquire lock..."); synchronized (mEntriesMap) { if (!mResumed) { @@ -616,7 +633,7 @@ public class ApplicationsState { if (DEBUG_LOCKING) Log.v(TAG, "...resume releasing lock"); } - public void pause() { + public void onPause() { if (DEBUG_LOCKING) Log.v(TAG, "pause about to acquire lock..."); synchronized (mEntriesMap) { if (mResumed) { @@ -735,8 +752,11 @@ public class ApplicationsState { Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND); } - public void release() { - pause(); + public void onDestroy() { + if (!mHasLifecycle) { + // TODO: Legacy, remove this later once all usages are switched to Lifecycle + onPause(); + } synchronized (mEntriesMap) { mSessions.remove(this); } diff --git a/packages/SettingsLib/src/com/android/settingslib/graph/BluetoothDeviceLayerDrawable.java b/packages/SettingsLib/src/com/android/settingslib/graph/BluetoothDeviceLayerDrawable.java index b7fd40485e4d..3c5ac8dff0af 100644 --- a/packages/SettingsLib/src/com/android/settingslib/graph/BluetoothDeviceLayerDrawable.java +++ b/packages/SettingsLib/src/com/android/settingslib/graph/BluetoothDeviceLayerDrawable.java @@ -73,7 +73,7 @@ public class BluetoothDeviceLayerDrawable extends LayerDrawable { final Drawable deviceDrawable = context.getDrawable(resId); final BatteryMeterDrawable batteryDrawable = new BatteryMeterDrawable(context, - R.color.meter_background_color, batteryLevel); + context.getColor(R.color.meter_background_color), batteryLevel); final int pad = context.getResources().getDimensionPixelSize(R.dimen.bt_battery_padding); batteryDrawable.setPadding(pad, pad, pad, pad); @@ -107,6 +107,8 @@ public class BluetoothDeviceLayerDrawable extends LayerDrawable { @VisibleForTesting static class BatteryMeterDrawable extends BatteryMeterDrawableBase { private final float mAspectRatio; + @VisibleForTesting + int mFrameColor; public BatteryMeterDrawable(Context context, int frameColor, int batteryLevel) { super(context, frameColor); @@ -118,6 +120,7 @@ public class BluetoothDeviceLayerDrawable extends LayerDrawable { final int tintColor = Utils.getColorAttr(context, android.R.attr.colorControlNormal); setColorFilter(new PorterDuffColorFilter(tintColor, PorterDuff.Mode.SRC_IN)); setBatteryLevel(batteryLevel); + mFrameColor = frameColor; } @Override diff --git a/packages/SettingsLib/src/com/android/settingslib/wrapper/PackageManagerWrapper.java b/packages/SettingsLib/src/com/android/settingslib/wrapper/PackageManagerWrapper.java index f12148083cbd..4ca5beff8eb2 100644 --- a/packages/SettingsLib/src/com/android/settingslib/wrapper/PackageManagerWrapper.java +++ b/packages/SettingsLib/src/com/android/settingslib/wrapper/PackageManagerWrapper.java @@ -139,11 +139,11 @@ public class PackageManagerWrapper { /** * Gets information about a particular package from the package manager. + * * @param packageName The name of the package we would like information about. - * @param i additional options flags. see javadoc for - * {@link PackageManager#getPackageInfo(String, int)} + * @param i additional options flags. see javadoc for + * {@link PackageManager#getPackageInfo(String, int)} * @return The PackageInfo for the requested package - * @throws NameNotFoundException */ public PackageInfo getPackageInfo(String packageName, int i) throws NameNotFoundException { return mPm.getPackageInfo(packageName, i); @@ -151,6 +151,7 @@ public class PackageManagerWrapper { /** * Retrieves the icon associated with this particular set of ApplicationInfo + * * @param info The ApplicationInfo to retrieve the icon for * @return The icon as a drawable. */ @@ -161,6 +162,7 @@ public class PackageManagerWrapper { /** * Retrieves the label associated with the particular set of ApplicationInfo + * * @param app The ApplicationInfo to retrieve the label for * @return the label as a CharSequence */ @@ -211,4 +213,20 @@ public class PackageManagerWrapper { public int getApplicationEnabledSetting(String packageName) { return mPm.getApplicationEnabledSetting(packageName); } + + /** + * Calls {@code PackageManager.getApplicationInfo} + */ + public ApplicationInfo getApplicationInfo(String packageName, int flags) + throws NameNotFoundException { + return mPm.getApplicationInfo(packageName, flags); + } + + /** + * Calls {@code PackageManager.getApplicationLabel} + */ + public CharSequence getApplicationLabel(ApplicationInfo info) { + return mPm.getApplicationLabel(info); + } } + diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/graph/BluetoothDeviceLayerDrawableTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/graph/BluetoothDeviceLayerDrawableTest.java index 1e65a0af5ba7..94f80d3d0ac7 100644 --- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/graph/BluetoothDeviceLayerDrawableTest.java +++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/graph/BluetoothDeviceLayerDrawableTest.java @@ -100,4 +100,15 @@ public class BluetoothDeviceLayerDrawableTest { assertThat(twinDrawable.getLayerInsetTop(1)).isEqualTo( drawable.getLayerInsetTop(1)); } + + @Test + public void testCreateLayerDrawable_bluetoothDrawable_hasCorrectFrameColor() { + BluetoothDeviceLayerDrawable drawable = BluetoothDeviceLayerDrawable.createLayerDrawable( + mContext, RES_ID, BATTERY_LEVEL); + BluetoothDeviceLayerDrawable.BatteryMeterDrawable batteryMeterDrawable = + (BluetoothDeviceLayerDrawable.BatteryMeterDrawable) drawable.getDrawable(1); + + assertThat(batteryMeterDrawable.mFrameColor).isEqualTo( + mContext.getColor(R.color.meter_background_color)); + } } diff --git a/packages/SystemUI/res/values-fr-rCA/strings.xml b/packages/SystemUI/res/values-fr-rCA/strings.xml index 6cab2ec064e6..f43a0488457d 100644 --- a/packages/SystemUI/res/values-fr-rCA/strings.xml +++ b/packages/SystemUI/res/values-fr-rCA/strings.xml @@ -336,7 +336,7 @@ <string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"épinglage d\'écran"</string> <string name="recents_search_bar_label" msgid="8074997400187836677">"rechercher"</string> <string name="recents_launch_error_message" msgid="2969287838120550506">"Impossible de lancer <xliff:g id="APP">%s</xliff:g>."</string> - <string name="recents_launch_disabled_message" msgid="1624523193008871793">"<xliff:g id="APP">%s</xliff:g> est désactivée en mode sécurisé."</string> + <string name="recents_launch_disabled_message" msgid="1624523193008871793">"<xliff:g id="APP">%s</xliff:g> est désactivée en mode sans échec."</string> <string name="recents_stack_action_button_label" msgid="6593727103310426253">"Effacer tout"</string> <string name="recents_drag_hint_message" msgid="2649739267073203985">"Glissez l\'élément ici pour utiliser l\'écran partagé"</string> <string name="recents_multistack_add_stack_dialog_split_horizontal" msgid="8848514474543427332">"Séparation horizontale"</string> diff --git a/packages/SystemUI/res/values-pa/strings.xml b/packages/SystemUI/res/values-pa/strings.xml index 987ce712e9c4..c2089a60436b 100644 --- a/packages/SystemUI/res/values-pa/strings.xml +++ b/packages/SystemUI/res/values-pa/strings.xml @@ -184,10 +184,10 @@ <string name="accessibility_notification_dismissed" msgid="854211387186306927">"ਸੂਚਨਾ ਰੱਦ ਕੀਤੀ।"</string> <string name="accessibility_desc_notification_shade" msgid="4690274844447504208">"ਸੂਚਨਾ ਸ਼ੇਡ।"</string> <string name="accessibility_desc_quick_settings" msgid="6186378411582437046">"ਤਤਕਾਲ ਸੈਟਿੰਗਾਂ।"</string> - <string name="accessibility_desc_lock_screen" msgid="5625143713611759164">"ਲੌਕ ਸਕ੍ਰੀਨ।"</string> + <string name="accessibility_desc_lock_screen" msgid="5625143713611759164">" ਲਾਕ ਸਕ੍ਰੀਨ।"</string> <string name="accessibility_desc_settings" msgid="3417884241751434521">"ਸੈਟਿੰਗਾਂ"</string> <string name="accessibility_desc_recent_apps" msgid="4876900986661819788">"ਰੂਪ-ਰੇਖਾ।"</string> - <string name="accessibility_desc_work_lock" msgid="4288774420752813383">"ਕਾਰਜ-ਸਥਾਨ ਲੌਕ ਸਕ੍ਰੀਨ"</string> + <string name="accessibility_desc_work_lock" msgid="4288774420752813383">"ਕਾਰਜ-ਸਥਾਨ ਲਾਕ ਸਕ੍ਰੀਨ"</string> <string name="accessibility_desc_close" msgid="7479755364962766729">"ਬੰਦ ਕਰੋ"</string> <string name="accessibility_quick_settings_wifi" msgid="5518210213118181692">"<xliff:g id="SIGNAL">%1$s</xliff:g>।"</string> <string name="accessibility_quick_settings_wifi_changed_off" msgid="8716484460897819400">"Wifi ਬੰਦ ਕੀਤਾ।"</string> @@ -258,11 +258,11 @@ <string name="status_bar_notification_inspect_item_title" msgid="5668348142410115323">"ਸੂਚਨਾ ਸੈਟਿੰਗਾਂ"</string> <string name="status_bar_notification_app_settings_title" msgid="5525260160341558869">"<xliff:g id="APP_NAME">%s</xliff:g> ਸੈਟਿੰਗਾਂ"</string> <string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"ਸਕ੍ਰੀਨ ਆਟੋਮੈਟਿਕਲੀ ਰੋਟੇਟ ਕਰੇਗੀ।"</string> - <string name="accessibility_rotation_lock_on_landscape" msgid="6731197337665366273">"ਸਕ੍ਰੀਨ ਲੈਂਡਸਕੇਪ ਅਨੁਕੂਲਨ ਵਿੱਚ ਲੌਕ ਕੀਤੀ ਹੈ।"</string> - <string name="accessibility_rotation_lock_on_portrait" msgid="5809367521644012115">"ਸਕ੍ਰੀਨ ਪੋਰਟਰੇਟ ਅਨੁਕੂਲਨ ਵਿੱਚ ਲੌਕ ਕੀਤੀ ਗਈ ਹੈ।"</string> + <string name="accessibility_rotation_lock_on_landscape" msgid="6731197337665366273">"ਸਕ੍ਰੀਨ ਲੈਂਡਸਕੇਪ ਅਨੁਕੂਲਨ ਵਿੱਚ ਲਾਕ ਕੀਤੀ ਹੈ।"</string> + <string name="accessibility_rotation_lock_on_portrait" msgid="5809367521644012115">"ਸਕ੍ਰੀਨ ਪੋਰਟਰੇਟ ਅਨੁਕੂਲਨ ਵਿੱਚ ਲਾਕ ਕੀਤੀ ਗਈ ਹੈ।"</string> <string name="accessibility_rotation_lock_off_changed" msgid="8134601071026305153">"ਸਕ੍ਰੀਨ ਹੁਣ ਆਟੋਮੈਟਿਕਲੀ ਰੋਟੇਟ ਕਰੇਗੀ।"</string> - <string name="accessibility_rotation_lock_on_landscape_changed" msgid="3135965553707519743">"ਸਕ੍ਰੀਨ ਹੁਣ ਲੈਂਡਸਕੇਪ ਅਨੁਕੂਲਨ ਵਿੱਚ ਲੌਕ ਕੀਤੀ ਗਈ ਹੈ।"</string> - <string name="accessibility_rotation_lock_on_portrait_changed" msgid="8922481981834012126">"ਸਕ੍ਰੀਨ ਹੁਣ ਪੋਰਟਰੇਟ ਅਨੁਕੂਲਨ ਵਿੱਚ ਲੌਕ ਕੀਤੀ ਗਈ ਹੈ।"</string> + <string name="accessibility_rotation_lock_on_landscape_changed" msgid="3135965553707519743">"ਸਕ੍ਰੀਨ ਹੁਣ ਲੈਂਡਸਕੇਪ ਅਨੁਕੂਲਨ ਵਿੱਚ ਲਾਕ ਕੀਤੀ ਗਈ ਹੈ।"</string> + <string name="accessibility_rotation_lock_on_portrait_changed" msgid="8922481981834012126">"ਸਕ੍ਰੀਨ ਹੁਣ ਪੋਰਟਰੇਟ ਅਨੁਕੂਲਨ ਵਿੱਚ ਲਾਕ ਕੀਤੀ ਗਈ ਹੈ।"</string> <string name="dessert_case" msgid="1295161776223959221">"ਡੈਜ਼ਰਟ ਕੇਸ"</string> <string name="start_dreams" msgid="5640361424498338327">"ਸਕ੍ਰੀਨ ਸੇਵਰ"</string> <string name="ethernet_label" msgid="7967563676324087464">"ਈਥਰਨੈਟ"</string> @@ -278,7 +278,7 @@ <string name="quick_settings_rotation_unlocked_label" msgid="7305323031808150099">"ਆਟੋ-ਰੋਟੇਟ"</string> <string name="accessibility_quick_settings_rotation" msgid="4231661040698488779">"ਸਕ੍ਰੀਨ ਨੂੰ ਆਪਣੇ ਆਪ ਘੁੰਮਾਓ"</string> <string name="accessibility_quick_settings_rotation_value" msgid="8187398200140760213">"<xliff:g id="ID_1">%s</xliff:g> ਮੋਡ"</string> - <string name="quick_settings_rotation_locked_label" msgid="6359205706154282377">"ਰੋਟੇਸ਼ਨ ਲੌਕ ਕੀਤੀ"</string> + <string name="quick_settings_rotation_locked_label" msgid="6359205706154282377">"ਰੋਟੇਸ਼ਨ ਲਾਕ ਕੀਤੀ"</string> <string name="quick_settings_rotation_locked_portrait_label" msgid="5102691921442135053">"ਪੋਰਟਰੇਟ"</string> <string name="quick_settings_rotation_locked_landscape_label" msgid="8553157770061178719">"ਲੈਂਡਸਕੇਪ"</string> <string name="quick_settings_ime_label" msgid="7073463064369468429">"ਇਨਪੁੱਟ ਵਿਧੀ"</string> @@ -721,7 +721,7 @@ <string name="accessibility_quick_settings_open_settings" msgid="7806613775728380737">"<xliff:g id="ID_1">%s</xliff:g> ਸੈਟਿੰਗਾਂ ਖੋਲ੍ਹੋ।"</string> <string name="accessibility_quick_settings_edit" msgid="7839992848995240393">"ਸੈਟਿੰਗਾਂ ਦੇ ਕ੍ਰਮ ਦਾ ਸੰਪਾਦਨ ਕਰੋ।"</string> <string name="accessibility_quick_settings_page" msgid="5032979051755200721">"<xliff:g id="ID_2">%2$d</xliff:g> ਦਾ <xliff:g id="ID_1">%1$d</xliff:g> ਪੰਨਾ"</string> - <string name="tuner_lock_screen" msgid="5755818559638850294">"ਲੌਕ ਸਕ੍ਰੀਨ"</string> + <string name="tuner_lock_screen" msgid="5755818559638850294">" ਲਾਕ ਸਕ੍ਰੀਨ"</string> <string name="pip_phone_expand" msgid="5889780005575693909">"ਵਿਸਤਾਰ ਕਰੋ"</string> <string name="pip_phone_minimize" msgid="1079119422589131792">"ਛੋਟਾ ਕਰੋ"</string> <string name="pip_phone_close" msgid="8416647892889710330">"ਬੰਦ ਕਰੋ"</string> diff --git a/packages/SystemUI/res/values-pl/strings.xml b/packages/SystemUI/res/values-pl/strings.xml index 7ff9b73b2bf6..a725e53ec762 100644 --- a/packages/SystemUI/res/values-pl/strings.xml +++ b/packages/SystemUI/res/values-pl/strings.xml @@ -244,7 +244,7 @@ <string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"Transmisja danych 4G została wstrzymana"</string> <string name="data_usage_disabled_dialog_mobile_title" msgid="6801382439018099779">"Mobilna transmisja danych jest wstrzymana"</string> <string name="data_usage_disabled_dialog_title" msgid="3932437232199671967">"Transmisja danych została wstrzymana"</string> - <string name="data_usage_disabled_dialog" msgid="4919541636934603816">"Osiągnięto ustawiony limit danych. Nie korzystasz już z komórkowej transmisji danych.\n\nJeśli włączysz ją ponownie, może zostać naliczona opłata za transmisję danych."</string> + <string name="data_usage_disabled_dialog" msgid="4919541636934603816">"Osiągnięto ustawiony limit danych. Nie korzystasz już z komórkowej transmisji danych.\n\nJeśli włączysz ją ponownie, może zostać naliczona opłata za użycie danych."</string> <string name="data_usage_disabled_dialog_enable" msgid="1412395410306390593">"Wznów"</string> <string name="status_bar_settings_signal_meter_disconnected" msgid="1940231521274147771">"Brak internetu"</string> <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="6557486452774597820">"Wi-Fi: połączono"</string> @@ -785,7 +785,7 @@ <string name="qs_dnd_keep" msgid="1825009164681928736">"Zachowaj"</string> <string name="qs_dnd_replace" msgid="8019520786644276623">"Zastąp"</string> <string name="running_foreground_services_title" msgid="381024150898615683">"Aplikacje działające w tle"</string> - <string name="running_foreground_services_msg" msgid="6326247670075574355">"Kliknij, by wyświetlić szczegóły wykorzystania baterii i transmisji danych"</string> + <string name="running_foreground_services_msg" msgid="6326247670075574355">"Kliknij, by wyświetlić szczegóły wykorzystania baterii i użycia danych"</string> <string name="data_usage_disable_mobile" msgid="5116269981510015864">"Wyłączyć mobilną transmisję danych?"</string> <string name="touch_filtered_warning" msgid="8671693809204767551">"Aplikacja Ustawienia nie może zweryfikować Twojej odpowiedzi, ponieważ inna aplikacja zasłania prośbę o udzielenie uprawnień."</string> </resources> diff --git a/packages/SystemUI/res/values-zh-rTW/strings.xml b/packages/SystemUI/res/values-zh-rTW/strings.xml index d767979b25c3..2152ae353e93 100644 --- a/packages/SystemUI/res/values-zh-rTW/strings.xml +++ b/packages/SystemUI/res/values-zh-rTW/strings.xml @@ -73,7 +73,7 @@ <string name="screenshot_saved_title" msgid="6461865960961414961">"已拍攝螢幕擷取畫面。"</string> <string name="screenshot_saved_text" msgid="2685605830386712477">"輕觸即可查看螢幕擷圖。"</string> <string name="screenshot_failed_title" msgid="705781116746922771">"無法拍攝螢幕擷取畫面。"</string> - <string name="screenshot_failed_to_save_unknown_text" msgid="7887826345701753830">"儲存螢幕擷圖時發生問題。"</string> + <string name="screenshot_failed_to_save_unknown_text" msgid="7887826345701753830">"儲存螢幕擷取畫面時發生問題。"</string> <string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"由於儲存空間有限,因此無法儲存螢幕擷取畫面。"</string> <string name="screenshot_failed_to_capture_text" msgid="173674476457581486">"這個應用程式或貴機構不允許擷取螢幕畫面"</string> <string name="usb_preference_title" msgid="6551050377388882787">"USB 檔案傳輸選項"</string> diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java index cd23c97c71b6..669c8bf9bdb1 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java @@ -452,6 +452,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener { */ public void setKeyguardGoingAway(boolean goingAway) { mKeyguardGoingAway = goingAway; + updateFingerprintListeningState(); } /** diff --git a/packages/SystemUI/src/com/android/systemui/BatteryMeterView.java b/packages/SystemUI/src/com/android/systemui/BatteryMeterView.java index 2b31967cea4f..2fe66a14a41d 100644 --- a/packages/SystemUI/src/com/android/systemui/BatteryMeterView.java +++ b/packages/SystemUI/src/com/android/systemui/BatteryMeterView.java @@ -15,6 +15,8 @@ */ package com.android.systemui; +import static android.app.StatusBarManager.DISABLE2_SYSTEM_ICONS; +import static android.app.StatusBarManager.DISABLE_NONE; import static android.provider.Settings.System.SHOW_BATTERY_PERCENT; import android.animation.ArgbEvaluator; @@ -52,6 +54,7 @@ import com.android.systemui.statusbar.policy.DarkIconDispatcher.DarkReceiver; import com.android.systemui.statusbar.policy.IconLogger; import com.android.systemui.tuner.TunerService; import com.android.systemui.tuner.TunerService.Tunable; +import com.android.systemui.util.Utils.DisableStateTracker; import java.text.NumberFormat; @@ -101,6 +104,9 @@ public class BatteryMeterView extends LinearLayout implements mSettingObserver = new SettingObserver(new Handler(context.getMainLooper())); + addOnAttachStateChangeListener( + new DisableStateTracker(DISABLE_NONE, DISABLE2_SYSTEM_ICONS)); + mSlotBattery = context.getString( com.android.internal.R.string.status_bar_battery); mBatteryIconView = new ImageView(context); diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeScreenBrightness.java b/packages/SystemUI/src/com/android/systemui/doze/DozeScreenBrightness.java index 03407e2b86e7..4bb4e79c91f6 100644 --- a/packages/SystemUI/src/com/android/systemui/doze/DozeScreenBrightness.java +++ b/packages/SystemUI/src/com/android/systemui/doze/DozeScreenBrightness.java @@ -22,6 +22,7 @@ import android.hardware.SensorEvent; import android.hardware.SensorEventListener; import android.hardware.SensorManager; import android.os.Handler; +import android.os.Trace; import com.android.internal.annotations.VisibleForTesting; @@ -94,9 +95,14 @@ public class DozeScreenBrightness implements DozeMachine.Part, SensorEventListen @Override public void onSensorChanged(SensorEvent event) { - if (mRegistered) { - mLastSensorValue = (int) event.values[0]; - updateBrightnessAndReady(); + Trace.beginSection("DozeScreenBrightness.onSensorChanged" + event.values[0]); + try { + if (mRegistered) { + mLastSensorValue = (int) event.values[0]; + updateBrightnessAndReady(); + } + } finally { + Trace.endSection(); } } diff --git a/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java b/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java index 44e60eed8c7c..a41fd22d4c0b 100644 --- a/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java +++ b/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java @@ -64,6 +64,7 @@ import com.android.systemui.Interpolators; import com.android.systemui.R; import com.android.systemui.recents.Recents; import com.android.systemui.recents.events.EventBus; +import com.android.systemui.recents.events.activity.DockedFirstAnimationFrameEvent; import com.android.systemui.recents.events.activity.DockedTopTaskEvent; import com.android.systemui.recents.events.activity.RecentsActivityStartingEvent; import com.android.systemui.recents.events.activity.UndockingTaskEvent; @@ -1192,6 +1193,10 @@ public class DividerView extends FrameLayout implements OnTouchListener, } } + public final void onBusEvent(DockedFirstAnimationFrameEvent event) { + saveSnapTargetBeforeMinimized(mSnapAlgorithm.getMiddleTarget()); + } + public final void onBusEvent(DockedTopTaskEvent event) { if (event.dragMode == NavigationBarGestureHelper.DRAG_MODE_NONE) { mState.growAfterRecentsDrawn = false; diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/SignalClusterView.java b/packages/SystemUI/src/com/android/systemui/statusbar/SignalClusterView.java index 759d2cf2f8bc..181931e12441 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/SignalClusterView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/SignalClusterView.java @@ -16,14 +16,15 @@ package com.android.systemui.statusbar; +import static android.app.StatusBarManager.DISABLE2_SYSTEM_ICONS; +import static android.app.StatusBarManager.DISABLE_NONE; + import android.annotation.DrawableRes; import android.content.Context; import android.content.res.ColorStateList; import android.content.res.Resources; import android.graphics.Color; import android.graphics.Rect; -import android.graphics.drawable.Animatable; -import android.graphics.drawable.AnimatedVectorDrawable; import android.graphics.drawable.Drawable; import android.telephony.SubscriptionInfo; import android.util.ArraySet; @@ -50,14 +51,14 @@ import com.android.systemui.statusbar.policy.NetworkControllerImpl; import com.android.systemui.statusbar.policy.SecurityController; import com.android.systemui.tuner.TunerService; import com.android.systemui.tuner.TunerService.Tunable; +import com.android.systemui.util.Utils.DisableStateTracker; import java.util.ArrayList; import java.util.List; // Intimately tied to the design of res/layout/signal_cluster_view.xml public class SignalClusterView extends LinearLayout implements NetworkControllerImpl.SignalCallback, - SecurityController.SecurityControllerCallback, Tunable, - DarkReceiver { + SecurityController.SecurityControllerCallback, Tunable, DarkReceiver { static final String TAG = "SignalClusterView"; static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG); @@ -148,6 +149,8 @@ public class SignalClusterView extends LinearLayout implements NetworkController mIconScaleFactor = typedValue.getFloat(); mNetworkController = Dependency.get(NetworkController.class); mSecurityController = Dependency.get(SecurityController.class); + addOnAttachStateChangeListener( + new DisableStateTracker(DISABLE_NONE, DISABLE2_SYSTEM_ICONS)); updateActivityEnabled(); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java index 4b6b264d90dd..274c024407bb 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java @@ -2523,8 +2523,11 @@ public class StatusBar extends SystemUI implements DemoMode, flagdbg.append(0 != ((diff1 & StatusBarManager.DISABLE_CLOCK)) ? '!' : ' '); flagdbg.append(0 != ((state1 & StatusBarManager.DISABLE_SEARCH)) ? 'S' : 's'); flagdbg.append(0 != ((diff1 & StatusBarManager.DISABLE_SEARCH)) ? '!' : ' '); + flagdbg.append("> disable2<"); flagdbg.append(0 != ((state2 & StatusBarManager.DISABLE2_QUICK_SETTINGS)) ? 'Q' : 'q'); flagdbg.append(0 != ((diff2 & StatusBarManager.DISABLE2_QUICK_SETTINGS)) ? '!' : ' '); + flagdbg.append(0 != ((state2 & StatusBarManager.DISABLE2_SYSTEM_ICONS)) ? 'I' : 'i'); + flagdbg.append(0 != ((diff2 & StatusBarManager.DISABLE2_SYSTEM_ICONS)) ? '!' : ' '); flagdbg.append('>'); Log.d(TAG, flagdbg.toString()); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconController.java index c2407652b2df..bcda60ebc62c 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconController.java @@ -14,10 +14,10 @@ package com.android.systemui.statusbar.phone; -import android.annotation.ColorInt; +import static android.app.StatusBarManager.DISABLE2_SYSTEM_ICONS; +import static android.app.StatusBarManager.DISABLE_NONE; + import android.content.Context; -import android.content.res.TypedArray; -import android.graphics.Color; import android.support.annotation.VisibleForTesting; import android.text.TextUtils; import android.util.ArraySet; @@ -29,11 +29,11 @@ import android.widget.LinearLayout; import android.widget.LinearLayout.LayoutParams; import com.android.internal.statusbar.StatusBarIcon; -import com.android.settingslib.Utils; import com.android.systemui.Dependency; import com.android.systemui.R; import com.android.systemui.statusbar.StatusBarIconView; import com.android.systemui.statusbar.policy.DarkIconDispatcher; +import com.android.systemui.util.Utils.DisableStateTracker; public interface StatusBarIconController { @@ -149,6 +149,14 @@ public interface StatusBarIconController { mContext = group.getContext(); mIconSize = mContext.getResources().getDimensionPixelSize( com.android.internal.R.dimen.status_bar_icon_size); + + DisableStateTracker tracker = + new DisableStateTracker(DISABLE_NONE, DISABLE2_SYSTEM_ICONS); + mGroup.addOnAttachStateChangeListener(tracker); + if (mGroup.isAttachedToWindow()) { + // In case we miss the first onAttachedToWindow event + tracker.onViewAttachedToWindow(mGroup); + } } protected void onIconAdded(int index, String slot, boolean blocked, diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconControllerImpl.java index 68f8e065a429..1c3ee758a3ce 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconControllerImpl.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconControllerImpl.java @@ -33,7 +33,6 @@ import com.android.systemui.statusbar.CommandQueue; import com.android.systemui.statusbar.StatusBarIconView; import com.android.systemui.statusbar.policy.ConfigurationController; import com.android.systemui.statusbar.policy.ConfigurationController.ConfigurationListener; -import com.android.systemui.statusbar.policy.DarkIconDispatcher; import com.android.systemui.statusbar.policy.IconLogger; import com.android.systemui.tuner.TunerService; import com.android.systemui.tuner.TunerService.Tunable; @@ -50,21 +49,17 @@ import java.util.ArrayList; public class StatusBarIconControllerImpl extends StatusBarIconList implements Tunable, ConfigurationListener, Dumpable, CommandQueue.Callbacks, StatusBarIconController { - private final DarkIconDispatcher mDarkIconDispatcher; - - private Context mContext; - private DemoStatusIcons mDemoStatusIcons; - private final ArrayList<IconManager> mIconGroups = new ArrayList<>(); - private final ArraySet<String> mIconBlacklist = new ArraySet<>(); private final IconLogger mIconLogger = Dependency.get(IconLogger.class); + private Context mContext; + private DemoStatusIcons mDemoStatusIcons; + public StatusBarIconControllerImpl(Context context) { super(context.getResources().getStringArray( com.android.internal.R.array.config_statusBarIcons)); Dependency.get(ConfigurationController.class).addCallback(this); - mDarkIconDispatcher = Dependency.get(DarkIconDispatcher.class); mContext = context; loadDimens(); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java index c217bda935c4..9d6fc5e9094e 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java @@ -804,6 +804,10 @@ public class NetworkControllerImpl extends BroadcastReceiver } else { mWifiSignalController.setActivity(WifiManager.DATA_ACTIVITY_NONE); } + String ssid = args.getString("ssid"); + if (ssid != null) { + mDemoWifiState.ssid = ssid; + } mDemoWifiState.enabled = show; mWifiSignalController.notifyListeners(); } diff --git a/packages/SystemUI/src/com/android/systemui/util/Utils.java b/packages/SystemUI/src/com/android/systemui/util/Utils.java index f4aebae7bdaf..eca612776f21 100644 --- a/packages/SystemUI/src/com/android/systemui/util/Utils.java +++ b/packages/SystemUI/src/com/android/systemui/util/Utils.java @@ -14,6 +14,11 @@ package com.android.systemui.util; +import android.view.View; + +import com.android.systemui.SysUiServiceProvider; +import com.android.systemui.statusbar.CommandQueue; + import java.util.List; import java.util.function.Consumer; @@ -28,4 +33,52 @@ public class Utils { c.accept(list.get(i)); } } + + /** + * Sets the visibility of an UI element according to the DISABLE_* flags in + * {@link android.app.StatusBarManager}. + */ + public static class DisableStateTracker implements CommandQueue.Callbacks, + View.OnAttachStateChangeListener { + private final int mMask1; + private final int mMask2; + private View mView; + private boolean mDisabled; + + public DisableStateTracker(int disableMask, int disable2Mask) { + mMask1 = disableMask; + mMask2 = disable2Mask; + } + + @Override + public void onViewAttachedToWindow(View v) { + mView = v; + SysUiServiceProvider.getComponent(v.getContext(), CommandQueue.class) + .addCallbacks(this); + } + + @Override + public void onViewDetachedFromWindow(View v) { + SysUiServiceProvider.getComponent(mView.getContext(), CommandQueue.class) + .removeCallbacks(this); + mView = null; + } + + /** + * Sets visibility of this {@link View} given the states passed from + * {@link com.android.systemui.statusbar.CommandQueue.Callbacks#disable(int, int)}. + */ + @Override + public void disable(int state1, int state2, boolean animate) { + final boolean disabled = ((state1 & mMask1) != 0) || ((state2 & mMask2) != 0); + if (disabled == mDisabled) return; + mDisabled = disabled; + mView.setVisibility(disabled ? View.GONE : View.VISIBLE); + } + + /** @return {@code true} if and only if this {@link View} is currently disabled */ + public boolean isDisabled() { + return mDisabled; + } + } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/car/CarQsFragmentTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/car/CarQsFragmentTest.java index 4f87b02ed35f..e023e87067e0 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/qs/car/CarQsFragmentTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/qs/car/CarQsFragmentTest.java @@ -14,6 +14,7 @@ package com.android.systemui.qs.car; import static org.junit.Assert.assertNotNull; +import static org.mockito.Mockito.mock; import android.content.Context; import android.support.test.filters.SmallTest; @@ -27,6 +28,7 @@ import android.widget.FrameLayout; import com.android.keyguard.CarrierText; import com.android.systemui.Dependency; import com.android.systemui.SysuiBaseFragmentTest; +import com.android.systemui.statusbar.CommandQueue; import com.android.systemui.statusbar.policy.Clock; import org.junit.Before; @@ -54,7 +56,7 @@ public class CarQsFragmentTest extends SysuiBaseFragmentTest { .replace(CarrierText.class, View.class) .replace(Clock.class, View.class) .build()); - + mSysuiContext.putComponent(CommandQueue.class, mock(CommandQueue.class)); mDependency.injectTestDependency(Dependency.BG_LOOPER, TestableLooper.get(this).getLooper()); } diff --git a/proto/src/metrics_constants.proto b/proto/src/metrics_constants.proto index 84c67a1976d4..1b0ff216636b 100644 --- a/proto/src/metrics_constants.proto +++ b/proto/src/metrics_constants.proto @@ -4626,6 +4626,11 @@ message MetricsEvent { // OS: P DIALOG_ENABLE_OEM_UNLOCKING = 1159; + // OPEN: Settings > Security > Nexus Imprint > [Fingerprint] + // CATEGORY: SETTINGS + // OS: P + FINGERPRINT_AUTHENTICATE_SIDECAR = 1160; + // Add new aosp constants above this line. // END OF AOSP CONSTANTS } diff --git a/rs/jni/Android.mk b/rs/jni/Android.mk index 21438e04f38c..0854b9582187 100644 --- a/rs/jni/Android.mk +++ b/rs/jni/Android.mk @@ -12,7 +12,7 @@ LOCAL_SHARED_LIBRARIES := \ libRS \ libcutils \ liblog \ - libskia \ + libhwui \ libutils \ libui \ libgui \ @@ -23,9 +23,7 @@ LOCAL_HEADER_LIBRARIES := \ LOCAL_C_INCLUDES += \ $(JNI_H_INCLUDE) \ - frameworks/rs \ - frameworks/base/core/jni \ - frameworks/base/libs/hwui + frameworks/rs LOCAL_CFLAGS += -Wno-unused-parameter LOCAL_CFLAGS += -Wall -Werror -Wunused -Wunreachable-code diff --git a/services/autofill/java/com/android/server/autofill/ui/SaveUi.java b/services/autofill/java/com/android/server/autofill/ui/SaveUi.java index cd9bdb7205b1..d48f23caedaa 100644 --- a/services/autofill/java/com/android/server/autofill/ui/SaveUi.java +++ b/services/autofill/java/com/android/server/autofill/ui/SaveUi.java @@ -271,6 +271,10 @@ final class SaveUi { mDialog = new Dialog(context, R.style.Theme_DeviceDefault_Light_Panel); mDialog.setContentView(view); + // Dialog can be dismissed when touched outside, but the negative listener should not be + // notified (hence the null argument). + mDialog.setOnDismissListener((d) -> mListener.onCancel(null)); + final Window window = mDialog.getWindow(); window.setType(WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY); window.addFlags(WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE diff --git a/services/core/java/com/android/server/BatteryService.java b/services/core/java/com/android/server/BatteryService.java index 83bd9ebded95..5106c8d731ff 100644 --- a/services/core/java/com/android/server/BatteryService.java +++ b/services/core/java/com/android/server/BatteryService.java @@ -20,6 +20,7 @@ import android.app.ActivityManagerInternal; import android.database.ContentObserver; import android.os.BatteryStats; +import android.os.PowerManager; import android.os.ResultReceiver; import android.os.ShellCallback; import android.os.ShellCommand; @@ -291,6 +292,8 @@ public final class BatteryService extends SystemService { if (mActivityManagerInternal.isSystemReady()) { Intent intent = new Intent(Intent.ACTION_REQUEST_SHUTDOWN); intent.putExtra(Intent.EXTRA_KEY_CONFIRM, false); + intent.putExtra(Intent.EXTRA_REASON, + PowerManager.SHUTDOWN_LOW_BATTERY); intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); mContext.startActivityAsUser(intent, UserHandle.CURRENT); } @@ -310,6 +313,8 @@ public final class BatteryService extends SystemService { if (mActivityManagerInternal.isSystemReady()) { Intent intent = new Intent(Intent.ACTION_REQUEST_SHUTDOWN); intent.putExtra(Intent.EXTRA_KEY_CONFIRM, false); + intent.putExtra(Intent.EXTRA_REASON, + PowerManager.SHUTDOWN_BATTERY_THERMAL_STATE); intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); mContext.startActivityAsUser(intent, UserHandle.CURRENT); } diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java index 3ac6f2e847f6..348c79979685 100644 --- a/services/core/java/com/android/server/ConnectivityService.java +++ b/services/core/java/com/android/server/ConnectivityService.java @@ -19,6 +19,7 @@ package com.android.server; import static android.Manifest.permission.RECEIVE_DATA_ACTIVITY_CHANGE; import static android.net.ConnectivityManager.CONNECTIVITY_ACTION; import static android.net.ConnectivityManager.NETID_UNSET; +import static android.net.ConnectivityManager.TYPE_ETHERNET; import static android.net.ConnectivityManager.TYPE_NONE; import static android.net.ConnectivityManager.TYPE_VPN; import static android.net.ConnectivityManager.getNetworkTypeName; @@ -90,6 +91,7 @@ import android.os.PowerManager; import android.os.Process; import android.os.RemoteException; import android.os.ResultReceiver; +import android.os.ServiceManager; import android.os.ServiceSpecificException; import android.os.SystemClock; import android.os.UserHandle; @@ -780,6 +782,13 @@ public class ConnectivityService extends IConnectivityManager.Stub mNetworksDefined++; // used only in the log() statement below. } + // Do the same for Ethernet, since it's often not specified in the configs, although many + // devices can use it via USB host adapters. + if (mNetConfigs[TYPE_ETHERNET] == null && hasService(Context.ETHERNET_SERVICE)) { + mLegacyTypeTracker.addSupportedType(TYPE_ETHERNET); + mNetworksDefined++; + } + if (VDBG) log("mNetworksDefined=" + mNetworksDefined); mProtectedNetworks = new ArrayList<Integer>(); @@ -5540,6 +5549,11 @@ public class ConnectivityService extends IConnectivityManager.Stub return new WakeupMessage(c, h, s, cmd, 0, 0, obj); } + @VisibleForTesting + public boolean hasService(String name) { + return ServiceManager.checkService(name) != null; + } + private void logDefaultNetworkEvent(NetworkAgentInfo newNai, NetworkAgentInfo prevNai) { int newNetid = NETID_UNSET; int prevNetid = NETID_UNSET; diff --git a/services/core/java/com/android/server/DiskStatsService.java b/services/core/java/com/android/server/DiskStatsService.java index 800081e51c9a..2d2c6b0bc8b3 100644 --- a/services/core/java/com/android/server/DiskStatsService.java +++ b/services/core/java/com/android/server/DiskStatsService.java @@ -202,6 +202,8 @@ public class DiskStatsService extends Binder { JSONObject json = new JSONObject(jsonString); pw.print("App Size: "); pw.println(json.getLong(DiskStatsFileLogger.APP_SIZE_AGG_KEY)); + pw.print("App Data Size: "); + pw.println(json.getLong(DiskStatsFileLogger.APP_DATA_SIZE_AGG_KEY)); pw.print("App Cache Size: "); pw.println(json.getLong(DiskStatsFileLogger.APP_CACHE_AGG_KEY)); pw.print("Photos Size: "); @@ -220,6 +222,8 @@ public class DiskStatsService extends Binder { pw.println(json.getJSONArray(DiskStatsFileLogger.PACKAGE_NAMES_KEY)); pw.print("App Sizes: "); pw.println(json.getJSONArray(DiskStatsFileLogger.APP_SIZES_KEY)); + pw.print("App Data Sizes: "); + pw.println(json.getJSONArray(DiskStatsFileLogger.APP_DATA_KEY)); pw.print("Cache Sizes: "); pw.println(json.getJSONArray(DiskStatsFileLogger.APP_CACHES_KEY)); } catch (IOException | JSONException e) { @@ -235,6 +239,8 @@ public class DiskStatsService extends Binder { proto.write(DiskStatsCachedValuesProto.AGG_APPS_SIZE, json.getLong(DiskStatsFileLogger.APP_SIZE_AGG_KEY)); + proto.write(DiskStatsCachedValuesProto.AGG_APPS_DATA_SIZE, + json.getLong(DiskStatsFileLogger.APP_DATA_SIZE_AGG_KEY)); proto.write(DiskStatsCachedValuesProto.AGG_APPS_CACHE_SIZE, json.getLong(DiskStatsFileLogger.APP_CACHE_AGG_KEY)); proto.write(DiskStatsCachedValuesProto.PHOTOS_SIZE, @@ -252,22 +258,26 @@ public class DiskStatsService extends Binder { JSONArray packageNamesArray = json.getJSONArray(DiskStatsFileLogger.PACKAGE_NAMES_KEY); JSONArray appSizesArray = json.getJSONArray(DiskStatsFileLogger.APP_SIZES_KEY); + JSONArray appDataSizesArray = json.getJSONArray(DiskStatsFileLogger.APP_DATA_KEY); JSONArray cacheSizesArray = json.getJSONArray(DiskStatsFileLogger.APP_CACHES_KEY); final int len = packageNamesArray.length(); - if (len == appSizesArray.length() && len == cacheSizesArray.length()) { + if (len == appSizesArray.length() + && len == appDataSizesArray.length() + && len == cacheSizesArray.length()) { for (int i = 0; i < len; i++) { long packageToken = proto.start(DiskStatsCachedValuesProto.APP_SIZES); proto.write(DiskStatsAppSizesProto.PACKAGE_NAME, packageNamesArray.getString(i)); proto.write(DiskStatsAppSizesProto.APP_SIZE, appSizesArray.getLong(i)); + proto.write(DiskStatsAppSizesProto.APP_DATA_SIZE, appDataSizesArray.getLong(i)); proto.write(DiskStatsAppSizesProto.CACHE_SIZE, cacheSizesArray.getLong(i)); proto.end(packageToken); } } else { - Slog.wtf(TAG, "Sizes of packageNamesArray, appSizesArray and cacheSizesArray " - + "are not the same"); + Slog.wtf(TAG, "Sizes of packageNamesArray, appSizesArray, appDataSizesArray " + + " and cacheSizesArray are not the same"); } proto.end(cachedValuesToken); diff --git a/services/core/java/com/android/server/NetworkManagementService.java b/services/core/java/com/android/server/NetworkManagementService.java index 2f95aa2cf2f6..8adc2598ea2d 100644 --- a/services/core/java/com/android/server/NetworkManagementService.java +++ b/services/core/java/com/android/server/NetworkManagementService.java @@ -1140,17 +1140,6 @@ public class NetworkManagementService extends INetworkManagementService.Stub } @Override - public void setInterfaceIpv6NdOffload(String iface, boolean enable) { - mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); - try { - mConnector.execute( - "interface", "ipv6ndoffload", iface, (enable ? "enable" : "disable")); - } catch (NativeDaemonConnectorException e) { - throw e.rethrowAsParcelableException(); - } - } - - @Override public void addRoute(int netId, RouteInfo route) { modifyRoute("add", "" + netId, route); } diff --git a/services/core/java/com/android/server/accounts/AccountManagerService.java b/services/core/java/com/android/server/accounts/AccountManagerService.java index 98e08e09049b..4e15e5d95103 100644 --- a/services/core/java/com/android/server/accounts/AccountManagerService.java +++ b/services/core/java/com/android/server/accounts/AccountManagerService.java @@ -2969,9 +2969,13 @@ public class AccountManagerService * have users launching arbitrary activities by tricking users to * interact with malicious notifications. */ - checkKeyIntent( + if (!checkKeyIntent( Binder.getCallingUid(), - intent); + intent)) { + onError(AccountManager.ERROR_CODE_INVALID_RESPONSE, + "invalid intent in bundle returned"); + return; + } doNotification( mAccounts, account, @@ -3366,9 +3370,13 @@ public class AccountManagerService Intent intent = null; if (result != null && (intent = result.getParcelable(AccountManager.KEY_INTENT)) != null) { - checkKeyIntent( + if (!checkKeyIntent( Binder.getCallingUid(), - intent); + intent)) { + onError(AccountManager.ERROR_CODE_INVALID_RESPONSE, + "invalid intent in bundle returned"); + return; + } } IAccountManagerResponse response; if (mExpectActivityLaunch && result != null @@ -4716,9 +4724,7 @@ public class AccountManagerService * into launching arbitrary intents on the device via by tricking to click authenticator * supplied entries in the system Settings app. */ - protected void checkKeyIntent( - int authUid, - Intent intent) throws SecurityException { + protected boolean checkKeyIntent(int authUid, Intent intent) { intent.setFlags(intent.getFlags() & ~(Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION | Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION @@ -4727,6 +4733,9 @@ public class AccountManagerService try { PackageManager pm = mContext.getPackageManager(); ResolveInfo resolveInfo = pm.resolveActivityAsUser(intent, 0, mAccounts.userId); + if (resolveInfo == null) { + return false; + } ActivityInfo targetActivityInfo = resolveInfo.activityInfo; int targetUid = targetActivityInfo.applicationInfo.uid; if (!isExportedSystemActivity(targetActivityInfo) @@ -4736,9 +4745,10 @@ public class AccountManagerService String activityName = targetActivityInfo.name; String tmpl = "KEY_INTENT resolved to an Activity (%s) in a package (%s) that " + "does not share a signature with the supplying authenticator (%s)."; - throw new SecurityException( - String.format(tmpl, activityName, pkgName, mAccountType)); + Log.e(TAG, String.format(tmpl, activityName, pkgName, mAccountType)); + return false; } + return true; } finally { Binder.restoreCallingIdentity(bid); } @@ -4888,9 +4898,13 @@ public class AccountManagerService } if (result != null && (intent = result.getParcelable(AccountManager.KEY_INTENT)) != null) { - checkKeyIntent( + if (!checkKeyIntent( Binder.getCallingUid(), - intent); + intent)) { + onError(AccountManager.ERROR_CODE_INVALID_RESPONSE, + "invalid intent in bundle returned"); + return; + } } if (result != null && !TextUtils.isEmpty(result.getString(AccountManager.KEY_AUTHTOKEN))) { diff --git a/services/core/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java index 90ad8a5d0131..2131731de045 100644 --- a/services/core/java/com/android/server/am/ActiveServices.java +++ b/services/core/java/com/android/server/am/ActiveServices.java @@ -3150,7 +3150,7 @@ public final class ActiveServices { sr.userId, sr.crashCount, sr.shortName, app.pid); bringDownServiceLocked(sr); } else if (!allowRestart - || !mAm.mUserController.isUserRunningLocked(sr.userId, 0)) { + || !mAm.mUserController.isUserRunning(sr.userId, 0)) { bringDownServiceLocked(sr); } else { boolean canceled = scheduleServiceRestartLocked(sr, true); diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java index 6df5fb7ccb0e..7295bcb9bc91 100644 --- a/services/core/java/com/android/server/am/ActivityManagerService.java +++ b/services/core/java/com/android/server/am/ActivityManagerService.java @@ -1711,6 +1711,7 @@ public class ActivityManagerService extends IActivityManager.Stub static final int PUSH_TEMP_WHITELIST_UI_MSG = 68; static final int SERVICE_FOREGROUND_CRASH_MSG = 69; static final int DISPATCH_OOM_ADJ_OBSERVER_MSG = 70; + static final int TOP_APP_KILLED_BY_LMK_MSG = 73; static final int FIRST_ACTIVITY_STACK_MSG = 100; static final int FIRST_BROADCAST_QUEUE_MSG = 200; @@ -1938,6 +1939,17 @@ public class ActivityManagerService extends IActivityManager.Stub dispatchProcessDied(pid, uid); break; } + case TOP_APP_KILLED_BY_LMK_MSG: { + final String appName = (String) msg.obj; + final AlertDialog d = new BaseErrorDialog(mUiContext); + d.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ERROR); + d.setTitle(mUiContext.getText(R.string.top_app_killed_title)); + d.setMessage(mUiContext.getString(R.string.top_app_killed_message, appName)); + d.setButton(DialogInterface.BUTTON_POSITIVE, mUiContext.getText(R.string.close), + obtainMessage(DISMISS_DIALOG_UI_MSG, d)); + d.show(); + break; + } case DISPATCH_UIDS_CHANGED_UI_MSG: { dispatchUidsChanged(); } break; @@ -2519,10 +2531,12 @@ public class ActivityManagerService extends IActivityManager.Stub } public void setWindowManager(WindowManagerService wm) { - mWindowManager = wm; - mStackSupervisor.setWindowManager(wm); - mActivityStarter.setWindowManager(wm); - mLockTaskController.setWindowManager(wm); + synchronized (this) { + mWindowManager = wm; + mStackSupervisor.setWindowManager(wm); + mActivityStarter.setWindowManager(wm); + mLockTaskController.setWindowManager(wm); + } } public void setUsageStatsManager(UsageStatsManagerInternal usageStatsManager) { @@ -5394,6 +5408,7 @@ public class ActivityManagerService extends IActivityManager.Stub boolean doLowMem = app.instr == null; boolean doOomAdj = doLowMem; if (!app.killedByAm) { + maybeNotifyTopAppKilled(app); Slog.i(TAG, "Process " + app.processName + " (pid " + pid + ") has died: " + ProcessList.makeOomAdjString(app.setAdj) + ProcessList.makeProcStateString(app.setProcState)); @@ -5427,6 +5442,23 @@ public class ActivityManagerService extends IActivityManager.Stub } } + /** Show system error dialog when a top app is killed by LMK */ + void maybeNotifyTopAppKilled(ProcessRecord app) { + if (!shouldNotifyTopAppKilled(app)) { + return; + } + + Message msg = mHandler.obtainMessage(TOP_APP_KILLED_BY_LMK_MSG); + msg.obj = mContext.getPackageManager().getApplicationLabel(app.info); + mUiHandler.sendMessage(msg); + } + + /** Only show notification when the top app is killed on low ram devices */ + private boolean shouldNotifyTopAppKilled(ProcessRecord app) { + return app.curSchedGroup == ProcessList.SCHED_GROUP_TOP_APP && + ActivityManager.isLowRamDeviceStatic(); + } + /** * If a stack trace dump file is configured, dump process stack traces. * @param clearTraces causes the dump file to be erased prior to the new @@ -6150,7 +6182,7 @@ public class ActivityManagerService extends IActivityManager.Stub Slog.w(TAG, "Failed trying to unstop package " + packageName + ": " + e); } - if (mUserController.isUserRunningLocked(user, 0)) { + if (mUserController.isUserRunning(user, 0)) { forceStopPackageLocked(packageName, pkgUid, "from pid " + callingPid); finishForceStopPackageLocked(packageName, pkgUid); } @@ -7308,33 +7340,32 @@ public class ActivityManagerService extends IActivityManager.Stub startProcessLocked(procs.get(ip), "on-hold", null); } } + if (mFactoryTest == FactoryTest.FACTORY_TEST_LOW_LEVEL) { + return; + } + // Start looking for apps that are abusing wake locks. + Message nmsg = mHandler.obtainMessage(CHECK_EXCESSIVE_POWER_USE_MSG); + mHandler.sendMessageDelayed(nmsg, mConstants.POWER_CHECK_INTERVAL); + // Tell anyone interested that we are done booting! + SystemProperties.set("sys.boot_completed", "1"); - if (mFactoryTest != FactoryTest.FACTORY_TEST_LOW_LEVEL) { - // Start looking for apps that are abusing wake locks. - Message nmsg = mHandler.obtainMessage(CHECK_EXCESSIVE_POWER_USE_MSG); - mHandler.sendMessageDelayed(nmsg, mConstants.POWER_CHECK_INTERVAL); - // Tell anyone interested that we are done booting! - SystemProperties.set("sys.boot_completed", "1"); - - // And trigger dev.bootcomplete if we are not showing encryption progress - if (!"trigger_restart_min_framework".equals(SystemProperties.get("vold.decrypt")) + // And trigger dev.bootcomplete if we are not showing encryption progress + if (!"trigger_restart_min_framework".equals(SystemProperties.get("vold.decrypt")) || "".equals(SystemProperties.get("vold.encrypt_progress"))) { - SystemProperties.set("dev.bootcomplete", "1"); - } - mUserController.sendBootCompletedLocked( - new IIntentReceiver.Stub() { - @Override - public void performReceive(Intent intent, int resultCode, - String data, Bundle extras, boolean ordered, - boolean sticky, int sendingUser) { - synchronized (ActivityManagerService.this) { - requestPssAllProcsLocked(SystemClock.uptimeMillis(), - true, false); - } - } - }); - mUserController.scheduleStartProfilesLocked(); + SystemProperties.set("dev.bootcomplete", "1"); } + mUserController.sendBootCompleted( + new IIntentReceiver.Stub() { + @Override + public void performReceive(Intent intent, int resultCode, + String data, Bundle extras, boolean ordered, + boolean sticky, int sendingUser) { + synchronized (ActivityManagerService.this) { + requestPssAllProcsLocked(SystemClock.uptimeMillis(), true, false); + } + } + }); + mUserController.scheduleStartProfiles(); } } @@ -11049,7 +11080,7 @@ public class ActivityManagerService extends IActivityManager.Stub boolean checkedGrants = false; if (checkUser) { // Looking for cross-user grants before enforcing the typical cross-users permissions - int tmpTargetUserId = mUserController.unsafeConvertIncomingUserLocked(userId); + int tmpTargetUserId = mUserController.unsafeConvertIncomingUser(userId); if (tmpTargetUserId != UserHandle.getUserId(callingUid)) { if (checkAuthorityGrants(callingUid, cpi, tmpTargetUserId, checkUser)) { return null; @@ -11437,7 +11468,7 @@ public class ActivityManagerService extends IActivityManager.Stub // Make sure that the user who owns this provider is running. If not, // we don't want to allow it to run. - if (!mUserController.isUserRunningLocked(userId, 0)) { + if (!mUserController.isUserRunning(userId, 0)) { Slog.w(TAG, "Unable to launch app " + cpi.applicationInfo.packageName + "/" + cpi.applicationInfo.uid + " for provider " @@ -12067,9 +12098,7 @@ public class ActivityManagerService extends IActivityManager.Stub int callingPid = Binder.getCallingPid(); long ident = 0; boolean clearedIdentity = false; - synchronized (this) { - userId = mUserController.unsafeConvertIncomingUserLocked(userId); - } + userId = mUserController.unsafeConvertIncomingUser(userId); if (canClearIdentity(callingPid, callingUid, userId)) { clearedIdentity = true; ident = Binder.clearCallingIdentity(); @@ -12487,7 +12516,7 @@ public class ActivityManagerService extends IActivityManager.Stub if (mUserController.shouldConfirmCredentials(userId)) { if (mKeyguardController.isKeyguardLocked()) { // Showing launcher to avoid user entering credential twice. - final int currentUserId = mUserController.getCurrentUserIdLocked(); + final int currentUserId = mUserController.getCurrentUserId(); startHomeActivityLocked(currentUserId, "notifyLockedProfile"); } mStackSupervisor.lockAllProfileTasks(userId); @@ -14067,9 +14096,8 @@ public class ActivityManagerService extends IActivityManager.Stub } retrieveSettings(); - final int currentUserId; + final int currentUserId = mUserController.getCurrentUserId(); synchronized (this) { - currentUserId = mUserController.getCurrentUserIdLocked(); readGrantedUriPermissionsLocked(); } @@ -14148,7 +14176,7 @@ public class ActivityManagerService extends IActivityManager.Stub Binder.restoreCallingIdentity(ident); } mStackSupervisor.resumeFocusedStackTopActivityLocked(); - mUserController.sendUserSwitchBroadcastsLocked(-1, currentUserId); + mUserController.sendUserSwitchBroadcasts(-1, currentUserId); traceLog.traceEnd(); // ActivityManagerStartApps traceLog.traceEnd(); // PhaseActivityManagerReady } @@ -18976,7 +19004,7 @@ public class ActivityManagerService extends IActivityManager.Stub // If not, we will just skip it. Make an exception for shutdown broadcasts // and upgrade steps. - if (userId != UserHandle.USER_ALL && !mUserController.isUserRunningLocked(userId, 0)) { + if (userId != UserHandle.USER_ALL && !mUserController.isUserRunning(userId, 0)) { if ((callingUid != SYSTEM_UID || (intent.getFlags() & Intent.FLAG_RECEIVER_BOOT_UPGRADE) == 0) && !Intent.ACTION_SHUTDOWN.equals(intent.getAction())) { @@ -19395,7 +19423,7 @@ public class ActivityManagerService extends IActivityManager.Stub int[] users; if (userId == UserHandle.USER_ALL) { // Caller wants broadcast to go to all started users. - users = mUserController.getStartedUserArrayLocked(); + users = mUserController.getStartedUserArray(); } else { // Caller wants broadcast to go to one specific user. users = new int[] {userId}; @@ -20161,7 +20189,7 @@ public class ActivityManagerService extends IActivityManager.Stub void updateUserConfigurationLocked() { final Configuration configuration = new Configuration(getGlobalConfiguration()); - final int currentUserId = mUserController.getCurrentUserIdLocked(); + final int currentUserId = mUserController.getCurrentUserId(); Settings.System.adjustConfigurationForUser(mContext.getContentResolver(), configuration, currentUserId, Settings.System.canWrite(mContext)); updateConfigurationLocked(configuration, null /* starting */, false /* initLocale */, @@ -20272,7 +20300,7 @@ public class ActivityManagerService extends IActivityManager.Stub Slog.i(TAG, "Config changes=" + Integer.toHexString(changes) + " " + mTempConfig); // TODO(multi-display): Update UsageEvents#Event to include displayId. mUsageStatsService.reportConfigurationChange(mTempConfig, - mUserController.getCurrentUserIdLocked()); + mUserController.getCurrentUserId()); // TODO: If our config changes, should we auto dismiss any currently showing dialogs? mShowDialogs = shouldShowDialogs(mTempConfig); @@ -22203,7 +22231,7 @@ public class ActivityManagerService extends IActivityManager.Stub String authority) { if (app == null) return; if (app.curProcState <= ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND) { - UserState userState = mUserController.getStartedUserStateLocked(app.userId); + UserState userState = mUserController.getStartedUserState(app.userId); if (userState == null) return; final long now = SystemClock.elapsedRealtime(); Long lastReported = userState.mProviderLastReportedFg.get(authority); @@ -23512,10 +23540,8 @@ public class ActivityManagerService extends IActivityManager.Stub } String getStartedUserState(int userId) { - synchronized (this) { - final UserState userState = mUserController.getStartedUserStateLocked(userId); - return UserState.stateToString(userState.state); - } + final UserState userState = mUserController.getStartedUserState(userId); + return UserState.stateToString(userState.state); } @Override @@ -23530,9 +23556,7 @@ public class ActivityManagerService extends IActivityManager.Stub Slog.w(TAG, msg); throw new SecurityException(msg); } - synchronized (this) { - return mUserController.isUserRunningLocked(userId, flags); - } + return mUserController.isUserRunning(userId, flags); } @Override @@ -23546,9 +23570,7 @@ public class ActivityManagerService extends IActivityManager.Stub Slog.w(TAG, msg); throw new SecurityException(msg); } - synchronized (this) { - return mUserController.getStartedUserArrayLocked(); - } + return mUserController.getStartedUserArray(); } @Override @@ -23569,9 +23591,7 @@ public class ActivityManagerService extends IActivityManager.Stub } public boolean isUserStopped(int userId) { - synchronized (this) { - return mUserController.getStartedUserStateLocked(userId) == null; - } + return mUserController.getStartedUserState(userId) == null; } ActivityInfo getActivityInfoForUser(ActivityInfo aInfo, int userId) { @@ -24159,7 +24179,7 @@ public class ActivityManagerService extends IActivityManager.Stub permission.INTERACT_ACROSS_USERS_FULL, "getLastResumedActivityUserId()"); synchronized (this) { if (mLastResumedActivity == null) { - return mUserController.getCurrentUserIdLocked(); + return mUserController.getCurrentUserId(); } return mLastResumedActivity.userId; } diff --git a/services/core/java/com/android/server/am/ActivityRecord.java b/services/core/java/com/android/server/am/ActivityRecord.java index 2241ed6ebcad..193443691ee5 100644 --- a/services/core/java/com/android/server/am/ActivityRecord.java +++ b/services/core/java/com/android/server/am/ActivityRecord.java @@ -1948,7 +1948,7 @@ final class ActivityRecord extends ConfigurationContainer implements AppWindowCo return (info.flags & FLAG_SHOW_FOR_ALL_USERS) != 0 || (mStackSupervisor.isCurrentProfileLocked(userId) - && service.mUserController.isUserRunningLocked(userId, 0 /* flags */)); + && service.mUserController.isUserRunning(userId, 0 /* flags */)); } /** diff --git a/services/core/java/com/android/server/am/ActivityStack.java b/services/core/java/com/android/server/am/ActivityStack.java index 361d91a07e59..829669327bf4 100644 --- a/services/core/java/com/android/server/am/ActivityStack.java +++ b/services/core/java/com/android/server/am/ActivityStack.java @@ -467,7 +467,7 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai mHandler = new ActivityStackHandler(mService.mHandler.getLooper()); mWindowManager = mService.mWindowManager; mStackId = stackId; - mCurrentUser = mService.mUserController.getCurrentUserIdLocked(); + mCurrentUser = mService.mUserController.getCurrentUserId(); mTaskPositioner = mStackId == FREEFORM_WORKSPACE_STACK_ID ? new LaunchingTaskPositioner() : null; mTmpRect2.setEmpty(); @@ -2136,7 +2136,14 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai try { // Protect against recursion. mStackSupervisor.inResumeTopActivity = true; - result = resumeTopActivityInnerLocked(prev, options); + // The contained logic must be synchronized, since we are both changing the visibility + // and updating the {@link Configuration}. {@link ActivityRecord#setVisibility} will + // ultimately cause the client code to schedule a layout. Since layouts retrieve the + // current {@link Configuration}, we must ensure that the below code updates it before + // the layout can occur. + synchronized (mWindowManager.getWindowManagerLock()) { + result = resumeTopActivityInnerLocked(prev, options); + } } finally { mStackSupervisor.inResumeTopActivity = false; } @@ -4503,7 +4510,7 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai Slog.i(TAG, "moveTaskToBack: " + tr); // If the task is locked, then show the lock task toast - if (!mService.mLockTaskController.checkLockedTask(tr)) { + if (mService.mLockTaskController.checkLockedTask(tr)) { return false; } diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java index bf0c3a4d261a..f423ce81bd75 100644 --- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java +++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java @@ -3660,7 +3660,7 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D /** Checks whether the userid is a profile of the current user. */ boolean isCurrentProfileLocked(int userId) { if (userId == mCurrentUser) return true; - return mService.mUserController.isCurrentProfileLocked(userId); + return mService.mUserController.isCurrentProfile(userId); } /** diff --git a/services/core/java/com/android/server/am/AppErrors.java b/services/core/java/com/android/server/am/AppErrors.java index 440b3d3baedd..fe380970c33b 100644 --- a/services/core/java/com/android/server/am/AppErrors.java +++ b/services/core/java/com/android/server/am/AppErrors.java @@ -507,7 +507,7 @@ class AppErrors { // launching the report UI under a different user. app.errorReportReceiver = null; - for (int userId : mService.mUserController.getCurrentProfileIdsLocked()) { + for (int userId : mService.mUserController.getCurrentProfileIds()) { if (app.userId == userId) { app.errorReportReceiver = ApplicationErrorReport.getErrorReportReceiver( mContext, app.info.packageName, app.info.flags); @@ -728,7 +728,7 @@ class AppErrors { boolean isBackground = (UserHandle.getAppId(proc.uid) >= Process.FIRST_APPLICATION_UID && proc.pid != MY_PID); - for (int userId : mService.mUserController.getCurrentProfileIdsLocked()) { + for (int userId : mService.mUserController.getCurrentProfileIds()) { isBackground &= (proc.userId != userId); } if (isBackground && !showBackground) { diff --git a/services/core/java/com/android/server/am/PendingIntentRecord.java b/services/core/java/com/android/server/am/PendingIntentRecord.java index ee593866da68..7930f5340205 100644 --- a/services/core/java/com/android/server/am/PendingIntentRecord.java +++ b/services/core/java/com/android/server/am/PendingIntentRecord.java @@ -308,7 +308,7 @@ final class PendingIntentRecord extends IIntentSender.Stub { boolean sendFinish = finishedReceiver != null; int userId = key.userId; if (userId == UserHandle.USER_CURRENT) { - userId = owner.mUserController.getCurrentOrTargetUserIdLocked(); + userId = owner.mUserController.getCurrentOrTargetUserId(); } int res = 0; switch (key.type) { diff --git a/services/core/java/com/android/server/am/UserController.java b/services/core/java/com/android/server/am/UserController.java index f2e294217999..36f6b111d56a 100644 --- a/services/core/java/com/android/server/am/UserController.java +++ b/services/core/java/com/android/server/am/UserController.java @@ -103,6 +103,14 @@ import java.util.concurrent.atomic.AtomicInteger; /** * Helper class for {@link ActivityManagerService} responsible for multi-user functionality. + * + * <p>This class use {@link #mLock} to synchronize access to internal state. Methods that require + * {@link #mLock} to be held should have "LU" suffix in the name. + * + * <p><strong>Important:</strong> Synchronized code, i.e. one executed inside a synchronized(mLock) + * block or inside LU method, should only access internal state of this class or make calls to + * other LU methods. Non-LU method calls or calls to external classes are discouraged as they + * may cause lock inversion. */ class UserController implements Handler.Callback { private static final String TAG = TAG_WITH_CLASS_NAME ? "UserController" : TAG_AM; @@ -136,7 +144,9 @@ class UserController implements Handler.Callback { // when it never calls back. private static final int USER_SWITCH_CALLBACKS_TIMEOUT_MS = 5 * 1000; - private final Object mLock; + // Lock for internal state. + private final Object mLock = new Object(); + private final Injector mInjector; private final Handler mHandler; private final Handler mUiHandler; @@ -175,7 +185,8 @@ class UserController implements Handler.Callback { /** * Mapping from each known user ID to the profile group ID it is associated with. */ - private final SparseIntArray mUserProfileGroupIdsSelfLocked = new SparseIntArray(); + @GuardedBy("mLock") + private final SparseIntArray mUserProfileGroupIds = new SparseIntArray(); /** * Registered observers of the user switching mechanics. @@ -206,7 +217,6 @@ class UserController implements Handler.Callback { @VisibleForTesting UserController(Injector injector) { mInjector = injector; - mLock = injector.getLock(); mHandler = mInjector.getHandler(this); mUiHandler = mInjector.getUiHandler(this); // User 0 is the first and only user that runs at boot. @@ -214,19 +224,18 @@ class UserController implements Handler.Callback { mStartedUsers.put(UserHandle.USER_SYSTEM, uss); mUserLru.add(UserHandle.USER_SYSTEM); mLockPatternUtils = mInjector.getLockPatternUtils(); - updateStartedUserArrayLocked(); + updateStartedUserArrayLU(); } void finishUserSwitch(UserState uss) { + finishUserBoot(uss); + startProfiles(); synchronized (mLock) { - finishUserBoot(uss); - - startProfilesLocked(); - stopRunningUsersLocked(MAX_RUNNING_USERS); + stopRunningUsersLU(MAX_RUNNING_USERS); } } - void stopRunningUsersLocked(int maxRunningUsers) { + void stopRunningUsersLU(int maxRunningUsers) { int num = mUserLru.size(); int i = 0; while (num > maxRunningUsers && i < mUserLru.size()) { @@ -255,7 +264,7 @@ class UserController implements Handler.Callback { continue; } // This is a user to be stopped. - if (stopUsersLocked(oldUserId, false, null) != USER_OP_SUCCESS) { + if (stopUsersLU(oldUserId, false, null) != USER_OP_SUCCESS) { num--; } num--; @@ -273,55 +282,57 @@ class UserController implements Handler.Callback { Slog.d(TAG, "Finishing user boot " + userId); synchronized (mLock) { // Bail if we ended up with a stale user - if (mStartedUsers.get(userId) != uss) return; + if (mStartedUsers.get(userId) != uss) { + return; + } + } - // We always walk through all the user lifecycle states to send - // consistent developer events. We step into RUNNING_LOCKED here, - // but we might immediately step into RUNNING below if the user - // storage is already unlocked. - if (uss.setState(STATE_BOOTING, STATE_RUNNING_LOCKED)) { - mInjector.getUserManagerInternal().setUserState(userId, uss.state); - // Do not report secondary users, runtime restarts or first boot/upgrade - if (userId == UserHandle.USER_SYSTEM - && !mInjector.isRuntimeRestarted() && !mInjector.isFirstBootOrUpgrade()) { - int uptimeSeconds = (int)(SystemClock.elapsedRealtime() / 1000); - MetricsLogger.histogram(mInjector.getContext(), - "framework_locked_boot_completed", uptimeSeconds); - final int MAX_UPTIME_SECONDS = 120; - if (uptimeSeconds > MAX_UPTIME_SECONDS) { - Slog.wtf("SystemServerTiming", - "finishUserBoot took too long. uptimeSeconds=" + uptimeSeconds); - } + // We always walk through all the user lifecycle states to send + // consistent developer events. We step into RUNNING_LOCKED here, + // but we might immediately step into RUNNING below if the user + // storage is already unlocked. + if (uss.setState(STATE_BOOTING, STATE_RUNNING_LOCKED)) { + mInjector.getUserManagerInternal().setUserState(userId, uss.state); + // Do not report secondary users, runtime restarts or first boot/upgrade + if (userId == UserHandle.USER_SYSTEM + && !mInjector.isRuntimeRestarted() && !mInjector.isFirstBootOrUpgrade()) { + int uptimeSeconds = (int)(SystemClock.elapsedRealtime() / 1000); + MetricsLogger.histogram(mInjector.getContext(), + "framework_locked_boot_completed", uptimeSeconds); + final int MAX_UPTIME_SECONDS = 120; + if (uptimeSeconds > MAX_UPTIME_SECONDS) { + Slog.wtf("SystemServerTiming", + "finishUserBoot took too long. uptimeSeconds=" + uptimeSeconds); } + } - mHandler.sendMessage(mHandler.obtainMessage(REPORT_LOCKED_BOOT_COMPLETE_MSG, - userId, 0)); - Intent intent = new Intent(Intent.ACTION_LOCKED_BOOT_COMPLETED, null); - intent.putExtra(Intent.EXTRA_USER_HANDLE, userId); - intent.addFlags(Intent.FLAG_RECEIVER_NO_ABORT - | Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND); - mInjector.broadcastIntentLocked(intent, null, resultTo, 0, null, null, - new String[] { android.Manifest.permission.RECEIVE_BOOT_COMPLETED }, - AppOpsManager.OP_NONE, null, true, false, MY_PID, SYSTEM_UID, userId); - } - - // We need to delay unlocking managed profiles until the parent user - // is also unlocked. - if (mInjector.getUserManager().isManagedProfile(userId)) { - final UserInfo parent = mInjector.getUserManager().getProfileParent(userId); - if (parent != null - && isUserRunningLocked(parent.id, ActivityManager.FLAG_AND_UNLOCKED)) { - Slog.d(TAG, "User " + userId + " (parent " + parent.id - + "): attempting unlock because parent is unlocked"); - maybeUnlockUser(userId); - } else { - String parentId = (parent == null) ? "<null>" : String.valueOf(parent.id); - Slog.d(TAG, "User " + userId + " (parent " + parentId - + "): delaying unlock because parent is locked"); - } - } else { + mHandler.sendMessage(mHandler.obtainMessage(REPORT_LOCKED_BOOT_COMPLETE_MSG, + userId, 0)); + Intent intent = new Intent(Intent.ACTION_LOCKED_BOOT_COMPLETED, null); + intent.putExtra(Intent.EXTRA_USER_HANDLE, userId); + intent.addFlags(Intent.FLAG_RECEIVER_NO_ABORT + | Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND); + mInjector.broadcastIntent(intent, null, resultTo, 0, null, null, + new String[]{android.Manifest.permission.RECEIVE_BOOT_COMPLETED}, + AppOpsManager.OP_NONE, null, true, false, MY_PID, SYSTEM_UID, userId); + } + + // We need to delay unlocking managed profiles until the parent user + // is also unlocked. + if (mInjector.getUserManager().isManagedProfile(userId)) { + final UserInfo parent = mInjector.getUserManager().getProfileParent(userId); + if (parent != null + && isUserRunning(parent.id, ActivityManager.FLAG_AND_UNLOCKED)) { + Slog.d(TAG, "User " + userId + " (parent " + parent.id + + "): attempting unlock because parent is unlocked"); maybeUnlockUser(userId); + } else { + String parentId = (parent == null) ? "<null>" : String.valueOf(parent.id); + Slog.d(TAG, "User " + userId + " (parent " + parentId + + "): delaying unlock because parent is locked"); } + } else { + maybeUnlockUser(userId); } } @@ -331,34 +342,30 @@ class UserController implements Handler.Callback { */ private void finishUserUnlocking(final UserState uss) { final int userId = uss.mHandle.getIdentifier(); - boolean proceedWithUnlock = false; + // Only keep marching forward if user is actually unlocked + if (!StorageManager.isUserKeyUnlocked(userId)) return; synchronized (mLock) { // Bail if we ended up with a stale user if (mStartedUsers.get(uss.mHandle.getIdentifier()) != uss) return; - // Only keep marching forward if user is actually unlocked - if (!StorageManager.isUserKeyUnlocked(userId)) return; - - if (uss.setState(STATE_RUNNING_LOCKED, STATE_RUNNING_UNLOCKING)) { - mInjector.getUserManagerInternal().setUserState(userId, uss.state); - proceedWithUnlock = true; + // Do not proceed if unexpected state + if (!uss.setState(STATE_RUNNING_LOCKED, STATE_RUNNING_UNLOCKING)) { + return; } } + mInjector.getUserManagerInternal().setUserState(userId, uss.state); + uss.mUnlockProgress.start(); - if (proceedWithUnlock) { - uss.mUnlockProgress.start(); - - // Prepare app storage before we go any further - uss.mUnlockProgress.setProgress(5, - mInjector.getContext().getString(R.string.android_start_title)); - mInjector.getUserManager().onBeforeUnlockUser(userId); - uss.mUnlockProgress.setProgress(20); + // Prepare app storage before we go any further + uss.mUnlockProgress.setProgress(5, + mInjector.getContext().getString(R.string.android_start_title)); + mInjector.getUserManager().onBeforeUnlockUser(userId); + uss.mUnlockProgress.setProgress(20); - // Dispatch unlocked to system services; when fully dispatched, - // that calls through to the next "unlocked" phase - mHandler.obtainMessage(SYSTEM_USER_UNLOCK_MSG, userId, 0, uss) - .sendToTarget(); - } + // Dispatch unlocked to system services; when fully dispatched, + // that calls through to the next "unlocked" phase + mHandler.obtainMessage(SYSTEM_USER_UNLOCK_MSG, userId, 0, uss) + .sendToTarget(); } /** @@ -367,63 +374,63 @@ class UserController implements Handler.Callback { */ void finishUserUnlocked(final UserState uss) { final int userId = uss.mHandle.getIdentifier(); + // Only keep marching forward if user is actually unlocked + if (!StorageManager.isUserKeyUnlocked(userId)) return; synchronized (mLock) { // Bail if we ended up with a stale user if (mStartedUsers.get(uss.mHandle.getIdentifier()) != uss) return; - // Only keep marching forward if user is actually unlocked - if (!StorageManager.isUserKeyUnlocked(userId)) return; - - if (uss.setState(STATE_RUNNING_UNLOCKING, STATE_RUNNING_UNLOCKED)) { - mInjector.getUserManagerInternal().setUserState(userId, uss.state); - uss.mUnlockProgress.finish(); - - // Dispatch unlocked to external apps - final Intent unlockedIntent = new Intent(Intent.ACTION_USER_UNLOCKED); - unlockedIntent.putExtra(Intent.EXTRA_USER_HANDLE, userId); - unlockedIntent.addFlags( - Intent.FLAG_RECEIVER_REGISTERED_ONLY | Intent.FLAG_RECEIVER_FOREGROUND); - mInjector.broadcastIntentLocked(unlockedIntent, null, null, 0, null, - null, null, AppOpsManager.OP_NONE, null, false, false, MY_PID, SYSTEM_UID, - userId); - - if (getUserInfo(userId).isManagedProfile()) { - UserInfo parent = mInjector.getUserManager().getProfileParent(userId); - if (parent != null) { - final Intent profileUnlockedIntent = new Intent( - Intent.ACTION_MANAGED_PROFILE_UNLOCKED); - profileUnlockedIntent.putExtra(Intent.EXTRA_USER, UserHandle.of(userId)); - profileUnlockedIntent.addFlags( - Intent.FLAG_RECEIVER_REGISTERED_ONLY + // Do not proceed if unexpected state + if (!uss.setState(STATE_RUNNING_UNLOCKING, STATE_RUNNING_UNLOCKED)) { + return; + } + } + mInjector.getUserManagerInternal().setUserState(userId, uss.state); + uss.mUnlockProgress.finish(); + // Dispatch unlocked to external apps + final Intent unlockedIntent = new Intent(Intent.ACTION_USER_UNLOCKED); + unlockedIntent.putExtra(Intent.EXTRA_USER_HANDLE, userId); + unlockedIntent.addFlags( + Intent.FLAG_RECEIVER_REGISTERED_ONLY | Intent.FLAG_RECEIVER_FOREGROUND); + mInjector.broadcastIntent(unlockedIntent, null, null, 0, null, + null, null, AppOpsManager.OP_NONE, null, false, false, MY_PID, SYSTEM_UID, + userId); + + if (getUserInfo(userId).isManagedProfile()) { + UserInfo parent = mInjector.getUserManager().getProfileParent(userId); + if (parent != null) { + final Intent profileUnlockedIntent = new Intent( + Intent.ACTION_MANAGED_PROFILE_UNLOCKED); + profileUnlockedIntent.putExtra(Intent.EXTRA_USER, UserHandle.of(userId)); + profileUnlockedIntent.addFlags( + Intent.FLAG_RECEIVER_REGISTERED_ONLY | Intent.FLAG_RECEIVER_FOREGROUND); - mInjector.broadcastIntentLocked(profileUnlockedIntent, - null, null, 0, null, null, null, AppOpsManager.OP_NONE, - null, false, false, MY_PID, SYSTEM_UID, - parent.id); - } - } + mInjector.broadcastIntent(profileUnlockedIntent, + null, null, 0, null, null, null, AppOpsManager.OP_NONE, + null, false, false, MY_PID, SYSTEM_UID, + parent.id); + } + } - // Send PRE_BOOT broadcasts if user fingerprint changed; we - // purposefully block sending BOOT_COMPLETED until after all - // PRE_BOOT receivers are finished to avoid ANR'ing apps - final UserInfo info = getUserInfo(userId); - if (!Objects.equals(info.lastLoggedInFingerprint, Build.FINGERPRINT)) { - // Suppress double notifications for managed profiles that - // were unlocked automatically as part of their parent user - // being unlocked. - final boolean quiet; - if (info.isManagedProfile()) { - quiet = !uss.tokenProvided - || !mLockPatternUtils.isSeparateProfileChallengeEnabled(userId); - } else { - quiet = false; - } - mInjector.sendPreBootBroadcast(userId, quiet, - () -> finishUserUnlockedCompleted(uss)); - } else { - finishUserUnlockedCompleted(uss); - } + // Send PRE_BOOT broadcasts if user fingerprint changed; we + // purposefully block sending BOOT_COMPLETED until after all + // PRE_BOOT receivers are finished to avoid ANR'ing apps + final UserInfo info = getUserInfo(userId); + if (!Objects.equals(info.lastLoggedInFingerprint, Build.FINGERPRINT)) { + // Suppress double notifications for managed profiles that + // were unlocked automatically as part of their parent user + // being unlocked. + final boolean quiet; + if (info.isManagedProfile()) { + quiet = !uss.tokenProvided + || !mLockPatternUtils.isSeparateProfileChallengeEnabled(userId); + } else { + quiet = false; } + mInjector.sendPreBootBroadcast(userId, quiet, + () -> finishUserUnlockedCompleted(uss)); + } else { + finishUserUnlockedCompleted(uss); } } @@ -432,60 +439,59 @@ class UserController implements Handler.Callback { synchronized (mLock) { // Bail if we ended up with a stale user if (mStartedUsers.get(uss.mHandle.getIdentifier()) != uss) return; - final UserInfo userInfo = getUserInfo(userId); - if (userInfo == null) { - return; - } + } + UserInfo userInfo = getUserInfo(userId); + if (userInfo == null) { + return; + } + // Only keep marching forward if user is actually unlocked + if (!StorageManager.isUserKeyUnlocked(userId)) return; - // Only keep marching forward if user is actually unlocked - if (!StorageManager.isUserKeyUnlocked(userId)) return; - - // Remember that we logged in - mInjector.getUserManager().onUserLoggedIn(userId); - - if (!userInfo.isInitialized()) { - if (userId != UserHandle.USER_SYSTEM) { - Slog.d(TAG, "Initializing user #" + userId); - Intent intent = new Intent(Intent.ACTION_USER_INITIALIZE); - intent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND - | Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND); - mInjector.broadcastIntentLocked(intent, null, - new IIntentReceiver.Stub() { - @Override - public void performReceive(Intent intent, int resultCode, - String data, Bundle extras, boolean ordered, - boolean sticky, int sendingUser) { - // Note: performReceive is called with mService lock held - mInjector.getUserManager().makeInitialized(userInfo.id); - } - }, 0, null, null, null, AppOpsManager.OP_NONE, - null, true, false, MY_PID, SYSTEM_UID, userId); - } - } + // Remember that we logged in + mInjector.getUserManager().onUserLoggedIn(userId); - Slog.i(TAG, "Sending BOOT_COMPLETE user #" + userId); - // Do not report secondary users, runtime restarts or first boot/upgrade - if (userId == UserHandle.USER_SYSTEM - && !mInjector.isRuntimeRestarted() && !mInjector.isFirstBootOrUpgrade()) { - int uptimeSeconds = (int) (SystemClock.elapsedRealtime() / 1000); - MetricsLogger.histogram(mInjector.getContext(), "framework_boot_completed", - uptimeSeconds); + if (!userInfo.isInitialized()) { + if (userId != UserHandle.USER_SYSTEM) { + Slog.d(TAG, "Initializing user #" + userId); + Intent intent = new Intent(Intent.ACTION_USER_INITIALIZE); + intent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND + | Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND); + mInjector.broadcastIntent(intent, null, + new IIntentReceiver.Stub() { + @Override + public void performReceive(Intent intent, int resultCode, + String data, Bundle extras, boolean ordered, + boolean sticky, int sendingUser) { + // Note: performReceive is called with mService lock held + mInjector.getUserManager().makeInitialized(userInfo.id); + } + }, 0, null, null, null, AppOpsManager.OP_NONE, + null, true, false, MY_PID, SYSTEM_UID, userId); } - final Intent bootIntent = new Intent(Intent.ACTION_BOOT_COMPLETED, null); - bootIntent.putExtra(Intent.EXTRA_USER_HANDLE, userId); - bootIntent.addFlags(Intent.FLAG_RECEIVER_NO_ABORT - | Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND); - mInjector.broadcastIntentLocked(bootIntent, null, new IIntentReceiver.Stub() { - @Override - public void performReceive(Intent intent, int resultCode, String data, - Bundle extras, boolean ordered, boolean sticky, int sendingUser) - throws RemoteException { - Slog.i(UserController.TAG, "Finished processing BOOT_COMPLETED for u" + userId); - } - }, 0, null, null, - new String[] { android.Manifest.permission.RECEIVE_BOOT_COMPLETED }, - AppOpsManager.OP_NONE, null, true, false, MY_PID, SYSTEM_UID, userId); } + + Slog.i(TAG, "Sending BOOT_COMPLETE user #" + userId); + // Do not report secondary users, runtime restarts or first boot/upgrade + if (userId == UserHandle.USER_SYSTEM + && !mInjector.isRuntimeRestarted() && !mInjector.isFirstBootOrUpgrade()) { + int uptimeSeconds = (int) (SystemClock.elapsedRealtime() / 1000); + MetricsLogger.histogram(mInjector.getContext(), "framework_boot_completed", + uptimeSeconds); + } + final Intent bootIntent = new Intent(Intent.ACTION_BOOT_COMPLETED, null); + bootIntent.putExtra(Intent.EXTRA_USER_HANDLE, userId); + bootIntent.addFlags(Intent.FLAG_RECEIVER_NO_ABORT + | Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND); + mInjector.broadcastIntent(bootIntent, null, new IIntentReceiver.Stub() { + @Override + public void performReceive(Intent intent, int resultCode, String data, + Bundle extras, boolean ordered, boolean sticky, int sendingUser) + throws RemoteException { + Slog.i(UserController.TAG, "Finished processing BOOT_COMPLETED for u" + userId); + } + }, 0, null, null, + new String[]{android.Manifest.permission.RECEIVE_BOOT_COMPLETED}, + AppOpsManager.OP_NONE, null, true, false, MY_PID, SYSTEM_UID, userId); } int restartUser(final int userId, final boolean foreground) { @@ -516,33 +522,33 @@ class UserController implements Handler.Callback { } enforceShellRestriction(UserManager.DISALLOW_DEBUGGING_FEATURES, userId); synchronized (mLock) { - return stopUsersLocked(userId, force, callback); + return stopUsersLU(userId, force, callback); } } /** * Stops the user along with its related users. The method calls - * {@link #getUsersToStopLocked(int)} to determine the list of users that should be stopped. + * {@link #getUsersToStopLU(int)} to determine the list of users that should be stopped. */ - private int stopUsersLocked(final int userId, boolean force, final IStopUserCallback callback) { + private int stopUsersLU(final int userId, boolean force, final IStopUserCallback callback) { if (userId == UserHandle.USER_SYSTEM) { return USER_OP_ERROR_IS_SYSTEM; } - if (isCurrentUserLocked(userId)) { + if (isCurrentUserLU(userId)) { return USER_OP_IS_CURRENT; } - int[] usersToStop = getUsersToStopLocked(userId); + int[] usersToStop = getUsersToStopLU(userId); // If one of related users is system or current, no related users should be stopped for (int i = 0; i < usersToStop.length; i++) { int relatedUserId = usersToStop[i]; - if ((UserHandle.USER_SYSTEM == relatedUserId) || isCurrentUserLocked(relatedUserId)) { + if ((UserHandle.USER_SYSTEM == relatedUserId) || isCurrentUserLU(relatedUserId)) { if (DEBUG_MU) Slog.i(TAG, "stopUsersLocked cannot stop related user " + relatedUserId); // We still need to stop the requested user if it's a force stop. if (force) { Slog.i(TAG, "Force stop user " + userId + ". Related users will not be stopped"); - stopSingleUserLocked(userId, callback); + stopSingleUserLU(userId, callback); return USER_OP_SUCCESS; } return USER_OP_ERROR_RELATED_USERS_CANNOT_STOP; @@ -550,25 +556,22 @@ class UserController implements Handler.Callback { } if (DEBUG_MU) Slog.i(TAG, "stopUsersLocked usersToStop=" + Arrays.toString(usersToStop)); for (int userIdToStop : usersToStop) { - stopSingleUserLocked(userIdToStop, userIdToStop == userId ? callback : null); + stopSingleUserLU(userIdToStop, userIdToStop == userId ? callback : null); } return USER_OP_SUCCESS; } - private void stopSingleUserLocked(final int userId, final IStopUserCallback callback) { + private void stopSingleUserLU(final int userId, final IStopUserCallback callback) { if (DEBUG_MU) Slog.i(TAG, "stopSingleUserLocked userId=" + userId); final UserState uss = mStartedUsers.get(userId); if (uss == null) { // User is not started, nothing to do... but we do need to // callback if requested. if (callback != null) { - mHandler.post(new Runnable() { - @Override - public void run() { - try { - callback.userStopped(userId); - } catch (RemoteException e) { - } + mHandler.post(() -> { + try { + callback.userStopped(userId); + } catch (RemoteException e) { } }); } @@ -583,10 +586,10 @@ class UserController implements Handler.Callback { && uss.state != UserState.STATE_SHUTDOWN) { uss.setState(UserState.STATE_STOPPING); mInjector.getUserManagerInternal().setUserState(userId, uss.state); - updateStartedUserArrayLocked(); + updateStartedUserArrayLU(); - long ident = Binder.clearCallingIdentity(); - try { + // Post to handler to obtain amLock + mHandler.post(() -> { // We are going to broadcast ACTION_USER_STOPPING and then // once that is done send a final ACTION_SHUTDOWN and then // stop the user. @@ -599,24 +602,18 @@ class UserController implements Handler.Callback { @Override public void performReceive(Intent intent, int resultCode, String data, Bundle extras, boolean ordered, boolean sticky, int sendingUser) { - mHandler.post(new Runnable() { - @Override - public void run() { - finishUserStopping(userId, uss); - } - }); + mHandler.post(() -> finishUserStopping(userId, uss)); } }; + // Clear broadcast queue for the user to avoid delivering stale broadcasts - mInjector.clearBroadcastQueueForUserLocked(userId); + mInjector.clearBroadcastQueueForUser(userId); // Kick things off. - mInjector.broadcastIntentLocked(stoppingIntent, + mInjector.broadcastIntent(stoppingIntent, null, stoppingReceiver, 0, null, null, new String[]{INTERACT_ACROSS_USERS}, AppOpsManager.OP_NONE, null, true, false, MY_PID, SYSTEM_UID, UserHandle.USER_ALL); - } finally { - Binder.restoreCallingIdentity(ident); - } + }); } } @@ -652,18 +649,17 @@ class UserController implements Handler.Callback { Integer.toString(userId), userId); mInjector.getSystemServiceManager().stopUser(userId); - synchronized (mLock) { - mInjector.broadcastIntentLocked(shutdownIntent, - null, shutdownReceiver, 0, null, null, null, - AppOpsManager.OP_NONE, - null, true, false, MY_PID, SYSTEM_UID, userId); - } + mInjector.broadcastIntent(shutdownIntent, + null, shutdownReceiver, 0, null, null, null, + AppOpsManager.OP_NONE, + null, true, false, MY_PID, SYSTEM_UID, userId); } void finishUserStopped(UserState uss) { final int userId = uss.mHandle.getIdentifier(); boolean stopped; ArrayList<IStopUserCallback> callbacks; + boolean forceStopUser = false; synchronized (mLock) { callbacks = new ArrayList<>(uss.mStopCallbacks); if (mStartedUsers.get(userId) != uss) { @@ -674,16 +670,18 @@ class UserController implements Handler.Callback { stopped = true; // User can no longer run. mStartedUsers.remove(userId); - mInjector.getUserManagerInternal().removeUserState(userId); mUserLru.remove(Integer.valueOf(userId)); - updateStartedUserArrayLocked(); - - mInjector.activityManagerOnUserStopped(userId); - // Clean up all state and processes associated with the user. - // Kill all the processes for the user. - forceStopUserLocked(userId, "finish user"); + updateStartedUserArrayLU(); + forceStopUser = true; } } + if (forceStopUser) { + mInjector.getUserManagerInternal().removeUserState(userId); + mInjector.activityManagerOnUserStopped(userId); + // Clean up all state and processes associated with the user. + // Kill all the processes for the user. + forceStopUser(userId, "finish user"); + } for (int i = 0; i < callbacks.size(); i++) { try { @@ -695,9 +693,7 @@ class UserController implements Handler.Callback { if (stopped) { mInjector.systemServiceManagerCleanupUser(userId); - synchronized (mLock) { - mInjector.getActivityStackSupervisor().removeUserLocked(userId); - } + mInjector.stackSupervisorRemoveUser(userId); // Remove the user if it is ephemeral. if (getUserInfo(userId).isEphemeral()) { mInjector.getUserManager().removeUser(userId); @@ -715,39 +711,36 @@ class UserController implements Handler.Callback { * Determines the list of users that should be stopped together with the specified * {@code userId}. The returned list includes {@code userId}. */ - private @NonNull int[] getUsersToStopLocked(int userId) { + private @NonNull int[] getUsersToStopLU(int userId) { int startedUsersSize = mStartedUsers.size(); IntArray userIds = new IntArray(); userIds.add(userId); - synchronized (mUserProfileGroupIdsSelfLocked) { - int userGroupId = mUserProfileGroupIdsSelfLocked.get(userId, + int userGroupId = mUserProfileGroupIds.get(userId, UserInfo.NO_PROFILE_GROUP_ID); + for (int i = 0; i < startedUsersSize; i++) { + UserState uss = mStartedUsers.valueAt(i); + int startedUserId = uss.mHandle.getIdentifier(); + // Skip unrelated users (profileGroupId mismatch) + int startedUserGroupId = mUserProfileGroupIds.get(startedUserId, UserInfo.NO_PROFILE_GROUP_ID); - for (int i = 0; i < startedUsersSize; i++) { - UserState uss = mStartedUsers.valueAt(i); - int startedUserId = uss.mHandle.getIdentifier(); - // Skip unrelated users (profileGroupId mismatch) - int startedUserGroupId = mUserProfileGroupIdsSelfLocked.get(startedUserId, - UserInfo.NO_PROFILE_GROUP_ID); - boolean sameGroup = (userGroupId != UserInfo.NO_PROFILE_GROUP_ID) - && (userGroupId == startedUserGroupId); - // userId has already been added - boolean sameUserId = startedUserId == userId; - if (!sameGroup || sameUserId) { - continue; - } - userIds.add(startedUserId); + boolean sameGroup = (userGroupId != UserInfo.NO_PROFILE_GROUP_ID) + && (userGroupId == startedUserGroupId); + // userId has already been added + boolean sameUserId = startedUserId == userId; + if (!sameGroup || sameUserId) { + continue; } + userIds.add(startedUserId); } return userIds.toArray(); } - private void forceStopUserLocked(int userId, String reason) { - mInjector.activityManagerForceStopPackageLocked(userId, reason); + private void forceStopUser(int userId, String reason) { + mInjector.activityManagerForceStopPackage(userId, reason); Intent intent = new Intent(Intent.ACTION_USER_STOPPED); intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY | Intent.FLAG_RECEIVER_FOREGROUND); intent.putExtra(Intent.EXTRA_USER_HANDLE, userId); - mInjector.broadcastIntentLocked(intent, + mInjector.broadcastIntent(intent, null, null, 0, null, null, null, AppOpsManager.OP_NONE, null, false, false, MY_PID, SYSTEM_UID, UserHandle.USER_ALL); } @@ -756,6 +749,7 @@ class UserController implements Handler.Callback { * Stops the guest or ephemeral user if it has gone to the background. */ private void stopGuestOrEphemeralUserIfBackground() { + IntArray userIds = new IntArray(); synchronized (mLock) { final int num = mUserLru.size(); for (int i = 0; i < num; i++) { @@ -766,35 +760,42 @@ class UserController implements Handler.Callback { || oldUss.state == UserState.STATE_SHUTDOWN) { continue; } - UserInfo userInfo = getUserInfo(oldUserId); - if (userInfo.isEphemeral()) { - LocalServices.getService(UserManagerInternal.class) - .onEphemeralUserStop(oldUserId); - } - if (userInfo.isGuest() || userInfo.isEphemeral()) { - // This is a user to be stopped. - stopUsersLocked(oldUserId, true, null); - break; + userIds.add(oldUserId); + } + } + final int userIdsSize = userIds.size(); + for (int i = 0; i < userIdsSize; i++) { + int oldUserId = userIds.get(i); + UserInfo userInfo = getUserInfo(oldUserId); + if (userInfo.isEphemeral()) { + LocalServices.getService(UserManagerInternal.class).onEphemeralUserStop(oldUserId); + } + if (userInfo.isGuest() || userInfo.isEphemeral()) { + // This is a user to be stopped. + synchronized (mLock) { + stopUsersLU(oldUserId, true, null); } + break; } } } - void scheduleStartProfilesLocked() { + void scheduleStartProfiles() { if (!mHandler.hasMessages(START_PROFILES_MSG)) { mHandler.sendMessageDelayed(mHandler.obtainMessage(START_PROFILES_MSG), DateUtils.SECOND_IN_MILLIS); } } - void startProfilesLocked() { + void startProfiles() { + int currentUserId = getCurrentUserId(); if (DEBUG_MU) Slog.i(TAG, "startProfilesLocked"); List<UserInfo> profiles = mInjector.getUserManager().getProfiles( - mCurrentUserId, false /* enabledOnly */); + currentUserId, false /* enabledOnly */); List<UserInfo> profilesToStart = new ArrayList<>(profiles.size()); for (UserInfo user : profiles) { if ((user.flags & UserInfo.FLAG_INITIALIZED) == UserInfo.FLAG_INITIALIZED - && user.id != mCurrentUserId && !user.isQuietModeEnabled()) { + && user.id != currentUserId && !user.isQuietModeEnabled()) { profilesToStart.add(user); } } @@ -856,143 +857,156 @@ class UserController implements Handler.Callback { final long ident = Binder.clearCallingIdentity(); try { - synchronized (mLock) { - final int oldUserId = mCurrentUserId; - if (oldUserId == userId) { - return true; - } + final int oldUserId = getCurrentUserId(); + if (oldUserId == userId) { + return true; + } - if (foreground) { - // TODO: I don't think this does what the caller think it does. Seems to only - // remove one locked task and won't work if multiple locked tasks are present. - mInjector.getLockTaskController().clearLockTaskMode("startUser"); - } + if (foreground) { + // TODO: I don't think this does what the caller think it does. Seems to only + // remove one locked task and won't work if multiple locked tasks are present. + mInjector.clearLockTaskMode("startUser"); + } - final UserInfo userInfo = getUserInfo(userId); - if (userInfo == null) { - Slog.w(TAG, "No user info for user #" + userId); - return false; - } - if (foreground && userInfo.isManagedProfile()) { - Slog.w(TAG, "Cannot switch to User #" + userId + ": not a full user"); - return false; - } + final UserInfo userInfo = getUserInfo(userId); + if (userInfo == null) { + Slog.w(TAG, "No user info for user #" + userId); + return false; + } + if (foreground && userInfo.isManagedProfile()) { + Slog.w(TAG, "Cannot switch to User #" + userId + ": not a full user"); + return false; + } - if (foreground && mUserSwitchUiEnabled) { - mInjector.getWindowManager().startFreezingScreen( - R.anim.screen_user_exit, R.anim.screen_user_enter); - } + if (foreground && mUserSwitchUiEnabled) { + mInjector.getWindowManager().startFreezingScreen( + R.anim.screen_user_exit, R.anim.screen_user_enter); + } - boolean needStart = false; + boolean needStart = false; + boolean updateUmState = false; + UserState uss; - // If the user we are switching to is not currently started, then - // we need to start it now. - if (mStartedUsers.get(userId) == null) { - UserState userState = new UserState(UserHandle.of(userId)); - mStartedUsers.put(userId, userState); - mInjector.getUserManagerInternal().setUserState(userId, userState.state); - updateStartedUserArrayLocked(); + // If the user we are switching to is not currently started, then + // we need to start it now. + synchronized (mLock) { + uss = mStartedUsers.get(userId); + if (uss == null) { + uss = new UserState(UserHandle.of(userId)); + mStartedUsers.put(userId, uss); + updateStartedUserArrayLU(); needStart = true; + updateUmState = true; } - - final UserState uss = mStartedUsers.get(userId); final Integer userIdInt = userId; mUserLru.remove(userIdInt); mUserLru.add(userIdInt); - - if (foreground) { + } + if (updateUmState) { + mInjector.getUserManagerInternal().setUserState(userId, uss.state); + } + if (foreground) { + synchronized (mLock) { mCurrentUserId = userId; - mInjector.updateUserConfigurationLocked(); mTargetUserId = UserHandle.USER_NULL; // reset, mCurrentUserId has caught up - updateCurrentProfileIdsLocked(); - mInjector.getWindowManager().setCurrentUser(userId, mCurrentProfileIds); - // Once the internal notion of the active user has switched, we lock the device - // with the option to show the user switcher on the keyguard. - if (mUserSwitchUiEnabled) { - mInjector.getWindowManager().setSwitchingUser(true); - mInjector.getWindowManager().lockNow(null); - } - } else { - final Integer currentUserIdInt = mCurrentUserId; - updateCurrentProfileIdsLocked(); - mInjector.getWindowManager().setCurrentProfileIds(mCurrentProfileIds); + } + mInjector.updateUserConfiguration(); + updateCurrentProfileIds(); + mInjector.getWindowManager().setCurrentUser(userId, getCurrentProfileIds()); + // Once the internal notion of the active user has switched, we lock the device + // with the option to show the user switcher on the keyguard. + if (mUserSwitchUiEnabled) { + mInjector.getWindowManager().setSwitchingUser(true); + mInjector.getWindowManager().lockNow(null); + } + } else { + final Integer currentUserIdInt = mCurrentUserId; + updateCurrentProfileIds(); + mInjector.getWindowManager().setCurrentProfileIds(getCurrentProfileIds()); + synchronized (mLock) { mUserLru.remove(currentUserIdInt); mUserLru.add(currentUserIdInt); } + } - // Make sure user is in the started state. If it is currently - // stopping, we need to knock that off. - if (uss.state == UserState.STATE_STOPPING) { - // If we are stopping, we haven't sent ACTION_SHUTDOWN, - // so we can just fairly silently bring the user back from - // the almost-dead. - uss.setState(uss.lastState); - mInjector.getUserManagerInternal().setUserState(userId, uss.state); - updateStartedUserArrayLocked(); - needStart = true; - } else if (uss.state == UserState.STATE_SHUTDOWN) { - // This means ACTION_SHUTDOWN has been sent, so we will - // need to treat this as a new boot of the user. - uss.setState(UserState.STATE_BOOTING); - mInjector.getUserManagerInternal().setUserState(userId, uss.state); - updateStartedUserArrayLocked(); - needStart = true; + // Make sure user is in the started state. If it is currently + // stopping, we need to knock that off. + if (uss.state == UserState.STATE_STOPPING) { + // If we are stopping, we haven't sent ACTION_SHUTDOWN, + // so we can just fairly silently bring the user back from + // the almost-dead. + uss.setState(uss.lastState); + mInjector.getUserManagerInternal().setUserState(userId, uss.state); + synchronized (mLock) { + updateStartedUserArrayLU(); + } + needStart = true; + } else if (uss.state == UserState.STATE_SHUTDOWN) { + // This means ACTION_SHUTDOWN has been sent, so we will + // need to treat this as a new boot of the user. + uss.setState(UserState.STATE_BOOTING); + mInjector.getUserManagerInternal().setUserState(userId, uss.state); + synchronized (mLock) { + updateStartedUserArrayLU(); } + needStart = true; + } - if (uss.state == UserState.STATE_BOOTING) { - // Give user manager a chance to propagate user restrictions - // to other services and prepare app storage - mInjector.getUserManager().onBeforeStartUser(userId); + if (uss.state == UserState.STATE_BOOTING) { + // Give user manager a chance to propagate user restrictions + // to other services and prepare app storage + mInjector.getUserManager().onBeforeStartUser(userId); - // Booting up a new user, need to tell system services about it. - // Note that this is on the same handler as scheduling of broadcasts, - // which is important because it needs to go first. - mHandler.sendMessage(mHandler.obtainMessage(SYSTEM_USER_START_MSG, userId, 0)); - } + // Booting up a new user, need to tell system services about it. + // Note that this is on the same handler as scheduling of broadcasts, + // which is important because it needs to go first. + mHandler.sendMessage( + mHandler.obtainMessage(SYSTEM_USER_START_MSG, userId, 0)); + } - if (foreground) { - mHandler.sendMessage(mHandler.obtainMessage(SYSTEM_USER_CURRENT_MSG, userId, - oldUserId)); - mHandler.removeMessages(REPORT_USER_SWITCH_MSG); - mHandler.removeMessages(USER_SWITCH_TIMEOUT_MSG); - mHandler.sendMessage(mHandler.obtainMessage(REPORT_USER_SWITCH_MSG, - oldUserId, userId, uss)); - mHandler.sendMessageDelayed(mHandler.obtainMessage(USER_SWITCH_TIMEOUT_MSG, - oldUserId, userId, uss), USER_SWITCH_TIMEOUT_MS); - } + if (foreground) { + mHandler.sendMessage(mHandler.obtainMessage(SYSTEM_USER_CURRENT_MSG, userId, + oldUserId)); + mHandler.removeMessages(REPORT_USER_SWITCH_MSG); + mHandler.removeMessages(USER_SWITCH_TIMEOUT_MSG); + mHandler.sendMessage(mHandler.obtainMessage(REPORT_USER_SWITCH_MSG, + oldUserId, userId, uss)); + mHandler.sendMessageDelayed(mHandler.obtainMessage(USER_SWITCH_TIMEOUT_MSG, + oldUserId, userId, uss), USER_SWITCH_TIMEOUT_MS); + } - if (needStart) { - // Send USER_STARTED broadcast - Intent intent = new Intent(Intent.ACTION_USER_STARTED); - intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY - | Intent.FLAG_RECEIVER_FOREGROUND); - intent.putExtra(Intent.EXTRA_USER_HANDLE, userId); - mInjector.broadcastIntentLocked(intent, - null, null, 0, null, null, null, AppOpsManager.OP_NONE, - null, false, false, MY_PID, SYSTEM_UID, userId); - } + if (needStart) { + // Send USER_STARTED broadcast + Intent intent = new Intent(Intent.ACTION_USER_STARTED); + intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY + | Intent.FLAG_RECEIVER_FOREGROUND); + intent.putExtra(Intent.EXTRA_USER_HANDLE, userId); + mInjector.broadcastIntent(intent, + null, null, 0, null, null, null, AppOpsManager.OP_NONE, + null, false, false, MY_PID, SYSTEM_UID, userId); + } - if (foreground) { - moveUserToForegroundLocked(uss, oldUserId, userId); - } else { - finishUserBoot(uss); - } + if (foreground) { + moveUserToForeground(uss, oldUserId, userId); + } else { + finishUserBoot(uss); + } - if (needStart) { - Intent intent = new Intent(Intent.ACTION_USER_STARTING); - intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY); - intent.putExtra(Intent.EXTRA_USER_HANDLE, userId); - mInjector.broadcastIntentLocked(intent, - null, new IIntentReceiver.Stub() { - @Override - public void performReceive(Intent intent, int resultCode, - String data, Bundle extras, boolean ordered, boolean sticky, - int sendingUser) throws RemoteException { - } - }, 0, null, null, - new String[] {INTERACT_ACROSS_USERS}, AppOpsManager.OP_NONE, - null, true, false, MY_PID, SYSTEM_UID, UserHandle.USER_ALL); - } + if (needStart) { + Intent intent = new Intent(Intent.ACTION_USER_STARTING); + intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY); + intent.putExtra(Intent.EXTRA_USER_HANDLE, userId); + mInjector.broadcastIntent(intent, + null, new IIntentReceiver.Stub() { + @Override + public void performReceive(Intent intent, int resultCode, + String data, Bundle extras, boolean ordered, + boolean sticky, + int sendingUser) throws RemoteException { + } + }, 0, null, null, + new String[]{INTERACT_ACROSS_USERS}, AppOpsManager.OP_NONE, + null, true, false, MY_PID, SYSTEM_UID, UserHandle.USER_ALL); } } finally { Binder.restoreCallingIdentity(ident); @@ -1036,7 +1050,7 @@ class UserController implements Handler.Callback { * when the the credential-encrypted storage isn't tied to a user-provided * PIN or pattern. */ - boolean maybeUnlockUser(final int userId) { + private boolean maybeUnlockUser(final int userId) { // Try unlocking storage using empty token return unlockUserCleared(userId, null, null, null); } @@ -1049,54 +1063,53 @@ class UserController implements Handler.Callback { } } - boolean unlockUserCleared(final int userId, byte[] token, byte[] secret, + private boolean unlockUserCleared(final int userId, byte[] token, byte[] secret, IProgressListener listener) { UserState uss; - synchronized (mLock) { - // TODO Move this block outside of synchronized if it causes lock contention - if (!StorageManager.isUserKeyUnlocked(userId)) { - final UserInfo userInfo = getUserInfo(userId); - final IStorageManager storageManager = getStorageManager(); - try { - // We always want to unlock user storage, even user is not started yet - storageManager.unlockUserKey(userId, userInfo.serialNumber, token, secret); - } catch (RemoteException | RuntimeException e) { - Slog.w(TAG, "Failed to unlock: " + e.getMessage()); - } + if (!StorageManager.isUserKeyUnlocked(userId)) { + final UserInfo userInfo = getUserInfo(userId); + final IStorageManager storageManager = getStorageManager(); + try { + // We always want to unlock user storage, even user is not started yet + storageManager.unlockUserKey(userId, userInfo.serialNumber, token, secret); + } catch (RemoteException | RuntimeException e) { + Slog.w(TAG, "Failed to unlock: " + e.getMessage()); } - // Bail if user isn't actually running, otherwise register the given - // listener to watch for unlock progress + } + synchronized (mLock) { + // Register the given listener to watch for unlock progress uss = mStartedUsers.get(userId); - if (uss == null) { - notifyFinished(userId, listener); - return false; - } else { + if (uss != null) { uss.mUnlockProgress.addListener(listener); uss.tokenProvided = (token != null); } } + // Bail if user isn't actually running + if (uss == null) { + notifyFinished(userId, listener); + return false; + } finishUserUnlocking(uss); - final ArraySet<Integer> childProfilesToUnlock = new ArraySet<>(); - synchronized (mLock) { + // We just unlocked a user, so let's now attempt to unlock any + // managed profiles under that user. - // We just unlocked a user, so let's now attempt to unlock any - // managed profiles under that user. - for (int i = 0; i < mStartedUsers.size(); i++) { - final int testUserId = mStartedUsers.keyAt(i); - final UserInfo parent = mInjector.getUserManager().getProfileParent(testUserId); - if (parent != null && parent.id == userId && testUserId != userId) { - Slog.d(TAG, "User " + testUserId + " (parent " + parent.id - + "): attempting unlock because parent was just unlocked"); - childProfilesToUnlock.add(testUserId); - } + // First, get list of userIds. Requires mLock, so we cannot make external calls, e.g. to UMS + int[] userIds; + synchronized (mLock) { + userIds = new int[mStartedUsers.size()]; + for (int i = 0; i < userIds.length; i++) { + userIds[i] = mStartedUsers.keyAt(i); } } - - final int size = childProfilesToUnlock.size(); - for (int i = 0; i < size; i++) { - maybeUnlockUser(childProfilesToUnlock.valueAt(i)); + for (int testUserId : userIds) { + final UserInfo parent = mInjector.getUserManager().getProfileParent(testUserId); + if (parent != null && parent.id == userId && testUserId != userId) { + Slog.d(TAG, "User " + testUserId + " (parent " + parent.id + + "): attempting unlock because parent was just unlocked"); + maybeUnlockUser(testUserId); + } } return true; @@ -1104,33 +1117,31 @@ class UserController implements Handler.Callback { boolean switchUser(final int targetUserId) { enforceShellRestriction(UserManager.DISALLOW_DEBUGGING_FEATURES, targetUserId); - int currentUserId; - UserInfo targetUserInfo; + int currentUserId = getCurrentUserId(); + UserInfo targetUserInfo = getUserInfo(targetUserId); + if (targetUserId == currentUserId) { + Slog.i(TAG, "user #" + targetUserId + " is already the current user"); + return true; + } + if (targetUserInfo == null) { + Slog.w(TAG, "No user info for user #" + targetUserId); + return false; + } + if (!targetUserInfo.isDemo() && UserManager.isDeviceInDemoMode(mInjector.getContext())) { + Slog.w(TAG, "Cannot switch to non-demo user #" + targetUserId + + " when device is in demo mode"); + return false; + } + if (!targetUserInfo.supportsSwitchTo()) { + Slog.w(TAG, "Cannot switch to User #" + targetUserId + ": not supported"); + return false; + } + if (targetUserInfo.isManagedProfile()) { + Slog.w(TAG, "Cannot switch to User #" + targetUserId + ": not a full user"); + return false; + } synchronized (mLock) { - currentUserId = getCurrentUserIdLocked(); - targetUserInfo = getUserInfo(targetUserId); - if (targetUserId == currentUserId) { - Slog.i(TAG, "user #" + targetUserId + " is already the current user"); - return true; - } - if (targetUserInfo == null) { - Slog.w(TAG, "No user info for user #" + targetUserId); - return false; - } - if (!targetUserInfo.isDemo() && UserManager.isDeviceInDemoMode(mInjector.getContext())) { - Slog.w(TAG, "Cannot switch to non-demo user #" + targetUserId - + " when device is in demo mode"); - return false; - } - if (!targetUserInfo.supportsSwitchTo()) { - Slog.w(TAG, "Cannot switch to User #" + targetUserId + ": not supported"); - return false; - } - if (targetUserInfo.isManagedProfile()) { - Slog.w(TAG, "Cannot switch to User #" + targetUserId + ": not a full user"); - return false; - } - setTargetUserIdLocked(targetUserId); + mTargetUserId = targetUserId; } if (mUserSwitchUiEnabled) { UserInfo currentUserInfo = getUserInfo(currentUserId); @@ -1146,12 +1157,12 @@ class UserController implements Handler.Callback { return true; } - void showUserSwitchDialog(Pair<UserInfo, UserInfo> fromToUserPair) { + private void showUserSwitchDialog(Pair<UserInfo, UserInfo> fromToUserPair) { // The dialog will show and then initiate the user switch by calling startUserInForeground mInjector.showUserSwitchingDialog(fromToUserPair.first, fromToUserPair.second); } - void dispatchForegroundProfileChanged(int userId) { + private void dispatchForegroundProfileChanged(int userId) { final int observerCount = mUserSwitchObservers.beginBroadcast(); for (int i = 0; i < observerCount; i++) { try { @@ -1176,7 +1187,7 @@ class UserController implements Handler.Callback { mUserSwitchObservers.finishBroadcast(); } - void dispatchLockedBootComplete(int userId) { + private void dispatchLockedBootComplete(int userId) { final int observerCount = mUserSwitchObservers.beginBroadcast(); for (int i = 0; i < observerCount; i++) { try { @@ -1202,23 +1213,23 @@ class UserController implements Handler.Callback { synchronized (mLock) { if (DEBUG_MU) Slog.i(TAG, "stopBackgroundUsersIfEnforced stopping " + oldUserId + " and related users"); - stopUsersLocked(oldUserId, false, null); + stopUsersLU(oldUserId, false, null); } } - void timeoutUserSwitch(UserState uss, int oldUserId, int newUserId) { + private void timeoutUserSwitch(UserState uss, int oldUserId, int newUserId) { synchronized (mLock) { Slog.e(TAG, "User switch timeout: from " + oldUserId + " to " + newUserId); mTimeoutUserSwitchCallbacks = mCurWaitingUserSwitchCallbacks; mHandler.removeMessages(USER_SWITCH_CALLBACKS_TIMEOUT_MSG); - sendContinueUserSwitchLocked(uss, oldUserId, newUserId); + sendContinueUserSwitchLU(uss, oldUserId, newUserId); // Report observers that never called back (USER_SWITCH_CALLBACKS_TIMEOUT) mHandler.sendMessageDelayed(mHandler.obtainMessage(USER_SWITCH_CALLBACKS_TIMEOUT_MSG, oldUserId, newUserId), USER_SWITCH_CALLBACKS_TIMEOUT_MS); } } - void timeoutUserSwitchCallbacks(int oldUserId, int newUserId) { + private void timeoutUserSwitchCallbacks(int oldUserId, int newUserId) { synchronized (mLock) { if (mTimeoutUserSwitchCallbacks != null && !mTimeoutUserSwitchCallbacks.isEmpty()) { Slog.wtf(TAG, "User switch timeout: from " + oldUserId + " to " + newUserId @@ -1261,7 +1272,7 @@ class UserController implements Handler.Callback { if (waitingCallbacksCount.decrementAndGet() == 0 && (curWaitingUserSwitchCallbacks == mCurWaitingUserSwitchCallbacks)) { - sendContinueUserSwitchLocked(uss, oldUserId, newUserId); + sendContinueUserSwitchLU(uss, oldUserId, newUserId); } } } @@ -1272,13 +1283,13 @@ class UserController implements Handler.Callback { } } else { synchronized (mLock) { - sendContinueUserSwitchLocked(uss, oldUserId, newUserId); + sendContinueUserSwitchLU(uss, oldUserId, newUserId); } } mUserSwitchObservers.finishBroadcast(); } - void sendContinueUserSwitchLocked(UserState uss, int oldUserId, int newUserId) { + void sendContinueUserSwitchLU(UserState uss, int oldUserId, int newUserId) { mCurWaitingUserSwitchCallbacks = null; mHandler.removeMessages(USER_SWITCH_TIMEOUT_MSG); mHandler.sendMessage(mHandler.obtainMessage(CONTINUE_USER_SWITCH_MSG, @@ -1288,9 +1299,7 @@ class UserController implements Handler.Callback { void continueUserSwitch(UserState uss, int oldUserId, int newUserId) { Slog.d(TAG, "Continue user switch oldUser #" + oldUserId + ", newUser #" + newUserId); if (mUserSwitchUiEnabled) { - synchronized (mLock) { - mInjector.getWindowManager().stopFreezingScreen(); - } + mInjector.getWindowManager().stopFreezingScreen(); } uss.switching = false; mHandler.removeMessages(REPORT_USER_SWITCH_COMPLETE_MSG); @@ -1300,19 +1309,18 @@ class UserController implements Handler.Callback { stopBackgroundUsersIfEnforced(oldUserId); } - void moveUserToForegroundLocked(UserState uss, int oldUserId, int newUserId) { - boolean homeInFront = - mInjector.getActivityStackSupervisor().switchUserLocked(newUserId, uss); + private void moveUserToForeground(UserState uss, int oldUserId, int newUserId) { + boolean homeInFront = mInjector.stackSupervisorSwitchUser(newUserId, uss); if (homeInFront) { - mInjector.startHomeActivityLocked(newUserId, "moveUserToForeground"); + mInjector.startHomeActivity(newUserId, "moveUserToForeground"); } else { - mInjector.getActivityStackSupervisor().resumeFocusedStackTopActivityLocked(); + mInjector.stackSupervisorResumeFocusedStackTopActivity(); } EventLogTags.writeAmSwitchUser(newUserId); - sendUserSwitchBroadcastsLocked(oldUserId, newUserId); + sendUserSwitchBroadcasts(oldUserId, newUserId); } - void sendUserSwitchBroadcastsLocked(int oldUserId, int newUserId) { + void sendUserSwitchBroadcasts(int oldUserId, int newUserId) { long ident = Binder.clearCallingIdentity(); try { Intent intent; @@ -1326,7 +1334,7 @@ class UserController implements Handler.Callback { intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY | Intent.FLAG_RECEIVER_FOREGROUND); intent.putExtra(Intent.EXTRA_USER_HANDLE, profileUserId); - mInjector.broadcastIntentLocked(intent, + mInjector.broadcastIntent(intent, null, null, 0, null, null, null, AppOpsManager.OP_NONE, null, false, false, MY_PID, SYSTEM_UID, profileUserId); } @@ -1341,7 +1349,7 @@ class UserController implements Handler.Callback { intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY | Intent.FLAG_RECEIVER_FOREGROUND); intent.putExtra(Intent.EXTRA_USER_HANDLE, profileUserId); - mInjector.broadcastIntentLocked(intent, + mInjector.broadcastIntent(intent, null, null, 0, null, null, null, AppOpsManager.OP_NONE, null, false, false, MY_PID, SYSTEM_UID, profileUserId); } @@ -1349,7 +1357,7 @@ class UserController implements Handler.Callback { intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY | Intent.FLAG_RECEIVER_FOREGROUND); intent.putExtra(Intent.EXTRA_USER_HANDLE, newUserId); - mInjector.broadcastIntentLocked(intent, + mInjector.broadcastIntent(intent, null, null, 0, null, null, new String[] {android.Manifest.permission.MANAGE_USERS}, AppOpsManager.OP_NONE, null, false, false, MY_PID, SYSTEM_UID, @@ -1374,7 +1382,7 @@ class UserController implements Handler.Callback { // the value the caller will receive and someone else changing it. // We assume that USER_CURRENT_OR_SELF will use the current user; later // we will switch to the calling user if access to the current user fails. - int targetUserId = unsafeConvertIncomingUserLocked(userId); + int targetUserId = unsafeConvertIncomingUser(userId); if (callingUid != 0 && callingUid != SYSTEM_UID) { final boolean allow; @@ -1442,9 +1450,9 @@ class UserController implements Handler.Callback { return targetUserId; } - int unsafeConvertIncomingUserLocked(int userId) { + int unsafeConvertIncomingUser(int userId) { return (userId == UserHandle.USER_CURRENT || userId == UserHandle.USER_CURRENT_OR_SELF) - ? getCurrentUserIdLocked(): userId; + ? getCurrentUserId(): userId; } void registerUserSwitchObserver(IUserSwitchObserver observer, String name) { @@ -1470,15 +1478,17 @@ class UserController implements Handler.Callback { mUserSwitchObservers.unregister(observer); } - UserState getStartedUserStateLocked(int userId) { - return mStartedUsers.get(userId); + UserState getStartedUserState(int userId) { + synchronized (mLock) { + return mStartedUsers.get(userId); + } } boolean hasStartedUserState(int userId) { return mStartedUsers.get(userId) != null; } - private void updateStartedUserArrayLocked() { + private void updateStartedUserArrayLU() { int num = 0; for (int i = 0; i < mStartedUsers.size(); i++) { UserState uss = mStartedUsers.valueAt(i); @@ -1499,15 +1509,20 @@ class UserController implements Handler.Callback { } } - void sendBootCompletedLocked(IIntentReceiver resultTo) { - for (int i = 0; i < mStartedUsers.size(); i++) { - UserState uss = mStartedUsers.valueAt(i); + void sendBootCompleted(IIntentReceiver resultTo) { + // Get a copy of mStartedUsers to use outside of lock + SparseArray<UserState> startedUsers; + synchronized (mLock) { + startedUsers = mStartedUsers.clone(); + } + for (int i = 0; i < startedUsers.size(); i++) { + UserState uss = startedUsers.valueAt(i); finishUserBoot(uss, resultTo); } } void onSystemReady() { - updateCurrentProfileIdsLocked(); + updateCurrentProfileIds(); } /** @@ -1515,33 +1530,35 @@ class UserController implements Handler.Callback { * user switch happens or when a new related user is started in the * background. */ - private void updateCurrentProfileIdsLocked() { - final List<UserInfo> profiles = mInjector.getUserManager().getProfiles(mCurrentUserId, + private void updateCurrentProfileIds() { + final List<UserInfo> profiles = mInjector.getUserManager().getProfiles(getCurrentUserId(), false /* enabledOnly */); int[] currentProfileIds = new int[profiles.size()]; // profiles will not be null for (int i = 0; i < currentProfileIds.length; i++) { currentProfileIds[i] = profiles.get(i).id; } - mCurrentProfileIds = currentProfileIds; + final List<UserInfo> users = mInjector.getUserManager().getUsers(false); + synchronized (mLock) { + mCurrentProfileIds = currentProfileIds; - synchronized (mUserProfileGroupIdsSelfLocked) { - mUserProfileGroupIdsSelfLocked.clear(); - final List<UserInfo> users = mInjector.getUserManager().getUsers(false); + mUserProfileGroupIds.clear(); for (int i = 0; i < users.size(); i++) { UserInfo user = users.get(i); if (user.profileGroupId != UserInfo.NO_PROFILE_GROUP_ID) { - mUserProfileGroupIdsSelfLocked.put(user.id, user.profileGroupId); + mUserProfileGroupIds.put(user.id, user.profileGroupId); } } } } - int[] getStartedUserArrayLocked() { - return mStartedUserArray; + int[] getStartedUserArray() { + synchronized (mLock) { + return mStartedUserArray; + } } - boolean isUserRunningLocked(int userId, int flags) { - UserState state = getStartedUserStateLocked(userId); + boolean isUserRunning(int userId, int flags) { + UserState state = getStartedUserState(userId); if (state == null) { return false; } @@ -1604,29 +1621,38 @@ class UserController implements Handler.Callback { return getUserInfo(mCurrentUserId); } synchronized (mLock) { - return getCurrentUserLocked(); + return getCurrentUserLU(); } } - UserInfo getCurrentUserLocked() { + UserInfo getCurrentUserLU() { int userId = mTargetUserId != UserHandle.USER_NULL ? mTargetUserId : mCurrentUserId; return getUserInfo(userId); } - int getCurrentOrTargetUserIdLocked() { + int getCurrentOrTargetUserId() { + synchronized (mLock) { + return mTargetUserId != UserHandle.USER_NULL ? mTargetUserId : mCurrentUserId; + } + } + + int getCurrentOrTargetUserIdLU() { return mTargetUserId != UserHandle.USER_NULL ? mTargetUserId : mCurrentUserId; } - int getCurrentUserIdLocked() { + + int getCurrentUserIdLU() { return mCurrentUserId; } - private boolean isCurrentUserLocked(int userId) { - return userId == getCurrentOrTargetUserIdLocked(); + int getCurrentUserId() { + synchronized (mLock) { + return mCurrentUserId; + } } - int setTargetUserIdLocked(int targetUserId) { - return mTargetUserId = targetUserId; + private boolean isCurrentUserLU(int userId) { + return userId == getCurrentOrTargetUserIdLU(); } int[] getUsers() { @@ -1673,22 +1699,26 @@ class UserController implements Handler.Callback { if (callingUserId == targetUserId) { return true; } - synchronized (mUserProfileGroupIdsSelfLocked) { - int callingProfile = mUserProfileGroupIdsSelfLocked.get(callingUserId, + synchronized (mLock) { + int callingProfile = mUserProfileGroupIds.get(callingUserId, UserInfo.NO_PROFILE_GROUP_ID); - int targetProfile = mUserProfileGroupIdsSelfLocked.get(targetUserId, + int targetProfile = mUserProfileGroupIds.get(targetUserId, UserInfo.NO_PROFILE_GROUP_ID); return callingProfile != UserInfo.NO_PROFILE_GROUP_ID && callingProfile == targetProfile; } } - boolean isCurrentProfileLocked(int userId) { - return ArrayUtils.contains(mCurrentProfileIds, userId); + boolean isCurrentProfile(int userId) { + synchronized (mLock) { + return ArrayUtils.contains(mCurrentProfileIds, userId); + } } - int[] getCurrentProfileIdsLocked() { - return mCurrentProfileIds; + int[] getCurrentProfileIds() { + synchronized (mLock) { + return mCurrentProfileIds; + } } /** @@ -1713,35 +1743,40 @@ class UserController implements Handler.Callback { } void dump(PrintWriter pw, boolean dumpAll) { - pw.println(" mStartedUsers:"); - for (int i = 0; i < mStartedUsers.size(); i++) { - UserState uss = mStartedUsers.valueAt(i); - pw.print(" User #"); pw.print(uss.mHandle.getIdentifier()); - pw.print(": "); uss.dump("", pw); - } - pw.print(" mStartedUserArray: ["); - for (int i = 0; i < mStartedUserArray.length; i++) { - if (i > 0) pw.print(", "); - pw.print(mStartedUserArray[i]); - } - pw.println("]"); - pw.print(" mUserLru: ["); - for (int i = 0; i < mUserLru.size(); i++) { - if (i > 0) pw.print(", "); - pw.print(mUserLru.get(i)); - } - pw.println("]"); - if (dumpAll) { - pw.print(" mStartedUserArray: "); pw.println(Arrays.toString(mStartedUserArray)); - } - synchronized (mUserProfileGroupIdsSelfLocked) { - if (mUserProfileGroupIdsSelfLocked.size() > 0) { + synchronized (mLock) { + pw.println(" mStartedUsers:"); + for (int i = 0; i < mStartedUsers.size(); i++) { + UserState uss = mStartedUsers.valueAt(i); + pw.print(" User #"); + pw.print(uss.mHandle.getIdentifier()); + pw.print(": "); + uss.dump("", pw); + } + pw.print(" mStartedUserArray: ["); + for (int i = 0; i < mStartedUserArray.length; i++) { + if (i > 0) + pw.print(", "); + pw.print(mStartedUserArray[i]); + } + pw.println("]"); + pw.print(" mUserLru: ["); + for (int i = 0; i < mUserLru.size(); i++) { + if (i > 0) + pw.print(", "); + pw.print(mUserLru.get(i)); + } + pw.println("]"); + if (dumpAll) { + pw.print(" mStartedUserArray: "); + pw.println(Arrays.toString(mStartedUserArray)); + } + if (mUserProfileGroupIds.size() > 0) { pw.println(" mUserProfileGroupIds:"); - for (int i=0; i<mUserProfileGroupIdsSelfLocked.size(); i++) { + for (int i=0; i< mUserProfileGroupIds.size(); i++) { pw.print(" User #"); - pw.print(mUserProfileGroupIdsSelfLocked.keyAt(i)); + pw.print(mUserProfileGroupIds.keyAt(i)); pw.print(" -> profile #"); - pw.println(mUserProfileGroupIdsSelfLocked.valueAt(i)); + pw.println(mUserProfileGroupIds.valueAt(i)); } } } @@ -1765,9 +1800,7 @@ class UserController implements Handler.Callback { timeoutUserSwitchCallbacks(msg.arg1, msg.arg2); break; case START_PROFILES_MSG: - synchronized (mLock) { - startProfilesLocked(); - } + startProfiles(); break; case SYSTEM_USER_START_MSG: mInjector.batteryStatsServiceNoteEvent( @@ -1778,9 +1811,7 @@ class UserController implements Handler.Callback { case SYSTEM_USER_UNLOCK_MSG: final int userId = msg.arg1; mInjector.getSystemServiceManager().unlockUser(userId); - synchronized (mLock) { - mInjector.loadUserRecentsLocked(userId); - } + mInjector.loadUserRecents(userId); if (userId == UserHandle.USER_SYSTEM) { mInjector.startPersistentApps(PackageManager.MATCH_DIRECT_BOOT_UNAWARE); } @@ -1823,10 +1854,6 @@ class UserController implements Handler.Callback { mService = service; } - protected Object getLock() { - return mService; - } - protected Handler getHandler(Handler.Callback callback) { return new Handler(mService.mHandlerThread.getLooper(), callback); } @@ -1843,13 +1870,16 @@ class UserController implements Handler.Callback { return new LockPatternUtils(getContext()); } - protected int broadcastIntentLocked(Intent intent, String resolvedType, + protected int broadcastIntent(Intent intent, String resolvedType, IIntentReceiver resultTo, int resultCode, String resultData, Bundle resultExtras, String[] requiredPermissions, int appOp, Bundle bOptions, boolean ordered, boolean sticky, int callingPid, int callingUid, int userId) { - return mService.broadcastIntentLocked(null, null, intent, resolvedType, resultTo, - resultCode, resultData, resultExtras, requiredPermissions, appOp, bOptions, - ordered, sticky, callingPid, callingUid, userId); + // TODO b/64165549 Verify that mLock is not held before calling AMS methods + synchronized (mService) { + return mService.broadcastIntentLocked(null, null, intent, resolvedType, resultTo, + resultCode, resultData, resultExtras, requiredPermissions, appOp, bOptions, + ordered, sticky, callingPid, callingUid, userId); + } } int checkCallingPermission(String permission) { @@ -1860,7 +1890,9 @@ class UserController implements Handler.Callback { return mService.mWindowManager; } void activityManagerOnUserStopped(int userId) { - mService.onUserStoppedLocked(userId); + synchronized (mService) { + mService.onUserStoppedLocked(userId); + } } void systemServiceManagerCleanupUser(int userId) { @@ -1916,9 +1948,11 @@ class UserController implements Handler.Callback { }.sendNext(); } - void activityManagerForceStopPackageLocked(int userId, String reason) { - mService.forceStopPackageLocked(null, -1, false, false, true, false, false, - userId, reason); + void activityManagerForceStopPackage(int userId, String reason) { + synchronized (mService) { + mService.forceStopPackageLocked(null, -1, false, false, true, false, false, + userId, reason); + } }; int checkComponentPermission(String permission, int pid, int uid, int owningUid, @@ -1926,20 +1960,28 @@ class UserController implements Handler.Callback { return mService.checkComponentPermission(permission, pid, uid, owningUid, exported); } - void startHomeActivityLocked(int userId, String reason) { - mService.startHomeActivityLocked(userId, reason); + protected void startHomeActivity(int userId, String reason) { + synchronized (mService) { + mService.startHomeActivityLocked(userId, reason); + } } - void updateUserConfigurationLocked() { - mService.updateUserConfigurationLocked(); + void updateUserConfiguration() { + synchronized (mService) { + mService.updateUserConfigurationLocked(); + } } - void clearBroadcastQueueForUserLocked(int userId) { - mService.clearBroadcastQueueForUserLocked(userId); + void clearBroadcastQueueForUser(int userId) { + synchronized (mService) { + mService.clearBroadcastQueueForUserLocked(userId); + } } - void loadUserRecentsLocked(int userId) { - mService.mRecentTasks.loadUserRecentsLocked(userId); + void loadUserRecents(int userId) { + synchronized (mService) { + mService.mRecentTasks.loadUserRecentsLocked(userId); + } } void startPersistentApps(int matchFlags) { @@ -1956,12 +1998,28 @@ class UserController implements Handler.Callback { d.show(); } - ActivityStackSupervisor getActivityStackSupervisor() { - return mService.mStackSupervisor; + void stackSupervisorRemoveUser(int userId) { + synchronized (mService) { + mService.mStackSupervisor.removeUserLocked(userId); + } } - LockTaskController getLockTaskController() { - return mService.mLockTaskController; + protected boolean stackSupervisorSwitchUser(int userId, UserState uss) { + synchronized (mService) { + return mService.mStackSupervisor.switchUserLocked(userId, uss); + } + } + + protected void stackSupervisorResumeFocusedStackTopActivity() { + synchronized (mService) { + mService.mStackSupervisor.resumeFocusedStackTopActivityLocked(); + } + } + + protected void clearLockTaskMode(String reason) { + synchronized (mService) { + mService.mLockTaskController.clearLockTaskMode(reason); + } } } } diff --git a/services/core/java/com/android/server/am/UserState.java b/services/core/java/com/android/server/am/UserState.java index 2e27387a6a09..d36d9cbef930 100644 --- a/services/core/java/com/android/server/am/UserState.java +++ b/services/core/java/com/android/server/am/UserState.java @@ -59,8 +59,10 @@ public final class UserState { /** * The last time that a provider was reported to usage stats as being brought to important * foreground procstate. + * <p><strong>Important: </strong>Only access this field when holding ActivityManagerService + * lock. */ - public final ArrayMap<String,Long> mProviderLastReportedFg = new ArrayMap<>(); + final ArrayMap<String,Long> mProviderLastReportedFg = new ArrayMap<>(); public UserState(UserHandle handle) { mHandle = handle; diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java index 11d0470ee8e5..3c1f2d42707a 100644 --- a/services/core/java/com/android/server/audio/AudioService.java +++ b/services/core/java/com/android/server/audio/AudioService.java @@ -461,6 +461,8 @@ public class AudioService extends IAudioService.Stub // Forced device usage for communications private int mForcedUseForComm; + private int mForcedUseForCommExt; // External state returned by getters: always consistent + // with requests by setters // List of binder death handlers for setMode() client processes. // The last process to have called setMode() is at the top of the list. @@ -2890,13 +2892,14 @@ public class AudioService extends IAudioService.Stub mForcedUseForComm = AudioSystem.FORCE_NONE; } + mForcedUseForCommExt = mForcedUseForComm; sendMsg(mAudioHandler, MSG_SET_FORCE_USE, SENDMSG_QUEUE, AudioSystem.FOR_COMMUNICATION, mForcedUseForComm, eventSource, 0); } /** @see AudioManager#isSpeakerphoneOn() */ public boolean isSpeakerphoneOn() { - return (mForcedUseForComm == AudioSystem.FORCE_SPEAKER); + return (mForcedUseForCommExt == AudioSystem.FORCE_SPEAKER); } /** @see AudioManager#setBluetoothScoOn(boolean) */ @@ -2904,6 +2907,13 @@ public class AudioService extends IAudioService.Stub if (!checkAudioSettingsPermission("setBluetoothScoOn()")) { return; } + + // Only enable calls from system components + if (Binder.getCallingUid() >= FIRST_APPLICATION_UID) { + mForcedUseForCommExt = on ? AudioSystem.FORCE_BT_SCO : AudioSystem.FORCE_NONE; + return; + } + // for logging only final String eventSource = new StringBuilder("setBluetoothScoOn(").append(on) .append(") from u/pid:").append(Binder.getCallingUid()).append("/") @@ -2913,11 +2923,21 @@ public class AudioService extends IAudioService.Stub public void setBluetoothScoOnInt(boolean on, String eventSource) { if (on) { + // do not accept SCO ON if SCO audio is not connected + synchronized(mScoClients) { + if ((mBluetoothHeadset != null) && + (mBluetoothHeadset.getAudioState(mBluetoothHeadsetDevice) + != BluetoothHeadset.STATE_AUDIO_CONNECTED)) { + mForcedUseForCommExt = AudioSystem.FORCE_BT_SCO; + return; + } + } mForcedUseForComm = AudioSystem.FORCE_BT_SCO; } else if (mForcedUseForComm == AudioSystem.FORCE_BT_SCO) { mForcedUseForComm = AudioSystem.FORCE_NONE; } - + mForcedUseForCommExt = mForcedUseForComm; + AudioSystem.setParameters("BT_SCO="+ (on ? "on" : "off")); sendMsg(mAudioHandler, MSG_SET_FORCE_USE, SENDMSG_QUEUE, AudioSystem.FOR_COMMUNICATION, mForcedUseForComm, eventSource, 0); sendMsg(mAudioHandler, MSG_SET_FORCE_USE, SENDMSG_QUEUE, @@ -2926,7 +2946,7 @@ public class AudioService extends IAudioService.Stub /** @see AudioManager#isBluetoothScoOn() */ public boolean isBluetoothScoOn() { - return (mForcedUseForComm == AudioSystem.FORCE_BT_SCO); + return (mForcedUseForCommExt == AudioSystem.FORCE_BT_SCO); } /** @see AudioManager#setBluetoothA2dpOn(boolean) */ diff --git a/services/core/java/com/android/server/connectivity/IpConnectivityMetrics.java b/services/core/java/com/android/server/connectivity/IpConnectivityMetrics.java index 475d786aedd1..f2445fa36006 100644 --- a/services/core/java/com/android/server/connectivity/IpConnectivityMetrics.java +++ b/services/core/java/com/android/server/connectivity/IpConnectivityMetrics.java @@ -34,6 +34,7 @@ import android.util.Base64; import android.util.Log; import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.VisibleForTesting; +import com.android.internal.util.RingBuffer; import com.android.internal.util.TokenBucket; import com.android.server.SystemService; import com.android.server.connectivity.metrics.nano.IpConnectivityLogClass.IpConnectivityEvent; @@ -44,7 +45,11 @@ import java.util.ArrayList; import java.util.List; import java.util.function.ToIntFunction; -/** {@hide} */ +/** + * Event buffering service for core networking and connectivity metrics. + * + * {@hide} + */ final public class IpConnectivityMetrics extends SystemService { private static final String TAG = IpConnectivityMetrics.class.getSimpleName(); private static final boolean DBG = false; @@ -58,7 +63,10 @@ final public class IpConnectivityMetrics extends SystemService { private static final String SERVICE_NAME = IpConnectivityLog.SERVICE_NAME; - // Default size of the event buffer. Once the buffer is full, incoming events are dropped. + // Default size of the event rolling log for bug report dumps. + private static final int DEFAULT_LOG_SIZE = 500; + // Default size of the event buffer for metrics reporting. + // Once the buffer is full, incoming events are dropped. private static final int DEFAULT_BUFFER_SIZE = 2000; // Maximum size of the event buffer. private static final int MAXIMUM_BUFFER_SIZE = DEFAULT_BUFFER_SIZE * 10; @@ -67,24 +75,38 @@ final public class IpConnectivityMetrics extends SystemService { private static final int ERROR_RATE_LIMITED = -1; - // Lock ensuring that concurrent manipulations of the event buffer are correct. + // Lock ensuring that concurrent manipulations of the event buffers are correct. // There are three concurrent operations to synchronize: // - appending events to the buffer. // - iterating throught the buffer. // - flushing the buffer content and replacing it by a new buffer. private final Object mLock = new Object(); + // Implementation instance of IIpConnectivityMetrics.aidl. @VisibleForTesting public final Impl impl = new Impl(); + // Subservice listening to Netd events via INetdEventListener.aidl. @VisibleForTesting NetdEventListenerService mNetdListener; + // Rolling log of the most recent events. This log is used for dumping + // connectivity events in bug reports. + @GuardedBy("mLock") + private final RingBuffer<ConnectivityMetricsEvent> mEventLog = + new RingBuffer(ConnectivityMetricsEvent.class, DEFAULT_LOG_SIZE); + // Buffer of connectivity events used for metrics reporting. This buffer + // does not rotate automatically and instead saturates when it becomes full. + // It is flushed at metrics reporting. @GuardedBy("mLock") private ArrayList<ConnectivityMetricsEvent> mBuffer; + // Total number of events dropped from mBuffer since last metrics reporting. @GuardedBy("mLock") private int mDropped; + // Capacity of mBuffer @GuardedBy("mLock") private int mCapacity; + // A list of rate limiting counters keyed by connectivity event types for + // metrics reporting mBuffer. @GuardedBy("mLock") private final ArrayMap<Class<?>, TokenBucket> mBuckets = makeRateLimitingBuckets(); @@ -132,6 +154,7 @@ final public class IpConnectivityMetrics extends SystemService { private int append(ConnectivityMetricsEvent event) { if (DBG) Log.d(TAG, "logEvent: " + event); synchronized (mLock) { + mEventLog.append(event); final int left = mCapacity - mBuffer.size(); if (event == null) { return left; @@ -216,6 +239,23 @@ final public class IpConnectivityMetrics extends SystemService { } } + /** + * Prints for bug reports the content of the rolling event log and the + * content of Netd event listener. + */ + private void cmdDumpsys(FileDescriptor fd, PrintWriter pw, String[] args) { + final ConnectivityMetricsEvent[] events; + synchronized (mLock) { + events = mEventLog.toArray(); + } + for (ConnectivityMetricsEvent ev : events) { + pw.println(ev.toString()); + } + if (mNetdListener != null) { + mNetdListener.list(pw); + } + } + private void cmdStats(FileDescriptor fd, PrintWriter pw, String[] args) { synchronized (mLock) { pw.println("Buffered events: " + mBuffer.size()); @@ -258,7 +298,8 @@ final public class IpConnectivityMetrics extends SystemService { cmdFlush(fd, pw, args); return; case CMD_DUMPSYS: - // Fallthrough to CMD_LIST when dumpsys.cpp dumps services states (bug reports) + cmdDumpsys(fd, pw, args); + return; case CMD_LIST: cmdList(fd, pw, args); return; diff --git a/services/core/java/com/android/server/connectivity/Nat464Xlat.java b/services/core/java/com/android/server/connectivity/Nat464Xlat.java index fbbdf0051266..fceacba4239c 100644 --- a/services/core/java/com/android/server/connectivity/Nat464Xlat.java +++ b/services/core/java/com/android/server/connectivity/Nat464Xlat.java @@ -152,7 +152,6 @@ public class Nat464Xlat extends BaseNetworkObserver { * turn ND offload off if on WiFi. */ private void enterRunningState() { - maybeSetIpv6NdOffload(mBaseIface, false); mState = State.RUNNING; } @@ -160,10 +159,6 @@ public class Nat464Xlat extends BaseNetworkObserver { * Stop clatd, and turn ND offload on if it had been turned off. */ private void enterStoppingState() { - if (isRunning()) { - maybeSetIpv6NdOffload(mBaseIface, true); - } - try { mNMService.stopClatd(mBaseIface); } catch(RemoteException|IllegalStateException e) { @@ -279,19 +274,6 @@ public class Nat464Xlat extends BaseNetworkObserver { } } - private void maybeSetIpv6NdOffload(String iface, boolean on) { - // TODO: migrate to NetworkCapabilities.TRANSPORT_*. - if (mNetwork.networkInfo.getType() != ConnectivityManager.TYPE_WIFI) { - return; - } - try { - Slog.d(TAG, (on ? "En" : "Dis") + "abling ND offload on " + iface); - mNMService.setInterfaceIpv6NdOffload(iface, on); - } catch(RemoteException|IllegalStateException e) { - Slog.w(TAG, "Changing IPv6 ND offload on " + iface + "failed: " + e); - } - } - /** * Adds stacked link on base link and transitions to RUNNING state. */ diff --git a/services/core/java/com/android/server/connectivity/NetdEventListenerService.java b/services/core/java/com/android/server/connectivity/NetdEventListenerService.java index 25dba3570e20..6206dfcd6622 100644 --- a/services/core/java/com/android/server/connectivity/NetdEventListenerService.java +++ b/services/core/java/com/android/server/connectivity/NetdEventListenerService.java @@ -38,6 +38,7 @@ import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.util.BitUtils; import com.android.internal.util.IndentingPrintWriter; +import com.android.internal.util.RingBuffer; import com.android.internal.util.TokenBucket; import com.android.server.connectivity.metrics.nano.IpConnectivityLogClass.IpConnectivityEvent; import java.io.PrintWriter; @@ -82,9 +83,8 @@ public class NetdEventListenerService extends INetdEventListener.Stub { private final ArrayMap<String, WakeupStats> mWakeupStats = new ArrayMap<>(); // Ring buffer array for storing packet wake up events sent by Netd. @GuardedBy("this") - private final WakeupEvent[] mWakeupEvents = new WakeupEvent[WAKEUP_EVENT_BUFFER_LENGTH]; - @GuardedBy("this") - private long mWakeupEventCursor = 0; + private final RingBuffer<WakeupEvent> mWakeupEvents = + new RingBuffer(WakeupEvent.class, WAKEUP_EVENT_BUFFER_LENGTH); private final ConnectivityManager mCm; @@ -175,13 +175,11 @@ public class NetdEventListenerService extends INetdEventListener.Stub { @GuardedBy("this") private void addWakeupEvent(String iface, long timestampMs, int uid) { - int index = wakeupEventIndex(mWakeupEventCursor); - mWakeupEventCursor++; WakeupEvent event = new WakeupEvent(); event.iface = iface; event.timestampMs = timestampMs; event.uid = uid; - mWakeupEvents[index] = event; + mWakeupEvents.append(event); WakeupStats stats = mWakeupStats.get(iface); if (stats == null) { stats = new WakeupStats(iface); @@ -190,23 +188,6 @@ public class NetdEventListenerService extends INetdEventListener.Stub { stats.countEvent(event); } - @GuardedBy("this") - private WakeupEvent[] getWakeupEvents() { - int length = (int) Math.min(mWakeupEventCursor, (long) mWakeupEvents.length); - WakeupEvent[] out = new WakeupEvent[length]; - // Reverse iteration from youngest event to oldest event. - long inCursor = mWakeupEventCursor - 1; - int outIdx = out.length - 1; - while (outIdx >= 0) { - out[outIdx--] = mWakeupEvents[wakeupEventIndex(inCursor--)]; - } - return out; - } - - private static int wakeupEventIndex(long cursor) { - return (int) Math.abs(cursor % WAKEUP_EVENT_BUFFER_LENGTH); - } - public synchronized void flushStatistics(List<IpConnectivityEvent> events) { flushProtos(events, mConnectEvents, IpConnectivityEventBuilder::toProto); flushProtos(events, mDnsEvents, IpConnectivityEventBuilder::toProto); @@ -230,7 +211,7 @@ public class NetdEventListenerService extends INetdEventListener.Stub { for (int i = 0; i < mWakeupStats.size(); i++) { pw.println(mWakeupStats.valueAt(i)); } - for (WakeupEvent wakeup : getWakeupEvents()) { + for (WakeupEvent wakeup : mWakeupEvents.toArray()) { pw.println(wakeup); } } diff --git a/services/core/java/com/android/server/locksettings/LockSettingsService.java b/services/core/java/com/android/server/locksettings/LockSettingsService.java index 14d9afb14cf9..a1a010618ec0 100644 --- a/services/core/java/com/android/server/locksettings/LockSettingsService.java +++ b/services/core/java/com/android/server/locksettings/LockSettingsService.java @@ -376,7 +376,7 @@ public class LockSettingsService extends ILockSettings.Stub { } public SyntheticPasswordManager getSyntheticPasswordManager(LockSettingsStorage storage) { - return new SyntheticPasswordManager(storage, getUserManager()); + return new SyntheticPasswordManager(getContext(), storage, getUserManager()); } public int binderGetCallingUid() { @@ -763,7 +763,8 @@ public class LockSettingsService extends ILockSettings.Stub { private void migrateOldDataAfterSystemReady() { try { // Migrate the FRP credential to the persistent data block - if (LockPatternUtils.frpCredentialEnabled() && !getBoolean("migrated_frp", false, 0)) { + if (LockPatternUtils.frpCredentialEnabled(mContext) + && !getBoolean("migrated_frp", false, 0)) { migrateFrpCredential(); setBoolean("migrated_frp", true, 0); Slog.i(TAG, "Migrated migrated_frp."); @@ -784,7 +785,7 @@ public class LockSettingsService extends ILockSettings.Stub { return; } for (UserInfo userInfo : mUserManager.getUsers()) { - if (userOwnsFrpCredential(userInfo) && isUserSecure(userInfo.id)) { + if (userOwnsFrpCredential(mContext, userInfo) && isUserSecure(userInfo.id)) { synchronized (mSpManager) { if (isSyntheticPasswordBasedCredentialLocked(userInfo.id)) { int actualQuality = (int) getLong(LockPatternUtils.PASSWORD_TYPE_KEY, @@ -2504,7 +2505,7 @@ public class LockSettingsService extends ILockSettings.Stub { } public void onSystemReady() { - if (frpCredentialEnabled()) { + if (frpCredentialEnabled(mContext)) { updateRegistration(); } else { // If we don't intend to use frpCredentials and we're not provisioned yet, send @@ -2533,7 +2534,7 @@ public class LockSettingsService extends ILockSettings.Stub { private void clearFrpCredentialIfOwnerNotSecure() { List<UserInfo> users = mUserManager.getUsers(); for (UserInfo user : users) { - if (userOwnsFrpCredential(user)) { + if (userOwnsFrpCredential(mContext, user)) { if (!isUserSecure(user.id)) { mStorage.writePersistentDataBlock(PersistentData.TYPE_NONE, user.id, 0, null); diff --git a/services/core/java/com/android/server/locksettings/LockSettingsStrongAuth.java b/services/core/java/com/android/server/locksettings/LockSettingsStrongAuth.java index 542b929d85f5..c9c93293e2ee 100644 --- a/services/core/java/com/android/server/locksettings/LockSettingsStrongAuth.java +++ b/services/core/java/com/android/server/locksettings/LockSettingsStrongAuth.java @@ -27,6 +27,7 @@ import android.app.AlarmManager.OnAlarmListener; import android.app.admin.DevicePolicyManager; import android.app.trust.IStrongAuthTracker; import android.content.Context; +import android.content.pm.PackageManager; import android.hardware.fingerprint.FingerprintManager; import android.os.Binder; import android.os.DeadObjectException; @@ -74,7 +75,10 @@ public class LockSettingsStrongAuth { } public void systemReady() { - mFingerprintManager = mContext.getSystemService(FingerprintManager.class); + final PackageManager pm = mContext.getPackageManager(); + if (pm.hasSystemFeature(PackageManager.FEATURE_FINGERPRINT)) { + mFingerprintManager = mContext.getSystemService(FingerprintManager.class); + } } private void handleAddStrongAuthTracker(IStrongAuthTracker tracker) { diff --git a/services/core/java/com/android/server/locksettings/SyntheticPasswordManager.java b/services/core/java/com/android/server/locksettings/SyntheticPasswordManager.java index 33a9a995c08c..9440f17164aa 100644 --- a/services/core/java/com/android/server/locksettings/SyntheticPasswordManager.java +++ b/services/core/java/com/android/server/locksettings/SyntheticPasswordManager.java @@ -19,6 +19,7 @@ package com.android.server.locksettings; import android.annotation.NonNull; import android.annotation.Nullable; import android.app.admin.DevicePolicyManager; +import android.content.Context; import android.content.pm.UserInfo; import android.hardware.weaver.V1_0.IWeaver; import android.hardware.weaver.V1_0.WeaverConfig; @@ -255,13 +256,16 @@ public class SyntheticPasswordManager { byte[] aggregatedSecret; } + private final Context mContext; private LockSettingsStorage mStorage; private IWeaver mWeaver; private WeaverConfig mWeaverConfig; private final UserManager mUserManager; - public SyntheticPasswordManager(LockSettingsStorage storage, UserManager userManager) { + public SyntheticPasswordManager(Context context, LockSettingsStorage storage, + UserManager userManager) { + mContext = context; mStorage = storage; mUserManager = userManager; } @@ -645,7 +649,7 @@ public class SyntheticPasswordManager { public void migrateFrpPasswordLocked(long handle, UserInfo userInfo, int requestedQuality) { if (mStorage.getPersistentDataBlock() != null - && LockPatternUtils.userOwnsFrpCredential(userInfo)) { + && LockPatternUtils.userOwnsFrpCredential(mContext, userInfo)) { PasswordData pwd = PasswordData.fromBytes(loadState(PASSWORD_DATA_NAME, handle, userInfo.id)); if (pwd.passwordType != LockPatternUtils.CREDENTIAL_TYPE_NONE) { @@ -662,7 +666,8 @@ public class SyntheticPasswordManager { private void synchronizeFrpPassword(PasswordData pwd, int requestedQuality, int userId) { if (mStorage.getPersistentDataBlock() != null - && LockPatternUtils.userOwnsFrpCredential(mUserManager.getUserInfo(userId))) { + && LockPatternUtils.userOwnsFrpCredential(mContext, + mUserManager.getUserInfo(userId))) { if (pwd.passwordType != LockPatternUtils.CREDENTIAL_TYPE_NONE) { mStorage.writePersistentDataBlock(PersistentData.TYPE_SP, userId, requestedQuality, pwd.toBytes()); @@ -675,7 +680,8 @@ public class SyntheticPasswordManager { private void synchronizeWeaverFrpPassword(PasswordData pwd, int requestedQuality, int userId, int weaverSlot) { if (mStorage.getPersistentDataBlock() != null - && LockPatternUtils.userOwnsFrpCredential(mUserManager.getUserInfo(userId))) { + && LockPatternUtils.userOwnsFrpCredential(mContext, + mUserManager.getUserInfo(userId))) { if (pwd.passwordType != LockPatternUtils.CREDENTIAL_TYPE_NONE) { mStorage.writePersistentDataBlock(PersistentData.TYPE_SP_WEAVER, weaverSlot, requestedQuality, pwd.toBytes()); diff --git a/services/core/java/com/android/server/notification/ImportanceExtractor.java b/services/core/java/com/android/server/notification/ImportanceExtractor.java index 46ec92b1bc9d..452121c05fdf 100644 --- a/services/core/java/com/android/server/notification/ImportanceExtractor.java +++ b/services/core/java/com/android/server/notification/ImportanceExtractor.java @@ -22,7 +22,7 @@ import android.util.Slog; * Determines the importance of the given notification. */ public class ImportanceExtractor implements NotificationSignalExtractor { - private static final String TAG = "ImportantTopicExtractor"; + private static final String TAG = "ImportanceExtractor"; private static final boolean DBG = false; private RankingConfig mConfig; diff --git a/services/core/java/com/android/server/notification/NotificationAdjustmentExtractor.java b/services/core/java/com/android/server/notification/NotificationAdjustmentExtractor.java index 7c8284589ddd..ce1126887bdc 100644 --- a/services/core/java/com/android/server/notification/NotificationAdjustmentExtractor.java +++ b/services/core/java/com/android/server/notification/NotificationAdjustmentExtractor.java @@ -22,7 +22,7 @@ import android.util.Slog; * Applies adjustments from the group helper and notification assistant */ public class NotificationAdjustmentExtractor implements NotificationSignalExtractor { - private static final String TAG = "BadgeExtractor"; + private static final String TAG = "AdjustmentExtractor"; private static final boolean DBG = false; diff --git a/services/core/java/com/android/server/notification/NotificationChannelExtractor.java b/services/core/java/com/android/server/notification/NotificationChannelExtractor.java index 46ab556ffc48..11c7ab75eb18 100644 --- a/services/core/java/com/android/server/notification/NotificationChannelExtractor.java +++ b/services/core/java/com/android/server/notification/NotificationChannelExtractor.java @@ -22,7 +22,7 @@ import android.util.Slog; * Stores the latest notification channel information for this notification */ public class NotificationChannelExtractor implements NotificationSignalExtractor { - private static final String TAG = "BadgeExtractor"; + private static final String TAG = "ChannelExtractor"; private static final boolean DBG = false; private RankingConfig mConfig; diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java index aa6b3a3ac22c..1f0c14517e62 100644 --- a/services/core/java/com/android/server/notification/NotificationManagerService.java +++ b/services/core/java/com/android/server/notification/NotificationManagerService.java @@ -4085,19 +4085,19 @@ public class NotificationManagerService extends SystemService { if (mSystemReady && mAudioManager != null) { Uri soundUri = record.getSound(); hasValidSound = soundUri != null && !Uri.EMPTY.equals(soundUri); - long[] vibration = record.getVibration(); // Demote sound to vibration if vibration missing & phone in vibration mode. if (vibration == null && hasValidSound && (mAudioManager.getRingerModeInternal() - == AudioManager.RINGER_MODE_VIBRATE)) { + == AudioManager.RINGER_MODE_VIBRATE) + && mAudioManager.getStreamVolume( + AudioAttributes.toLegacyStreamType(record.getAudioAttributes())) == 0) { vibration = mFallbackVibrationPattern; } hasValidVibrate = vibration != null; boolean hasAudibleAlert = hasValidSound || hasValidVibrate; - if (hasAudibleAlert && !shouldMuteNotificationLocked(record)) { if (DBG) Slog.v(TAG, "Interrupting!"); if (hasValidSound) { @@ -4194,8 +4194,9 @@ public class NotificationManagerService extends SystemService { boolean looping = (record.getNotification().flags & Notification.FLAG_INSISTENT) != 0; // do not play notifications if there is a user of exclusive audio focus // or the device is in vibrate mode - if (!mAudioManager.isAudioFocusExclusive() && mAudioManager.getRingerModeInternal() - != AudioManager.RINGER_MODE_VIBRATE) { + if (!mAudioManager.isAudioFocusExclusive() && (mAudioManager.getRingerModeInternal() + != AudioManager.RINGER_MODE_VIBRATE || mAudioManager.getStreamVolume( + AudioAttributes.toLegacyStreamType(record.getAudioAttributes())) != 0)) { final long identity = Binder.clearCallingIdentity(); try { final IRingtonePlayer player = mAudioManager.getRingtonePlayer(); diff --git a/services/core/java/com/android/server/notification/PriorityExtractor.java b/services/core/java/com/android/server/notification/PriorityExtractor.java index 5d5d39def13a..7a287dba0ad3 100644 --- a/services/core/java/com/android/server/notification/PriorityExtractor.java +++ b/services/core/java/com/android/server/notification/PriorityExtractor.java @@ -23,7 +23,7 @@ import android.util.Slog; * Determines if the given notification can bypass Do Not Disturb. */ public class PriorityExtractor implements NotificationSignalExtractor { - private static final String TAG = "ImportantTopicExtractor"; + private static final String TAG = "PriorityExtractor"; private static final boolean DBG = false; private RankingConfig mConfig; diff --git a/services/core/java/com/android/server/notification/ZenModeHelper.java b/services/core/java/com/android/server/notification/ZenModeHelper.java index ffdafc562673..9fcc67df500a 100644 --- a/services/core/java/com/android/server/notification/ZenModeHelper.java +++ b/services/core/java/com/android/server/notification/ZenModeHelper.java @@ -567,7 +567,7 @@ public class ZenModeHelper { proto.write(ZenModeProto.ENABLED_ACTIVE_CONDITIONS, rule.toString()); } } - proto.write(ZenModeProto.POLICY, mConfig.toNotificationPolicy().toString()); + mConfig.toNotificationPolicy().toProto(proto, ZenModeProto.POLICY); proto.write(ZenModeProto.SUPPRESSED_EFFECTS, mSuppressedEffects); } } diff --git a/services/core/java/com/android/server/pm/PackageDexOptimizer.java b/services/core/java/com/android/server/pm/PackageDexOptimizer.java index 4fafe34b3063..925f595fc9d4 100644 --- a/services/core/java/com/android/server/pm/PackageDexOptimizer.java +++ b/services/core/java/com/android/server/pm/PackageDexOptimizer.java @@ -23,6 +23,7 @@ import android.content.pm.PackageParser; import android.os.FileUtils; import android.os.PowerManager; import android.os.SystemClock; +import android.os.SystemProperties; import android.os.UserHandle; import android.os.WorkSource; import android.util.Log; @@ -103,7 +104,17 @@ public class PackageDexOptimizer { } static boolean canOptimizePackage(PackageParser.Package pkg) { - return (pkg.applicationInfo.flags & ApplicationInfo.FLAG_HAS_CODE) != 0; + // We do not dexopt a package with no code. + if ((pkg.applicationInfo.flags & ApplicationInfo.FLAG_HAS_CODE) == 0) { + return false; + } + + // We do not dexopt a priv-app package when pm.dexopt.priv-apps is false. + if (pkg.isPrivilegedApp()) { + return SystemProperties.getBoolean("pm.dexopt.priv-apps", true); + } + + return true; } /** @@ -425,7 +436,7 @@ public class PackageDexOptimizer { } if (useInfo.isUsedByOtherApps(path)) { - pw.println("used be other apps: " + useInfo.getLoadingPackages(path)); + pw.println("used by other apps: " + useInfo.getLoadingPackages(path)); } Map<String, PackageDexUsage.DexUseInfo> dexUseInfoMap = useInfo.getDexUseInfoMap(); @@ -441,7 +452,7 @@ public class PackageDexOptimizer { // TODO(calin): get the status of the oat file (needs installd call) pw.println("class loader context: " + dexUseInfo.getClassLoaderContext()); if (dexUseInfo.isUsedByOtherApps()) { - pw.println("used be other apps: " + dexUseInfo.getLoadingPackages()); + pw.println("used by other apps: " + dexUseInfo.getLoadingPackages()); } pw.decreaseIndent(); } diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java index d54ed611b4ef..3f31b0814e20 100644 --- a/services/core/java/com/android/server/pm/PackageManagerService.java +++ b/services/core/java/com/android/server/pm/PackageManagerService.java @@ -9784,7 +9784,9 @@ public class PackageManagerService extends IPackageManager.Stub pkg.applicationInfo.uid, pkg.packageName)) { Log.e(TAG, "Installer failed to copy system profile!"); } else { - useProfileForDexopt = true; + // Disabled as this causes speed-profile compilation during first boot + // even if things are already compiled. + // useProfileForDexopt = true; } } catch (Exception e) { Log.e(TAG, "Failed to copy profile " + profileFile.getAbsolutePath() + " ", @@ -9841,18 +9843,6 @@ public class PackageManagerService extends IPackageManager.Stub PackageManagerServiceCompilerMapping.getCompilerFilterForReason( PackageManagerService.REASON_BACKGROUND_DEXOPT); } - // If the OTA updates a system app which was previously preopted to a non-preopted state - // the app might end up being verified at runtime. That's because by default the apps - // are verify-profile but for preopted apps there's no profile. - // Do a hacky check to ensure that if we have no profiles (a reasonable indication - // that before the OTA the app was preopted) the app gets compiled with a non-profile - // filter (by default 'quicken'). - // Note that at this stage unused apps are already filtered. - if (isSystemApp(pkg) && - DexFile.isProfileGuidedCompilerFilter(pkgCompilerFilter) && - !Environment.getReferenceProfile(pkg.packageName).exists()) { - pkgCompilerFilter = getNonProfileGuidedCompilerFilter(pkgCompilerFilter); - } // checkProfiles is false to avoid merging profiles during boot which // might interfere with background compilation (b/28612421). @@ -10736,6 +10726,12 @@ public class PackageManagerService extends IPackageManager.Stub assertPackageIsValid(pkg, policyFlags, scanFlags); + if (Build.IS_DEBUGGABLE && + pkg.isPrivilegedApp() && + !SystemProperties.getBoolean("pm.dexopt.priv-apps", true)) { + PackageManagerServiceUtils.logPackageHasUncompressedCode(pkg); + } + // Initialize package source and resource directories final File scanFile = new File(pkg.codePath); final File destCodeFile = new File(pkg.applicationInfo.getCodePath()); diff --git a/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java b/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java index 25fef0a0ce31..48ddf5e9658f 100644 --- a/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java +++ b/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java @@ -22,6 +22,8 @@ import com.android.server.pm.dex.PackageDexUsage; import static com.android.server.pm.PackageManagerService.DEBUG_DEXOPT; import static com.android.server.pm.PackageManagerService.TAG; +import com.android.internal.util.ArrayUtils; + import android.annotation.NonNull; import android.app.AppGlobals; import android.content.Intent; @@ -33,6 +35,8 @@ import android.os.UserHandle; import android.system.ErrnoException; import android.util.ArraySet; import android.util.Log; +import android.util.Slog; +import android.util.jar.StrictJarFile; import dalvik.system.VMRuntime; import libcore.io.Libcore; @@ -41,9 +45,11 @@ import java.io.IOException; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; +import java.util.Iterator; import java.util.LinkedList; import java.util.List; import java.util.function.Predicate; +import java.util.zip.ZipEntry; /** * Class containing helper methods for the PackageManagerService. @@ -253,4 +259,59 @@ public class PackageManagerServiceUtils { } return false; } + + /** + * Checks that the archive located at {@code fileName} has uncompressed dex file and so + * files that can be direclty mapped. + */ + public static void logApkHasUncompressedCode(String fileName) { + StrictJarFile jarFile = null; + try { + jarFile = new StrictJarFile(fileName, + false /*verify*/, false /*signatureSchemeRollbackProtectionsEnforced*/); + Iterator<ZipEntry> it = jarFile.iterator(); + while (it.hasNext()) { + ZipEntry entry = it.next(); + if (entry.getName().endsWith(".dex")) { + if (entry.getMethod() != ZipEntry.STORED) { + Slog.wtf(TAG, "APK " + fileName + " has compressed dex code " + + entry.getName()); + } else if ((entry.getDataOffset() & 0x3) != 0) { + Slog.wtf(TAG, "APK " + fileName + " has unaligned dex code " + + entry.getName()); + } + } else if (entry.getName().endsWith(".so")) { + if (entry.getMethod() != ZipEntry.STORED) { + Slog.wtf(TAG, "APK " + fileName + " has compressed native code " + + entry.getName()); + } else if ((entry.getDataOffset() & (0x1000 - 1)) != 0) { + Slog.wtf(TAG, "APK " + fileName + " has unaligned native code " + + entry.getName()); + } + } + } + } catch (IOException ignore) { + Slog.wtf(TAG, "Error when parsing APK " + fileName); + } finally { + try { + if (jarFile != null) { + jarFile.close(); + } + } catch (IOException ignore) {} + } + return; + } + + /** + * Checks that the APKs in the given package have uncompressed dex file and so + * files that can be direclty mapped. + */ + public static void logPackageHasUncompressedCode(PackageParser.Package pkg) { + logApkHasUncompressedCode(pkg.baseCodePath); + if (!ArrayUtils.isEmpty(pkg.splitCodePaths)) { + for (int i = 0; i < pkg.splitCodePaths.length; i++) { + logApkHasUncompressedCode(pkg.splitCodePaths[i]); + } + } + } } diff --git a/services/core/java/com/android/server/pm/ShortcutService.java b/services/core/java/com/android/server/pm/ShortcutService.java index 0e572d821572..15d20716a322 100644 --- a/services/core/java/com/android/server/pm/ShortcutService.java +++ b/services/core/java/com/android/server/pm/ShortcutService.java @@ -484,12 +484,13 @@ public class ShortcutService extends IShortcutService.Stub { final private IUidObserver mUidObserver = new IUidObserver.Stub() { @Override public void onUidStateChanged(int uid, int procState, long procStateSeq) { - handleOnUidStateChanged(uid, procState); + injectPostToHandler(() -> handleOnUidStateChanged(uid, procState)); } @Override public void onUidGone(int uid, boolean disabled) { - handleOnUidStateChanged(uid, ActivityManager.PROCESS_STATE_NONEXISTENT); + injectPostToHandler(() -> + handleOnUidStateChanged(uid, ActivityManager.PROCESS_STATE_NONEXISTENT)); } @Override diff --git a/services/core/java/com/android/server/power/PowerManagerService.java b/services/core/java/com/android/server/power/PowerManagerService.java index 338ad2a951c9..b917dae2adf8 100644 --- a/services/core/java/com/android/server/power/PowerManagerService.java +++ b/services/core/java/com/android/server/power/PowerManagerService.java @@ -206,6 +206,8 @@ public final class PowerManagerService extends SystemService private static final String REASON_REBOOT = "reboot"; private static final String REASON_USERREQUESTED = "shutdown,userrequested"; private static final String REASON_THERMAL_SHUTDOWN = "shutdown,thermal"; + private static final String REASON_LOW_BATTERY = "shutdown,battery"; + private static final String REASON_BATTERY_THERMAL_STATE = "shutdown,thermal,battery"; private static final String TRACE_SCREEN_ON = "Screen turning on"; @@ -4651,6 +4653,10 @@ public final class PowerManagerService extends SystemService return PowerManager.SHUTDOWN_REASON_USER_REQUESTED; case REASON_THERMAL_SHUTDOWN: return PowerManager.SHUTDOWN_REASON_THERMAL_SHUTDOWN; + case REASON_LOW_BATTERY: + return PowerManager.SHUTDOWN_REASON_LOW_BATTERY; + case REASON_BATTERY_THERMAL_STATE: + return PowerManager.SHUTDOWN_REASON_BATTERY_THERMAL; default: return PowerManager.SHUTDOWN_REASON_UNKNOWN; } diff --git a/services/core/java/com/android/server/storage/AppCollector.java b/services/core/java/com/android/server/storage/AppCollector.java index 03b754f777b3..0b51f9cc7b7c 100644 --- a/services/core/java/com/android/server/storage/AppCollector.java +++ b/services/core/java/com/android/server/storage/AppCollector.java @@ -135,7 +135,7 @@ public class AppCollector { PackageStats packageStats = new PackageStats(app.packageName, user.id); packageStats.cacheSize = storageStats.getCacheBytes(); - packageStats.codeSize = storageStats.getCodeBytes(); + packageStats.codeSize = storageStats.getAppBytes(); packageStats.dataSize = storageStats.getDataBytes(); stats.add(packageStats); } catch (NameNotFoundException | IOException e) { diff --git a/services/core/java/com/android/server/storage/DiskStatsFileLogger.java b/services/core/java/com/android/server/storage/DiskStatsFileLogger.java index 0094ab5559d8..1db3ec4ca506 100644 --- a/services/core/java/com/android/server/storage/DiskStatsFileLogger.java +++ b/services/core/java/com/android/server/storage/DiskStatsFileLogger.java @@ -56,10 +56,12 @@ public class DiskStatsFileLogger { public static final String SYSTEM_KEY = "systemSize"; public static final String MISC_KEY = "otherSize"; public static final String APP_SIZE_AGG_KEY = "appSize"; + public static final String APP_DATA_SIZE_AGG_KEY = "appDataSize"; public static final String APP_CACHE_AGG_KEY = "cacheSize"; public static final String PACKAGE_NAMES_KEY = "packageNames"; public static final String APP_SIZES_KEY = "appSizes"; public static final String APP_CACHES_KEY = "cacheSizes"; + public static final String APP_DATA_KEY = "appDataSizes"; public static final String LAST_QUERY_TIMESTAMP_KEY = "queryTime"; private MeasurementResult mResult; @@ -114,31 +116,39 @@ public class DiskStatsFileLogger { private void addAppsToJson(JSONObject json) throws JSONException { JSONArray names = new JSONArray(); JSONArray appSizeList = new JSONArray(); + JSONArray appDataSizeList = new JSONArray(); JSONArray cacheSizeList = new JSONArray(); long appSizeSum = 0L; + long appDataSizeSum = 0L; long cacheSizeSum = 0L; boolean isExternal = Environment.isExternalStorageEmulated(); for (Map.Entry<String, PackageStats> entry : filterOnlyPrimaryUser().entrySet()) { PackageStats stat = entry.getValue(); - long appSize = stat.codeSize + stat.dataSize; + long appSize = stat.codeSize; + long appDataSize = stat.dataSize; long cacheSize = stat.cacheSize; if (isExternal) { - appSize += stat.externalCodeSize + stat.externalDataSize; + appSize += stat.externalCodeSize; + appDataSize += stat.externalDataSize; cacheSize += stat.externalCacheSize; } appSizeSum += appSize; + appDataSizeSum += appDataSize; cacheSizeSum += cacheSize; names.put(stat.packageName); appSizeList.put(appSize); + appDataSizeList.put(appDataSize); cacheSizeList.put(cacheSize); } json.put(PACKAGE_NAMES_KEY, names); json.put(APP_SIZES_KEY, appSizeList); json.put(APP_CACHES_KEY, cacheSizeList); + json.put(APP_DATA_KEY, appDataSizeList); json.put(APP_SIZE_AGG_KEY, appSizeSum); json.put(APP_CACHE_AGG_KEY, cacheSizeSum); + json.put(APP_DATA_SIZE_AGG_KEY, appDataSizeSum); } /** diff --git a/services/core/java/com/android/server/timezone/IntentHelperImpl.java b/services/core/java/com/android/server/timezone/IntentHelperImpl.java index bc0f6e4b283b..6e6259d902dc 100644 --- a/services/core/java/com/android/server/timezone/IntentHelperImpl.java +++ b/services/core/java/com/android/server/timezone/IntentHelperImpl.java @@ -24,6 +24,7 @@ import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.os.PatternMatcher; +import android.os.UserHandle; import android.util.Slog; /** @@ -76,7 +77,9 @@ final class IntentHelperImpl implements IntentHelper { // not expected to need local data. Receiver packageUpdateReceiver = new Receiver(packageTracker); - mContext.registerReceiver(packageUpdateReceiver, packageIntentFilter); + mContext.registerReceiverAsUser( + packageUpdateReceiver, UserHandle.SYSTEM, packageIntentFilter, + null /* broadcastPermission */, null /* default handler */); } /** Sends an intent to trigger an update check. */ diff --git a/services/core/java/com/android/server/timezone/PackageTrackerHelperImpl.java b/services/core/java/com/android/server/timezone/PackageTrackerHelperImpl.java index 2e0c21bf007d..b89dd3838ae9 100644 --- a/services/core/java/com/android/server/timezone/PackageTrackerHelperImpl.java +++ b/services/core/java/com/android/server/timezone/PackageTrackerHelperImpl.java @@ -26,6 +26,7 @@ import android.content.pm.ProviderInfo; import android.content.pm.ResolveInfo; import android.content.res.Resources; import android.os.SystemClock; +import android.os.UserHandle; import android.util.Slog; import java.util.List; @@ -114,8 +115,8 @@ final class PackageTrackerHelperImpl implements ClockHelper, ConfigHelper, Packa @Override public boolean contentProviderRegistered(String authority, String requiredPackageName) { int flags = PackageManager.MATCH_DISABLED_UNTIL_USED_COMPONENTS; - ProviderInfo providerInfo = - mPackageManager.resolveContentProvider(authority, flags); + ProviderInfo providerInfo = mPackageManager.resolveContentProviderAsUser( + authority, flags, UserHandle.SYSTEM.getIdentifier()); if (providerInfo == null) { Slog.i(TAG, "contentProviderRegistered: No content provider registered with authority=" + authority); @@ -136,7 +137,8 @@ final class PackageTrackerHelperImpl implements ClockHelper, ConfigHelper, Packa throws PackageManager.NameNotFoundException { int flags = PackageManager.MATCH_DISABLED_UNTIL_USED_COMPONENTS; - List<ResolveInfo> resolveInfo = mPackageManager.queryBroadcastReceivers(intent, flags); + List<ResolveInfo> resolveInfo = mPackageManager.queryBroadcastReceiversAsUser( + intent, flags, UserHandle.SYSTEM); if (resolveInfo.size() != 1) { Slog.i(TAG, "receiverRegistered: Zero or multiple broadcast receiver registered for" + " intent=" + intent + ", found=" + resolveInfo); diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java index 6a5f6fafb275..10adc5a65388 100644 --- a/services/core/java/com/android/server/wm/WindowManagerService.java +++ b/services/core/java/com/android/server/wm/WindowManagerService.java @@ -2193,8 +2193,18 @@ public class WindowManagerService extends IWindowManager.Stub // and needs process it before handling the corresponding window frame. the variable // {@code mergedConfiguration} is an out parameter that will be passed back to the // client over IPC and checked there. - win.getMergedConfiguration(mergedConfiguration); - win.setReportedConfiguration(mergedConfiguration); + // Note: in the cases where the window is tied to an activity, we should not send a + // configuration update when the window has requested to be hidden. Doing so can lead + // to the client erroneously accepting a configuration that would have otherwise caused + // an activity restart. We instead hand back the last reported + // {@link MergedConfiguration}. + if (win.mAppToken == null || !win.mAppToken.isClientHidden()) { + win.getMergedConfiguration(mergedConfiguration); + } else { + win.getLastReportedMergedConfiguration(mergedConfiguration); + } + + win.setLastReportedMergedConfiguration(mergedConfiguration); outFrame.set(win.mCompatFrame); outOverscanInsets.set(win.mOverscanInsets); diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java index 8a2cb5a148d8..49a7944a97bd 100644 --- a/services/core/java/com/android/server/wm/WindowState.java +++ b/services/core/java/com/android/server/wm/WindowState.java @@ -257,7 +257,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP * We'll send configuration to client only if it is different from the last applied one and * client won't perform unnecessary updates. */ - private final Configuration mLastReportedConfiguration = new Configuration(); + private final MergedConfiguration mLastReportedConfiguration = new MergedConfiguration(); /** * Actual position of the surface shown on-screen (may be modified by animation). These are @@ -1244,7 +1244,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP // this is not necessarily what the client has processed yet. Find a // better indicator consistent with the client. return (mOrientationChanging || (isVisible() - && getConfiguration().orientation != mLastReportedConfiguration.orientation)) + && getConfiguration().orientation != getLastReportedConfiguration().orientation)) && !mSeamlesslyRotated && !mOrientationChangeTimedOut; } @@ -1758,7 +1758,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP /** Returns true if last applied config was not yet requested by client. */ boolean isConfigChanged() { - return !mLastReportedConfiguration.equals(getConfiguration()); + return !getLastReportedConfiguration().equals(getConfiguration()); } void onWindowReplacementTimeout() { @@ -2312,8 +2312,16 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP outConfiguration.setConfiguration(globalConfig, overrideConfig); } - void setReportedConfiguration(MergedConfiguration config) { - mLastReportedConfiguration.setTo(config.getMergedConfiguration()); + void setLastReportedMergedConfiguration(MergedConfiguration config) { + mLastReportedConfiguration.setTo(config); + } + + void getLastReportedMergedConfiguration(MergedConfiguration config) { + config.setTo(mLastReportedConfiguration); + } + + private Configuration getLastReportedConfiguration() { + return mLastReportedConfiguration.getMergedConfiguration(); } void adjustStartingWindowFlags() { @@ -2853,7 +2861,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP new MergedConfiguration(mService.mRoot.getConfiguration(), getMergedOverrideConfiguration()); - setReportedConfiguration(mergedConfiguration); + setLastReportedMergedConfiguration(mergedConfiguration); if (DEBUG_ORIENTATION && mWinAnimator.mDrawState == DRAW_PENDING) Slog.i(TAG, "Resizing " + this + " WITH DRAW PENDING"); @@ -3173,7 +3181,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP pw.print(" mShowToOwnerOnly="); pw.print(mShowToOwnerOnly); pw.print(" package="); pw.print(mAttrs.packageName); pw.print(" appop="); pw.println(AppOpsManager.opToName(mAppOp)); - pw.print(prefix); pw.print("mAttrs="); pw.println(mAttrs); + pw.print(prefix); pw.print("mAttrs="); pw.println(mAttrs.toString(prefix)); pw.print(prefix); pw.print("Requested w="); pw.print(mRequestedWidth); pw.print(" h="); pw.print(mRequestedHeight); pw.print(" mLayoutSeq="); pw.println(mLayoutSeq); @@ -3254,7 +3262,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP } pw.print(prefix); pw.print("mFullConfiguration="); pw.println(getConfiguration()); pw.print(prefix); pw.print("mLastReportedConfiguration="); - pw.println(mLastReportedConfiguration); + pw.println(getLastReportedConfiguration()); } pw.print(prefix); pw.print("mHasSurface="); pw.print(mHasSurface); pw.print(" mShownPosition="); mShownPosition.printShortString(pw); @@ -3314,7 +3322,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP pw.print(prefix); pw.print("mOrientationChanging="); pw.print(mOrientationChanging); pw.print(" configOrientationChanging="); - pw.print(mLastReportedConfiguration.orientation + pw.print(getLastReportedConfiguration().orientation != getConfiguration().orientation); pw.print(" mAppFreezing="); pw.print(mAppFreezing); pw.print(" mTurnOnScreen="); pw.print(mTurnOnScreen); diff --git a/services/core/jni/Android.mk b/services/core/jni/Android.mk index bf9f941ad9a3..9655637933ad 100644 --- a/services/core/jni/Android.mk +++ b/services/core/jni/Android.mk @@ -78,7 +78,6 @@ LOCAL_SHARED_LIBRARIES += \ libschedulerservicehidl \ libsensorservice \ libsensorservicehidl \ - libskia \ libgui \ libusbhost \ libsuspend \ diff --git a/services/core/jni/com_android_server_UsbDescriptorParser.cpp b/services/core/jni/com_android_server_UsbDescriptorParser.cpp index 98c5ec1bd4d5..df85e318619a 100644 --- a/services/core/jni/com_android_server_UsbDescriptorParser.cpp +++ b/services/core/jni/com_android_server_UsbDescriptorParser.cpp @@ -18,7 +18,7 @@ #include "utils/Log.h" #include "jni.h" -#include "JNIHelp.h" +#include <nativehelper/JNIHelp.h> #include <usbhost/usbhost.h> diff --git a/services/core/jni/com_android_server_locksettings_SyntheticPasswordManager.cpp b/services/core/jni/com_android_server_locksettings_SyntheticPasswordManager.cpp index 248dedb7832b..bc13fdec6cbc 100644 --- a/services/core/jni/com_android_server_locksettings_SyntheticPasswordManager.cpp +++ b/services/core/jni/com_android_server_locksettings_SyntheticPasswordManager.cpp @@ -16,7 +16,7 @@ #define LOG_TAG "SyntheticPasswordManager" -#include "JNIHelp.h" +#include <nativehelper/JNIHelp.h> #include "jni.h" #include <android_runtime/Log.h> diff --git a/services/core/jni/com_android_server_power_PowerManagerService.cpp b/services/core/jni/com_android_server_power_PowerManagerService.cpp index 39f90ca47995..b6c3df707c31 100644 --- a/services/core/jni/com_android_server_power_PowerManagerService.cpp +++ b/services/core/jni/com_android_server_power_PowerManagerService.cpp @@ -19,7 +19,7 @@ //#define LOG_NDEBUG 0 #include <android/hardware/power/1.1/IPower.h> -#include "JNIHelp.h" +#include <nativehelper/JNIHelp.h> #include "jni.h" #include <nativehelper/ScopedUtfChars.h> diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java index 948c028d46ca..2e939b75d432 100644 --- a/services/java/com/android/server/SystemServer.java +++ b/services/java/com/android/server/SystemServer.java @@ -682,6 +682,7 @@ public final class SystemServer { VibratorService vibrator = null; IStorageManager storageManager = null; NetworkManagementService networkManagement = null; + IpSecService ipSecService = null; NetworkStatsService networkStats = null; NetworkPolicyManagerService networkPolicy = null; ConnectivityService connectivity = null; @@ -1031,6 +1032,15 @@ public final class SystemServer { reportWtf("starting NetworkManagement Service", e); } traceEnd(); + + traceBeginAndSlog("StartIpSecService"); + try { + ipSecService = IpSecService.create(context); + ServiceManager.addService(Context.IPSEC_SERVICE, ipSecService); + } catch (Throwable e) { + reportWtf("starting IpSec Service", e); + } + traceEnd(); } if (!disableNonCoreServices && !disableTextServices) { @@ -1654,6 +1664,7 @@ public final class SystemServer { final TelephonyRegistry telephonyRegistryF = telephonyRegistry; final MediaRouterService mediaRouterF = mediaRouter; final MmsServiceBroker mmsServiceF = mmsService; + final IpSecService ipSecServiceF = ipSecService; final WindowManagerService windowManagerF = wm; // We now tell the activity manager it is okay to run third party @@ -1724,6 +1735,13 @@ public final class SystemServer { .networkScoreAndNetworkManagementServiceReady(); } traceEnd(); + traceBeginAndSlog("MakeIpSecServiceReady"); + try { + if (ipSecServiceF != null) ipSecServiceF.systemReady(); + } catch (Throwable e) { + reportWtf("making IpSec Service ready", e); + } + traceEnd(); traceBeginAndSlog("MakeNetworkStatsServiceReady"); try { if (networkStatsF != null) networkStatsF.systemReady(); diff --git a/services/tests/notification/src/com/android/server/notification/BuzzBeepBlinkTest.java b/services/tests/notification/src/com/android/server/notification/BuzzBeepBlinkTest.java index 529ac3a192ae..9fa1d68b8628 100644 --- a/services/tests/notification/src/com/android/server/notification/BuzzBeepBlinkTest.java +++ b/services/tests/notification/src/com/android/server/notification/BuzzBeepBlinkTest.java @@ -558,6 +558,7 @@ public class BuzzBeepBlinkTest extends NotificationTestCase { // the phone is quiet when(mAudioManager.getRingerModeInternal()).thenReturn(AudioManager.RINGER_MODE_VIBRATE); + when(mAudioManager.getStreamVolume(anyInt())).thenReturn(0); mService.buzzBeepBlinkLocked(r); @@ -568,6 +569,22 @@ public class BuzzBeepBlinkTest extends NotificationTestCase { } @Test + public void testNoDemoteSoundToVibrateIfNonNotificationStream() throws Exception { + NotificationRecord r = getBeepyNotification(); + assertTrue(r.getSound() != null); + assertNull(r.getVibration()); + + // the phone is quiet + when(mAudioManager.getRingerModeInternal()).thenReturn(AudioManager.RINGER_MODE_VIBRATE); + when(mAudioManager.getStreamVolume(anyInt())).thenReturn(1); + + mService.buzzBeepBlinkLocked(r); + + verifyNeverVibrate(); + verifyBeepLooped(); + } + + @Test public void testDemoteSoundToVibrate() throws Exception { NotificationRecord r = getBeepyNotification(); assertTrue(r.getSound() != null); @@ -575,6 +592,7 @@ public class BuzzBeepBlinkTest extends NotificationTestCase { // the phone is quiet when(mAudioManager.getRingerModeInternal()).thenReturn(AudioManager.RINGER_MODE_VIBRATE); + when(mAudioManager.getStreamVolume(anyInt())).thenReturn(0); mService.buzzBeepBlinkLocked(r); diff --git a/services/tests/servicestests/src/com/android/server/am/UserControllerTest.java b/services/tests/servicestests/src/com/android/server/am/UserControllerTest.java index 419a161669aa..d6d0209bca7d 100644 --- a/services/tests/servicestests/src/com/android/server/am/UserControllerTest.java +++ b/services/tests/servicestests/src/com/android/server/am/UserControllerTest.java @@ -30,6 +30,7 @@ import android.os.Looper; import android.os.Message; import android.os.RemoteException; import android.os.UserManagerInternal; +import android.platform.test.annotations.Presubmit; import android.test.AndroidTestCase; import android.test.suitebuilder.annotation.SmallTest; import android.util.Log; @@ -59,14 +60,20 @@ import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.Matchers.any; import static org.mockito.Matchers.anyBoolean; import static org.mockito.Matchers.anyInt; +import static org.mockito.Matchers.anyString; import static org.mockito.Matchers.eq; import static org.mockito.Mockito.doAnswer; +import static org.mockito.Mockito.doNothing; +import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verifyZeroInteractions; import static org.mockito.Mockito.when; +/** + * Usage: bit FrameworksServicesTests:com.android.server.am.UserControllerTest + */ +@Presubmit public class UserControllerTest extends AndroidTestCase { private static final int TEST_USER_ID = 10; private static final int NONEXIST_USER_ID = 2; @@ -96,8 +103,11 @@ public class UserControllerTest extends AndroidTestCase { @Override public void setUp() throws Exception { super.setUp(); - System.setProperty("dexmaker.share_classloader", "true"); - mInjector = new TestInjector(getContext()); + mInjector = Mockito.spy(new TestInjector(getContext())); + doNothing().when(mInjector).clearLockTaskMode(anyString()); + doNothing().when(mInjector).startHomeActivity(anyInt(), anyString()); + doReturn(false).when(mInjector).stackSupervisorSwitchUser(anyInt(), any()); + doNothing().when(mInjector).stackSupervisorResumeFocusedStackTopActivity(); mUserController = new UserController(mInjector); setUpUser(TEST_USER_ID, 0); } @@ -106,6 +116,7 @@ public class UserControllerTest extends AndroidTestCase { protected void tearDown() throws Exception { super.tearDown(); mInjector.handlerThread.quit(); + Mockito.validateMockitoUsage(); } @SmallTest @@ -115,7 +126,7 @@ public class UserControllerTest extends AndroidTestCase { Mockito.verify(mInjector.getWindowManager(), never()).stopFreezingScreen(); Mockito.verify(mInjector.getWindowManager(), times(1)).setSwitchingUser(anyBoolean()); Mockito.verify(mInjector.getWindowManager()).setSwitchingUser(true); - Mockito.verify(mInjector.getLockTaskController()).clearLockTaskMode(anyString()); + Mockito.verify(mInjector).clearLockTaskMode(anyString()); startForegroundUserAssertions(); } @@ -125,7 +136,7 @@ public class UserControllerTest extends AndroidTestCase { Mockito.verify( mInjector.getWindowManager(), never()).startFreezingScreen(anyInt(), anyInt()); Mockito.verify(mInjector.getWindowManager(), never()).setSwitchingUser(anyBoolean()); - verifyZeroInteractions(mInjector.getLockTaskController()); + Mockito.verify(mInjector, never()).clearLockTaskMode(anyString()); startBackgroundUserAssertions(); } @@ -306,16 +317,14 @@ public class UserControllerTest extends AndroidTestCase { return result; } - private static class TestInjector extends UserController.Injector { - final Object lock = new Object(); + // Should be public to allow mocking + public static class TestInjector extends UserController.Injector { TestHandler handler; TestHandler uiHandler; HandlerThread handlerThread; UserManagerService userManagerMock; UserManagerInternal userManagerInternalMock; WindowManagerService windowManagerMock; - ActivityStackSupervisor activityStackSupervisor; - LockTaskController lockTaskController; private Context mCtx; List<Intent> sentIntents = new ArrayList<>(); @@ -329,13 +338,6 @@ public class UserControllerTest extends AndroidTestCase { userManagerMock = mock(UserManagerService.class); userManagerInternalMock = mock(UserManagerInternal.class); windowManagerMock = mock(WindowManagerService.class); - activityStackSupervisor = mock(ActivityStackSupervisor.class); - lockTaskController = mock(LockTaskController.class); - } - - @Override - protected Object getLock() { - return lock; } @Override @@ -375,12 +377,12 @@ public class UserControllerTest extends AndroidTestCase { } @Override - void updateUserConfigurationLocked() { - Log.i(TAG, "updateUserConfigurationLocked"); + void updateUserConfiguration() { + Log.i(TAG, "updateUserConfiguration"); } @Override - protected int broadcastIntentLocked(Intent intent, String resolvedType, + protected int broadcastIntent(Intent intent, String resolvedType, IIntentReceiver resultTo, int resultCode, String resultData, Bundle resultExtras, String[] requiredPermissions, int appOp, Bundle bOptions, boolean ordered, boolean sticky, int callingPid, int callingUid, int userId) { @@ -388,20 +390,6 @@ public class UserControllerTest extends AndroidTestCase { sentIntents.add(intent); return 0; } - - @Override - void startHomeActivityLocked(int userId, String reason) { - Log.i(TAG, "startHomeActivityLocked " + userId); - } - - @Override - ActivityStackSupervisor getActivityStackSupervisor() { - return activityStackSupervisor; - } - - LockTaskController getLockTaskController() { - return lockTaskController; - } } private static class TestHandler extends Handler { diff --git a/services/tests/servicestests/src/com/android/server/locksettings/BaseLockSettingsServiceTests.java b/services/tests/servicestests/src/com/android/server/locksettings/BaseLockSettingsServiceTests.java index 13cf9df01a4e..7cba28050780 100644 --- a/services/tests/servicestests/src/com/android/server/locksettings/BaseLockSettingsServiceTests.java +++ b/services/tests/servicestests/src/com/android/server/locksettings/BaseLockSettingsServiceTests.java @@ -106,7 +106,8 @@ public class BaseLockSettingsServiceTests extends AndroidTestCase { return mService; } }; - mSpManager = new MockSyntheticPasswordManager(mStorage, mGateKeeperService, mUserManager); + mSpManager = new MockSyntheticPasswordManager(mContext, mStorage, mGateKeeperService, + mUserManager); mService = new LockSettingsServiceTestable(mContext, mLockPatternUtils, mStorage, mGateKeeperService, mKeyStore, setUpStorageManagerMock(), mActivityManager, mSpManager); diff --git a/services/tests/servicestests/src/com/android/server/locksettings/MockSyntheticPasswordManager.java b/services/tests/servicestests/src/com/android/server/locksettings/MockSyntheticPasswordManager.java index cf035932322d..6f681797b88a 100644 --- a/services/tests/servicestests/src/com/android/server/locksettings/MockSyntheticPasswordManager.java +++ b/services/tests/servicestests/src/com/android/server/locksettings/MockSyntheticPasswordManager.java @@ -15,6 +15,7 @@ */ package com.android.server.locksettings; +import android.content.Context; import android.hardware.weaver.V1_0.IWeaver; import android.os.RemoteException; import android.os.UserManager; @@ -35,9 +36,9 @@ public class MockSyntheticPasswordManager extends SyntheticPasswordManager { private FakeGateKeeperService mGateKeeper; private IWeaver mWeaverService; - public MockSyntheticPasswordManager(LockSettingsStorage storage, + public MockSyntheticPasswordManager(Context context, LockSettingsStorage storage, FakeGateKeeperService gatekeeper, UserManager userManager) { - super(storage, userManager); + super(context, storage, userManager); mGateKeeper = gatekeeper; } diff --git a/services/tests/servicestests/src/com/android/server/locksettings/SyntheticPasswordTests.java b/services/tests/servicestests/src/com/android/server/locksettings/SyntheticPasswordTests.java index 2c9aa9d6a245..2ad05801916a 100644 --- a/services/tests/servicestests/src/com/android/server/locksettings/SyntheticPasswordTests.java +++ b/services/tests/servicestests/src/com/android/server/locksettings/SyntheticPasswordTests.java @@ -58,7 +58,7 @@ public class SyntheticPasswordTests extends BaseLockSettingsServiceTests { final int USER_ID = 10; final String PASSWORD = "user-password"; final String BADPASSWORD = "bad-password"; - MockSyntheticPasswordManager manager = new MockSyntheticPasswordManager(mStorage, + MockSyntheticPasswordManager manager = new MockSyntheticPasswordManager(mContext, mStorage, mGateKeeperService, mUserManager); AuthenticationToken authToken = manager.newSyntheticPasswordAndSid(mGateKeeperService, null, null, USER_ID); diff --git a/services/tests/servicestests/src/com/android/server/storage/DiskStatsLoggingServiceTest.java b/services/tests/servicestests/src/com/android/server/storage/DiskStatsLoggingServiceTest.java index 375edf3cb5ae..b647b99df894 100644 --- a/services/tests/servicestests/src/com/android/server/storage/DiskStatsLoggingServiceTest.java +++ b/services/tests/servicestests/src/com/android/server/storage/DiskStatsLoggingServiceTest.java @@ -149,11 +149,13 @@ public class DiskStatsLoggingServiceTest extends AndroidTestCase { assertThat(json.getLong(DiskStatsFileLogger.DOWNLOADS_KEY)).isEqualTo(3L); assertThat(json.getLong(DiskStatsFileLogger.SYSTEM_KEY)).isEqualTo(10L); assertThat(json.getLong(DiskStatsFileLogger.MISC_KEY)).isEqualTo(7L); - assertThat(json.getLong(DiskStatsFileLogger.APP_SIZE_AGG_KEY)).isEqualTo(15L); + assertThat(json.getLong(DiskStatsFileLogger.APP_SIZE_AGG_KEY)).isEqualTo(10L); + assertThat(json.getLong(DiskStatsFileLogger.APP_DATA_SIZE_AGG_KEY)).isEqualTo(5L); assertThat(json.getLong(DiskStatsFileLogger.APP_CACHE_AGG_KEY)).isEqualTo(55L); assertThat( json.getJSONArray(DiskStatsFileLogger.PACKAGE_NAMES_KEY).length()).isEqualTo(1L); assertThat(json.getJSONArray(DiskStatsFileLogger.APP_SIZES_KEY).length()).isEqualTo(1L); + assertThat(json.getJSONArray(DiskStatsFileLogger.APP_DATA_KEY).length()).isEqualTo(1L); assertThat(json.getJSONArray(DiskStatsFileLogger.APP_CACHES_KEY).length()).isEqualTo(1L); } diff --git a/services/tests/servicestests/src/com/android/server/wm/WindowTestUtils.java b/services/tests/servicestests/src/com/android/server/wm/WindowTestUtils.java index 0315c8d6f9ba..1aafac66bae4 100644 --- a/services/tests/servicestests/src/com/android/server/wm/WindowTestUtils.java +++ b/services/tests/servicestests/src/com/android/server/wm/WindowTestUtils.java @@ -32,6 +32,7 @@ import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED; import static android.content.res.Configuration.EMPTY; import static com.android.server.wm.WindowContainer.POSITION_TOP; import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; /** * A collection of static functions that can be referenced by other test packages to provide access @@ -51,7 +52,10 @@ public class WindowTestUtils { * Retrieves an instance of a mock {@link WindowManagerService}. */ public static WindowManagerService getMockWindowManagerService() { - return mock(WindowManagerService.class); + final WindowManagerService service = mock(WindowManagerService.class); + final WindowHashMap windowMap = new WindowHashMap(); + when(service.getWindowManagerLock()).thenReturn(windowMap); + return service; } /** diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java index cde0bdfd08b0..c0564c55a7e0 100644 --- a/telephony/java/android/telephony/TelephonyManager.java +++ b/telephony/java/android/telephony/TelephonyManager.java @@ -107,8 +107,6 @@ public class TelephonyManager { public static final String MODEM_ACTIVITY_RESULT_KEY = BatteryStats.RESULT_RECEIVER_CONTROLLER_KEY; - private static ITelephonyRegistry sRegistry; - /** * The allowed states of Wi-Fi calling. * @@ -179,11 +177,6 @@ public class TelephonyManager { mContext = context; } mSubscriptionManager = SubscriptionManager.from(mContext); - - if (sRegistry == null) { - sRegistry = ITelephonyRegistry.Stub.asInterface(ServiceManager.getService( - "telephony.registry")); - } } /** @hide */ @@ -3513,6 +3506,10 @@ public class TelephonyManager { return ITelecomService.Stub.asInterface(ServiceManager.getService(Context.TELECOM_SERVICE)); } + private ITelephonyRegistry getTelephonyRegistry() { + return ITelephonyRegistry.Stub.asInterface(ServiceManager.getService("telephony.registry")); + } + // // // PhoneStateListener @@ -3552,12 +3549,16 @@ public class TelephonyManager { if (listener.mSubId == null) { listener.mSubId = mSubId; } - sRegistry.listenForSubscriber(listener.mSubId, getOpPackageName(), - listener.callback, events, notifyNow); + + ITelephonyRegistry registry = getTelephonyRegistry(); + if (registry != null) { + registry.listenForSubscriber(listener.mSubId, getOpPackageName(), + listener.callback, events, notifyNow); + } else { + Rlog.w(TAG, "telephony registry not ready."); + } } catch (RemoteException ex) { // system process dead - } catch (NullPointerException ex) { - // system process dead } } diff --git a/tests/net/java/com/android/internal/util/RingBufferTest.java b/tests/net/java/com/android/internal/util/RingBufferTest.java new file mode 100644 index 000000000000..7a2344317223 --- /dev/null +++ b/tests/net/java/com/android/internal/util/RingBufferTest.java @@ -0,0 +1,145 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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.internal.util; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.fail; + +import android.support.test.filters.SmallTest; +import android.support.test.runner.AndroidJUnit4; + +import org.junit.Test; +import org.junit.runner.RunWith; +import java.util.Arrays; +import java.util.Objects; + + +@SmallTest +@RunWith(AndroidJUnit4.class) +public class RingBufferTest { + + @Test + public void testEmptyRingBuffer() { + RingBuffer<String> buffer = new RingBuffer<>(String.class, 100); + + assertArraysEqual(new String[0], buffer.toArray()); + } + + @Test + public void testIncorrectConstructorArguments() { + try { + RingBuffer<String> buffer = new RingBuffer<>(String.class, -10); + fail("Should not be able to create a negative capacity RingBuffer"); + } catch (IllegalArgumentException expected) { + } + + try { + RingBuffer<String> buffer = new RingBuffer<>(String.class, 0); + fail("Should not be able to create a 0 capacity RingBuffer"); + } catch (IllegalArgumentException expected) { + } + } + + @Test + public void testRingBufferWithNoWrapping() { + RingBuffer<String> buffer = new RingBuffer<>(String.class, 100); + + buffer.append("a"); + buffer.append("b"); + buffer.append("c"); + buffer.append("d"); + buffer.append("e"); + + String[] expected = {"a", "b", "c", "d", "e"}; + assertArraysEqual(expected, buffer.toArray()); + } + + @Test + public void testRingBufferWithCapacity1() { + RingBuffer<String> buffer = new RingBuffer<>(String.class, 1); + + buffer.append("a"); + assertArraysEqual(new String[]{"a"}, buffer.toArray()); + + buffer.append("b"); + assertArraysEqual(new String[]{"b"}, buffer.toArray()); + + buffer.append("c"); + assertArraysEqual(new String[]{"c"}, buffer.toArray()); + + buffer.append("d"); + assertArraysEqual(new String[]{"d"}, buffer.toArray()); + + buffer.append("e"); + assertArraysEqual(new String[]{"e"}, buffer.toArray()); + } + + @Test + public void testRingBufferWithWrapping() { + int capacity = 100; + RingBuffer<String> buffer = new RingBuffer<>(String.class, capacity); + + buffer.append("a"); + buffer.append("b"); + buffer.append("c"); + buffer.append("d"); + buffer.append("e"); + + String[] expected1 = {"a", "b", "c", "d", "e"}; + assertArraysEqual(expected1, buffer.toArray()); + + String[] expected2 = new String[capacity]; + int firstIndex = 0; + int lastIndex = capacity - 1; + + expected2[firstIndex] = "e"; + for (int i = 1; i < capacity; i++) { + buffer.append("x"); + expected2[i] = "x"; + } + assertArraysEqual(expected2, buffer.toArray()); + + buffer.append("x"); + expected2[firstIndex] = "x"; + assertArraysEqual(expected2, buffer.toArray()); + + for (int i = 0; i < 10; i++) { + for (String s : expected2) { + buffer.append(s); + } + } + assertArraysEqual(expected2, buffer.toArray()); + + buffer.append("a"); + expected2[lastIndex] = "a"; + assertArraysEqual(expected2, buffer.toArray()); + } + + static <T> void assertArraysEqual(T[] expected, T[] got) { + if (expected.length != got.length) { + fail(Arrays.toString(expected) + " and " + Arrays.toString(got) + + " did not have the same length"); + } + + for (int i = 0; i < expected.length; i++) { + if (!Objects.equals(expected[i], got[i])) { + fail(Arrays.toString(expected) + " and " + Arrays.toString(got) + + " were not equal"); + } + } + } +} diff --git a/tests/net/java/com/android/server/ConnectivityServiceTest.java b/tests/net/java/com/android/server/ConnectivityServiceTest.java index a8147380386f..9c498c795443 100644 --- a/tests/net/java/com/android/server/ConnectivityServiceTest.java +++ b/tests/net/java/com/android/server/ConnectivityServiceTest.java @@ -19,6 +19,8 @@ package com.android.server; import static android.net.ConnectivityManager.CONNECTIVITY_ACTION; import static android.net.ConnectivityManager.TYPE_ETHERNET; import static android.net.ConnectivityManager.TYPE_MOBILE; +import static android.net.ConnectivityManager.TYPE_MOBILE_FOTA; +import static android.net.ConnectivityManager.TYPE_MOBILE_MMS; import static android.net.ConnectivityManager.TYPE_NONE; import static android.net.ConnectivityManager.TYPE_WIFI; import static android.net.ConnectivityManager.getNetworkTypeName; @@ -782,6 +784,13 @@ public class ConnectivityServiceTest extends AndroidTestCase { return new FakeWakeupMessage(context, handler, cmdName, cmd, 0, 0, obj); } + @Override + public boolean hasService(String name) { + // Currenty, the only relevant service that ConnectivityService checks for is + // ETHERNET_SERVICE. + return Context.ETHERNET_SERVICE.equals(name); + } + public WrappedNetworkMonitor getLastCreatedWrappedNetworkMonitor() { return mLastCreatedNetworkMonitor; } @@ -929,6 +938,13 @@ public class ConnectivityServiceTest extends AndroidTestCase { // will fail. Failing here is much easier to debug. assertTrue(mCm.isNetworkSupported(TYPE_WIFI)); assertTrue(mCm.isNetworkSupported(TYPE_MOBILE)); + assertTrue(mCm.isNetworkSupported(TYPE_MOBILE_MMS)); + assertFalse(mCm.isNetworkSupported(TYPE_MOBILE_FOTA)); + + // Check that TYPE_ETHERNET is supported. Unlike the asserts above, which only validate our + // mocks, this assert exercises the ConnectivityService code path that ensures that + // TYPE_ETHERNET is supported if the ethernet service is running. + assertTrue(mCm.isNetworkSupported(TYPE_ETHERNET)); } @SmallTest diff --git a/tests/net/java/com/android/server/connectivity/Nat464XlatTest.java b/tests/net/java/com/android/server/connectivity/Nat464XlatTest.java index de28de6b3185..dfe31bde4ecf 100644 --- a/tests/net/java/com/android/server/connectivity/Nat464XlatTest.java +++ b/tests/net/java/com/android/server/connectivity/Nat464XlatTest.java @@ -126,7 +126,6 @@ public class Nat464XlatTest { mLooper.dispatchNext(); verify(mNms).getInterfaceConfig(eq(STACKED_IFACE)); - verify(mNms).setInterfaceIpv6NdOffload(eq(BASE_IFACE), eq(false)); verify(mConnectivity).handleUpdateLinkProperties(eq(mNai), c.capture()); assertFalse(c.getValue().getStackedLinks().isEmpty()); assertTrue(c.getValue().getAllInterfaceNames().contains(STACKED_IFACE)); @@ -136,7 +135,6 @@ public class Nat464XlatTest { nat.stop(); verify(mNms).stopClatd(eq(BASE_IFACE)); - verify(mNms).setInterfaceIpv6NdOffload(eq(BASE_IFACE), eq(true)); // Stacked interface removed notification arrives. nat.interfaceRemoved(STACKED_IFACE); @@ -167,7 +165,6 @@ public class Nat464XlatTest { mLooper.dispatchNext(); verify(mNms).getInterfaceConfig(eq(STACKED_IFACE)); - verify(mNms).setInterfaceIpv6NdOffload(eq(BASE_IFACE), eq(false)); verify(mConnectivity, times(1)).handleUpdateLinkProperties(eq(mNai), c.capture()); assertFalse(c.getValue().getStackedLinks().isEmpty()); assertTrue(c.getValue().getAllInterfaceNames().contains(STACKED_IFACE)); @@ -179,7 +176,6 @@ public class Nat464XlatTest { verify(mNms).unregisterObserver(eq(nat)); verify(mNms).stopClatd(eq(BASE_IFACE)); - verify(mNms).setInterfaceIpv6NdOffload(eq(BASE_IFACE), eq(true)); verify(mConnectivity, times(2)).handleUpdateLinkProperties(eq(mNai), c.capture()); assertTrue(c.getValue().getStackedLinks().isEmpty()); assertFalse(c.getValue().getAllInterfaceNames().contains(STACKED_IFACE)); diff --git a/tools/aapt2/Android.bp b/tools/aapt2/Android.bp index 43918da75ad4..f0ebf10ec527 100644 --- a/tools/aapt2/Android.bp +++ b/tools/aapt2/Android.bp @@ -139,6 +139,7 @@ cc_library_host_static { "xml/XmlDom.cpp", "xml/XmlPullParser.cpp", "xml/XmlUtil.cpp", + "Configuration.proto", "Resources.proto", "ResourcesInternal.proto", ], diff --git a/tools/aapt2/ConfigDescription.cpp b/tools/aapt2/ConfigDescription.cpp index a9278c136cff..59a6e1281783 100644 --- a/tools/aapt2/ConfigDescription.cpp +++ b/tools/aapt2/ConfigDescription.cpp @@ -876,6 +876,12 @@ ConfigDescription ConfigDescription::CopyWithoutSdkVersion() const { return copy; } +std::string ConfigDescription::GetBcp47LanguageTag(bool canonicalize) const { + char locale[RESTABLE_MAX_LOCALE_LEN]; + getBcp47Locale(locale, canonicalize); + return std::string(locale); +} + bool ConfigDescription::Dominates(const ConfigDescription& o) const { if (*this == o) { return true; diff --git a/tools/aapt2/ConfigDescription.h b/tools/aapt2/ConfigDescription.h index 65c96175091c..c1d0e1084186 100644 --- a/tools/aapt2/ConfigDescription.h +++ b/tools/aapt2/ConfigDescription.h @@ -61,6 +61,9 @@ struct ConfigDescription : public android::ResTable_config { ConfigDescription CopyWithoutSdkVersion() const; + // Returns the BCP-47 language tag of this configuration's locale. + std::string GetBcp47LanguageTag(bool canonicalize = false) const; + /** * A configuration X dominates another configuration Y, if X has at least the * precedence of Y and X is strictly more general than Y: for any type defined diff --git a/tools/aapt2/Configuration.proto b/tools/aapt2/Configuration.proto new file mode 100644 index 000000000000..fc636a43ec40 --- /dev/null +++ b/tools/aapt2/Configuration.proto @@ -0,0 +1,207 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +syntax = "proto3"; + +package aapt.pb; + +option java_package = "com.android.aapt"; +option optimize_for = LITE_RUNTIME; + +// A description of the requirements a device must have in order for a +// resource to be matched and selected. +message Configuration { + enum LayoutDirection { + LAYOUT_DIRECTION_UNSET = 0; + LAYOUT_DIRECTION_LTR = 1; + LAYOUT_DIRECTION_RTL = 2; + } + + enum ScreenLayoutSize { + SCREEN_LAYOUT_SIZE_UNSET = 0; + SCREEN_LAYOUT_SIZE_SMALL = 1; + SCREEN_LAYOUT_SIZE_NORMAL = 2; + SCREEN_LAYOUT_SIZE_LARGE = 3; + SCREEN_LAYOUT_SIZE_XLARGE = 4; + } + + enum ScreenLayoutLong { + SCREEN_LAYOUT_LONG_UNSET = 0; + SCREEN_LAYOUT_LONG_LONG = 1; + SCREEN_LAYOUT_LONG_NOTLONG = 2; + } + + enum ScreenRound { + SCREEN_ROUND_UNSET = 0; + SCREEN_ROUND_ROUND = 1; + SCREEN_ROUND_NOTROUND = 2; + } + + enum WideColorGamut { + WIDE_COLOR_GAMUT_UNSET = 0; + WIDE_COLOR_GAMUT_WIDECG = 1; + WIDE_COLOR_GAMUT_NOWIDECG = 2; + } + + enum Hdr { + HDR_UNSET = 0; + HDR_HIGHDR = 1; + HDR_LOWDR = 2; + } + + enum Orientation { + ORIENTATION_UNSET = 0; + ORIENTATION_PORT = 1; + ORIENTATION_LAND = 2; + ORIENTATION_SQUARE = 3; + } + + enum UiModeType { + UI_MODE_TYPE_UNSET = 0; + UI_MODE_TYPE_NORMAL = 1; + UI_MODE_TYPE_DESK = 2; + UI_MODE_TYPE_CAR = 3; + UI_MODE_TYPE_TELEVISION = 4; + UI_MODE_TYPE_APPLIANCE = 5; + UI_MODE_TYPE_WATCH = 6; + UI_MODE_TYPE_VRHEADSET = 7; + } + + enum UiModeNight { + UI_MODE_NIGHT_UNSET = 0; + UI_MODE_NIGHT_NIGHT = 1; + UI_MODE_NIGHT_NOTNIGHT = 2; + } + + enum Touchscreen { + TOUCHSCREEN_UNSET = 0; + TOUCHSCREEN_NOTOUCH = 1; + TOUCHSCREEN_STYLUS = 2; + TOUCHSCREEN_FINGER = 3; + } + + enum KeysHidden { + KEYS_HIDDEN_UNSET = 0; + KEYS_HIDDEN_KEYSEXPOSED = 1; + KEYS_HIDDEN_KEYSHIDDEN = 2; + KEYS_HIDDEN_KEYSSOFT = 3; + } + + enum Keyboard { + KEYBOARD_UNSET = 0; + KEYBOARD_NOKEYS = 1; + KEYBOARD_QWERTY = 2; + KEYBOARD_TWELVEKEY = 3; + } + + enum NavHidden { + NAV_HIDDEN_UNSET = 0; + NAV_HIDDEN_NAVEXPOSED = 1; + NAV_HIDDEN_NAVHIDDEN = 2; + } + + enum Navigation { + NAVIGATION_UNSET = 0; + NAVIGATION_NONAV = 1; + NAVIGATION_DPAD = 2; + NAVIGATION_TRACKBALL = 3; + NAVIGATION_WHEEL = 4; + } + + // + // Axis/dimensions that are understood by the runtime. + // + + // Mobile country code. + uint32 mcc = 1; + + // Mobile network code. + uint32 mnc = 2; + + // BCP-47 locale tag. + string locale = 3; + + // Left-to-right, right-to-left... + LayoutDirection layout_direction = 4; + + // Screen width in pixels. Prefer screen_width_dp. + uint32 screen_width = 5; + + // Screen height in pixels. Prefer screen_height_dp. + uint32 screen_height = 6; + + // Screen width in density independent pixels (dp). + uint32 screen_width_dp = 7; + + // Screen height in density independent pixels (dp). + uint32 screen_height_dp = 8; + + // The smallest screen dimension, regardless of orientation, in dp. + uint32 smallest_screen_width_dp = 9; + + // Whether the device screen is classified as small, normal, large, xlarge. + ScreenLayoutSize screen_layout_size = 10; + + // Whether the device screen is long. + ScreenLayoutLong screen_layout_long = 11; + + // Whether the screen is round (Android Wear). + ScreenRound screen_round = 12; + + // Whether the screen supports wide color gamut. + WideColorGamut wide_color_gamut = 13; + + // Whether the screen has high dynamic range. + Hdr hdr = 14; + + // Which orientation the device is in (portrait, landscape). + Orientation orientation = 15; + + // Which type of UI mode the device is in (television, car, etc.). + UiModeType ui_mode_type = 16; + + // Whether the device is in night mode. + UiModeNight ui_mode_night = 17; + + // The device's screen density in dots-per-inch (dpi). + uint32 density = 18; + + // Whether a touchscreen exists, supports a stylus, or finger. + Touchscreen touchscreen = 19; + + // Whether the keyboard hardware keys are currently hidden, exposed, or + // if the keyboard is a software keyboard. + KeysHidden keys_hidden = 20; + + // The type of keyboard present (none, QWERTY, 12-key). + Keyboard keyboard = 21; + + // Whether the navigation is exposed or hidden. + NavHidden nav_hidden = 22; + + // The type of navigation present on the device + // (trackball, wheel, dpad, etc.). + Navigation navigation = 23; + + // The minimum SDK version of the device. + uint32 sdk_version = 24; + + // + // Build-time only dimensions. + // + + string product = 25; +} diff --git a/tools/aapt2/Locale.cpp b/tools/aapt2/Locale.cpp index 7664fac44be1..d81921f23904 100644 --- a/tools/aapt2/Locale.cpp +++ b/tools/aapt2/Locale.cpp @@ -24,9 +24,10 @@ #include "util/Util.h" -namespace aapt { +using ::android::ResTable_config; +using ::android::StringPiece; -using android::ResTable_config; +namespace aapt { void LocaleValue::set_language(const char* language_chars) { size_t i = 0; @@ -72,7 +73,7 @@ static inline bool is_number(const std::string& str) { return std::all_of(std::begin(str), std::end(str), ::isdigit); } -bool LocaleValue::InitFromFilterString(const android::StringPiece& str) { +bool LocaleValue::InitFromFilterString(const StringPiece& str) { // A locale (as specified in the filter) is an underscore separated name such // as "en_US", "en_Latn_US", or "en_US_POSIX". std::vector<std::string> parts = util::SplitAndLowercase(str, '_'); @@ -138,6 +139,71 @@ bool LocaleValue::InitFromFilterString(const android::StringPiece& str) { return true; } +bool LocaleValue::InitFromBcp47Tag(const StringPiece& bcp47tag) { + return InitFromBcp47TagImpl(bcp47tag, '-'); +} + +bool LocaleValue::InitFromBcp47TagImpl(const StringPiece& bcp47tag, const char separator) { + std::vector<std::string> subtags = util::SplitAndLowercase(bcp47tag, separator); + if (subtags.size() == 1) { + set_language(subtags[0].c_str()); + } else if (subtags.size() == 2) { + set_language(subtags[0].c_str()); + + // The second tag can either be a region, a variant or a script. + switch (subtags[1].size()) { + case 2: + case 3: + set_region(subtags[1].c_str()); + break; + case 4: + if ('0' <= subtags[1][0] && subtags[1][0] <= '9') { + // This is a variant: fall through + } else { + set_script(subtags[1].c_str()); + break; + } + case 5: + case 6: + case 7: + case 8: + set_variant(subtags[1].c_str()); + break; + default: + return false; + } + } else if (subtags.size() == 3) { + // The language is always the first subtag. + set_language(subtags[0].c_str()); + + // The second subtag can either be a script or a region code. + // If its size is 4, it's a script code, else it's a region code. + if (subtags[1].size() == 4) { + set_script(subtags[1].c_str()); + } else if (subtags[1].size() == 2 || subtags[1].size() == 3) { + set_region(subtags[1].c_str()); + } else { + return false; + } + + // The third tag can either be a region code (if the second tag was + // a script), else a variant code. + if (subtags[2].size() >= 4) { + set_variant(subtags[2].c_str()); + } else { + set_region(subtags[2].c_str()); + } + } else if (subtags.size() == 4) { + set_language(subtags[0].c_str()); + set_script(subtags[1].c_str()); + set_region(subtags[2].c_str()); + set_variant(subtags[3].c_str()); + } else { + return false; + } + return true; +} + ssize_t LocaleValue::InitFromParts(std::vector<std::string>::iterator iter, std::vector<std::string>::iterator end) { const std::vector<std::string>::iterator start_iter = iter; @@ -145,71 +211,13 @@ ssize_t LocaleValue::InitFromParts(std::vector<std::string>::iterator iter, std::string& part = *iter; if (part[0] == 'b' && part[1] == '+') { // This is a "modified" BCP 47 language tag. Same semantics as BCP 47 tags, - // except that the separator is "+" and not "-". - std::vector<std::string> subtags = util::SplitAndLowercase(part, '+'); - subtags.erase(subtags.begin()); - if (subtags.size() == 1) { - set_language(subtags[0].c_str()); - } else if (subtags.size() == 2) { - set_language(subtags[0].c_str()); - - // The second tag can either be a region, a variant or a script. - switch (subtags[1].size()) { - case 2: - case 3: - set_region(subtags[1].c_str()); - break; - case 4: - if ('0' <= subtags[1][0] && subtags[1][0] <= '9') { - // This is a variant: fall through - } else { - set_script(subtags[1].c_str()); - break; - } - case 5: - case 6: - case 7: - case 8: - set_variant(subtags[1].c_str()); - break; - default: - return -1; - } - } else if (subtags.size() == 3) { - // The language is always the first subtag. - set_language(subtags[0].c_str()); - - // The second subtag can either be a script or a region code. - // If its size is 4, it's a script code, else it's a region code. - if (subtags[1].size() == 4) { - set_script(subtags[1].c_str()); - } else if (subtags[1].size() == 2 || subtags[1].size() == 3) { - set_region(subtags[1].c_str()); - } else { - return -1; - } - - // The third tag can either be a region code (if the second tag was - // a script), else a variant code. - if (subtags[2].size() >= 4) { - set_variant(subtags[2].c_str()); - } else { - set_region(subtags[2].c_str()); - } - } else if (subtags.size() == 4) { - set_language(subtags[0].c_str()); - set_script(subtags[1].c_str()); - set_region(subtags[2].c_str()); - set_variant(subtags[3].c_str()); - } else { + // except that the separator is "+" and not "-". Skip the prefix 'b+'. + if (!InitFromBcp47TagImpl(StringPiece(part).substr(2), '+')) { return -1; } - ++iter; - } else { - if ((part.length() == 2 || part.length() == 3) && is_alpha(part) && - part != "car") { + if ((part.length() == 2 || part.length() == 3) && is_alpha(part) && part != "car") { set_language(part.c_str()); ++iter; @@ -222,7 +230,6 @@ ssize_t LocaleValue::InitFromParts(std::vector<std::string>::iterator iter, } } } - return static_cast<ssize_t>(iter - start_iter); } diff --git a/tools/aapt2/Locale.h b/tools/aapt2/Locale.h index 3d73b2eb17bf..6d8b598415cc 100644 --- a/tools/aapt2/Locale.h +++ b/tools/aapt2/Locale.h @@ -41,6 +41,9 @@ struct LocaleValue { */ bool InitFromFilterString(const android::StringPiece& config); + // Initializes this LocaleValue from a BCP-47 locale tag. + bool InitFromBcp47Tag(const android::StringPiece& bcp47tag); + /** * Initialize this LocaleValue from parts of a vector. */ @@ -67,6 +70,8 @@ struct LocaleValue { inline bool operator>(const LocaleValue& o) const; private: + bool InitFromBcp47TagImpl(const android::StringPiece& bcp47tag, const char separator); + void set_language(const char* language); void set_region(const char* language); void set_script(const char* script); diff --git a/tools/aapt2/Resources.proto b/tools/aapt2/Resources.proto index 71f33b0853ad..174b7f6b7c8c 100644 --- a/tools/aapt2/Resources.proto +++ b/tools/aapt2/Resources.proto @@ -14,77 +14,80 @@ * limitations under the License. */ -// Keep proto2 syntax because we require the distinction between fields that -// are set and unset. -syntax = "proto2"; +syntax = "proto3"; -option java_package = "com.android.aapt"; -option optimize_for = LITE_RUNTIME; +import "frameworks/base/tools/aapt2/Configuration.proto"; package aapt.pb; -// A configuration description that wraps the binary form of the C++ class -// aapt::ConfigDescription, with an added product definition. -// TODO(adamlesinski): Flesh this out to be represented in proto. -message ConfigDescription { - optional bytes data = 1; - optional string product = 2; -} +option java_package = "com.android.aapt"; +option optimize_for = LITE_RUNTIME; // A string pool that wraps the binary form of the C++ class android::ResStringPool. message StringPool { - optional bytes data = 1; + bytes data = 1; } // The position of a declared entity within a file. message SourcePosition { - optional uint32 line_number = 1; - optional uint32 column_number = 2; + uint32 line_number = 1; + uint32 column_number = 2; } // Developer friendly source file information for an entity in the resource table. message Source { // The index of the string path within the source string pool of a ResourceTable. - optional uint32 path_idx = 1; - optional SourcePosition position = 2; + uint32 path_idx = 1; + SourcePosition position = 2; } // Top level message representing a resource table. message ResourceTable { // The string pool containing source paths referenced throughout the resource table. This does // not end up in the final binary ARSC file. - optional StringPool source_pool = 1; + StringPool source_pool = 1; // Resource definitions corresponding to an Android package. repeated Package package = 2; } +// A package ID in the range [0x00, 0xff]. +message PackageId { + uint32 id = 1; +} + // Defines resources for an Android package. message Package { // The package ID of this package, in the range [0x00, 0xff]. - // The ID 0x00 is reserved for shared libraries, or when the ID is assigned at run-time. - // The ID 0x01 is reserved for the 'android' package (framework). - // The ID range [0x02, 0x7f) is reserved for auto-assignment to shared libraries at run-time. - // The ID 0x7f is reserved for the application package. - // IDs > 0x7f are reserved for the application as well and are treated as feature splits. - optional uint32 package_id = 1; + // - ID 0x00 is reserved for shared libraries, or when the ID is assigned at run-time. + // - ID 0x01 is reserved for the 'android' package (framework). + // - ID range [0x02, 0x7f) is reserved for auto-assignment to shared libraries at run-time. + // - ID 0x7f is reserved for the application package. + // - IDs > 0x7f are reserved for the application as well and are treated as feature splits. + // This may not be set if no ID was assigned. + PackageId package_id = 1; // The Java compatible Android package name of the app. - optional string package_name = 2; + string package_name = 2; // The series of types defined by the package. repeated Type type = 3; } +// A type ID in the range [0x01, 0xff]. +message TypeId { + uint32 id = 1; +} + // A set of resources grouped under a common type. Such types include string, layout, xml, dimen, // attr, etc. This maps to the second part of a resource identifier in Java (R.type.entry). message Type { - // The ID of the type. This may be 0, which indicates no ID is set. - optional uint32 id = 1; + // The ID of the type. This may not be set if no ID was assigned. + TypeId type_id = 1; // The name of the type. This corresponds to the 'type' part of a full resource name of the form // package:type/entry. The set of legal type names is listed in Resource.cpp. - optional string name = 2; + string name = 2; // The entries defined for this type. repeated Entry entry = 3; @@ -112,17 +115,22 @@ message SymbolStatus { PUBLIC = 2; } - optional Visibility visibility = 1; + Visibility visibility = 1; // The path at which this entry's visibility was defined (eg. public.xml). - optional Source source = 2; + Source source = 2; // The comment associated with the <public> tag. - optional string comment = 3; + string comment = 3; // Whether the symbol can be merged into another resource table without there being an existing // definition to override. Used for overlays and set to true when <add-resource> is specified. - optional bool allow_new = 4; + bool allow_new = 4; +} + +// An entry ID in the range [0x0000, 0xffff]. +message EntryId { + uint32 id = 1; } // An entry declaration. An entry has a full resource ID that is the combination of package ID, @@ -132,14 +140,15 @@ message Entry { // The ID of this entry. Together with the package ID and type ID, this forms a full resource ID // of the form 0xPPTTEEEE, where PP is the package ID, TT is the type ID, and EEEE is the entry // ID. - optional uint32 id = 1; + // This may not be set if no ID was assigned. + EntryId entry_id = 1; // The name of this entry. This corresponds to the 'entry' part of a full resource name of the // form package:type/entry. - optional string name = 2; + string name = 2; // The symbol status of this entry, which includes visibility information. - optional SymbolStatus symbol_status = 3; + SymbolStatus symbol_status = 3; // The set of values defined for this entry, each corresponding to a different // configuration/variant. @@ -148,50 +157,54 @@ message Entry { // A Configuration/Value pair. message ConfigValue { - optional ConfigDescription config = 1; - optional Value value = 2; + Configuration config = 1; + Value value = 2; } // The generic meta-data for every value in a resource table. message Value { // Where the value was defined. - optional Source source = 1; + Source source = 1; // Any comment associated with the value. - optional string comment = 2; + string comment = 2; // Whether the value can be overridden. - optional bool weak = 3; + bool weak = 3; - // If the value is an Item, this is set. - optional Item item = 4; - - // If the value is a CompoundValue, this is set. - optional CompoundValue compound_value = 5; + // The value is either an Item or a CompoundValue. + oneof value { + Item item = 4; + CompoundValue compound_value = 5; + } } // An Item is an abstract type. It represents a value that can appear inline in many places, such // as XML attribute values or on the right hand side of style attribute definitions. The concrete // type is one of the types below. Only one can be set. message Item { - optional Reference ref = 1; - optional String str = 2; - optional RawString raw_str = 3; - optional StyledString styled_str = 4; - optional FileReference file = 5; - optional Id id = 6; - optional Primitive prim = 7; + oneof value { + Reference ref = 1; + String str = 2; + RawString raw_str = 3; + StyledString styled_str = 4; + FileReference file = 5; + Id id = 6; + Primitive prim = 7; + } } // A CompoundValue is an abstract type. It represents a value that is a made of other values. // These can only usually appear as top-level resources. The concrete type is one of the types // below. Only one can be set. message CompoundValue { - optional Attribute attr = 1; - optional Style style = 2; - optional Styleable styleable = 3; - optional Array array = 4; - optional Plural plural = 5; + oneof value { + Attribute attr = 1; + Style style = 2; + Styleable styleable = 3; + Array array = 4; + Plural plural = 5; + } } // A value that is a reference to another resource. This reference can be by name or resource ID. @@ -204,16 +217,16 @@ message Reference { ATTRIBUTE = 1; } - optional Type type = 1; + Type type = 1; - // The resource ID (0xPPTTEEEE) of the resource being referred. - optional uint32 id = 2; + // The resource ID (0xPPTTEEEE) of the resource being referred. This is optional. + uint32 id = 2; - // The optional resource name. - optional string name = 3; + // The name of the resource being referred. This is optional if the resource ID is set. + string name = 3; // Whether this reference is referencing a private resource (@*package:type/entry). - optional bool private = 4; + bool private = 4; } // A value that represents an ID. This is just a placeholder, as ID values are used to occupy a @@ -223,32 +236,32 @@ message Id { // A value that is a string. message String { - optional string value = 1; + string value = 1; } // A value that is a raw string, which is unescaped/uninterpreted. This is typically used to // represent the value of a style attribute before the attribute is compiled and the set of // allowed values is known. message RawString { - optional string value = 1; + string value = 1; } // A string with styling information, like html tags that specify boldness, italics, etc. message StyledString { // The raw text of the string. - optional string value = 1; + string value = 1; // A Span marks a region of the string text that is styled. message Span { // The name of the tag, and its attributes, encoded as follows: // tag_name;attr1=value1;attr2=value2;[...] - optional string tag = 1; + string tag = 1; // The first character position this span applies to, in UTF-16 offset. - optional uint32 first_char = 2; + uint32 first_char = 2; // The last character position this span applies to, in UTF-16 offset. - optional uint32 last_char = 3; + uint32 last_char = 3; } repeated Span span = 2; @@ -257,14 +270,14 @@ message StyledString { // A value that is a reference to an external entity, like an XML file or a PNG. message FileReference { // Path to a file within the APK (typically res/type-config/entry.ext). - optional string path = 1; + string path = 1; } // A value that represents a primitive data type (float, int, boolean, etc.). // Corresponds to the fields (type/data) of the C struct android::Res_value. message Primitive { - optional uint32 type = 1; - optional uint32 data = 2; + uint32 type = 1; + uint32 data = 2; } // A value that represents an XML attribute and what values it accepts. @@ -272,21 +285,22 @@ message Attribute { // A Symbol used to represent an enum or a flag. message Symbol { // Where the enum/flag item was defined. - optional Source source = 1; + Source source = 1; // Any comments associated with the enum or flag. - optional string comment = 2; + string comment = 2; // The name of the enum/flag as a reference. Enums/flag items are generated as ID resource // values. - optional Reference name = 3; + Reference name = 3; // The value of the enum/flag. - optional uint32 value = 4; + uint32 value = 4; } // Bitmask of formats allowed for an attribute. enum FormatFlags { + NONE = 0x0; // Proto3 requires a default of 0. ANY = 0x0000ffff; // Allows any type except ENUM and FLAGS. REFERENCE = 0x01; // Allows Reference values. STRING = 0x02; // Allows String/StyledString values. @@ -304,15 +318,15 @@ message Attribute { // A bitmask of types that this XML attribute accepts. Corresponds to the flags in the // enum FormatFlags. - optional uint32 format_flags = 1; + uint32 format_flags = 1; // The smallest integer allowed for this XML attribute. Only makes sense if the format includes // FormatFlags::INTEGER. - optional int32 min_int = 2; + int32 min_int = 2; // The largest integer allowed for this XML attribute. Only makes sense if the format includes // FormatFlags::INTEGER. - optional int32 max_int = 3; + int32 max_int = 3; // The set of enums/flags defined in this attribute. Only makes sense if the format includes // either FormatFlags::ENUM or FormatFlags::FLAGS. Having both is an error. @@ -324,23 +338,23 @@ message Style { // An XML attribute/value pair defined in the style. message Entry { // Where the entry was defined. - optional Source source = 1; + Source source = 1; // Any comments associated with the entry. - optional string comment = 2; + string comment = 2; // A reference to the XML attribute. - optional Reference key = 3; + Reference key = 3; // The Item defined for this XML attribute. - optional Item item = 4; + Item item = 4; } // The optinal style from which this style inherits attributes. - optional Reference parent = 1; + Reference parent = 1; // The source file information of the parent inheritance declaration. - optional Source parent_source = 2; + Source parent_source = 2; // The set of XML attribute/value pairs for this style. repeated Entry entry = 3; @@ -352,13 +366,13 @@ message Styleable { // An attribute defined for this styleable. message Entry { // Where the attribute was defined within the <declare-styleable> block. - optional Source source = 1; + Source source = 1; // Any comments associated with the declaration. - optional string comment = 2; + string comment = 2; // The reference to the attribute. - optional Reference attr = 3; + Reference attr = 3; } // The set of attribute declarations. @@ -370,13 +384,13 @@ message Array { // A single element of the array. message Element { // Where the element was defined. - optional Source source = 1; + Source source = 1; // Any comments associated with the element. - optional string comment = 2; + string comment = 2; // The value assigned to this element. - optional Item item = 3; + Item item = 3; } // The list of array elements. @@ -398,16 +412,16 @@ message Plural { // The plural value for a given arity. message Entry { // Where the plural was defined. - optional Source source = 1; + Source source = 1; // Any comments associated with the plural. - optional string comment = 2; + string comment = 2; // The arity of the plural. - optional Arity arity = 3; + Arity arity = 3; // The value assigned to this plural. - optional Item item = 4; + Item item = 4; } // The set of arity/plural mappings. @@ -417,14 +431,13 @@ message Plural { // Defines an abstract XmlNode that must be either an XmlElement, or // a text node represented by a string. message XmlNode { - // If set, this node is an element/tag. - optional XmlElement element = 1; - - // If set, this node is a chunk of text. - optional string text = 2; + oneof node { + XmlElement element = 1; + string text = 2; + } // Source line and column info. - optional SourcePosition source = 3; + SourcePosition source = 3; } // An <element> in an XML document. @@ -433,10 +446,10 @@ message XmlElement { repeated XmlNamespace namespace_declaration = 1; // The namespace URI of this element. - optional string namespace_uri = 2; + string namespace_uri = 2; // The name of this element. - optional string name = 3; + string name = 3; // The attributes of this element. repeated XmlAttribute attribute = 4; @@ -447,25 +460,25 @@ message XmlElement { // A namespace declaration on an XmlElement (xmlns:android="http://..."). message XmlNamespace { - optional string prefix = 1; - optional string uri = 2; + string prefix = 1; + string uri = 2; // Source line and column info. - optional SourcePosition source = 3; + SourcePosition source = 3; } // An attribute defined on an XmlElement (android:text="..."). message XmlAttribute { - optional string namespace_uri = 1; - optional string name = 2; - optional string value = 3; + string namespace_uri = 1; + string name = 2; + string value = 3; // Source line and column info. - optional SourcePosition source = 4; + SourcePosition source = 4; - // The resource ID (0xPPTTEEEE) of the attribute. - optional uint32 resource_id = 5; + // The optional resource ID (0xPPTTEEEE) of the attribute. + uint32 resource_id = 5; - // The interpreted/compiled version of the `value` string. - optional Item compiled_item = 6; + // The optional interpreted/compiled version of the `value` string. + Item compiled_item = 6; } diff --git a/tools/aapt2/ResourcesInternal.proto b/tools/aapt2/ResourcesInternal.proto index 31179174b843..0b0a252a3452 100644 --- a/tools/aapt2/ResourcesInternal.proto +++ b/tools/aapt2/ResourcesInternal.proto @@ -14,39 +14,40 @@ * limitations under the License. */ -syntax = "proto2"; - -option java_package = "android.aapt.pb.internal"; -option optimize_for = LITE_RUNTIME; +syntax = "proto3"; +import "frameworks/base/tools/aapt2/Configuration.proto"; import "frameworks/base/tools/aapt2/Resources.proto"; package aapt.pb.internal; +option java_package = "android.aapt.pb.internal"; +option optimize_for = LITE_RUNTIME; + // The top level message representing an external resource file (layout XML, PNG, etc). // This is used to represent a compiled file before it is linked. Only useful to aapt2. message CompiledFile { message Symbol { // The name of the symbol (in the form package:type/name). - optional string resource_name = 1; + string resource_name = 1; // The position in the file at which this symbol is defined. For debug use. - optional aapt.pb.SourcePosition source = 2; + aapt.pb.SourcePosition source = 2; } // The name of the resource (in the form package:type/name). - optional string resource_name = 1; + string resource_name = 1; // The configuration for which the resource is defined. - optional aapt.pb.ConfigDescription config = 2; + aapt.pb.Configuration config = 2; // The filesystem path to where the source file originated. // Mainly used to display helpful error messages. - optional string source_path = 3; + string source_path = 3; // Any symbols this file auto-generates/exports (eg. @+id/foo in an XML file). repeated Symbol exported_symbol = 4; // If this is a compiled XML file, this is the root node. - optional aapt.pb.XmlNode xml_root = 5; + aapt.pb.XmlNode xml_root = 5; } diff --git a/tools/aapt2/proto/ProtoHelpers.cpp b/tools/aapt2/proto/ProtoHelpers.cpp index aa99c982f6ae..18f7e1d2ff7d 100644 --- a/tools/aapt2/proto/ProtoHelpers.cpp +++ b/tools/aapt2/proto/ProtoHelpers.cpp @@ -16,6 +16,8 @@ #include "proto/ProtoHelpers.h" +#include "Locale.h" + namespace aapt { void SerializeStringPoolToPb(const StringPool& pool, pb::StringPool* out_pb_pool) { @@ -42,13 +44,8 @@ void SerializeSourceToPb(const Source& source, StringPool* src_pool, pb::Source* void DeserializeSourceFromPb(const pb::Source& pb_source, const android::ResStringPool& src_pool, Source* out_source) { - if (pb_source.has_path_idx()) { - out_source->path = util::GetString(src_pool, pb_source.path_idx()); - } - - if (pb_source.has_position()) { - out_source->line = static_cast<size_t>(pb_source.position().line_number()); - } + out_source->path = util::GetString(src_pool, pb_source.path_idx()); + out_source->line = static_cast<size_t>(pb_source.position().line_number()); } pb::SymbolStatus_Visibility SerializeVisibilityToPb(SymbolState state) { @@ -75,26 +72,507 @@ SymbolState DeserializeVisibilityFromPb(pb::SymbolStatus_Visibility pb_visibilit return SymbolState::kUndefined; } -void SerializeConfig(const ConfigDescription& config, pb::ConfigDescription* out_pb_config) { - android::ResTable_config flat_config = config; - flat_config.size = sizeof(flat_config); - flat_config.swapHtoD(); - out_pb_config->set_data(&flat_config, sizeof(flat_config)); +void SerializeConfig(const ConfigDescription& config, pb::Configuration* out_pb_config) { + out_pb_config->set_mcc(config.mcc); + out_pb_config->set_mnc(config.mnc); + out_pb_config->set_locale(config.GetBcp47LanguageTag()); + + switch (config.screenLayout & ConfigDescription::MASK_LAYOUTDIR) { + case ConfigDescription::LAYOUTDIR_LTR: + out_pb_config->set_layout_direction(pb::Configuration_LayoutDirection_LAYOUT_DIRECTION_LTR); + break; + + case ConfigDescription::LAYOUTDIR_RTL: + out_pb_config->set_layout_direction(pb::Configuration_LayoutDirection_LAYOUT_DIRECTION_RTL); + break; + } + + out_pb_config->set_screen_width(config.screenWidth); + out_pb_config->set_screen_height(config.screenHeight); + out_pb_config->set_screen_width_dp(config.screenWidthDp); + out_pb_config->set_screen_height_dp(config.screenHeightDp); + out_pb_config->set_smallest_screen_width_dp(config.smallestScreenWidthDp); + + switch (config.screenLayout & ConfigDescription::MASK_SCREENSIZE) { + case ConfigDescription::SCREENSIZE_SMALL: + out_pb_config->set_screen_layout_size( + pb::Configuration_ScreenLayoutSize_SCREEN_LAYOUT_SIZE_SMALL); + break; + + case ConfigDescription::SCREENSIZE_NORMAL: + out_pb_config->set_screen_layout_size( + pb::Configuration_ScreenLayoutSize_SCREEN_LAYOUT_SIZE_NORMAL); + break; + + case ConfigDescription::SCREENSIZE_LARGE: + out_pb_config->set_screen_layout_size( + pb::Configuration_ScreenLayoutSize_SCREEN_LAYOUT_SIZE_LARGE); + break; + + case ConfigDescription::SCREENSIZE_XLARGE: + out_pb_config->set_screen_layout_size( + pb::Configuration_ScreenLayoutSize_SCREEN_LAYOUT_SIZE_XLARGE); + break; + } + + switch (config.screenLayout & ConfigDescription::MASK_SCREENLONG) { + case ConfigDescription::SCREENLONG_YES: + out_pb_config->set_screen_layout_long( + pb::Configuration_ScreenLayoutLong_SCREEN_LAYOUT_LONG_LONG); + break; + + case ConfigDescription::SCREENLONG_NO: + out_pb_config->set_screen_layout_long( + pb::Configuration_ScreenLayoutLong_SCREEN_LAYOUT_LONG_NOTLONG); + break; + } + + switch (config.screenLayout2 & ConfigDescription::MASK_SCREENROUND) { + case ConfigDescription::SCREENROUND_YES: + out_pb_config->set_screen_round(pb::Configuration_ScreenRound_SCREEN_ROUND_ROUND); + break; + + case ConfigDescription::SCREENROUND_NO: + out_pb_config->set_screen_round(pb::Configuration_ScreenRound_SCREEN_ROUND_NOTROUND); + break; + } + + switch (config.colorMode & ConfigDescription::MASK_WIDE_COLOR_GAMUT) { + case ConfigDescription::WIDE_COLOR_GAMUT_YES: + out_pb_config->set_wide_color_gamut(pb::Configuration_WideColorGamut_WIDE_COLOR_GAMUT_WIDECG); + break; + + case ConfigDescription::WIDE_COLOR_GAMUT_NO: + out_pb_config->set_wide_color_gamut( + pb::Configuration_WideColorGamut_WIDE_COLOR_GAMUT_NOWIDECG); + break; + } + + switch (config.colorMode & ConfigDescription::MASK_HDR) { + case ConfigDescription::HDR_YES: + out_pb_config->set_hdr(pb::Configuration_Hdr_HDR_HIGHDR); + break; + + case ConfigDescription::HDR_NO: + out_pb_config->set_hdr(pb::Configuration_Hdr_HDR_LOWDR); + break; + } + + switch (config.orientation) { + case ConfigDescription::ORIENTATION_PORT: + out_pb_config->set_orientation(pb::Configuration_Orientation_ORIENTATION_PORT); + break; + + case ConfigDescription::ORIENTATION_LAND: + out_pb_config->set_orientation(pb::Configuration_Orientation_ORIENTATION_LAND); + break; + + case ConfigDescription::ORIENTATION_SQUARE: + out_pb_config->set_orientation(pb::Configuration_Orientation_ORIENTATION_SQUARE); + break; + } + + switch (config.uiMode & ConfigDescription::MASK_UI_MODE_TYPE) { + case ConfigDescription::UI_MODE_TYPE_NORMAL: + out_pb_config->set_ui_mode_type(pb::Configuration_UiModeType_UI_MODE_TYPE_NORMAL); + break; + + case ConfigDescription::UI_MODE_TYPE_DESK: + out_pb_config->set_ui_mode_type(pb::Configuration_UiModeType_UI_MODE_TYPE_DESK); + break; + + case ConfigDescription::UI_MODE_TYPE_CAR: + out_pb_config->set_ui_mode_type(pb::Configuration_UiModeType_UI_MODE_TYPE_CAR); + break; + + case ConfigDescription::UI_MODE_TYPE_TELEVISION: + out_pb_config->set_ui_mode_type(pb::Configuration_UiModeType_UI_MODE_TYPE_TELEVISION); + break; + + case ConfigDescription::UI_MODE_TYPE_APPLIANCE: + out_pb_config->set_ui_mode_type(pb::Configuration_UiModeType_UI_MODE_TYPE_APPLIANCE); + break; + + case ConfigDescription::UI_MODE_TYPE_WATCH: + out_pb_config->set_ui_mode_type(pb::Configuration_UiModeType_UI_MODE_TYPE_WATCH); + break; + + case ConfigDescription::UI_MODE_TYPE_VR_HEADSET: + out_pb_config->set_ui_mode_type(pb::Configuration_UiModeType_UI_MODE_TYPE_VRHEADSET); + break; + } + + switch (config.uiMode & ConfigDescription::MASK_UI_MODE_NIGHT) { + case ConfigDescription::UI_MODE_NIGHT_YES: + out_pb_config->set_ui_mode_night(pb::Configuration_UiModeNight_UI_MODE_NIGHT_NIGHT); + break; + + case ConfigDescription::UI_MODE_NIGHT_NO: + out_pb_config->set_ui_mode_night(pb::Configuration_UiModeNight_UI_MODE_NIGHT_NOTNIGHT); + break; + } + + out_pb_config->set_density(config.density); + + switch (config.touchscreen) { + case ConfigDescription::TOUCHSCREEN_NOTOUCH: + out_pb_config->set_touchscreen(pb::Configuration_Touchscreen_TOUCHSCREEN_NOTOUCH); + break; + + case ConfigDescription::TOUCHSCREEN_STYLUS: + out_pb_config->set_touchscreen(pb::Configuration_Touchscreen_TOUCHSCREEN_STYLUS); + break; + + case ConfigDescription::TOUCHSCREEN_FINGER: + out_pb_config->set_touchscreen(pb::Configuration_Touchscreen_TOUCHSCREEN_FINGER); + break; + } + + switch (config.inputFlags & ConfigDescription::MASK_KEYSHIDDEN) { + case ConfigDescription::KEYSHIDDEN_NO: + out_pb_config->set_keys_hidden(pb::Configuration_KeysHidden_KEYS_HIDDEN_KEYSEXPOSED); + break; + + case ConfigDescription::KEYSHIDDEN_YES: + out_pb_config->set_keys_hidden(pb::Configuration_KeysHidden_KEYS_HIDDEN_KEYSHIDDEN); + break; + + case ConfigDescription::KEYSHIDDEN_SOFT: + out_pb_config->set_keys_hidden(pb::Configuration_KeysHidden_KEYS_HIDDEN_KEYSSOFT); + break; + } + + switch (config.keyboard) { + case ConfigDescription::KEYBOARD_NOKEYS: + out_pb_config->set_keyboard(pb::Configuration_Keyboard_KEYBOARD_NOKEYS); + break; + + case ConfigDescription::KEYBOARD_QWERTY: + out_pb_config->set_keyboard(pb::Configuration_Keyboard_KEYBOARD_QWERTY); + break; + + case ConfigDescription::KEYBOARD_12KEY: + out_pb_config->set_keyboard(pb::Configuration_Keyboard_KEYBOARD_TWELVEKEY); + break; + } + + switch (config.inputFlags & ConfigDescription::MASK_NAVHIDDEN) { + case ConfigDescription::NAVHIDDEN_NO: + out_pb_config->set_nav_hidden(pb::Configuration_NavHidden_NAV_HIDDEN_NAVEXPOSED); + break; + + case ConfigDescription::NAVHIDDEN_YES: + out_pb_config->set_nav_hidden(pb::Configuration_NavHidden_NAV_HIDDEN_NAVHIDDEN); + break; + } + + switch (config.navigation) { + case ConfigDescription::NAVIGATION_NONAV: + out_pb_config->set_navigation(pb::Configuration_Navigation_NAVIGATION_NONAV); + break; + + case ConfigDescription::NAVIGATION_DPAD: + out_pb_config->set_navigation(pb::Configuration_Navigation_NAVIGATION_DPAD); + break; + + case ConfigDescription::NAVIGATION_TRACKBALL: + out_pb_config->set_navigation(pb::Configuration_Navigation_NAVIGATION_TRACKBALL); + break; + + case ConfigDescription::NAVIGATION_WHEEL: + out_pb_config->set_navigation(pb::Configuration_Navigation_NAVIGATION_WHEEL); + break; + } + + out_pb_config->set_sdk_version(config.sdkVersion); } -bool DeserializeConfigDescriptionFromPb(const pb::ConfigDescription& pb_config, +bool DeserializeConfigDescriptionFromPb(const pb::Configuration& pb_config, ConfigDescription* out_config) { - if (!pb_config.has_data()) { - return false; + out_config->mcc = static_cast<uint16_t>(pb_config.mcc()); + out_config->mnc = static_cast<uint16_t>(pb_config.mnc()); + + if (!pb_config.locale().empty()) { + LocaleValue lv; + if (!lv.InitFromBcp47Tag(pb_config.locale())) { + return false; + } + lv.WriteTo(out_config); + } + + switch (pb_config.layout_direction()) { + case pb::Configuration_LayoutDirection_LAYOUT_DIRECTION_LTR: + out_config->screenLayout = (out_config->screenLayout & ~ConfigDescription::MASK_LAYOUTDIR) | + ConfigDescription::LAYOUTDIR_LTR; + break; + + case pb::Configuration_LayoutDirection_LAYOUT_DIRECTION_RTL: + out_config->screenLayout = (out_config->screenLayout & ~ConfigDescription::MASK_LAYOUTDIR) | + ConfigDescription::LAYOUTDIR_RTL; + break; + + default: + break; + } + + out_config->smallestScreenWidthDp = static_cast<uint16_t>(pb_config.smallest_screen_width_dp()); + out_config->screenWidthDp = static_cast<uint16_t>(pb_config.screen_width_dp()); + out_config->screenHeightDp = static_cast<uint16_t>(pb_config.screen_height_dp()); + + switch (pb_config.screen_layout_size()) { + case pb::Configuration_ScreenLayoutSize_SCREEN_LAYOUT_SIZE_SMALL: + out_config->screenLayout = (out_config->screenLayout & ~ConfigDescription::MASK_SCREENSIZE) | + ConfigDescription::SCREENSIZE_SMALL; + break; + + case pb::Configuration_ScreenLayoutSize_SCREEN_LAYOUT_SIZE_NORMAL: + out_config->screenLayout = (out_config->screenLayout & ~ConfigDescription::MASK_SCREENSIZE) | + ConfigDescription::SCREENSIZE_NORMAL; + break; + + case pb::Configuration_ScreenLayoutSize_SCREEN_LAYOUT_SIZE_LARGE: + out_config->screenLayout = (out_config->screenLayout & ~ConfigDescription::MASK_SCREENSIZE) | + ConfigDescription::SCREENSIZE_LARGE; + break; + + case pb::Configuration_ScreenLayoutSize_SCREEN_LAYOUT_SIZE_XLARGE: + out_config->screenLayout = (out_config->screenLayout & ~ConfigDescription::MASK_SCREENSIZE) | + ConfigDescription::SCREENSIZE_XLARGE; + break; + + default: + break; + } + + switch (pb_config.screen_layout_long()) { + case pb::Configuration_ScreenLayoutLong_SCREEN_LAYOUT_LONG_LONG: + out_config->screenLayout = (out_config->screenLayout & ~ConfigDescription::MASK_SCREENLONG) | + ConfigDescription::SCREENLONG_YES; + break; + + case pb::Configuration_ScreenLayoutLong_SCREEN_LAYOUT_LONG_NOTLONG: + out_config->screenLayout = (out_config->screenLayout & ~ConfigDescription::MASK_SCREENLONG) | + ConfigDescription::SCREENLONG_NO; + break; + + default: + break; } - const android::ResTable_config* config; - if (pb_config.data().size() > sizeof(*config)) { - return false; + switch (pb_config.screen_round()) { + case pb::Configuration_ScreenRound_SCREEN_ROUND_ROUND: + out_config->screenLayout2 = + (out_config->screenLayout2 & ~ConfigDescription::MASK_SCREENROUND) | + ConfigDescription::SCREENROUND_YES; + break; + + case pb::Configuration_ScreenRound_SCREEN_ROUND_NOTROUND: + out_config->screenLayout2 = + (out_config->screenLayout2 & ~ConfigDescription::MASK_SCREENROUND) | + ConfigDescription::SCREENROUND_NO; + break; + + default: + break; + } + + switch (pb_config.wide_color_gamut()) { + case pb::Configuration_WideColorGamut_WIDE_COLOR_GAMUT_WIDECG: + out_config->colorMode = (out_config->colorMode & ~ConfigDescription::MASK_WIDE_COLOR_GAMUT) | + ConfigDescription::WIDE_COLOR_GAMUT_YES; + break; + + case pb::Configuration_WideColorGamut_WIDE_COLOR_GAMUT_NOWIDECG: + out_config->colorMode = (out_config->colorMode & ~ConfigDescription::MASK_WIDE_COLOR_GAMUT) | + ConfigDescription::WIDE_COLOR_GAMUT_NO; + break; + + default: + break; + } + + switch (pb_config.hdr()) { + case pb::Configuration_Hdr_HDR_HIGHDR: + out_config->colorMode = + (out_config->colorMode & ~ConfigDescription::MASK_HDR) | ConfigDescription::HDR_YES; + break; + + case pb::Configuration_Hdr_HDR_LOWDR: + out_config->colorMode = + (out_config->colorMode & ~ConfigDescription::MASK_HDR) | ConfigDescription::HDR_NO; + break; + + default: + break; + } + + switch (pb_config.orientation()) { + case pb::Configuration_Orientation_ORIENTATION_PORT: + out_config->orientation = ConfigDescription::ORIENTATION_PORT; + break; + + case pb::Configuration_Orientation_ORIENTATION_LAND: + out_config->orientation = ConfigDescription::ORIENTATION_LAND; + break; + + case pb::Configuration_Orientation_ORIENTATION_SQUARE: + out_config->orientation = ConfigDescription::ORIENTATION_SQUARE; + break; + + default: + break; + } + + switch (pb_config.ui_mode_type()) { + case pb::Configuration_UiModeType_UI_MODE_TYPE_NORMAL: + out_config->uiMode = (out_config->uiMode & ~ConfigDescription::MASK_UI_MODE_TYPE) | + ConfigDescription::UI_MODE_TYPE_NORMAL; + break; + + case pb::Configuration_UiModeType_UI_MODE_TYPE_DESK: + out_config->uiMode = (out_config->uiMode & ~ConfigDescription::MASK_UI_MODE_TYPE) | + ConfigDescription::UI_MODE_TYPE_DESK; + break; + + case pb::Configuration_UiModeType_UI_MODE_TYPE_CAR: + out_config->uiMode = (out_config->uiMode & ~ConfigDescription::MASK_UI_MODE_TYPE) | + ConfigDescription::UI_MODE_TYPE_CAR; + break; + + case pb::Configuration_UiModeType_UI_MODE_TYPE_TELEVISION: + out_config->uiMode = (out_config->uiMode & ~ConfigDescription::MASK_UI_MODE_TYPE) | + ConfigDescription::UI_MODE_TYPE_TELEVISION; + break; + + case pb::Configuration_UiModeType_UI_MODE_TYPE_APPLIANCE: + out_config->uiMode = (out_config->uiMode & ~ConfigDescription::MASK_UI_MODE_TYPE) | + ConfigDescription::UI_MODE_TYPE_APPLIANCE; + break; + + case pb::Configuration_UiModeType_UI_MODE_TYPE_WATCH: + out_config->uiMode = (out_config->uiMode & ~ConfigDescription::MASK_UI_MODE_TYPE) | + ConfigDescription::UI_MODE_TYPE_WATCH; + break; + + case pb::Configuration_UiModeType_UI_MODE_TYPE_VRHEADSET: + out_config->uiMode = (out_config->uiMode & ~ConfigDescription::MASK_UI_MODE_TYPE) | + ConfigDescription::UI_MODE_TYPE_VR_HEADSET; + break; + + default: + break; + } + + switch (pb_config.ui_mode_night()) { + case pb::Configuration_UiModeNight_UI_MODE_NIGHT_NIGHT: + out_config->uiMode = (out_config->uiMode & ~ConfigDescription::MASK_UI_MODE_NIGHT) | + ConfigDescription::UI_MODE_NIGHT_YES; + break; + + case pb::Configuration_UiModeNight_UI_MODE_NIGHT_NOTNIGHT: + out_config->uiMode = (out_config->uiMode & ~ConfigDescription::MASK_UI_MODE_NIGHT) | + ConfigDescription::UI_MODE_NIGHT_NO; + break; + + default: + break; + } + + out_config->density = static_cast<uint16_t>(pb_config.density()); + + switch (pb_config.touchscreen()) { + case pb::Configuration_Touchscreen_TOUCHSCREEN_NOTOUCH: + out_config->touchscreen = ConfigDescription::TOUCHSCREEN_NOTOUCH; + break; + + case pb::Configuration_Touchscreen_TOUCHSCREEN_STYLUS: + out_config->touchscreen = ConfigDescription::TOUCHSCREEN_STYLUS; + break; + + case pb::Configuration_Touchscreen_TOUCHSCREEN_FINGER: + out_config->touchscreen = ConfigDescription::TOUCHSCREEN_FINGER; + break; + + default: + break; + } + + switch (pb_config.keys_hidden()) { + case pb::Configuration_KeysHidden_KEYS_HIDDEN_KEYSEXPOSED: + out_config->inputFlags = (out_config->inputFlags & ~ConfigDescription::MASK_KEYSHIDDEN) | + ConfigDescription::KEYSHIDDEN_NO; + break; + + case pb::Configuration_KeysHidden_KEYS_HIDDEN_KEYSHIDDEN: + out_config->inputFlags = (out_config->inputFlags & ~ConfigDescription::MASK_KEYSHIDDEN) | + ConfigDescription::KEYSHIDDEN_YES; + break; + + case pb::Configuration_KeysHidden_KEYS_HIDDEN_KEYSSOFT: + out_config->inputFlags = (out_config->inputFlags & ~ConfigDescription::MASK_KEYSHIDDEN) | + ConfigDescription::KEYSHIDDEN_SOFT; + break; + + default: + break; + } + + switch (pb_config.keyboard()) { + case pb::Configuration_Keyboard_KEYBOARD_NOKEYS: + out_config->keyboard = ConfigDescription::KEYBOARD_NOKEYS; + break; + + case pb::Configuration_Keyboard_KEYBOARD_QWERTY: + out_config->keyboard = ConfigDescription::KEYBOARD_QWERTY; + break; + + case pb::Configuration_Keyboard_KEYBOARD_TWELVEKEY: + out_config->keyboard = ConfigDescription::KEYBOARD_12KEY; + break; + + default: + break; + } + + switch (pb_config.nav_hidden()) { + case pb::Configuration_NavHidden_NAV_HIDDEN_NAVEXPOSED: + out_config->inputFlags = (out_config->inputFlags & ~ConfigDescription::MASK_NAVHIDDEN) | + ConfigDescription::NAVHIDDEN_NO; + break; + + case pb::Configuration_NavHidden_NAV_HIDDEN_NAVHIDDEN: + out_config->inputFlags = (out_config->inputFlags & ~ConfigDescription::MASK_NAVHIDDEN) | + ConfigDescription::NAVHIDDEN_YES; + break; + + default: + break; + } + + switch (pb_config.navigation()) { + case pb::Configuration_Navigation_NAVIGATION_NONAV: + out_config->navigation = ConfigDescription::NAVIGATION_NONAV; + break; + + case pb::Configuration_Navigation_NAVIGATION_DPAD: + out_config->navigation = ConfigDescription::NAVIGATION_DPAD; + break; + + case pb::Configuration_Navigation_NAVIGATION_TRACKBALL: + out_config->navigation = ConfigDescription::NAVIGATION_TRACKBALL; + break; + + case pb::Configuration_Navigation_NAVIGATION_WHEEL: + out_config->navigation = ConfigDescription::NAVIGATION_WHEEL; + break; + + default: + break; } - config = reinterpret_cast<const android::ResTable_config*>(pb_config.data().data()); - out_config->copyFromDtoH(*config); + out_config->screenWidth = static_cast<uint16_t>(pb_config.screen_width()); + out_config->screenHeight = static_cast<uint16_t>(pb_config.screen_height()); + out_config->sdkVersion = static_cast<uint16_t>(pb_config.sdk_version()); return true; } diff --git a/tools/aapt2/proto/ProtoHelpers.h b/tools/aapt2/proto/ProtoHelpers.h index 2f268f44752c..714a2b27bf7f 100644 --- a/tools/aapt2/proto/ProtoHelpers.h +++ b/tools/aapt2/proto/ProtoHelpers.h @@ -20,11 +20,12 @@ #include "androidfw/ResourceTypes.h" #include "ConfigDescription.h" +#include "Configuration.pb.h" #include "ResourceTable.h" -#include "Source.h" -#include "StringPool.h" #include "Resources.pb.h" #include "ResourcesInternal.pb.h" +#include "Source.h" +#include "StringPool.h" namespace aapt { @@ -39,9 +40,9 @@ pb::SymbolStatus_Visibility SerializeVisibilityToPb(SymbolState state); SymbolState DeserializeVisibilityFromPb(pb::SymbolStatus_Visibility pb_visibility); -void SerializeConfig(const ConfigDescription& config, pb::ConfigDescription* out_pb_config); +void SerializeConfig(const ConfigDescription& config, pb::Configuration* out_pb_config); -bool DeserializeConfigDescriptionFromPb(const pb::ConfigDescription& pb_config, +bool DeserializeConfigDescriptionFromPb(const pb::Configuration& pb_config, ConfigDescription* out_config); pb::Reference_Type SerializeReferenceTypeToPb(Reference::Type type); diff --git a/tools/aapt2/proto/TableProtoDeserializer.cpp b/tools/aapt2/proto/TableProtoDeserializer.cpp index b9d5878f2f71..4a88d61ef84c 100644 --- a/tools/aapt2/proto/TableProtoDeserializer.cpp +++ b/tools/aapt2/proto/TableProtoDeserializer.cpp @@ -64,7 +64,7 @@ class PackagePbDeserializer { bool DeserializeFromPb(const pb::Package& pb_package, ResourceTable* table) { Maybe<uint8_t> id; if (pb_package.has_package_id()) { - id = static_cast<uint8_t>(pb_package.package_id()); + id = static_cast<uint8_t>(pb_package.package_id().id()); } std::map<ResourceId, ResourceNameRef> id_index; @@ -90,10 +90,7 @@ class PackagePbDeserializer { &entry->symbol_status.source); } - if (pb_status.has_comment()) { - entry->symbol_status.comment = pb_status.comment(); - } - + entry->symbol_status.comment = pb_status.comment(); entry->symbol_status.allow_new = pb_status.allow_new(); SymbolState visibility = DeserializeVisibilityFromPb(pb_status.visibility()); @@ -101,15 +98,15 @@ class PackagePbDeserializer { if (visibility == SymbolState::kPublic) { // This is a public symbol, we must encode the ID now if there is one. - if (pb_entry.has_id()) { - entry->id = static_cast<uint16_t>(pb_entry.id()); + if (pb_entry.has_entry_id()) { + entry->id = static_cast<uint16_t>(pb_entry.entry_id().id()); } if (type->symbol_status.state != SymbolState::kPublic) { // If the type has not been made public, do so now. type->symbol_status.state = SymbolState::kPublic; - if (pb_type.has_id()) { - type->id = static_cast<uint8_t>(pb_type.id()); + if (pb_type.has_type_id()) { + type->id = static_cast<uint8_t>(pb_type.type_id().id()); } } } else if (visibility == SymbolState::kPrivate) { @@ -119,13 +116,14 @@ class PackagePbDeserializer { } } - ResourceId resid(pb_package.package_id(), pb_type.id(), pb_entry.id()); + ResourceId resid(pb_package.package_id().id(), pb_type.type_id().id(), + pb_entry.entry_id().id()); if (resid.is_valid()) { id_index[resid] = ResourceNameRef(pkg->name, type->type, entry->name); } for (const pb::ConfigValue& pb_config_value : pb_entry.config_value()) { - const pb::ConfigDescription& pb_config = pb_config_value.config(); + const pb::Configuration& pb_config = pb_config_value.config(); ConfigDescription config; if (!DeserializeConfigDescriptionFromPb(pb_config, &config)) { @@ -321,11 +319,11 @@ class PackagePbDeserializer { out_ref->reference_type = DeserializeReferenceTypeFromPb(pb_ref.type()); out_ref->private_reference = pb_ref.private_(); - if (pb_ref.has_id()) { + if (pb_ref.id() != 0) { out_ref->id = ResourceId(pb_ref.id()); } - if (pb_ref.has_name()) { + if (!pb_ref.name().empty()) { ResourceNameRef name_ref; if (!ResourceUtils::ParseResourceName(pb_ref.name(), &name_ref, nullptr)) { diag_->Error(DiagMessage(source_) << "invalid reference name '" << pb_ref.name() << "'"); @@ -344,10 +342,7 @@ class PackagePbDeserializer { DeserializeSourceFromPb(pb_item.source(), *source_pool_, &source); out_value->SetSource(std::move(source)); } - - if (pb_item.has_comment()) { - out_value->SetComment(pb_item.comment()); - } + out_value->SetComment(pb_item.comment()); } private: @@ -400,14 +395,16 @@ std::unique_ptr<ResourceFile> DeserializeCompiledFileFromPb( } file->name = name_ref.ToResourceName(); file->source.path = pb_file.source_path(); - DeserializeConfigDescriptionFromPb(pb_file.config(), &file->config); + if (!DeserializeConfigDescriptionFromPb(pb_file.config(), &file->config)) { + diag->Error(DiagMessage(source) << "invalid resource configuration in compiled file header"); + return {}; + } for (const pb::internal::CompiledFile_Symbol& pb_symbol : pb_file.exported_symbol()) { // Need to create an lvalue here so that nameRef can point to something real. if (!ResourceUtils::ParseResourceName(pb_symbol.resource_name(), &name_ref)) { diag->Error(DiagMessage(source) - << "invalid resource name for exported symbol in " - "compiled file header: " + << "invalid resource name for exported symbol in compiled file header: " << pb_file.resource_name()); return {}; } diff --git a/tools/aapt2/proto/TableProtoSerializer.cpp b/tools/aapt2/proto/TableProtoSerializer.cpp index a08df71eae1e..3d5407c137b1 100644 --- a/tools/aapt2/proto/TableProtoSerializer.cpp +++ b/tools/aapt2/proto/TableProtoSerializer.cpp @@ -179,15 +179,11 @@ class PbSerializerVisitor : public RawValueVisitor { template <typename T> void SerializeItemCommonToPb(const Item& item, T* pb_item) { SerializeSourceToPb(item.GetSource(), source_pool_, pb_item->mutable_source()); - if (!item.GetComment().empty()) { - pb_item->set_comment(item.GetComment()); - } + pb_item->set_comment(item.GetComment()); } void SerializeReferenceToPb(const Reference& ref, pb::Reference* pb_ref) { - if (ref.id) { - pb_ref->set_id(ref.id.value().id); - } + pb_ref->set_id(ref.id.value_or_default(ResourceId(0x0)).id); if (ref.name) { pb_ref->set_name(ref.name.value().ToString()); @@ -221,21 +217,21 @@ std::unique_ptr<pb::ResourceTable> SerializeTableToPb(ResourceTable* table) { for (auto& package : table->packages) { pb::Package* pb_package = pb_table->add_package(); if (package->id) { - pb_package->set_package_id(package->id.value()); + pb_package->mutable_package_id()->set_id(package->id.value()); } pb_package->set_package_name(package->name); for (auto& type : package->types) { pb::Type* pb_type = pb_package->add_type(); if (type->id) { - pb_type->set_id(type->id.value()); + pb_type->mutable_type_id()->set_id(type->id.value()); } pb_type->set_name(ToString(type->type).to_string()); for (auto& entry : type->entries) { pb::Entry* pb_entry = pb_type->add_entry(); if (entry->id) { - pb_entry->set_id(entry->id.value()); + pb_entry->mutable_entry_id()->set_id(entry->id.value()); } pb_entry->set_name(entry->name); @@ -249,20 +245,13 @@ std::unique_ptr<pb::ResourceTable> SerializeTableToPb(ResourceTable* table) { for (auto& config_value : entry->values) { pb::ConfigValue* pb_config_value = pb_entry->add_config_value(); SerializeConfig(config_value->config, pb_config_value->mutable_config()); - if (!config_value->product.empty()) { - pb_config_value->mutable_config()->set_product(config_value->product); - } + pb_config_value->mutable_config()->set_product(config_value->product); pb::Value* pb_value = pb_config_value->mutable_value(); SerializeSourceToPb(config_value->value->GetSource(), &source_pool, pb_value->mutable_source()); - if (!config_value->value->GetComment().empty()) { - pb_value->set_comment(config_value->value->GetComment()); - } - - if (config_value->value->IsWeak()) { - pb_value->set_weak(true); - } + pb_value->set_comment(config_value->value->GetComment()); + pb_value->set_weak(config_value->value->IsWeak()); PbSerializerVisitor visitor(&source_pool, pb_value); config_value->value->Accept(&visitor); @@ -293,10 +282,10 @@ CompiledFileOutputStream::CompiledFileOutputStream(ZeroCopyOutputStream* out) : } void CompiledFileOutputStream::EnsureAlignedWrite() { - const int padding = out_.ByteCount() % 4; - if (padding > 0) { + const int overflow = out_.ByteCount() % 4; + if (overflow > 0) { uint32_t zero = 0u; - out_.WriteRaw(&zero, padding); + out_.WriteRaw(&zero, 4 - overflow); } } @@ -333,10 +322,10 @@ CompiledFileInputStream::CompiledFileInputStream(const void* data, size_t size) : in_(static_cast<const uint8_t*>(data), size) {} void CompiledFileInputStream::EnsureAlignedRead() { - const int padding = in_.CurrentPosition() % 4; - if (padding > 0) { + const int overflow = in_.CurrentPosition() % 4; + if (overflow > 0) { // Reads are always 4 byte aligned. - in_.Skip(padding); + in_.Skip(4 - overflow); } } diff --git a/tools/aapt2/proto/TableProtoSerializer_test.cpp b/tools/aapt2/proto/TableProtoSerializer_test.cpp index 80608b3d9c05..8f6414c68a43 100644 --- a/tools/aapt2/proto/TableProtoSerializer_test.cpp +++ b/tools/aapt2/proto/TableProtoSerializer_test.cpp @@ -19,6 +19,7 @@ #include "ResourceTable.h" #include "test/Test.h" +using ::android::StringPiece; using ::google::protobuf::io::StringOutputStream; using ::testing::Eq; using ::testing::NotNull; @@ -239,4 +240,97 @@ TEST(TableProtoSerializer, DeserializeCorruptHeaderSafely) { EXPECT_FALSE(in_file_stream.ReadDataMetaData(&offset, &len)); } +static void ExpectConfigSerializes(const StringPiece& config_str) { + const ConfigDescription expected_config = test::ParseConfigOrDie(config_str); + pb::Configuration pb_config; + SerializeConfig(expected_config, &pb_config); + + ConfigDescription actual_config; + ASSERT_TRUE(DeserializeConfigDescriptionFromPb(pb_config, &actual_config)); + EXPECT_EQ(expected_config, actual_config); +} + +TEST(TableProtoSerializer, SerializeDeserializeConfiguration) { + ExpectConfigSerializes(""); + + ExpectConfigSerializes("mcc123"); + + ExpectConfigSerializes("mnc123"); + + ExpectConfigSerializes("en"); + ExpectConfigSerializes("en-rGB"); + ExpectConfigSerializes("b+en+GB"); + + ExpectConfigSerializes("ldltr"); + ExpectConfigSerializes("ldrtl"); + + ExpectConfigSerializes("sw3600dp"); + + ExpectConfigSerializes("w300dp"); + + ExpectConfigSerializes("h400dp"); + + ExpectConfigSerializes("small"); + ExpectConfigSerializes("normal"); + ExpectConfigSerializes("large"); + ExpectConfigSerializes("xlarge"); + + ExpectConfigSerializes("long"); + ExpectConfigSerializes("notlong"); + + ExpectConfigSerializes("round"); + ExpectConfigSerializes("notround"); + + ExpectConfigSerializes("widecg"); + ExpectConfigSerializes("nowidecg"); + + ExpectConfigSerializes("highdr"); + ExpectConfigSerializes("lowdr"); + + ExpectConfigSerializes("port"); + ExpectConfigSerializes("land"); + ExpectConfigSerializes("square"); + + ExpectConfigSerializes("desk"); + ExpectConfigSerializes("car"); + ExpectConfigSerializes("television"); + ExpectConfigSerializes("appliance"); + ExpectConfigSerializes("watch"); + ExpectConfigSerializes("vrheadset"); + + ExpectConfigSerializes("night"); + ExpectConfigSerializes("notnight"); + + ExpectConfigSerializes("300dpi"); + ExpectConfigSerializes("hdpi"); + + ExpectConfigSerializes("notouch"); + ExpectConfigSerializes("stylus"); + ExpectConfigSerializes("finger"); + + ExpectConfigSerializes("keysexposed"); + ExpectConfigSerializes("keyshidden"); + ExpectConfigSerializes("keyssoft"); + + ExpectConfigSerializes("nokeys"); + ExpectConfigSerializes("qwerty"); + ExpectConfigSerializes("12key"); + + ExpectConfigSerializes("navhidden"); + ExpectConfigSerializes("navexposed"); + + ExpectConfigSerializes("nonav"); + ExpectConfigSerializes("dpad"); + ExpectConfigSerializes("trackball"); + ExpectConfigSerializes("wheel"); + + ExpectConfigSerializes("300x200"); + + ExpectConfigSerializes("v8"); + + ExpectConfigSerializes( + "mcc123-mnc456-b+en+GB-ldltr-sw300dp-w300dp-h400dp-large-long-round-widecg-highdr-land-car-" + "night-xhdpi-stylus-keysexposed-qwerty-navhidden-dpad-300x200-v23"); +} + } // namespace aapt |