diff options
403 files changed, 7116 insertions, 3597 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 f6410834f257..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(); @@ -25661,7 +25723,7 @@ package android.net { field public static final android.os.Parcelable.Creator<android.net.LinkProperties> CREATOR; } - public class LocalServerSocket { + public class LocalServerSocket implements java.io.Closeable { ctor public LocalServerSocket(java.lang.String) throws java.io.IOException; ctor public LocalServerSocket(java.io.FileDescriptor) throws java.io.IOException; method public android.net.LocalSocket accept() throws java.io.IOException; diff --git a/api/system-current.txt b/api/system-current.txt index eee24dea55dc..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(); @@ -27896,7 +27960,7 @@ package android.net { field public static final android.os.Parcelable.Creator<android.net.LinkProperties> CREATOR; } - public class LocalServerSocket { + public class LocalServerSocket implements java.io.Closeable { ctor public LocalServerSocket(java.lang.String) throws java.io.IOException; ctor public LocalServerSocket(java.io.FileDescriptor) throws java.io.IOException; method public android.net.LocalSocket accept() throws java.io.IOException; diff --git a/api/test-current.txt b/api/test-current.txt index 2d7f67fe1650..2512e8e666b5 100644 --- a/api/test-current.txt +++ b/api/test-current.txt @@ -3866,6 +3866,8 @@ package android.app { method public deprecated void restartPackage(java.lang.String); method public static void setVrThread(int); method public void setWatchHeapLimit(long); + method public static boolean supportsMultiWindow(android.content.Context); + method public static boolean supportsSplitScreenMultiWindow(android.content.Context); field public static final java.lang.String ACTION_REPORT_HEAP_LIMIT = "android.app.action.REPORT_HEAP_LIMIT"; field public static final int LOCK_TASK_MODE_LOCKED = 1; // 0x1 field public static final int LOCK_TASK_MODE_NONE = 0; // 0x0 @@ -9045,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"; @@ -10199,6 +10202,7 @@ package android.content.pm { field public static final int PERSIST_ACROSS_REBOOTS = 2; // 0x2 field public static final int PERSIST_NEVER = 1; // 0x1 field public static final int PERSIST_ROOT_ONLY = 0; // 0x0 + field public static final int RESIZE_MODE_RESIZEABLE = 2; // 0x2 field public static final int SCREEN_ORIENTATION_BEHIND = 3; // 0x3 field public static final int SCREEN_ORIENTATION_FULL_SENSOR = 10; // 0xa field public static final int SCREEN_ORIENTATION_FULL_USER = 13; // 0xd @@ -25835,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(); @@ -25857,7 +25922,7 @@ package android.net { field public static final android.os.Parcelable.Creator<android.net.LinkProperties> CREATOR; } - public class LocalServerSocket { + public class LocalServerSocket implements java.io.Closeable { ctor public LocalServerSocket(java.lang.String) throws java.io.IOException; ctor public LocalServerSocket(java.io.FileDescriptor) throws java.io.IOException; method public android.net.LocalSocket accept() throws java.io.IOException; @@ -31820,6 +31885,21 @@ package android.os { method public static void setThreadPolicy(android.os.StrictMode.ThreadPolicy); method public static void setViolationLogger(android.os.StrictMode.ViolationLogger); method public static void setVmPolicy(android.os.StrictMode.VmPolicy); + field public static final int DETECT_CUSTOM = 8; // 0x8 + field public static final int DETECT_DISK_READ = 2; // 0x2 + field public static final int DETECT_DISK_WRITE = 1; // 0x1 + field public static final int DETECT_NETWORK = 4; // 0x4 + field public static final int DETECT_RESOURCE_MISMATCH = 16; // 0x10 + field public static final int DETECT_UNBUFFERED_IO = 32; // 0x20 + field public static final int DETECT_VM_ACTIVITY_LEAKS = 1024; // 0x400 + field public static final int DETECT_VM_CLEARTEXT_NETWORK = 16384; // 0x4000 + field public static final int DETECT_VM_CLOSABLE_LEAKS = 512; // 0x200 + field public static final int DETECT_VM_CONTENT_URI_WITHOUT_PERMISSION = 32768; // 0x8000 + field public static final int DETECT_VM_CURSOR_LEAKS = 256; // 0x100 + field public static final int DETECT_VM_FILE_URI_EXPOSURE = 8192; // 0x2000 + field public static final int DETECT_VM_INSTANCE_LEAKS = 2048; // 0x800 + field public static final int DETECT_VM_REGISTRATION_LEAKS = 4096; // 0x1000 + field public static final int DETECT_VM_UNTAGGED_SOCKET = -2147483648; // 0x80000000 } public static final class StrictMode.ThreadPolicy { 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/incidentd/tests/EncodedBuffer_test.cpp b/cmds/incidentd/tests/EncodedBuffer_test.cpp index 98c39bded512..37a938a6de07 100644 --- a/cmds/incidentd/tests/EncodedBuffer_test.cpp +++ b/cmds/incidentd/tests/EncodedBuffer_test.cpp @@ -42,40 +42,17 @@ const string FIX64_FIELD_3 = "\x19\xff\xff\xff\xff\xff\xff\xff\xff"; // -1 const string FIX32_FIELD_4 = "\x25\xff\xff\xff\xff"; // -1 const string MESSAGE_FIELD_5 = "\x2a\x10" + VARINT_FIELD_1 + STRING_FIELD_2; -static Privacy* create_privacy(uint32_t field_id, uint8_t type, uint8_t dest) { - struct Privacy* p = (struct Privacy*)malloc(sizeof(struct Privacy)); - p->field_id = field_id; - p->type = type; - p->children = NULL; - p->dest = dest; - p->patterns = NULL; - return p; -} - -static Privacy* create_message_privacy(uint32_t field_id, Privacy** children) -{ - struct Privacy* p = (struct Privacy*)malloc(sizeof(struct Privacy)); - p->field_id = field_id; - p->type = MESSAGE_TYPE; - p->children = children; - p->dest = EXPLICIT; - p->patterns = NULL; - return p; -} - -static Privacy* create_string_privacy(uint32_t field_id, uint8_t dest, const char** patterns) -{ - struct Privacy* p = (struct Privacy*)malloc(sizeof(struct Privacy)); - p->field_id = field_id; - p->type = STRING_TYPE; - p->children = NULL; - p->dest = dest; - p->patterns = patterns; - return p; -} - class EncodedBufferTest : public Test { public: + virtual ~EncodedBufferTest() { + // Delete in reverse order of construction, to be consistent with + // regular allocation/deallocation. + while (!privacies.empty()) { + delete privacies.back(); + privacies.pop_back(); + } + } + virtual void SetUp() override { ASSERT_NE(tf.fd, -1); } @@ -113,9 +90,48 @@ public: assertStrip(dest, expected, create_message_privacy(300, list)); } + Privacy* create_privacy(uint32_t field_id, uint8_t type, uint8_t dest) { + Privacy* p = new_uninit_privacy(); + p->field_id = field_id; + p->type = type; + p->children = NULL; + p->dest = dest; + p->patterns = NULL; + return p; + } + + Privacy* create_message_privacy(uint32_t field_id, Privacy** children) { + Privacy* p = new_uninit_privacy(); + p->field_id = field_id; + p->type = MESSAGE_TYPE; + p->children = children; + p->dest = EXPLICIT; + p->patterns = NULL; + return p; + } + + Privacy* create_string_privacy(uint32_t field_id, uint8_t dest, const char** patterns) { + Privacy* p = new_uninit_privacy(); + p->field_id = field_id; + p->type = STRING_TYPE; + p->children = NULL; + p->dest = dest; + p->patterns = patterns; + return p; + } + FdBuffer buffer; private: TemporaryFile tf; + // Littering this code with unique_ptr (or similar) is ugly, so we just + // mass-free everything after the test completes. + std::vector<Privacy *> privacies; + + Privacy *new_uninit_privacy() { + Privacy* p = new Privacy; + privacies.push_back(p); + return p; + } }; TEST_F(EncodedBufferTest, NullFieldPolicy) { 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/.clang-format b/cmds/statsd/.clang-format new file mode 100644 index 000000000000..3d64beeecda6 --- /dev/null +++ b/cmds/statsd/.clang-format @@ -0,0 +1,14 @@ +BasedOnStyle: Google +AllowShortIfStatementsOnASingleLine: true +AllowShortFunctionsOnASingleLine: false +AllowShortLoopsOnASingleLine: true +BinPackArguments: true +BinPackParameters: true +ColumnLimit: 100 +CommentPragmas: NOLINT:.* +ContinuationIndentWidth: 8 +DerivePointerAlignment: false +IndentWidth: 4 +PointerAlignment: Left +TabWidth: 4 +AccessModifierOffset: -4 diff --git a/cmds/statsd/Android.mk b/cmds/statsd/Android.mk index 6de530319727..b9ee7ff201d5 100644 --- a/cmds/statsd/Android.mk +++ b/cmds/statsd/Android.mk @@ -40,8 +40,8 @@ include $(CLEAR_VARS) LOCAL_MODULE := statsd LOCAL_SRC_FILES := \ - ../../core/java/android/os/IStatsManager.aidl \ ../../core/java/android/os/IStatsCompanionService.aidl \ + ../../core/java/android/os/IStatsManager.aidl \ src/StatsService.cpp \ src/AnomalyMonitor.cpp \ src/LogEntryPrinter.cpp \ @@ -119,6 +119,7 @@ LOCAL_C_INCLUDES += $(LOCAL_PATH)/src \ STATSD_PROTO_INCLUDES LOCAL_SRC_FILES := \ + ../../core/java/android/os/IStatsCompanionService.aidl \ ../../core/java/android/os/IStatsManager.aidl \ src/StatsService.cpp \ tests/indexed_priority_queue_test.cpp \ diff --git a/cmds/statsd/src/AnomalyMonitor.cpp b/cmds/statsd/src/AnomalyMonitor.cpp index d73de957881a..92fe84487d4d 100644 --- a/cmds/statsd/src/AnomalyMonitor.cpp +++ b/cmds/statsd/src/AnomalyMonitor.cpp @@ -17,22 +17,38 @@ #define LOG_TAG "AnomalyMonitor" #define DEBUG true -#include <AnomalyMonitor.h> +#include "AnomalyMonitor.h" -#include <binder/IServiceManager.h> #include <cutils/log.h> +namespace android { +namespace os { namespace statsd { AnomalyMonitor::AnomalyMonitor(uint32_t minDiffToUpdateRegisteredAlarmTimeSec) - : mRegisteredAlarmTimeSec(0), - mMinUpdateTimeSec(minDiffToUpdateRegisteredAlarmTimeSec) { + : mRegisteredAlarmTimeSec(0), mMinUpdateTimeSec(minDiffToUpdateRegisteredAlarmTimeSec) { } AnomalyMonitor::~AnomalyMonitor() { } +void AnomalyMonitor::setStatsCompanionService(sp<IStatsCompanionService> statsCompanionService) { + std::lock_guard<std::mutex> lock(mLock); + sp<IStatsCompanionService> tmpForLock = mStatsCompanionService; + mStatsCompanionService = statsCompanionService; + if (statsCompanionService == nullptr) { + if (DEBUG) ALOGD("Erasing link to statsCompanionService"); + return; + } + if (DEBUG) ALOGD("Creating link to statsCompanionService"); + const sp<const AnomalyAlarm> top = mPq.top(); + if (top != nullptr) { + updateRegisteredAlarmTime_l(top->timestampSec); + } +} + void AnomalyMonitor::add(sp<const AnomalyAlarm> alarm) { + std::lock_guard<std::mutex> lock(mLock); if (alarm == nullptr) { ALOGW("Asked to add a null alarm."); return; @@ -42,70 +58,50 @@ void AnomalyMonitor::add(sp<const AnomalyAlarm> alarm) { ALOGW("Asked to add a 0-time alarm."); return; } - std::lock_guard<std::mutex> lock(mLock); // TODO: Ensure that refractory period is respected. if (DEBUG) ALOGD("Adding alarm with time %u", alarm->timestampSec); mPq.push(alarm); if (mRegisteredAlarmTimeSec < 1 || - alarm->timestampSec + mMinUpdateTimeSec < mRegisteredAlarmTimeSec) { - updateRegisteredAlarmTime(alarm->timestampSec); + alarm->timestampSec + mMinUpdateTimeSec < mRegisteredAlarmTimeSec) { + updateRegisteredAlarmTime_l(alarm->timestampSec); } } void AnomalyMonitor::remove(sp<const AnomalyAlarm> alarm) { + std::lock_guard<std::mutex> lock(mLock); if (alarm == nullptr) { ALOGW("Asked to remove a null alarm."); return; } - std::lock_guard<std::mutex> lock(mLock); if (DEBUG) ALOGD("Removing alarm with time %u", alarm->timestampSec); mPq.remove(alarm); if (mPq.empty()) { if (DEBUG) ALOGD("Queue is empty. Cancel any alarm."); mRegisteredAlarmTimeSec = 0; - // TODO: Make this resistant to doing work when companion is not ready yet - sp<IStatsCompanionService> statsCompanionService = getStatsCompanion_l(); - if (statsCompanionService != nullptr) { - statsCompanionService->cancelAnomalyAlarm(); + if (mStatsCompanionService != nullptr) { + mStatsCompanionService->cancelAnomalyAlarm(); } return; } uint32_t soonestAlarmTimeSec = mPq.top()->timestampSec; if (DEBUG) ALOGD("Soonest alarm is %u", soonestAlarmTimeSec); if (soonestAlarmTimeSec > mRegisteredAlarmTimeSec + mMinUpdateTimeSec) { - updateRegisteredAlarmTime(soonestAlarmTimeSec); + updateRegisteredAlarmTime_l(soonestAlarmTimeSec); } } -void AnomalyMonitor::updateRegisteredAlarmTime(uint32_t timestampSec) { +void AnomalyMonitor::updateRegisteredAlarmTime_l(uint32_t timestampSec) { if (DEBUG) ALOGD("Updating reg alarm time to %u", timestampSec); mRegisteredAlarmTimeSec = timestampSec; - sp<IStatsCompanionService> statsCompanionService = getStatsCompanion_l(); - if (statsCompanionService != nullptr) { - statsCompanionService->setAnomalyAlarm(secToMs(mRegisteredAlarmTimeSec)); - } -} - -sp<IStatsCompanionService> AnomalyMonitor::getStatsCompanion_l() { - if (mStatsCompanion != nullptr) { - return mStatsCompanion; - } - // Get statscompanion service from service manager - const sp<IServiceManager> sm(defaultServiceManager()); - if (sm != nullptr) { - const String16 name("statscompanion"); - mStatsCompanion = - interface_cast<IStatsCompanionService>(sm->checkService(name)); - if (mStatsCompanion == nullptr) { - ALOGW("statscompanion service unavailable!"); - return nullptr; - } + if (mStatsCompanionService != nullptr) { + mStatsCompanionService->setAnomalyAlarm(secToMs(mRegisteredAlarmTimeSec)); } - return mStatsCompanion; } int64_t AnomalyMonitor::secToMs(uint32_t timeSec) { - return ((int64_t) timeSec) * 1000; + return ((int64_t)timeSec) * 1000; } -} // namespace statsd
\ No newline at end of file +} // namespace statsd +} // namespace os +} // namespace android diff --git a/cmds/statsd/src/AnomalyMonitor.h b/cmds/statsd/src/AnomalyMonitor.h index 5418cf0dc552..d78be5460572 100644 --- a/cmds/statsd/src/AnomalyMonitor.h +++ b/cmds/statsd/src/AnomalyMonitor.h @@ -17,16 +17,19 @@ #ifndef ANOMALY_MONITOR_H #define ANOMALY_MONITOR_H -#include <indexed_priority_queue.h> #include <android/os/IStatsCompanionService.h> +#include <indexed_priority_queue.h> #include <utils/RefBase.h> #include <queue> #include <vector> -using namespace android::os; using namespace android; +using android::os::IStatsCompanionService; + +namespace android { +namespace os { namespace statsd { /** @@ -52,8 +55,8 @@ struct AnomalyAlarm : public RefBase { /** * Manages alarms for Anomaly Detection. */ -class AnomalyMonitor { - public: +class AnomalyMonitor : public RefBase { +public: /** * @param minDiffToUpdateRegisteredAlarmTimeSec If the soonest alarm differs * from the registered alarm by more than this amount, update the registered @@ -63,6 +66,14 @@ class AnomalyMonitor { ~AnomalyMonitor(); /** + * Tells AnomalyMonitor what IStatsCompanionService to use and, if + * applicable, immediately registers an existing alarm with it. + * If nullptr, AnomalyMonitor will continue to add/remove alarms, but won't + * update IStatsCompanionService (until such time as it is set non-null). + */ + void setStatsCompanionService(sp<IStatsCompanionService> statsCompanionService); + + /** * Adds the given alarm (reference) to the queue. */ void add(sp<const AnomalyAlarm> alarm); @@ -83,8 +94,7 @@ class AnomalyMonitor { return mRegisteredAlarmTimeSec; } - private: - /** Lock for accessing/writing to mPq. */ +private: std::mutex mLock; /** @@ -103,11 +113,11 @@ class AnomalyMonitor { /** * Binder interface for communicating with StatsCompanionService. */ - sp<IStatsCompanionService> mStatsCompanion; + sp<IStatsCompanionService> mStatsCompanionService = nullptr; /** * Amount by which the soonest projected alarm must differ from - * mRegisteredAlarmTimeSec before updateRegisteredAlarmTime is called. + * mRegisteredAlarmTimeSec before updateRegisteredAlarmTime_l is called. */ uint32_t mMinUpdateTimeSec; @@ -115,15 +125,14 @@ class AnomalyMonitor { * Updates the alarm registered with StatsCompanionService to the given time. * Also correspondingly updates mRegisteredAlarmTimeSec. */ - void updateRegisteredAlarmTime(uint32_t timestampSec); - - /** Returns the StatsCompanionService. */ - sp<IStatsCompanionService> getStatsCompanion_l(); + void updateRegisteredAlarmTime_l(uint32_t timestampSec); /** Converts uint32 timestamp in seconds to a Java long in msec. */ int64_t secToMs(uint32_t timeSec); }; -} // namespace statsd +} // namespace statsd +} // namespace os +} // namespace android -#endif // ANOMALY_MONITOR_H
\ No newline at end of file +#endif // ANOMALY_MONITOR_H
\ No newline at end of file diff --git a/cmds/statsd/src/DropboxReader.cpp b/cmds/statsd/src/DropboxReader.cpp index cda2f431e435..27a01c8c1a5f 100644 --- a/cmds/statsd/src/DropboxReader.cpp +++ b/cmds/statsd/src/DropboxReader.cpp @@ -13,31 +13,33 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -#include <android/os/DropBoxManager.h> #include <android-base/file.h> +#include <android/os/DropBoxManager.h> #include <androidfw/ZipUtils.h> #include "DropboxReader.h" -using android::sp; using android::String16; -using android::binder::Status; +using android::ZipUtils; using android::base::unique_fd; -using android::os::statsd::EventMetricData; +using android::binder::Status; using android::os::DropBoxManager; -using android::ZipUtils; +using android::sp; using std::vector; +namespace android { +namespace os { +namespace statsd { + status_t DropboxReader::readStatsLogs(FILE* out, const string& tag, long msec) { sp<DropBoxManager> dropbox = new DropBoxManager(); StatsLogReport logReport; long timestamp = msec; // instead of while(true), put a hard limit 1000. Dropbox won't have more than 1000 files. - for(int i = 0; i < 1000; i++ ) { + for (int i = 0; i < 1000; i++) { DropBoxManager::Entry entry; - Status status = dropbox->getNextEntry(String16(tag.c_str()), - timestamp, &entry); + Status status = dropbox->getNextEntry(String16(tag.c_str()), timestamp, &entry); if (!status.isOk()) { ALOGD("No more entries, or failed to read. We can't tell unfortunately."); return android::OK; @@ -66,15 +68,14 @@ status_t DropboxReader::readStatsLogs(FILE* out, const string& tag, long msec) { } bool DropboxReader::parseFromGzipFile(const unique_fd& fd, StatsLogReport& logReport) { - FILE *file = fdopen(fd, "r"); + FILE* file = fdopen(fd, "r"); bool result = false; bool scanResult; int method; long compressedLen; long uncompressedLen; unsigned long crc32; - scanResult = ZipUtils::examineGzip(file, &method, &uncompressedLen, - &compressedLen, &crc32); + scanResult = ZipUtils::examineGzip(file, &method, &uncompressedLen, &compressedLen, &crc32); if (scanResult && method == kCompressDeflated) { vector<uint8_t> buf(uncompressedLen); if (ZipUtils::inflateToBuffer(file, &buf[0], uncompressedLen, compressedLen)) { @@ -104,8 +105,8 @@ bool DropboxReader::parseFromFile(const unique_fd& fd, StatsLogReport& logReport } void DropboxReader::printLog(FILE* out, const StatsLogReport& logReport) { - fprintf(out, "start_time_msec=%lld, end_time_msec=%lld, ", - logReport.start_report_millis(), logReport.end_report_millis()); + fprintf(out, "start_time_msec=%lld, end_time_msec=%lld, ", logReport.start_report_millis(), + logReport.end_report_millis()); for (int i = 0; i < logReport.event_metrics().data_size(); i++) { EventMetricData eventMetricData = logReport.event_metrics().data(i); for (int j = 0; j < eventMetricData.key_value_pair_size(); j++) { @@ -117,3 +118,7 @@ void DropboxReader::printLog(FILE* out, const StatsLogReport& logReport) { } fprintf(out, "\n"); } + +} // namespace statsd +} // namespace os +} // namespace android diff --git a/cmds/statsd/src/DropboxReader.h b/cmds/statsd/src/DropboxReader.h index f7d5a8205f57..a5a28d9113da 100644 --- a/cmds/statsd/src/DropboxReader.h +++ b/cmds/statsd/src/DropboxReader.h @@ -23,10 +23,13 @@ #include <stdio.h> using android::base::unique_fd; -using android::os::statsd::StatsLogReport; using android::status_t; using std::string; +namespace android { +namespace os { +namespace statsd { + class DropboxReader { public: // msec is the start timestamp. @@ -37,9 +40,13 @@ private: static bool parseFromGzipFile(const unique_fd& fd, StatsLogReport& logReport); static void printLog(FILE* out, const StatsLogReport& logReport); enum { - kCompressStored = 0, // no compression - kCompressDeflated = 8, // standard deflate + kCompressStored = 0, // no compression + kCompressDeflated = 8, // standard deflate }; }; -#endif //DROPBOX_READER_H +} // namespace statsd +} // namespace os +} // namespace android + +#endif // DROPBOX_READER_H diff --git a/cmds/statsd/src/DropboxWriter.cpp b/cmds/statsd/src/DropboxWriter.cpp index 01a9eac317d8..b72e530e413a 100644 --- a/cmds/statsd/src/DropboxWriter.cpp +++ b/cmds/statsd/src/DropboxWriter.cpp @@ -18,28 +18,30 @@ #include "DropboxWriter.h" -using android::os::DropBoxManager; +using android::String16; using android::binder::Status; +using android::os::DropBoxManager; using android::sp; -using android::String16; using std::vector; -DropboxWriter::DropboxWriter(const string& tag) - : mTag(tag), mLogReport(), mBufferSize(0) { +namespace android { +namespace os { +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() { @@ -48,12 +50,15 @@ void DropboxWriter::flush() { vector<uint8_t> buffer(numBytes); sp<DropBoxManager> dropbox = new DropBoxManager(); mLogReport.SerializeToArray(&buffer[0], numBytes); - Status status = dropbox->addData(String16(mTag.c_str()), &buffer[0], - numBytes, 0 /* no flag */); + Status status = dropbox->addData(String16(mTag.c_str()), &buffer[0], numBytes, 0 /* no flag */); if (!status.isOk()) { ALOGE("failed to write to dropbox"); - //TODO: What to do if flush fails?? + // TODO: What to do if flush fails?? } mLogReport.Clear(); mBufferSize = 0; } + +} // namespace statsd +} // namespace os +} // namespace android diff --git a/cmds/statsd/src/DropboxWriter.h b/cmds/statsd/src/DropboxWriter.h index 31b3f2764bb9..6107685c187f 100644 --- a/cmds/statsd/src/DropboxWriter.h +++ b/cmds/statsd/src/DropboxWriter.h @@ -20,7 +20,10 @@ #include <frameworks/base/cmds/statsd/src/stats_log.pb.h> using std::string; -using android::os::statsd::StatsLogReport; + +namespace android { +namespace os { +namespace statsd { class DropboxWriter { public: @@ -29,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(); @@ -49,17 +52,20 @@ private: StatsLogReport mLogReport; /* Current *serialized* size of the logs kept in memory. - To save computation, we will not calculate the size of the StatsLogReport every time when a new - entry is added, which would recursively call ByteSize() on every log entry. Instead, we keep - the sum of all individual stats log entry sizes. The size of a proto is approximately the sum - of the size of all member protos. + To save computation, we will not calculate the size of the StatsLogReport every time when a + new entry is added, which would recursively call ByteSize() on every log entry. Instead, we + keep the sum of all individual stats log entry sizes. The size of a proto is approximately + the sum of the size of all member protos. */ size_t mBufferSize = 0; /* 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); }; -#endif //DROPBOX_WRITER_H +} // namespace statsd +} // namespace os +} // namespace android + +#endif // DROPBOX_WRITER_H diff --git a/cmds/statsd/src/LogEntryPrinter.cpp b/cmds/statsd/src/LogEntryPrinter.cpp index ba07308086ca..63465b094da2 100644 --- a/cmds/statsd/src/LogEntryPrinter.cpp +++ b/cmds/statsd/src/LogEntryPrinter.cpp @@ -22,9 +22,11 @@ using namespace android; -LogEntryPrinter::LogEntryPrinter(int out) - :m_out(out) -{ +namespace android { +namespace os { +namespace statsd { + +LogEntryPrinter::LogEntryPrinter(int out) : m_out(out) { // Initialize the EventTagMap, which is how we know the names of the numeric event tags. // If this fails, we can't print well, but something will print. m_tags = android_openEventTagMap(NULL); @@ -34,23 +36,20 @@ LogEntryPrinter::LogEntryPrinter(int out) android_log_setPrintFormat(m_format, FORMAT_THREADTIME); } -LogEntryPrinter::~LogEntryPrinter() -{ +LogEntryPrinter::~LogEntryPrinter() { if (m_tags != NULL) { android_closeEventTagMap(m_tags); } android_log_format_free(m_format); } -void -LogEntryPrinter::OnLogEvent(const log_msg& msg) -{ +void LogEntryPrinter::OnLogEvent(const log_msg& msg) { status_t err; AndroidLogEntry entry; char buf[1024]; - err = android_log_processBinaryLogBuffer(&(const_cast<log_msg*>(&msg)->entry_v1), - &entry, m_tags, buf, sizeof(buf)); + err = android_log_processBinaryLogBuffer(&(const_cast<log_msg*>(&msg)->entry_v1), &entry, + m_tags, buf, sizeof(buf)); if (err == NO_ERROR) { android_log_printLogLine(m_format, m_out, &entry); } else { @@ -59,3 +58,6 @@ LogEntryPrinter::OnLogEvent(const log_msg& msg) } } +} // namespace statsd +} // namespace os +} // namespace android diff --git a/cmds/statsd/src/LogEntryPrinter.h b/cmds/statsd/src/LogEntryPrinter.h index 61ffddca0916..4f79028889c9 100644 --- a/cmds/statsd/src/LogEntryPrinter.h +++ b/cmds/statsd/src/LogEntryPrinter.h @@ -23,11 +23,14 @@ #include <stdio.h> +namespace android { +namespace os { +namespace statsd { + /** * Decodes the log entry and prints it to the supplied file descriptor. */ -class LogEntryPrinter : public LogListener -{ +class LogEntryPrinter : public LogListener { public: LogEntryPrinter(int out); virtual ~LogEntryPrinter(); @@ -51,4 +54,8 @@ private: AndroidLogFormat* m_format; }; -#endif // LOG_ENTRY_PRINTER_H +} // namespace statsd +} // namespace os +} // namespace android + +#endif // LOG_ENTRY_PRINTER_H diff --git a/cmds/statsd/src/LogReader.cpp b/cmds/statsd/src/LogReader.cpp index 2a9e5005499c..c4ac33724bc7 100644 --- a/cmds/statsd/src/LogReader.cpp +++ b/cmds/statsd/src/LogReader.cpp @@ -26,38 +26,32 @@ using namespace android; using namespace std; -#define SNOOZE_INITIAL_MS 100 -#define SNOOZE_MAX_MS (10 * 60 * 1000) // Ten minutes +namespace android { +namespace os { +namespace statsd { +#define SNOOZE_INITIAL_MS 100 +#define SNOOZE_MAX_MS (10 * 60 * 1000) // Ten minutes // ================================================================================ -LogListener::LogListener() -{ +LogListener::LogListener() { } -LogListener::~LogListener() -{ +LogListener::~LogListener() { } - // ================================================================================ -LogReader::LogReader() -{ +LogReader::LogReader() { } -LogReader::~LogReader() -{ +LogReader::~LogReader() { } -void -LogReader::AddListener(const sp<LogListener>& listener) -{ +void LogReader::AddListener(const sp<LogListener>& listener) { m_listeners.push_back(listener); } -void -LogReader::Run() -{ +void LogReader::Run() { int nextSnoozeMs = SNOOZE_INITIAL_MS; // In an ideal world, this outer loop will only ever run one iteration, but it @@ -96,9 +90,7 @@ LogReader::Run() } } -int -LogReader::connect_and_read() -{ +int LogReader::connect_and_read() { int lineCount = 0; status_t err; logger_list* loggers; @@ -106,8 +98,8 @@ LogReader::connect_and_read() // Prepare the logging context loggers = android_logger_list_alloc(ANDROID_LOG_RDONLY, - /* don't stop after N lines */ 0, - /* no pid restriction */ 0); + /* don't stop after N lines */ 0, + /* no pid restriction */ 0); // Open the buffer(s) eventLogger = android_logger_open(loggers, LOG_ID_STATS); @@ -129,7 +121,7 @@ LogReader::connect_and_read() // Call the listeners for (vector<sp<LogListener> >::iterator it = m_listeners.begin(); - it != m_listeners.end(); it++) { + it != m_listeners.end(); it++) { (*it)->OnLogEvent(msg); } } @@ -141,3 +133,6 @@ LogReader::connect_and_read() return lineCount; } +} // namespace statsd +} // namespace os +} // namespace android diff --git a/cmds/statsd/src/LogReader.h b/cmds/statsd/src/LogReader.h index 08a17a31aa18..fc19585ac6f0 100644 --- a/cmds/statsd/src/LogReader.h +++ b/cmds/statsd/src/LogReader.h @@ -18,16 +18,18 @@ #define LOGREADER_H #include <log/log_read.h> - #include <utils/RefBase.h> #include <vector> +namespace android { +namespace os { +namespace statsd { + /** - * Callback for LogReader + * Callback for LogReader */ -class LogListener : public virtual android::RefBase -{ +class LogListener : public virtual android::RefBase { public: LogListener(); virtual ~LogListener(); @@ -40,8 +42,7 @@ public: /** * Class to read logs from logd. */ -class LogReader : public virtual android::RefBase -{ +class LogReader : public virtual android::RefBase { public: /** * Construct the LogReader with a pointer back to the StatsService @@ -58,9 +59,9 @@ public: */ void AddListener(const android::sp<LogListener>& listener); - /** - * Run the main LogReader loop - */ + /** + * Run the main LogReader loop + */ void Run(); private: @@ -78,4 +79,8 @@ private: int connect_and_read(); }; -#endif // LOGREADER_H +} // namespace statsd +} // namespace os +} // namespace android + +#endif // LOGREADER_H diff --git a/cmds/statsd/src/StatsLogProcessor.cpp b/cmds/statsd/src/StatsLogProcessor.cpp index c2fffd8a2d84..280f9afcc66c 100644 --- a/cmds/statsd/src/StatsLogProcessor.cpp +++ b/cmds/statsd/src/StatsLogProcessor.cpp @@ -17,15 +17,16 @@ #include <StatsLogProcessor.h> #include <log/log_event_list.h> -#include <utils/Errors.h> #include <parse_util.h> +#include <utils/Errors.h> using namespace android; -using android::os::statsd::EventMetricData; -using android::os::statsd::StatsLogReport; -StatsLogProcessor::StatsLogProcessor() : m_dropbox_writer("all-logs") -{ +namespace android { +namespace os { +namespace statsd { + +StatsLogProcessor::StatsLogProcessor() : m_dropbox_writer("all-logs") { // Initialize the EventTagMap, which is how we know the names of the numeric event tags. // If this fails, we can't print well, but something will print. m_tags = android_openEventTagMap(NULL); @@ -35,39 +36,34 @@ StatsLogProcessor::StatsLogProcessor() : m_dropbox_writer("all-logs") android_log_setPrintFormat(m_format, FORMAT_THREADTIME); } -StatsLogProcessor::~StatsLogProcessor() -{ +StatsLogProcessor::~StatsLogProcessor() { if (m_tags != NULL) { android_closeEventTagMap(m_tags); } android_log_format_free(m_format); } -void -StatsLogProcessor::OnLogEvent(const log_msg& msg) -{ +void StatsLogProcessor::OnLogEvent(const log_msg& msg) { status_t err; AndroidLogEntry entry; char buf[1024]; - err = android_log_processBinaryLogBuffer(&(const_cast<log_msg*>(&msg)->entry_v1), - &entry, m_tags, buf, sizeof(buf)); + err = android_log_processBinaryLogBuffer(&(const_cast<log_msg*>(&msg)->entry_v1), &entry, + m_tags, buf, sizeof(buf)); // 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); } } -void -StatsLogProcessor::UpdateConfig(const int config_source, StatsdConfig config) -{ +void StatsLogProcessor::UpdateConfig(const int config_source, StatsdConfig config) { m_configs[config_source] = config; ALOGD("Updated configuration for source %i", config_source); } + +} // namespace statsd +} // namespace os +} // namespace android diff --git a/cmds/statsd/src/StatsLogProcessor.h b/cmds/statsd/src/StatsLogProcessor.h index 5df84245a406..1e525c07216c 100644 --- a/cmds/statsd/src/StatsLogProcessor.h +++ b/cmds/statsd/src/StatsLogProcessor.h @@ -20,10 +20,11 @@ #include <unordered_map> -using android::os::statsd::StatsdConfig; +namespace android { +namespace os { +namespace statsd { -class StatsLogProcessor : public LogListener -{ +class StatsLogProcessor : public LogListener { public: StatsLogProcessor(); virtual ~StatsLogProcessor(); @@ -51,4 +52,9 @@ private: */ std::unordered_map<int, StatsdConfig> m_configs; }; -#endif //STATS_LOG_PROCESSOR_H + +} // namespace statsd +} // namespace os +} // namespace android + +#endif // STATS_LOG_PROCESSOR_H diff --git a/cmds/statsd/src/StatsService.cpp b/cmds/statsd/src/StatsService.cpp index 24413f65fb9f..a28f0850ccea 100644 --- a/cmds/statsd/src/StatsService.cpp +++ b/cmds/statsd/src/StatsService.cpp @@ -15,6 +15,7 @@ */ #define LOG_TAG "statsd" +#define DEBUG true #include "StatsService.h" #include "DropboxReader.h" @@ -28,25 +29,26 @@ #include <utils/Looper.h> #include <utils/String16.h> -#include <unistd.h> #include <stdio.h> #include <stdlib.h> +#include <unistd.h> using namespace android; -using android::os::statsd::StatsdConfig; -// ================================================================================ +namespace android { +namespace os { +namespace statsd { + StatsService::StatsService(const sp<Looper>& handlerLooper) + : mAnomalyMonitor(new AnomalyMonitor(2)) // TODO: Change this based on the config { ALOGD("stats service constructed"); } -StatsService::~StatsService() -{ +StatsService::~StatsService() { } -status_t -StatsService::setProcessor(const sp<StatsLogProcessor>& main_processor) { +status_t StatsService::setProcessor(const sp<StatsLogProcessor>& main_processor) { m_processor = main_processor; ALOGD("stats service set to processor %p", m_processor.get()); return NO_ERROR; @@ -54,9 +56,8 @@ StatsService::setProcessor(const sp<StatsLogProcessor>& main_processor) { // Implement our own because the default binder implementation isn't // properly handling SHELL_COMMAND_TRANSACTION -status_t -StatsService::onTransact(uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) -{ +status_t StatsService::onTransact(uint32_t code, const Parcel& data, Parcel* reply, + uint32_t flags) { status_t err; switch (code) { @@ -69,10 +70,9 @@ StatsService::onTransact(uint32_t code, const Parcel& data, Parcel* reply, uint3 for (int i = 0; i < argc && data.dataAvail() > 0; i++) { args.add(String8(data.readString16())); } - sp<IShellCallback> shellCallback = IShellCallback::asInterface( - data.readStrongBinder()); - sp<IResultReceiver> resultReceiver = IResultReceiver::asInterface( - data.readStrongBinder()); + sp<IShellCallback> shellCallback = IShellCallback::asInterface(data.readStrongBinder()); + sp<IResultReceiver> resultReceiver = + IResultReceiver::asInterface(data.readStrongBinder()); FILE* fin = fdopen(in, "r"); FILE* fout = fdopen(out, "w"); @@ -100,15 +100,11 @@ StatsService::onTransact(uint32_t code, const Parcel& data, Parcel* reply, uint3 return NO_ERROR; } - default: { - return BnStatsManager::onTransact(code, data, reply, flags); - } + default: { return BnStatsManager::onTransact(code, data, reply, flags); } } } -status_t -StatsService::dump(int fd, const Vector<String16>& args) -{ +status_t StatsService::dump(int fd, const Vector<String16>& args) { FILE* out = fdopen(fd, "w"); if (out == NULL) { return NO_MEMORY; // the fd is already open @@ -117,7 +113,7 @@ StatsService::dump(int fd, const Vector<String16>& args) fprintf(out, "StatsService::dump:"); ALOGD("StatsService::dump:"); const int N = args.size(); - for (int i=0; i<N; i++) { + for (int i = 0; i < N; i++) { fprintf(out, " %s", String8(args[i]).string()); ALOGD(" %s", String8(args[i]).string()); } @@ -127,9 +123,7 @@ StatsService::dump(int fd, const Vector<String16>& args) return NO_ERROR; } -status_t -StatsService::command(FILE* in, FILE* out, FILE* err, Vector<String8>& args) -{ +status_t StatsService::command(FILE* in, FILE* out, FILE* err, Vector<String8>& args) { if (args.size() > 0) { if (!args[0].compare(String8("print-stats-log")) && args.size() > 1) { return doPrintStatsLog(out, args); @@ -143,9 +137,7 @@ StatsService::command(FILE* in, FILE* out, FILE* err, Vector<String8>& args) return NO_ERROR; } -status_t -StatsService::doLoadConfig(FILE* in) -{ +status_t StatsService::doLoadConfig(FILE* in) { string content; if (!android::base::ReadFdToString(fileno(in), &content)) { return UNKNOWN_ERROR; @@ -161,22 +153,102 @@ StatsService::doLoadConfig(FILE* in) } } -Status -StatsService::systemRunning() -{ +Status StatsService::informAnomalyAlarmFired() { + if (DEBUG) ALOGD("StatsService::informAnomalyAlarmFired was called"); + + if (IPCThreadState::self()->getCallingUid() != AID_SYSTEM) { + return Status::fromExceptionCode(Status::EX_SECURITY, + "Only system uid can call informAnomalyAlarmFired"); + } + + if (DEBUG) ALOGD("StatsService::informAnomalyAlarmFired succeeded"); + // TODO: check through all counters/timers and see if an anomaly has indeed occurred. + + return Status::ok(); +} + +Status StatsService::informPollAlarmFired() { + if (DEBUG) ALOGD("StatsService::informPollAlarmFired was called"); + + if (IPCThreadState::self()->getCallingUid() != AID_SYSTEM) { + return Status::fromExceptionCode(Status::EX_SECURITY, + "Only system uid can call informPollAlarmFired"); + } + + if (DEBUG) ALOGD("StatsService::informPollAlarmFired succeeded"); + // TODO: determine what services to poll and poll (or ask StatsCompanionService to poll) them. + + return Status::ok(); +} + +Status StatsService::systemRunning() { if (IPCThreadState::self()->getCallingUid() != AID_SYSTEM) { return Status::fromExceptionCode(Status::EX_SECURITY, - "Only system uid can call systemRunning"); + "Only system uid can call systemRunning"); } // When system_server is up and running, schedule the dropbox task to run. ALOGD("StatsService::systemRunning"); + sayHiToStatsCompanion(); + return Status::ok(); } -status_t -StatsService::doPrintStatsLog(FILE* out, const Vector<String8>& args) { +void StatsService::sayHiToStatsCompanion() { + // TODO: This method needs to be private. It is temporarily public and unsecured for testing + // purposes. + sp<IStatsCompanionService> statsCompanion = getStatsCompanionService(); + if (statsCompanion != nullptr) { + if (DEBUG) ALOGD("Telling statsCompanion that statsd is ready"); + statsCompanion->statsdReady(); + } else { + if (DEBUG) ALOGD("Could not access statsCompanion"); + } +} + +sp<IStatsCompanionService> StatsService::getStatsCompanionService() { + sp<IStatsCompanionService> statsCompanion = nullptr; + // Get statscompanion service from service manager + const sp<IServiceManager> sm(defaultServiceManager()); + if (sm != nullptr) { + const String16 name("statscompanion"); + statsCompanion = interface_cast<IStatsCompanionService>(sm->checkService(name)); + if (statsCompanion == nullptr) { + ALOGW("statscompanion service unavailable!"); + return nullptr; + } + } + return statsCompanion; +} + +Status StatsService::statsCompanionReady() { + if (DEBUG) ALOGD("StatsService::statsCompanionReady was called"); + + if (IPCThreadState::self()->getCallingUid() != AID_SYSTEM) { + return Status::fromExceptionCode(Status::EX_SECURITY, + "Only system uid can call statsCompanionReady"); + } + + sp<IStatsCompanionService> statsCompanion = getStatsCompanionService(); + if (statsCompanion == nullptr) { + return Status::fromExceptionCode( + Status::EX_NULL_POINTER, + "statscompanion unavailable despite it contacting statsd!"); + } + if (DEBUG) ALOGD("StatsService::statsCompanionReady linking to statsCompanion."); + IInterface::asBinder(statsCompanion)->linkToDeath(new StatsdDeathRecipient(mAnomalyMonitor)); + mAnomalyMonitor->setStatsCompanionService(statsCompanion); + + return Status::ok(); +} + +void StatsdDeathRecipient::binderDied(const wp<IBinder>& who) { + ALOGW("statscompanion service died"); + mAnmlyMntr->setStatsCompanionService(nullptr); +} + +status_t StatsService::doPrintStatsLog(FILE* out, const Vector<String8>& args) { long msec = 0; if (args.size() > 2) { @@ -185,9 +257,14 @@ StatsService::doPrintStatsLog(FILE* out, const Vector<String8>& args) { return DropboxReader::readStatsLogs(out, args[1].string(), msec); } -void -StatsService::printCmdHelp(FILE* out) { +void StatsService::printCmdHelp(FILE* out) { fprintf(out, "Usage:\n"); fprintf(out, "\t print-stats-log [tag_required] [timestamp_nsec_optional]\n"); - fprintf(out, "\t config\t Loads a new config from command-line (must be proto in wire-encoded format).\n"); + fprintf(out, + "\t config\t Loads a new config from command-line (must be proto in wire-encoded " + "format).\n"); } + +} // namespace statsd +} // namespace os +} // namespace android diff --git a/cmds/statsd/src/StatsService.h b/cmds/statsd/src/StatsService.h index ef52b5628c29..a956cbf83fd4 100644 --- a/cmds/statsd/src/StatsService.h +++ b/cmds/statsd/src/StatsService.h @@ -17,9 +17,11 @@ #ifndef STATS_SERVICE_H #define STATS_SERVICE_H +#include "AnomalyMonitor.h" #include "StatsLogProcessor.h" #include <android/os/BnStatsManager.h> +#include <android/os/IStatsCompanionService.h> #include <binder/IResultReceiver.h> #include <binder/IShellCallback.h> #include <frameworks/base/cmds/statsd/src/statsd_config.pb.h> @@ -33,9 +35,11 @@ using namespace android::base; using namespace android::binder; using namespace android::os; using namespace std; -using android::os::statsd::StatsdConfig; -// ================================================================================ +namespace android { +namespace os { +namespace statsd { + class StatsService : public BnStatsManager { public: StatsService(const sp<Looper>& handlerLooper); @@ -49,13 +53,49 @@ public: virtual Status systemRunning(); + // Inform statsd that statsCompanion is ready. + virtual Status statsCompanionReady(); + + virtual Status informAnomalyAlarmFired(); + + virtual Status informPollAlarmFired(); + virtual status_t setProcessor(const sp<StatsLogProcessor>& main_processor); + // TODO: public for testing since statsd doesn't run when system starts. Change to private + // later. + /** Inform statsCompanion that statsd is ready. */ + virtual void sayHiToStatsCompanion(); + private: - sp<StatsLogProcessor> m_processor; // Reference to the processor for updating configs. + sp<StatsLogProcessor> m_processor; // Reference to the processor for updating configs. + + const sp<AnomalyMonitor> mAnomalyMonitor; // TODO: Move this to a more logical file/class + status_t doPrintStatsLog(FILE* out, const Vector<String8>& args); + void printCmdHelp(FILE* out); + status_t doLoadConfig(FILE* in); + + /** Fetches the StatsCompanionService. */ + sp<IStatsCompanionService> getStatsCompanionService(); +}; + +// --- StatsdDeathRecipient --- +class StatsdDeathRecipient : public IBinder::DeathRecipient { +public: + StatsdDeathRecipient(sp<AnomalyMonitor> anomalyMonitor) : mAnmlyMntr(anomalyMonitor) { + } + + virtual void binderDied(const wp<IBinder>& who); + +private: + const sp<AnomalyMonitor> mAnmlyMntr; }; -#endif // STATS_SERVICE_H +} // namespace statsd +} // namespace os +} // namespace android + +#endif // STATS_SERVICE_H diff --git a/cmds/statsd/src/indexed_priority_queue.h b/cmds/statsd/src/indexed_priority_queue.h index d302f855b1bf..c749c3ee6d17 100644 --- a/cmds/statsd/src/indexed_priority_queue.h +++ b/cmds/statsd/src/indexed_priority_queue.h @@ -20,15 +20,17 @@ // ALOGE can be called from this file. If header loaded by another class, use their LOG_TAG instead. #ifndef LOG_TAG #define LOG_TAG "statsd(indexed_priority_queue)" -#endif //LOG_TAG +#endif // LOG_TAG #include <cutils/log.h> -#include <unordered_map> #include <utils/RefBase.h> +#include <unordered_map> #include <vector> using namespace android; +namespace android { +namespace os { namespace statsd { /** Defines a hash function for sp<AA>, returning the hash of the underlying pointer. */ @@ -47,7 +49,7 @@ struct SpHash { */ template <class AA, class Comparator> class indexed_priority_queue { - public: +public: indexed_priority_queue(); /** Adds a into the priority queue. If already present or a==nullptr, does nothing. */ void push(sp<const AA> a); @@ -60,11 +62,15 @@ class indexed_priority_queue { /** Returns min element. Returns nullptr iff empty(). */ sp<const AA> top() const; /** Returns number of elements in priority queue. */ - size_t size() const { return pq.size() - 1; } // pq is 1-indexed + size_t size() const { + return pq.size() - 1; + } // pq is 1-indexed /** Returns true iff priority queue is empty. */ - bool empty() const { return size() < 1; } + bool empty() const { + return size() < 1; + } - private: +private: /** Vector representing a min-heap (1-indexed, with nullptr at 0). */ std::vector<sp<const AA>> pq; /** Mapping of each element in pq to its index in pq (i.e. the inverse of a=pq[i]). */ @@ -81,22 +87,22 @@ class indexed_priority_queue { // Implementation must be done in this file due to use of template. template <class AA, class Comparator> -indexed_priority_queue<AA,Comparator>::indexed_priority_queue() { +indexed_priority_queue<AA, Comparator>::indexed_priority_queue() { init(); } template <class AA, class Comparator> -void indexed_priority_queue<AA,Comparator>::push(sp<const AA> a) { +void indexed_priority_queue<AA, Comparator>::push(sp<const AA> a) { if (a == nullptr) return; if (contains(a)) return; pq.push_back(a); - size_t idx = size(); // index of last element since 1-indexed + size_t idx = size(); // index of last element since 1-indexed indices.insert({a, idx}); - sift_up(idx); // get the pq back in order + sift_up(idx); // get the pq back in order } template <class AA, class Comparator> -void indexed_priority_queue<AA,Comparator>::remove(sp<const AA> a) { +void indexed_priority_queue<AA, Comparator>::remove(sp<const AA> a) { if (a == nullptr) return; if (!contains(a)) return; size_t idx = indices[a]; @@ -104,7 +110,7 @@ void indexed_priority_queue<AA,Comparator>::remove(sp<const AA> a) { ALOGE("indexed_priority_queue: Invalid index in map of indices."); return; } - if (idx == size()) { // if a is the last element, i.e. at index idx == size() == (pq.size()-1) + if (idx == size()) { // if a is the last element, i.e. at index idx == size() == (pq.size()-1) pq.pop_back(); indices.erase(a); return; @@ -122,62 +128,66 @@ void indexed_priority_queue<AA,Comparator>::remove(sp<const AA> a) { } template <class AA, class Comparator> -void indexed_priority_queue<AA,Comparator>::clear() { +void indexed_priority_queue<AA, Comparator>::clear() { pq.clear(); indices.clear(); init(); } template <class AA, class Comparator> -sp<const AA> indexed_priority_queue<AA,Comparator>::top() const { +sp<const AA> indexed_priority_queue<AA, Comparator>::top() const { if (empty()) return nullptr; return pq[1]; } template <class AA, class Comparator> -void indexed_priority_queue<AA,Comparator>::init() { - pq.push_back(nullptr); // so that pq is 1-indexed. - indices.insert({nullptr, 0}); // just to be consistent with pq. +void indexed_priority_queue<AA, Comparator>::init() { + pq.push_back(nullptr); // so that pq is 1-indexed. + indices.insert({nullptr, 0}); // just to be consistent with pq. } template <class AA, class Comparator> -void indexed_priority_queue<AA,Comparator>::sift_up(size_t idx) { +void indexed_priority_queue<AA, Comparator>::sift_up(size_t idx) { while (idx > 1) { - size_t parent = idx/2; - if (higher(idx, parent)) swap_indices(idx, parent); - else break; + size_t parent = idx / 2; + if (higher(idx, parent)) + swap_indices(idx, parent); + else + break; idx = parent; } } template <class AA, class Comparator> -void indexed_priority_queue<AA,Comparator>::sift_down(size_t idx) { - while (2*idx <= size()) { +void indexed_priority_queue<AA, Comparator>::sift_down(size_t idx) { + while (2 * idx <= size()) { size_t child = 2 * idx; - if (child < size() && higher(child+1, child)) child++; - if (higher(child, idx)) swap_indices(child, idx); - else break; + if (child < size() && higher(child + 1, child)) child++; + if (higher(child, idx)) + swap_indices(child, idx); + else + break; idx = child; } } template <class AA, class Comparator> -bool indexed_priority_queue<AA,Comparator>::higher(size_t idx1, size_t idx2) const { +bool indexed_priority_queue<AA, Comparator>::higher(size_t idx1, size_t idx2) const { if (!(0u < idx1 && idx1 < pq.size() && 0u < idx2 && idx2 < pq.size())) { ALOGE("indexed_priority_queue: Attempting to access invalid index"); - return false; // got to do something. + return false; // got to do something. } return Comparator()(pq[idx1], pq[idx2]); } template <class AA, class Comparator> -bool indexed_priority_queue<AA,Comparator>::contains(sp<const AA> a) const { - if (a == nullptr) return false; // publicly, we pretend that nullptr is not actually in pq. +bool indexed_priority_queue<AA, Comparator>::contains(sp<const AA> a) const { + if (a == nullptr) return false; // publicly, we pretend that nullptr is not actually in pq. return indices.count(a) > 0; } template <class AA, class Comparator> -void indexed_priority_queue<AA,Comparator>::swap_indices(size_t i, size_t j) { +void indexed_priority_queue<AA, Comparator>::swap_indices(size_t i, size_t j) { if (!(0u < i && i < pq.size() && 0u < j && j < pq.size())) { ALOGE("indexed_priority_queue: Attempting to swap invalid index"); return; @@ -190,6 +200,8 @@ void indexed_priority_queue<AA,Comparator>::swap_indices(size_t i, size_t j) { indices[val_j] = i; } -} // namespace statsd +} // namespace statsd +} // namespace os +} // namespace android -#endif //STATSD_INDEXED_PRIORITY_QUEUE_H +#endif // STATSD_INDEXED_PRIORITY_QUEUE_H diff --git a/cmds/statsd/src/main.cpp b/cmds/statsd/src/main.cpp index f9265c642dfb..b303321d8ef2 100644 --- a/cmds/statsd/src/main.cpp +++ b/cmds/statsd/src/main.cpp @@ -18,8 +18,8 @@ #include "LogEntryPrinter.h" #include "LogReader.h" -#include "StatsService.h" #include "StatsLogProcessor.h" +#include "StatsService.h" #include <binder/IInterface.h> #include <binder/IPCThreadState.h> @@ -31,11 +31,12 @@ #include <utils/StrongPointer.h> #include <stdio.h> -#include <sys/types.h> #include <sys/stat.h> +#include <sys/types.h> #include <unistd.h> using namespace android; +using namespace android::os::statsd; // ================================================================================ /** @@ -48,9 +49,7 @@ struct log_reader_thread_data { /** * Thread func for where the log reader runs. */ -static void* -log_reader_thread_func(void* cookie) -{ +static void* log_reader_thread_func(void* cookie) { log_reader_thread_data* data = static_cast<log_reader_thread_data*>(cookie); sp<LogReader> reader = new LogReader(); @@ -74,9 +73,7 @@ log_reader_thread_func(void* cookie) /** * Creates and starts the thread to own the LogReader. */ -static status_t -start_log_reader_thread(const sp<StatsService>& service) -{ +static status_t start_log_reader_thread(const sp<StatsService>& service) { status_t err; pthread_attr_t attr; pthread_t thread; @@ -107,9 +104,7 @@ start_log_reader_thread(const sp<StatsService>& service) } // ================================================================================ -int -main(int /*argc*/, char** /*argv*/) -{ +int main(int /*argc*/, char** /*argv*/) { status_t err; // Set up the looper @@ -117,7 +112,7 @@ main(int /*argc*/, char** /*argv*/) // Set up the binder sp<ProcessState> ps(ProcessState::self()); - ps->setThreadPoolMaxThreadCount(1); // everything is oneway, let it queue and save ram + ps->setThreadPoolMaxThreadCount(1); // everything is oneway, let it queue and save ram ps->startThreadPool(); ps->giveThreadPoolName(); IPCThreadState::self()->disableBackgroundScheduling(true); @@ -129,6 +124,10 @@ main(int /*argc*/, char** /*argv*/) return -1; } + // TODO: This line is temporary, since statsd doesn't start up automatically (and therefore + // the call in StatsService::SystemRunning() won't ever be called right now). + service->sayHiToStatsCompanion(); + // Start the log reader thread err = start_log_reader_thread(service); if (err != NO_ERROR) { diff --git a/cmds/statsd/src/parse_util.cpp b/cmds/statsd/src/parse_util.cpp index 9caeacf3b538..6464ee166dc9 100644 --- a/cmds/statsd/src/parse_util.cpp +++ b/cmds/statsd/src/parse_util.cpp @@ -14,9 +14,10 @@ * limitations under the License. */ -#include <parse_util.h> #include <log/log_event_list.h> +#include <parse_util.h> +using android::os::statsd::EVENT_TIMESTAMP; using android::os::statsd::EventMetricData; using android::os::statsd::KeyId; using android::os::statsd::KeyId_IsValid; @@ -24,67 +25,77 @@ using android::os::statsd::KeyValuePair; using android::os::statsd::TagId; using android::os::statsd::TagId_IsValid; +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; - android_log_context context = create_android_log_parser(const_cast<log_msg*>(&msg)->msg() - + sizeof(uint32_t), - const_cast<log_msg*>(&msg)->len() - - sizeof(uint32_t)); + + // 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); + keyValuePair->set_value_int(msg.entry_v1.sec * NS_PER_SEC + msg.entry_v1.nsec); + + // start iterating k,v pairs. + android_log_context context = + create_android_log_parser(const_cast<log_msg*>(&msg)->msg() + sizeof(uint32_t), + const_cast<log_msg*>(&msg)->len() - sizeof(uint32_t)); android_log_list_element elem; if (context) { 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* 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* keyValuePair = eventMetricData.add_key_value_pair(); keyValuePair->set_key(static_cast<KeyId>(key)); keyValuePair->set_value_float(val); } 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* keyValuePair = eventMetricData.add_key_value_pair(); keyValuePair->set_key(static_cast<KeyId>(key)); keyValuePair->set_value_str(val); } 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* keyValuePair = eventMetricData.add_key_value_pair(); keyValuePair->set_key(static_cast<KeyId>(key)); keyValuePair->set_value_int(val); } diff --git a/cmds/statsd/src/parse_util.h b/cmds/statsd/src/parse_util.h index 8750f822102d..e9f4c2735cea 100644 --- a/cmds/statsd/src/parse_util.h +++ b/cmds/statsd/src/parse_util.h @@ -16,8 +16,8 @@ #ifndef PARSE_UTIL_H #define PARSE_UTIL_H -#include "LogReader.h" #include "DropboxWriter.h" +#include "LogReader.h" #include <log/logprint.h> @@ -25,4 +25,4 @@ using android::os::statsd::EventMetricData; EventMetricData parse(const log_msg msg); -#endif // PARSE_UTIL_H +#endif // PARSE_UTIL_H diff --git a/cmds/statsd/src/stats_constants.proto b/cmds/statsd/src/stats_constants.proto index 3f8bd1c5a9fc..9758a2e0cb89 100644 --- a/cmds/statsd/src/stats_constants.proto +++ b/cmds/statsd/src/stats_constants.proto @@ -24,7 +24,8 @@ option java_outer_classname = "StatsConstantsProto"; enum TagId { WAKELOCK = 1; - SCREEN = 1003; + SCREEN = 2; + PROCESS = 1112; // TODO: Temporary usage only for testing. } enum KeyId { diff --git a/cmds/statsd/tests/LogReader_test.cpp b/cmds/statsd/tests/LogReader_test.cpp index ca538b082f89..2002143edfc1 100644 --- a/cmds/statsd/tests/LogReader_test.cpp +++ b/cmds/statsd/tests/LogReader_test.cpp @@ -21,4 +21,3 @@ TEST(LogReaderTest, TestNothingAtAll) { printf("yay!"); } - diff --git a/cmds/statsd/tests/indexed_priority_queue_test.cpp b/cmds/statsd/tests/indexed_priority_queue_test.cpp index a679128dd37e..e4d4d25afe00 100644 --- a/cmds/statsd/tests/indexed_priority_queue_test.cpp +++ b/cmds/statsd/tests/indexed_priority_queue_test.cpp @@ -18,7 +18,7 @@ #include <gtest/gtest.h> -using namespace statsd; +using namespace android::os::statsd; /** struct for template in indexed_priority_queue */ struct AATest : public RefBase { @@ -133,7 +133,6 @@ TEST(indexed_priority_queue, push_same_aa) { EXPECT_TRUE(ipq.contains(aa4_b)); } - TEST(indexed_priority_queue, remove_nonexistant) { indexed_priority_queue<AATest, AATest::Smaller> ipq; sp<const AATest> aa4 = new AATest{4}; diff --git a/config/compiled-classes-phone b/config/compiled-classes-phone index c1cbb648aae6..df68f14efec9 100644 --- a/config/compiled-classes-phone +++ b/config/compiled-classes-phone @@ -3824,7 +3824,6 @@ android.system.PacketSocketAddress android.system.StructAddrinfo android.system.StructFlock android.system.StructGroupReq -android.system.StructGroupSourceReq android.system.StructIcmpHdr android.system.StructIfaddrs android.system.StructLinger diff --git a/config/preloaded-classes b/config/preloaded-classes index 2844efb302de..337d7a0ad8bb 100644 --- a/config/preloaded-classes +++ b/config/preloaded-classes @@ -2006,7 +2006,6 @@ android.system.PacketSocketAddress android.system.StructAddrinfo android.system.StructFlock android.system.StructGroupReq -android.system.StructGroupSourceReq android.system.StructIfaddrs android.system.StructLinger android.system.StructPasswd diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java index 78d05f5123c8..5e2e333b4c9c 100644 --- a/core/java/android/app/ActivityManager.java +++ b/core/java/android/app/ActivityManager.java @@ -1152,6 +1152,7 @@ public class ActivityManager { * E.g. freeform, split-screen, picture-in-picture. * @hide */ + @TestApi static public boolean supportsMultiWindow(Context context) { // On watches, multi-window is used to present essential system UI, and thus it must be // supported regardless of device memory characteristics. @@ -1166,6 +1167,7 @@ public class ActivityManager { * Returns true if the system supports split screen multi-window. * @hide */ + @TestApi static public boolean supportsSplitScreenMultiWindow(Context context) { return supportsMultiWindow(context) && Resources.getSystem().getBoolean( diff --git a/core/java/android/app/ITaskStackListener.aidl b/core/java/android/app/ITaskStackListener.aidl index b5b101773f15..a56965bdbd4d 100644 --- a/core/java/android/app/ITaskStackListener.aidl +++ b/core/java/android/app/ITaskStackListener.aidl @@ -30,7 +30,7 @@ oneway interface ITaskStackListener { void onTaskStackChanged(); /** Called whenever an Activity is moved to the pinned stack from another stack. */ - void onActivityPinned(String packageName, int taskId); + void onActivityPinned(String packageName, int userId, int taskId); /** Called whenever an Activity is moved from the pinned stack to another stack. */ void onActivityUnpinned(); 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 ee6c1cbaecfe..60f4ed01805c 100644 --- a/core/java/android/app/Notification.java +++ b/core/java/android/app/Notification.java @@ -67,7 +67,6 @@ import android.text.style.TextAppearanceSpan; import android.util.ArraySet; import android.util.Log; import android.util.SparseArray; -import android.util.TypedValue; import android.view.Gravity; import android.view.NotificationHeaderView; import android.view.View; @@ -3906,7 +3905,6 @@ public class Notification implements Parcelable if (p.title != null) { contentView.setViewVisibility(R.id.title, View.VISIBLE); contentView.setTextViewText(R.id.title, processTextSpans(p.title)); - updateTextSizePrimary(contentView, R.id.title); if (!p.ambient) { setTextViewColorPrimary(contentView, R.id.title); } @@ -3918,7 +3916,6 @@ public class Notification implements Parcelable int textId = showProgress ? com.android.internal.R.id.text_line_1 : com.android.internal.R.id.text; contentView.setTextViewText(textId, processTextSpans(p.text)); - updateTextSizeSecondary(contentView, textId); if (!p.ambient) { setTextViewColorSecondary(contentView, textId); } @@ -3930,25 +3927,6 @@ public class Notification implements Parcelable return contentView; } - private void updateTextSizeSecondary(RemoteViews contentView, int textId) { - updateTextSizeColorized(contentView, textId, - com.android.internal.R.dimen.notification_text_size_colorized, - com.android.internal.R.dimen.notification_text_size); - } - - private void updateTextSizePrimary(RemoteViews contentView, int textId) { - updateTextSizeColorized(contentView, textId, - com.android.internal.R.dimen.notification_title_text_size_colorized, - com.android.internal.R.dimen.notification_title_text_size); - } - - private void updateTextSizeColorized(RemoteViews contentView, int textId, - int colorizedDimen, int normalDimen) { - int size = mContext.getResources().getDimensionPixelSize(isColorized() - ? colorizedDimen : normalDimen); - contentView.setTextViewTextSize(textId, TypedValue.COMPLEX_UNIT_PX, size); - } - private CharSequence processTextSpans(CharSequence text) { if (hasForegroundColor()) { return NotificationColorUtil.clearColorSpans(text); @@ -5874,7 +5852,6 @@ public class Notification implements Parcelable builder.setTextViewColorSecondary(contentView, R.id.big_text); contentView.setViewVisibility(R.id.big_text, TextUtils.isEmpty(bigTextText) ? View.GONE : View.VISIBLE); - builder.updateTextSizeSecondary(contentView, R.id.big_text); contentView.setBoolean(R.id.big_text, "setHasImage", builder.mN.hasLargeIcon()); } } @@ -6208,7 +6185,6 @@ public class Notification implements Parcelable contentView.setViewVisibility(rowId, View.VISIBLE); contentView.setTextViewText(rowId, mBuilder.processTextSpans( makeMessageLine(m, mBuilder))); - mBuilder.updateTextSizeSecondary(contentView, rowId); mBuilder.setTextViewColorSecondary(contentView, rowId); if (contractedMessage == m) { @@ -6576,7 +6552,6 @@ public class Notification implements Parcelable contentView.setViewVisibility(rowIds[i], View.VISIBLE); contentView.setTextViewText(rowIds[i], mBuilder.processTextSpans(mBuilder.processLegacyText(str))); - mBuilder.updateTextSizeSecondary(contentView, rowIds[i]); mBuilder.setTextViewColorSecondary(contentView, rowIds[i]); contentView.setViewPadding(rowIds[i], 0, topPadding, 0, 0); handleInboxImageMargin(contentView, rowIds[i], first); 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/TaskStackListener.java b/core/java/android/app/TaskStackListener.java index a52ca0a64cd2..4674c9cd2389 100644 --- a/core/java/android/app/TaskStackListener.java +++ b/core/java/android/app/TaskStackListener.java @@ -31,7 +31,8 @@ public abstract class TaskStackListener extends ITaskStackListener.Stub { } @Override - public void onActivityPinned(String packageName, int taskId) throws RemoteException { + public void onActivityPinned(String packageName, int userId, int taskId) + throws RemoteException { } @Override diff --git a/core/java/android/app/timezone/RulesUpdaterContract.java b/core/java/android/app/timezone/RulesUpdaterContract.java index 9c62f46b6e36..74ed658875ab 100644 --- a/core/java/android/app/timezone/RulesUpdaterContract.java +++ b/core/java/android/app/timezone/RulesUpdaterContract.java @@ -51,7 +51,7 @@ public final class RulesUpdaterContract { * applies. */ public static final String ACTION_TRIGGER_RULES_UPDATE_CHECK = - "android.intent.action.timezone.TRIGGER_RULES_UPDATE_CHECK"; + "com.android.intent.action.timezone.TRIGGER_RULES_UPDATE_CHECK"; /** * The extra containing the {@code byte[]} that should be passed to @@ -61,7 +61,7 @@ public final class RulesUpdaterContract { * {@link #ACTION_TRIGGER_RULES_UPDATE_CHECK} intent has been processed. */ public static final String EXTRA_CHECK_TOKEN = - "android.intent.extra.timezone.CHECK_TOKEN"; + "com.android.intent.extra.timezone.CHECK_TOKEN"; /** * Creates an intent that would trigger a time zone rules update check. @@ -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/appwidget/AppWidgetHostView.java b/core/java/android/appwidget/AppWidgetHostView.java index 8a1eae2da976..dc9970a7ca42 100644 --- a/core/java/android/appwidget/AppWidgetHostView.java +++ b/core/java/android/appwidget/AppWidgetHostView.java @@ -23,17 +23,12 @@ import android.content.pm.LauncherApps; import android.content.pm.PackageManager; import android.content.pm.PackageManager.NameNotFoundException; import android.content.res.Resources; -import android.graphics.Bitmap; -import android.graphics.Canvas; import android.graphics.Color; -import android.graphics.Paint; import android.graphics.Rect; import android.os.Build; import android.os.Bundle; import android.os.CancellationSignal; -import android.os.Parcel; import android.os.Parcelable; -import android.os.SystemClock; import android.util.AttributeSet; import android.util.Log; import android.util.SparseArray; @@ -58,17 +53,17 @@ import java.util.concurrent.Executor; * {@link RemoteViews}. */ public class AppWidgetHostView extends FrameLayout { + static final String TAG = "AppWidgetHostView"; + private static final String KEY_JAILED_ARRAY = "jail"; + static final boolean LOGD = false; - static final boolean CROSSFADE = false; static final int VIEW_MODE_NOINIT = 0; static final int VIEW_MODE_CONTENT = 1; static final int VIEW_MODE_ERROR = 2; static final int VIEW_MODE_DEFAULT = 3; - static final int FADE_DURATION = 1000; - // When we're inflating the initialLayout for a AppWidget, we only allow // views that are allowed in RemoteViews. static final LayoutInflater.Filter sInflaterFilter = new LayoutInflater.Filter() { @@ -85,9 +80,6 @@ public class AppWidgetHostView extends FrameLayout { View mView; int mViewMode = VIEW_MODE_NOINIT; int mLayoutId = -1; - long mFadeStartTime = -1; - Bitmap mOld; - Paint mOldPaint = new Paint(); private OnClickHandler mOnClickHandler; private Executor mAsyncExecutor; @@ -212,9 +204,12 @@ public class AppWidgetHostView extends FrameLayout { @Override protected void dispatchSaveInstanceState(SparseArray<Parcelable> container) { - final ParcelableSparseArray jail = new ParcelableSparseArray(); + final SparseArray<Parcelable> jail = new SparseArray<>(); super.dispatchSaveInstanceState(jail); - container.put(generateId(), jail); + + Bundle bundle = new Bundle(); + bundle.putSparseParcelableArray(KEY_JAILED_ARRAY, jail); + container.put(generateId(), bundle); } private int generateId() { @@ -226,12 +221,12 @@ public class AppWidgetHostView extends FrameLayout { protected void dispatchRestoreInstanceState(SparseArray<Parcelable> container) { final Parcelable parcelable = container.get(generateId()); - ParcelableSparseArray jail = null; - if (parcelable != null && parcelable instanceof ParcelableSparseArray) { - jail = (ParcelableSparseArray) parcelable; + SparseArray<Parcelable> jail = null; + if (parcelable instanceof Bundle) { + jail = ((Bundle) parcelable).getSparseParcelableArray(KEY_JAILED_ARRAY); } - if (jail == null) jail = new ParcelableSparseArray(); + if (jail == null) jail = new SparseArray<>(); try { super.dispatchRestoreInstanceState(jail); @@ -383,31 +378,10 @@ public class AppWidgetHostView extends FrameLayout { * @hide */ protected void applyRemoteViews(RemoteViews remoteViews, boolean useAsyncIfPossible) { - if (LOGD) Log.d(TAG, "updateAppWidget called mOld=" + mOld); - boolean recycled = false; View content = null; Exception exception = null; - // Capture the old view into a bitmap so we can do the crossfade. - if (CROSSFADE) { - if (mFadeStartTime < 0) { - if (mView != null) { - final int width = mView.getWidth(); - final int height = mView.getHeight(); - try { - mOld = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888); - } catch (OutOfMemoryError e) { - // we just won't do the fade - mOld = null; - } - if (mOld != null) { - //mView.drawIntoBitmap(mOld); - } - } - } - } - if (mLastExecutionSignal != null) { mLastExecutionSignal.cancel(); mLastExecutionSignal = null; @@ -484,16 +458,6 @@ public class AppWidgetHostView extends FrameLayout { removeView(mView); mView = content; } - - if (CROSSFADE) { - if (mFadeStartTime < 0) { - // if there is already an animation in progress, don't do anything -- - // the new view will pop in on top of the old one during the cross fade, - // and that looks okay. - mFadeStartTime = SystemClock.uptimeMillis(); - invalidate(); - } - } } private void updateContentDescription(AppWidgetProviderInfo info) { @@ -617,45 +581,6 @@ public class AppWidgetHostView extends FrameLayout { } } - @Override - protected boolean drawChild(Canvas canvas, View child, long drawingTime) { - if (CROSSFADE) { - int alpha; - int l = child.getLeft(); - int t = child.getTop(); - if (mFadeStartTime > 0) { - alpha = (int)(((drawingTime-mFadeStartTime)*255)/FADE_DURATION); - if (alpha > 255) { - alpha = 255; - } - Log.d(TAG, "drawChild alpha=" + alpha + " l=" + l + " t=" + t - + " w=" + child.getWidth()); - if (alpha != 255 && mOld != null) { - mOldPaint.setAlpha(255-alpha); - //canvas.drawBitmap(mOld, l, t, mOldPaint); - } - } else { - alpha = 255; - } - int restoreTo = canvas.saveLayerAlpha(l, t, child.getWidth(), child.getHeight(), alpha, - Canvas.HAS_ALPHA_LAYER_SAVE_FLAG | Canvas.CLIP_TO_LAYER_SAVE_FLAG); - boolean rv = super.drawChild(canvas, child, drawingTime); - canvas.restoreToCount(restoreTo); - if (alpha < 255) { - invalidate(); - } else { - mFadeStartTime = -1; - if (mOld != null) { - mOld.recycle(); - mOld = null; - } - } - return rv; - } else { - return super.drawChild(canvas, child, drawingTime); - } - } - /** * Prepare the given view to be shown. This might include adjusting * {@link FrameLayout.LayoutParams} before inserting. @@ -740,36 +665,4 @@ public class AppWidgetHostView extends FrameLayout { super.onInitializeAccessibilityNodeInfoInternal(info); info.setClassName(AppWidgetHostView.class.getName()); } - - private static class ParcelableSparseArray extends SparseArray<Parcelable> implements Parcelable { - public int describeContents() { - return 0; - } - - public void writeToParcel(Parcel dest, int flags) { - final int count = size(); - dest.writeInt(count); - for (int i = 0; i < count; i++) { - dest.writeInt(keyAt(i)); - dest.writeParcelable(valueAt(i), 0); - } - } - - public static final Parcelable.Creator<ParcelableSparseArray> CREATOR = - new Parcelable.Creator<ParcelableSparseArray>() { - public ParcelableSparseArray createFromParcel(Parcel source) { - final ParcelableSparseArray array = new ParcelableSparseArray(); - final ClassLoader loader = array.getClass().getClassLoader(); - final int count = source.readInt(); - for (int i = 0; i < count; i++) { - array.put(source.readInt(), source.readParcelable(loader)); - } - return array; - } - - public ParcelableSparseArray[] newArray(int size) { - return new ParcelableSparseArray[size]; - } - }; - } } diff --git a/core/java/android/content/ComponentName.java b/core/java/android/content/ComponentName.java index ea6b7690b431..0d36bddc8665 100644 --- a/core/java/android/content/ComponentName.java +++ b/core/java/android/content/ComponentName.java @@ -21,9 +21,9 @@ import android.annotation.Nullable; import android.os.Parcel; import android.os.Parcelable; import android.text.TextUtils; +import android.util.proto.ProtoOutputStream; import java.io.PrintWriter; -import java.lang.Comparable; /** * Identifier for a specific application component @@ -33,7 +33,7 @@ import java.lang.Comparable; * pieces of information, encapsulated here, are required to identify * a component: the package (a String) it exists in, and the class (a String) * name inside of that package. - * + * */ public final class ComponentName implements Parcelable, Cloneable, Comparable<ComponentName> { private final String mPackage; @@ -91,7 +91,7 @@ public final class ComponentName implements Parcelable, Cloneable, Comparable<Co /** * Create a new component identifier. - * + * * @param pkg The name of the package that the component exists in. Can * not be null. * @param cls The name of the class inside of <var>pkg</var> that @@ -106,7 +106,7 @@ public final class ComponentName implements Parcelable, Cloneable, Comparable<Co /** * Create a new component identifier from a Context and class name. - * + * * @param pkg A Context for the package implementing the component, * from which the actual package name will be retrieved. * @param cls The name of the class inside of <var>pkg</var> that @@ -120,7 +120,7 @@ public final class ComponentName implements Parcelable, Cloneable, Comparable<Co /** * Create a new component identifier from a Context and Class object. - * + * * @param pkg A Context for the package implementing the component, from * which the actual package name will be retrieved. * @param cls The Class object of the desired component, from which the @@ -141,14 +141,14 @@ public final class ComponentName implements Parcelable, Cloneable, Comparable<Co public @NonNull String getPackageName() { return mPackage; } - + /** * Return the class name of this component. */ public @NonNull String getClassName() { return mClass; } - + /** * Return the class name, either fully qualified or in a shortened form * (with a leading '.') if it is a suffix of the package. @@ -163,7 +163,7 @@ public final class ComponentName implements Parcelable, Cloneable, Comparable<Co } return mClass; } - + private static void appendShortClassName(StringBuilder sb, String packageName, String className) { if (className.startsWith(packageName)) { @@ -195,26 +195,26 @@ public final class ComponentName implements Parcelable, Cloneable, Comparable<Co * class names contained in the ComponentName. You can later recover * the ComponentName from this string through * {@link #unflattenFromString(String)}. - * + * * @return Returns a new String holding the package and class names. This * is represented as the package name, concatenated with a '/' and then the * class name. - * + * * @see #unflattenFromString(String) */ public @NonNull String flattenToString() { return mPackage + "/" + mClass; } - + /** * The same as {@link #flattenToString()}, but abbreviates the class * name if it is a suffix of the package. The result can still be used * with {@link #unflattenFromString(String)}. - * + * * @return Returns a new String holding the package and class names. This * is represented as the package name, concatenated with a '/' and then the * class name. - * + * * @see #unflattenFromString(String) */ public @NonNull String flattenToShortString() { @@ -250,11 +250,11 @@ public final class ComponentName implements Parcelable, Cloneable, Comparable<Co * followed by a '.' then the final class name will be the concatenation * of the package name with the string following the '/'. Thus * "com.foo/.Blah" becomes package="com.foo" class="com.foo.Blah". - * + * * @param str The String that was returned by flattenToString(). * @return Returns a new ComponentName containing the package and class * names that were encoded in <var>str</var> - * + * * @see #flattenToString() */ public static @Nullable ComponentName unflattenFromString(@NonNull String str) { @@ -269,7 +269,7 @@ public final class ComponentName implements Parcelable, Cloneable, Comparable<Co } return new ComponentName(pkg, cls); } - + /** * Return string representation of this class without the class's name * as a prefix. @@ -283,6 +283,12 @@ public final class ComponentName implements Parcelable, Cloneable, Comparable<Co return "ComponentInfo{" + mPackage + "/" + mClass + "}"; } + /** Put this here so that individual services don't have to reimplement this. @hide */ + public void toProto(ProtoOutputStream proto) { + proto.write(ComponentNameProto.PACKAGE_NAME, mPackage); + proto.write(ComponentNameProto.CLASS_NAME, mClass); + } + @Override public boolean equals(Object obj) { try { @@ -311,7 +317,7 @@ public final class ComponentName implements Parcelable, Cloneable, Comparable<Co } return this.mClass.compareTo(that.mClass); } - + public int describeContents() { return 0; } @@ -324,10 +330,10 @@ public final class ComponentName implements Parcelable, Cloneable, Comparable<Co /** * Write a ComponentName to a Parcel, handling null pointers. Must be * read with {@link #readFromParcel(Parcel)}. - * + * * @param c The ComponentName to be written. * @param out The Parcel in which the ComponentName will be placed. - * + * * @see #readFromParcel(Parcel) */ public static void writeToParcel(ComponentName c, Parcel out) { @@ -337,23 +343,23 @@ public final class ComponentName implements Parcelable, Cloneable, Comparable<Co out.writeString(null); } } - + /** * Read a ComponentName from a Parcel that was previously written * with {@link #writeToParcel(ComponentName, Parcel)}, returning either * a null or new object as appropriate. - * + * * @param in The Parcel from which to read the ComponentName * @return Returns a new ComponentName matching the previously written * object, or null if a null had been written. - * + * * @see #writeToParcel(ComponentName, Parcel) */ public static ComponentName readFromParcel(Parcel in) { String pkg = in.readString(); return pkg != null ? new ComponentName(pkg, in) : null; } - + public static final Parcelable.Creator<ComponentName> CREATOR = new Parcelable.Creator<ComponentName>() { public ComponentName createFromParcel(Parcel in) { @@ -371,7 +377,7 @@ public final class ComponentName implements Parcelable, Cloneable, Comparable<Co * must not use this with data written by * {@link #writeToParcel(ComponentName, Parcel)} since it is not possible * to handle a null ComponentObject here. - * + * * @param in The Parcel containing the previously written ComponentName, * positioned at the location in the buffer where it was written. */ 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/Intent.java b/core/java/android/content/Intent.java index c238ffbbaf4d..c9ad9519824d 100644 --- a/core/java/android/content/Intent.java +++ b/core/java/android/content/Intent.java @@ -9444,7 +9444,7 @@ public class Intent implements Parcelable, Cloneable { for (int i=0; i<N; i++) { char c = data.charAt(i); if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') - || c == '.' || c == '-') { + || (c >= '0' && c <= '9') || c == '.' || c == '-' || c == '+') { continue; } if (c == ':' && i > 0) { diff --git a/core/java/android/content/pm/ActivityInfo.java b/core/java/android/content/pm/ActivityInfo.java index 486ff43a6467..41667c4c3ce3 100644 --- a/core/java/android/content/pm/ActivityInfo.java +++ b/core/java/android/content/pm/ActivityInfo.java @@ -17,6 +17,7 @@ package android.content.pm; import android.annotation.IntDef; +import android.annotation.TestApi; import android.content.Intent; import android.content.res.Configuration; import android.content.res.Configuration.NativeConfig; @@ -180,6 +181,7 @@ public class ActivityInfo extends ComponentInfo implements Parcelable { * Activity explicitly requested to be resizeable. * @hide */ + @TestApi public static final int RESIZE_MODE_RESIZEABLE = 2; /** * Activity is resizeable and supported picture-in-picture mode. This flag is now deprecated @@ -1215,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: @@ -1255,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/database/sqlite/SQLiteConnection.java b/core/java/android/database/sqlite/SQLiteConnection.java index f894f0536b52..c28583ea867a 100644 --- a/core/java/android/database/sqlite/SQLiteConnection.java +++ b/core/java/android/database/sqlite/SQLiteConnection.java @@ -104,7 +104,7 @@ public final class SQLiteConnection implements CancellationSignal.OnCancelListen private PreparedStatement mPreparedStatementPool; // The recent operations log. - private final OperationLog mRecentOperations = new OperationLog(); + private final OperationLog mRecentOperations; // The native SQLiteConnection pointer. (FOR INTERNAL USE ONLY) private long mConnectionPtr; @@ -162,6 +162,7 @@ public final class SQLiteConnection implements CancellationSignal.OnCancelListen SQLiteDatabaseConfiguration configuration, int connectionId, boolean primaryConnection) { mPool = pool; + mRecentOperations = new OperationLog(mPool); mConfiguration = new SQLiteDatabaseConfiguration(configuration); mConnectionId = connectionId; mIsPrimaryConnection = primaryConnection; @@ -1298,6 +1299,11 @@ public final class SQLiteConnection implements CancellationSignal.OnCancelListen private final Operation[] mOperations = new Operation[MAX_RECENT_OPERATIONS]; private int mIndex; private int mGeneration; + private final SQLiteConnectionPool mPool; + + OperationLog(SQLiteConnectionPool pool) { + mPool = pool; + } public int beginOperation(String kind, String sql, Object[] bindArgs) { synchronized (mOperations) { @@ -1381,8 +1387,10 @@ public final class SQLiteConnection implements CancellationSignal.OnCancelListen } operation.mEndTime = SystemClock.uptimeMillis(); operation.mFinished = true; + final long execTime = operation.mEndTime - operation.mStartTime; + mPool.onStatementExecuted(execTime); return SQLiteDebug.DEBUG_LOG_SLOW_QUERIES && SQLiteDebug.shouldLogSlowQuery( - operation.mEndTime - operation.mStartTime); + execTime); } return false; } @@ -1426,11 +1434,16 @@ public final class SQLiteConnection implements CancellationSignal.OnCancelListen int index = mIndex; Operation operation = mOperations[index]; if (operation != null) { + // Note: SimpleDateFormat is not thread-safe, cannot be compile-time created, + // and is relatively expensive to create during preloading. This method is only + // used when dumping a connection, which is a rare (mainly error) case. + SimpleDateFormat opDF = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS"); int n = 0; do { StringBuilder msg = new StringBuilder(); msg.append(" ").append(n).append(": ["); - msg.append(operation.getFormattedStartTime()); + String formattedStartTime = opDF.format(new Date(operation.mStartWallTime)); + msg.append(formattedStartTime); msg.append("] "); operation.describe(msg, verbose); printer.println(msg.toString()); @@ -1518,12 +1531,5 @@ public final class SQLiteConnection implements CancellationSignal.OnCancelListen return methodName; } - private String getFormattedStartTime() { - // Note: SimpleDateFormat is not thread-safe, cannot be compile-time created, and is - // relatively expensive to create during preloading. This method is only used - // when dumping a connection, which is a rare (mainly error) case. So: - // DO NOT CACHE. - return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS").format(new Date(mStartWallTime)); - } } } diff --git a/core/java/android/database/sqlite/SQLiteConnectionPool.java b/core/java/android/database/sqlite/SQLiteConnectionPool.java index b66bf18fca1d..8b0fef4fe2bc 100644 --- a/core/java/android/database/sqlite/SQLiteConnectionPool.java +++ b/core/java/android/database/sqlite/SQLiteConnectionPool.java @@ -37,6 +37,7 @@ import java.util.ArrayList; import java.util.Map; import java.util.WeakHashMap; import java.util.concurrent.atomic.AtomicBoolean; +import java.util.concurrent.atomic.AtomicLong; import java.util.concurrent.locks.LockSupport; /** @@ -102,6 +103,8 @@ public final class SQLiteConnectionPool implements Closeable { @GuardedBy("mLock") private IdleConnectionHandler mIdleConnectionHandler; + private final AtomicLong mTotalExecutionTimeCounter = new AtomicLong(0); + // Describes what should happen to an acquired connection when it is returned to the pool. enum AcquiredConnectionStatus { // The connection should be returned to the pool as usual. @@ -523,6 +526,10 @@ public final class SQLiteConnectionPool implements Closeable { mConnectionLeaked.set(true); } + void onStatementExecuted(long executionTimeMs) { + mTotalExecutionTimeCounter.addAndGet(executionTimeMs); + } + // Can't throw. private void closeAvailableConnectionsAndLogExceptionsLocked() { closeAvailableNonPrimaryConnectionsAndLogExceptionsLocked(); @@ -1076,6 +1083,7 @@ public final class SQLiteConnectionPool implements Closeable { printer.println("Connection pool for " + mConfiguration.path + ":"); printer.println(" Open: " + mIsOpen); printer.println(" Max connections: " + mMaxConnectionPoolSize); + printer.println(" Total execution time: " + mTotalExecutionTimeCounter); if (mConfiguration.isLookasideConfigSet()) { printer.println(" Lookaside config: sz=" + mConfiguration.lookasideSlotSize + " cnt=" + mConfiguration.lookasideSlotCount); diff --git a/core/java/android/hardware/Camera.java b/core/java/android/hardware/Camera.java index aa35a6610db7..931b5c913851 100644 --- a/core/java/android/hardware/Camera.java +++ b/core/java/android/hardware/Camera.java @@ -16,10 +16,11 @@ package android.hardware; -import android.app.ActivityThread; +import static android.system.OsConstants.*; + import android.annotation.SdkConstant; import android.annotation.SdkConstant.SdkConstantType; -import android.app.job.JobInfo; +import android.app.ActivityThread; import android.content.Context; import android.graphics.ImageFormat; import android.graphics.Point; @@ -34,11 +35,11 @@ import android.os.RemoteException; import android.os.ServiceManager; import android.renderscript.Allocation; import android.renderscript.Element; -import android.renderscript.RenderScript; import android.renderscript.RSIllegalArgumentException; +import android.renderscript.RenderScript; import android.renderscript.Type; -import android.util.Log; import android.text.TextUtils; +import android.util.Log; import android.view.Surface; import android.view.SurfaceHolder; @@ -48,8 +49,6 @@ import java.util.ArrayList; import java.util.LinkedHashMap; import java.util.List; -import static android.system.OsConstants.*; - /** * The Camera class is used to set image capture settings, start/stop preview, * snap pictures, and retrieve frames for encoding for video. This class is a @@ -243,12 +242,19 @@ public class Camera { /** * Returns the number of physical cameras available on this device. + * + * @return total number of accessible camera devices, or 0 if there are no + * cameras or an error was encountered enumerating them. */ public native static int getNumberOfCameras(); /** * Returns the information about a particular camera. * If {@link #getNumberOfCameras()} returns N, the valid id is 0 to N-1. + * + * @throws RuntimeException if an invalid ID is provided, or if there is an + * error retrieving the information (generally due to a hardware or other + * low-level failure). */ public static void getCameraInfo(int cameraId, CameraInfo cameraInfo) { _getCameraInfo(cameraId, cameraInfo); @@ -362,7 +368,10 @@ public class Camera { /** * Creates a new Camera object to access the first back-facing camera on the * device. If the device does not have a back-facing camera, this returns - * null. + * null. Otherwise acts like the {@link #open(int)} call. + * + * @return a new Camera object for the first back-facing camera, or null if there is no + * backfacing camera * @see #open(int) */ public static Camera open() { @@ -609,6 +618,8 @@ public class Camera { * * @throws IOException if a connection cannot be re-established (for * example, if the camera is still in use by another process). + * @throws RuntimeException if release() has been called on this Camera + * instance. */ public native final void reconnect() throws IOException; @@ -637,6 +648,8 @@ public class Camera { * or null to remove the preview surface * @throws IOException if the method fails (for example, if the surface * is unavailable or unsuitable). + * @throws RuntimeException if release() has been called on this Camera + * instance. */ public final void setPreviewDisplay(SurfaceHolder holder) throws IOException { if (holder != null) { @@ -684,6 +697,8 @@ public class Camera { * texture * @throws IOException if the method fails (for example, if the surface * texture is unavailable or unsuitable). + * @throws RuntimeException if release() has been called on this Camera + * instance. */ public native final void setPreviewTexture(SurfaceTexture surfaceTexture) throws IOException; @@ -733,12 +748,20 @@ public class Camera { * {@link #setPreviewCallbackWithBuffer(Camera.PreviewCallback)} were * called, {@link Camera.PreviewCallback#onPreviewFrame(byte[], Camera)} * will be called when preview data becomes available. + * + * @throws RuntimeException if starting preview fails; usually this would be + * because of a hardware or other low-level error, or because release() + * has been called on this Camera instance. */ public native final void startPreview(); /** * Stops capturing and drawing preview frames to the surface, and * resets the camera for a future call to {@link #startPreview()}. + * + * @throws RuntimeException if stopping preview fails; usually this would be + * because of a hardware or other low-level error, or because release() + * has been called on this Camera instance. */ public final void stopPreview() { _stopPreview(); @@ -777,6 +800,8 @@ public class Camera { * * @param cb a callback object that receives a copy of each preview frame, * or null to stop receiving callbacks. + * @throws RuntimeException if release() has been called on this Camera + * instance. * @see android.media.MediaActionSound */ public final void setPreviewCallback(PreviewCallback cb) { @@ -803,6 +828,8 @@ public class Camera { * * @param cb a callback object that receives a copy of the next preview frame, * or null to stop receiving callbacks. + * @throws RuntimeException if release() has been called on this Camera + * instance. * @see android.media.MediaActionSound */ public final void setOneShotPreviewCallback(PreviewCallback cb) { @@ -840,6 +867,8 @@ public class Camera { * * @param cb a callback object that receives a copy of the preview frame, * or null to stop receiving callbacks and clear the buffer queue. + * @throws RuntimeException if release() has been called on this Camera + * instance. * @see #addCallbackBuffer(byte[]) * @see android.media.MediaActionSound */ @@ -1259,6 +1288,9 @@ public class Camera { * success sound to the user.</p> * * @param cb the callback to run + * @throws RuntimeException if starting autofocus fails; usually this would + * be because of a hardware or other low-level error, or because + * release() has been called on this Camera instance. * @see #cancelAutoFocus() * @see android.hardware.Camera.Parameters#setAutoExposureLock(boolean) * @see android.hardware.Camera.Parameters#setAutoWhiteBalanceLock(boolean) @@ -1279,6 +1311,9 @@ public class Camera { * this function will return the focus position to the default. * If the camera does not support auto-focus, this is a no-op. * + * @throws RuntimeException if canceling autofocus fails; usually this would + * be because of a hardware or other low-level error, or because + * release() has been called on this Camera instance. * @see #autoFocus(Camera.AutoFocusCallback) */ public final void cancelAutoFocus() @@ -1333,6 +1368,9 @@ public class Camera { * Sets camera auto-focus move callback. * * @param cb the callback to run + * @throws RuntimeException if enabling the focus move callback fails; + * usually this would be because of a hardware or other low-level error, + * or because release() has been called on this Camera instance. */ public void setAutoFocusMoveCallback(AutoFocusMoveCallback cb) { mAutoFocusMoveCallback = cb; @@ -1384,7 +1422,7 @@ public class Camera { }; /** - * Equivalent to takePicture(shutter, raw, null, jpeg). + * Equivalent to <pre>takePicture(Shutter, raw, null, jpeg)</pre>. * * @see #takePicture(ShutterCallback, PictureCallback, PictureCallback, PictureCallback) */ @@ -1422,6 +1460,9 @@ public class Camera { * @param raw the callback for raw (uncompressed) image data, or null * @param postview callback with postview image data, may be null * @param jpeg the callback for JPEG image data, or null + * @throws RuntimeException if starting picture capture fails; usually this + * would be because of a hardware or other low-level error, or because + * release() has been called on this Camera instance. */ public final void takePicture(ShutterCallback shutter, PictureCallback raw, PictureCallback postview, PictureCallback jpeg) { @@ -1534,6 +1575,9 @@ public class Camera { * * @param degrees the angle that the picture will be rotated clockwise. * Valid values are 0, 90, 180, and 270. + * @throws RuntimeException if setting orientation fails; usually this would + * be because of a hardware or other low-level error, or because + * release() has been called on this Camera instance. * @see #setPreviewDisplay(SurfaceHolder) */ public native final void setDisplayOrientation(int degrees); @@ -1559,6 +1603,9 @@ public class Camera { * changed. {@code false} if the shutter sound state could not be * changed. {@code true} is also returned if shutter sound playback * is already set to the requested state. + * @throws RuntimeException if the call fails; usually this would be because + * of a hardware or other low-level error, or because release() has been + * called on this Camera instance. * @see #takePicture * @see CameraInfo#canDisableShutterSound * @see ShutterCallback @@ -1903,6 +1950,9 @@ public class Camera { * If modifications are made to the returned Parameters, they must be passed * to {@link #setParameters(Camera.Parameters)} to take effect. * + * @throws RuntimeException if reading parameters fails; usually this would + * be because of a hardware or other low-level error, or because + * release() has been called on this Camera instance. * @see #setParameters(Camera.Parameters) */ public Parameters getParameters() { 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/net/LocalServerSocket.java b/core/java/android/net/LocalServerSocket.java index 3fcde33071e9..d1f49d2082f5 100644 --- a/core/java/android/net/LocalServerSocket.java +++ b/core/java/android/net/LocalServerSocket.java @@ -16,14 +16,15 @@ package android.net; -import java.io.IOException; +import java.io.Closeable; import java.io.FileDescriptor; +import java.io.IOException; /** * Non-standard class for creating an inbound UNIX-domain socket * in the Linux abstract namespace. */ -public class LocalServerSocket { +public class LocalServerSocket implements Closeable { private final LocalSocketImpl impl; private final LocalSocketAddress localAddress; @@ -106,7 +107,7 @@ public class LocalServerSocket { * * @throws IOException */ - public void close() throws IOException + @Override public void close() throws IOException { impl.close(); } 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/IStatsCompanionService.aidl b/core/java/android/os/IStatsCompanionService.aidl index a29e375bcfbd..a83d31390775 100644 --- a/core/java/android/os/IStatsCompanionService.aidl +++ b/core/java/android/os/IStatsCompanionService.aidl @@ -20,7 +20,12 @@ package android.os; * Binder interface to communicate with the Java-based statistics service helper. * {@hide} */ -interface IStatsCompanionService { +oneway interface IStatsCompanionService { + /** + * Tell statscompanion that stastd is up and running. + */ + void statsdReady(); + /** * Register an alarm for anomaly detection to fire at the given timestamp (ms since epoch). * If anomaly alarm had already been registered, it will be replaced with the new timestamp. @@ -28,6 +33,7 @@ interface IStatsCompanionService { * alarm is inexact. */ void setAnomalyAlarm(long timestampMs); + /** Cancel any anomaly detection alarm. */ void cancelAnomalyAlarm(); @@ -39,6 +45,7 @@ interface IStatsCompanionService { * and alarm is inexact. */ void setPollingAlarms(long timestampMs, long intervalMs); + /** Cancel any repeating polling alarm. */ void cancelPollingAlarms(); } diff --git a/core/java/android/os/IStatsManager.aidl b/core/java/android/os/IStatsManager.aidl index 9b5139dc5092..f8f28134063d 100644 --- a/core/java/android/os/IStatsManager.aidl +++ b/core/java/android/os/IStatsManager.aidl @@ -17,12 +17,32 @@ package android.os; /** - * Binder interface to communicate with the statistics collection service. + * Binder interface to communicate with the statistics management service. * {@hide} */ -oneway interface IStatsManager { +interface IStatsManager { /** - * Tell the incident daemon that the android system server is up and running. + * Tell the stats daemon that the android system server is up and running. */ - void systemRunning(); + oneway void systemRunning(); + + /** + * Tell the stats daemon that the StatsCompanionService is up and running. + * Two-way binder call so that caller knows message received. + */ + void statsCompanionReady(); + + /** + * Tells statsd that an anomaly may have occurred, so statsd can check whether this is so and + * act accordingly. + * Two-way binder call so that caller's method (and corresponding wakelocks) will linger. + */ + void informAnomalyAlarmFired(); + + /** + * Tells statsd that it is time to poll some stats. Statsd will be responsible for determing + * what stats to poll and initiating the polling. + * Two-way binder call so that caller's method (and corresponding wakelocks) will linger. + */ + void informPollAlarmFired(); } diff --git a/core/java/android/os/Parcel.java b/core/java/android/os/Parcel.java index 031ca91c3eaa..857e8a60098d 100644 --- a/core/java/android/os/Parcel.java +++ b/core/java/android/os/Parcel.java @@ -1340,6 +1340,13 @@ public final class Parcel { * @see Parcelable */ public final <T extends Parcelable> void writeTypedList(List<T> val) { + writeTypedList(val, 0); + } + + /** + * @hide + */ + public <T extends Parcelable> void writeTypedList(List<T> val, int parcelableFlags) { if (val == null) { writeInt(-1); return; @@ -1348,13 +1355,7 @@ public final class Parcel { int i=0; writeInt(N); while (i < N) { - T item = val.get(i); - if (item != null) { - writeInt(1); - item.writeToParcel(this, 0); - } else { - writeInt(0); - } + writeTypedObject(val.get(i), parcelableFlags); i++; } } @@ -1456,116 +1457,7 @@ public final class Parcel { int N = val.length; writeInt(N); for (int i = 0; i < N; i++) { - T item = val[i]; - if (item != null) { - writeInt(1); - item.writeToParcel(this, parcelableFlags); - } else { - writeInt(0); - } - } - } else { - writeInt(-1); - } - } - - /** - * Write a uniform (all items are null or the same class) array list of - * parcelables. - * - * @param list The list to write. - * - * @hide - */ - public final <T extends Parcelable> void writeTypedArrayList(@Nullable ArrayList<T> list, - int parcelableFlags) { - if (list != null) { - int N = list.size(); - writeInt(N); - boolean wroteCreator = false; - for (int i = 0; i < N; i++) { - T item = list.get(i); - if (item != null) { - writeInt(1); - if (!wroteCreator) { - writeParcelableCreator(item); - wroteCreator = true; - } - item.writeToParcel(this, parcelableFlags); - } else { - writeInt(0); - } - } - } else { - writeInt(-1); - } - } - - /** - * Reads a uniform (all items are null or the same class) array list of - * parcelables. - * - * @return The list or null. - * - * @hide - */ - public final @Nullable <T> ArrayList<T> readTypedArrayList(@Nullable ClassLoader loader) { - int N = readInt(); - if (N <= 0) { - return null; - } - Parcelable.Creator<?> creator = null; - ArrayList<T> result = new ArrayList<T>(N); - for (int i = 0; i < N; i++) { - if (readInt() != 0) { - if (creator == null) { - creator = readParcelableCreator(loader); - if (creator == null) { - return null; - } - } - final T parcelable; - if (creator instanceof Parcelable.ClassLoaderCreator<?>) { - Parcelable.ClassLoaderCreator<?> classLoaderCreator = - (Parcelable.ClassLoaderCreator<?>) creator; - parcelable = (T) classLoaderCreator.createFromParcel(this, loader); - } else { - parcelable = (T) creator.createFromParcel(this); - } - result.add(parcelable); - } else { - result.add(null); - } - } - return result; - } - - /** - * Write a uniform (all items are null or the same class) array set of - * parcelables. - * - * @param set The set to write. - * - * @hide - */ - public final <T extends Parcelable> void writeTypedArraySet(@Nullable ArraySet<T> set, - int parcelableFlags) { - if (set != null) { - int N = set.size(); - writeInt(N); - boolean wroteCreator = false; - for (int i = 0; i < N; i++) { - T item = set.valueAt(i); - if (item != null) { - writeInt(1); - if (!wroteCreator) { - writeParcelableCreator(item); - wroteCreator = true; - } - item.writeToParcel(this, parcelableFlags); - } else { - writeInt(0); - } + writeTypedObject(val[i], parcelableFlags); } } else { writeInt(-1); @@ -1573,43 +1465,6 @@ public final class Parcel { } /** - * Reads a uniform (all items are null or the same class) array set of - * parcelables. - * - * @return The set or null. - * - * @hide - */ - public final @Nullable <T> ArraySet<T> readTypedArraySet(@Nullable ClassLoader loader) { - int N = readInt(); - if (N <= 0) { - return null; - } - Parcelable.Creator<?> creator = null; - ArraySet<T> result = new ArraySet<T>(N); - for (int i = 0; i < N; i++) { - T parcelable = null; - if (readInt() != 0) { - if (creator == null) { - creator = readParcelableCreator(loader); - if (creator == null) { - return null; - } - } - if (creator instanceof Parcelable.ClassLoaderCreator<?>) { - Parcelable.ClassLoaderCreator<?> classLoaderCreator = - (Parcelable.ClassLoaderCreator<?>) creator; - parcelable = (T) classLoaderCreator.createFromParcel(this, loader); - } else { - parcelable = (T) creator.createFromParcel(this); - } - } - result.append(parcelable); - } - return result; - } - - /** * Flatten the Parcelable object into the parcel. * * @param val The Parcelable object to be written. @@ -2458,11 +2313,7 @@ public final class Parcel { } ArrayList<T> l = new ArrayList<T>(N); while (N > 0) { - if (readInt() != 0) { - l.add(c.createFromParcel(this)); - } else { - l.add(null); - } + l.add(readTypedObject(c)); N--; } return l; @@ -2485,18 +2336,10 @@ public final class Parcel { int N = readInt(); int i = 0; for (; i < M && i < N; i++) { - if (readInt() != 0) { - list.set(i, c.createFromParcel(this)); - } else { - list.set(i, null); - } + list.set(i, readTypedObject(c)); } for (; i<N; i++) { - if (readInt() != 0) { - list.add(c.createFromParcel(this)); - } else { - list.add(null); - } + list.add(readTypedObject(c)); } for (; i<M; i++) { list.remove(N); @@ -2641,9 +2484,7 @@ public final class Parcel { } T[] l = c.newArray(N); for (int i=0; i<N; i++) { - if (readInt() != 0) { - l[i] = c.createFromParcel(this); - } + l[i] = readTypedObject(c); } return l; } @@ -2652,11 +2493,7 @@ public final class Parcel { int N = readInt(); if (N == val.length) { for (int i=0; i<N; i++) { - if (readInt() != 0) { - val[i] = c.createFromParcel(this); - } else { - val[i] = null; - } + val[i] = readTypedObject(c); } } else { throw new RuntimeException("bad array lengths"); diff --git a/core/java/android/os/ParcelableException.java b/core/java/android/os/ParcelableException.java index d84d62997d93..7f71905d7f28 100644 --- a/core/java/android/os/ParcelableException.java +++ b/core/java/android/os/ParcelableException.java @@ -52,10 +52,12 @@ public final class ParcelableException extends RuntimeException implements Parce final String msg = in.readString(); try { final Class<?> clazz = Class.forName(name, true, Parcelable.class.getClassLoader()); - return (Throwable) clazz.getConstructor(String.class).newInstance(msg); + if (Throwable.class.isAssignableFrom(clazz)) { + return (Throwable) clazz.getConstructor(String.class).newInstance(msg); + } } catch (ReflectiveOperationException e) { - throw new RuntimeException(name + ": " + msg); } + return new RuntimeException(name + ": " + msg); } /** {@hide} */ 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/os/StrictMode.java b/core/java/android/os/StrictMode.java index 2528439a5e1f..826ec1eb129e 100644 --- a/core/java/android/os/StrictMode.java +++ b/core/java/android/os/StrictMode.java @@ -154,12 +154,15 @@ public final class StrictMode { // Byte 1: Thread-policy /** @hide */ + @TestApi public static final int DETECT_DISK_WRITE = 0x01; // for ThreadPolicy /** @hide */ + @TestApi public static final int DETECT_DISK_READ = 0x02; // for ThreadPolicy /** @hide */ + @TestApi public static final int DETECT_NETWORK = 0x04; // for ThreadPolicy /** @@ -167,6 +170,7 @@ public final class StrictMode { * * @hide */ + @TestApi public static final int DETECT_CUSTOM = 0x08; // for ThreadPolicy /** @@ -174,9 +178,11 @@ public final class StrictMode { * * @hide */ + @TestApi public static final int DETECT_RESOURCE_MISMATCH = 0x10; // for ThreadPolicy /** @hide */ + @TestApi public static final int DETECT_UNBUFFERED_IO = 0x20; // for ThreadPolicy private static final int ALL_THREAD_DETECT_BITS = @@ -194,6 +200,7 @@ public final class StrictMode { * * @hide */ + @TestApi public static final int DETECT_VM_CURSOR_LEAKS = 0x01 << 8; // for VmPolicy /** @@ -201,6 +208,7 @@ public final class StrictMode { * * @hide */ + @TestApi public static final int DETECT_VM_CLOSABLE_LEAKS = 0x02 << 8; // for VmPolicy /** @@ -208,25 +216,32 @@ public final class StrictMode { * * @hide */ + @TestApi public static final int DETECT_VM_ACTIVITY_LEAKS = 0x04 << 8; // for VmPolicy /** @hide */ - private static final int DETECT_VM_INSTANCE_LEAKS = 0x08 << 8; // for VmPolicy + @TestApi + public static final int DETECT_VM_INSTANCE_LEAKS = 0x08 << 8; // for VmPolicy /** @hide */ + @TestApi public static final int DETECT_VM_REGISTRATION_LEAKS = 0x10 << 8; // for VmPolicy /** @hide */ - private static final int DETECT_VM_FILE_URI_EXPOSURE = 0x20 << 8; // for VmPolicy + @TestApi + public static final int DETECT_VM_FILE_URI_EXPOSURE = 0x20 << 8; // for VmPolicy /** @hide */ - private static final int DETECT_VM_CLEARTEXT_NETWORK = 0x40 << 8; // for VmPolicy + @TestApi + public static final int DETECT_VM_CLEARTEXT_NETWORK = 0x40 << 8; // for VmPolicy /** @hide */ - private static final int DETECT_VM_CONTENT_URI_WITHOUT_PERMISSION = 0x80 << 8; // for VmPolicy + @TestApi + public static final int DETECT_VM_CONTENT_URI_WITHOUT_PERMISSION = 0x80 << 8; // for VmPolicy /** @hide */ - private static final int DETECT_VM_UNTAGGED_SOCKET = 0x80 << 24; // for VmPolicy + @TestApi + public static final int DETECT_VM_UNTAGGED_SOCKET = 0x80 << 24; // for VmPolicy private static final int ALL_VM_DETECT_BITS = DETECT_VM_CURSOR_LEAKS @@ -1858,6 +1873,10 @@ public final class StrictMode { } /** @hide */ + public static final String CLEARTEXT_DETECTED_MSG = + "Detected cleartext network traffic from UID "; + + /** @hide */ public static void onCleartextNetworkDetected(byte[] firstPacket) { byte[] rawAddr = null; if (firstPacket != null) { @@ -1873,14 +1892,10 @@ public final class StrictMode { } final int uid = android.os.Process.myUid(); - String msg = "Detected cleartext network traffic from UID " + uid; + String msg = CLEARTEXT_DETECTED_MSG + uid; if (rawAddr != null) { try { - msg = - "Detected cleartext network traffic from UID " - + uid - + " to " - + InetAddress.getByAddress(rawAddr); + msg += " to " + InetAddress.getByAddress(rawAddr); } catch (UnknownHostException ignored) { } } @@ -1891,12 +1906,13 @@ public final class StrictMode { } /** @hide */ + public static final String UNTAGGED_SOCKET_VIOLATION_MESSAGE = + "Untagged socket detected; use" + + " TrafficStats.setThreadSocketTag() to track all network usage"; + + /** @hide */ public static void onUntaggedSocket() { - onVmPolicyViolation( - null, - new Throwable( - "Untagged socket detected; use" - + " TrafficStats.setThreadSocketTag() to track all network usage")); + onVmPolicyViolation(null, new Throwable(UNTAGGED_SOCKET_VIOLATION_MESSAGE)); } // Map from VM violation fingerprint to uptime millis. diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java index a5c55ba74a70..3c3e466bebb6 100755 --- a/core/java/android/provider/Settings.java +++ b/core/java/android/provider/Settings.java @@ -10200,7 +10200,7 @@ public final class Settings { "allow_user_switching_when_system_user_locked"; /** - * Boot count since the device starts running APK level 24. + * Boot count since the device starts running API level 24. * <p> * Type: int */ 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/service/autofill/AutofillServiceInfo.java b/core/java/android/service/autofill/AutofillServiceInfo.java index f14740066c95..5c7388f79a49 100644 --- a/core/java/android/service/autofill/AutofillServiceInfo.java +++ b/core/java/android/service/autofill/AutofillServiceInfo.java @@ -146,4 +146,9 @@ public final class AutofillServiceInfo { public String getSettingsActivity() { return mSettingsActivity; } + + @Override + public String toString() { + return mServiceInfo == null ? "null" : mServiceInfo.toString(); + } } diff --git a/core/java/android/service/autofill/Dataset.java b/core/java/android/service/autofill/Dataset.java index cb341b1d7828..2a9a39f7a297 100644 --- a/core/java/android/service/autofill/Dataset.java +++ b/core/java/android/service/autofill/Dataset.java @@ -323,8 +323,8 @@ public final class Dataset implements Parcelable { @Override public void writeToParcel(Parcel parcel, int flags) { parcel.writeParcelable(mPresentation, flags); - parcel.writeTypedArrayList(mFieldIds, flags); - parcel.writeTypedArrayList(mFieldValues, flags); + parcel.writeTypedList(mFieldIds, flags); + parcel.writeTypedList(mFieldValues, flags); parcel.writeParcelableList(mFieldPresentations, flags); parcel.writeParcelable(mAuthentication, flags); parcel.writeString(mId); @@ -340,8 +340,9 @@ public final class Dataset implements Parcelable { final Builder builder = (presentation == null) ? new Builder() : new Builder(presentation); - final ArrayList<AutofillId> ids = parcel.readTypedArrayList(null); - final ArrayList<AutofillValue> values = parcel.readTypedArrayList(null); + final ArrayList<AutofillId> ids = parcel.createTypedArrayList(AutofillId.CREATOR); + final ArrayList<AutofillValue> values = + parcel.createTypedArrayList(AutofillValue.CREATOR); final ArrayList<RemoteViews> presentations = new ArrayList<>(); parcel.readParcelableList(presentations, null); final int idCount = (ids != null) ? ids.size() : 0; diff --git a/core/java/android/service/autofill/SaveRequest.java b/core/java/android/service/autofill/SaveRequest.java index 1a6c5b0bcc08..65fdb5c45938 100644 --- a/core/java/android/service/autofill/SaveRequest.java +++ b/core/java/android/service/autofill/SaveRequest.java @@ -48,7 +48,8 @@ public final class SaveRequest implements Parcelable { } private SaveRequest(@NonNull Parcel parcel) { - this(parcel.readTypedArrayList(null), parcel.readBundle(), parcel.createStringArrayList()); + this(parcel.createTypedArrayList(FillContext.CREATOR), + parcel.readBundle(), parcel.createStringArrayList()); } /** @@ -84,7 +85,7 @@ public final class SaveRequest implements Parcelable { @Override public void writeToParcel(Parcel parcel, int flags) { - parcel.writeTypedArrayList(mFillContexts, flags); + parcel.writeTypedList(mFillContexts, flags); parcel.writeBundle(mClientState); parcel.writeStringList(mDatasetIds); } diff --git a/core/java/android/service/carrier/CarrierService.java b/core/java/android/service/carrier/CarrierService.java index 813acc232289..2707f1467bcf 100644 --- a/core/java/android/service/carrier/CarrierService.java +++ b/core/java/android/service/carrier/CarrierService.java @@ -17,10 +17,13 @@ package android.service.carrier; import android.annotation.CallSuper; import android.app.Service; import android.content.Intent; +import android.os.Bundle; import android.os.IBinder; import android.os.PersistableBundle; import android.os.RemoteException; +import android.os.ResultReceiver; import android.os.ServiceManager; +import android.util.Log; import com.android.internal.telephony.ITelephonyRegistry; @@ -48,6 +51,8 @@ import com.android.internal.telephony.ITelephonyRegistry; */ public abstract class CarrierService extends Service { + private static final String LOG_TAG = "CarrierService"; + public static final String CARRIER_SERVICE_INTERFACE = "android.service.carrier.CarrierService"; private static ITelephonyRegistry sRegistry; @@ -133,11 +138,26 @@ public abstract class CarrierService extends Service { /** * A wrapper around ICarrierService that forwards calls to implementations of * {@link CarrierService}. + * @hide */ - private class ICarrierServiceWrapper extends ICarrierService.Stub { + public class ICarrierServiceWrapper extends ICarrierService.Stub { + /** @hide */ + public static final int RESULT_OK = 0; + /** @hide */ + public static final int RESULT_ERROR = 1; + /** @hide */ + public static final String KEY_CONFIG_BUNDLE = "config_bundle"; + @Override - public PersistableBundle getCarrierConfig(CarrierIdentifier id) { - return CarrierService.this.onLoadConfig(id); + public void getCarrierConfig(CarrierIdentifier id, ResultReceiver result) { + try { + Bundle data = new Bundle(); + data.putParcelable(KEY_CONFIG_BUNDLE, CarrierService.this.onLoadConfig(id)); + result.send(RESULT_OK, data); + } catch (Exception e) { + Log.e(LOG_TAG, "Error in onLoadConfig: " + e.getMessage(), e); + result.send(RESULT_ERROR, null); + } } } } diff --git a/core/java/android/service/carrier/ICarrierService.aidl b/core/java/android/service/carrier/ICarrierService.aidl index 4c875851cfc8..ac6f9614d8f5 100644 --- a/core/java/android/service/carrier/ICarrierService.aidl +++ b/core/java/android/service/carrier/ICarrierService.aidl @@ -17,6 +17,7 @@ package android.service.carrier; import android.os.PersistableBundle; +import android.os.ResultReceiver; import android.service.carrier.CarrierIdentifier; /** @@ -28,5 +29,5 @@ import android.service.carrier.CarrierIdentifier; interface ICarrierService { /** @see android.service.carrier.CarrierService#onLoadConfig */ - PersistableBundle getCarrierConfig(in CarrierIdentifier id); + oneway void getCarrierConfig(in CarrierIdentifier id, in ResultReceiver result); } diff --git a/core/java/android/text/DynamicLayout.java b/core/java/android/text/DynamicLayout.java index 5e40935cf6d2..24260c4f32c3 100644 --- a/core/java/android/text/DynamicLayout.java +++ b/core/java/android/text/DynamicLayout.java @@ -384,7 +384,7 @@ public class DynamicLayout extends Layout private DynamicLayout(@NonNull Builder b) { super(createEllipsizer(b.mEllipsize, b.mDisplay), - b.mPaint, b.mWidth, b.mAlignment, b.mSpacingMult, b.mSpacingAdd); + b.mPaint, b.mWidth, b.mAlignment, b.mTextDir, b.mSpacingMult, b.mSpacingAdd); mDisplay = b.mDisplay; mIncludePad = b.mIncludePad; diff --git a/core/java/android/text/StaticLayout.java b/core/java/android/text/StaticLayout.java index c124c7fd6a0c..3303b54e462b 100644 --- a/core/java/android/text/StaticLayout.java +++ b/core/java/android/text/StaticLayout.java @@ -616,7 +616,7 @@ public class StaticLayout extends Layout { : (b.mText instanceof Spanned) ? new SpannedEllipsizer(b.mText) : new Ellipsizer(b.mText), - b.mPaint, b.mWidth, b.mAlignment, b.mSpacingMult, b.mSpacingAdd); + b.mPaint, b.mWidth, b.mAlignment, b.mTextDir, b.mSpacingMult, b.mSpacingAdd); if (b.mEllipsize != null) { Ellipsizer e = (Ellipsizer) getText(); 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/SurfaceControl.java b/core/java/android/view/SurfaceControl.java index 91932dd40dd8..31daefff2ec4 100644 --- a/core/java/android/view/SurfaceControl.java +++ b/core/java/android/view/SurfaceControl.java @@ -18,6 +18,7 @@ package android.view; import static android.view.WindowManager.LayoutParams.INVALID_WINDOW_TYPE; +import android.annotation.Size; import android.graphics.Bitmap; import android.graphics.GraphicBuffer; import android.graphics.Rect; @@ -65,6 +66,7 @@ public class SurfaceControl { private static native void nativeSetSize(long nativeObject, int w, int h); private static native void nativeSetTransparentRegionHint(long nativeObject, Region region); private static native void nativeSetAlpha(long nativeObject, float alpha); + private static native void nativeSetColor(long nativeObject, float[] color); private static native void nativeSetMatrix(long nativeObject, float dsdx, float dtdx, float dtdy, float dsdy); private static native void nativeSetFlags(long nativeObject, int flags, int mask); @@ -105,8 +107,8 @@ public class SurfaceControl { long surfaceObject, long frame); private static native void nativeReparentChildren(long nativeObject, IBinder handle); - private static native void nativeReparentChild(long nativeObject, - IBinder parentHandle, IBinder childHandle); + private static native void nativeReparent(long nativeObject, + IBinder parentHandle); private static native void nativeSeverChildren(long nativeObject); private static native void nativeSetOverrideScalingMode(long nativeObject, int scalingMode); @@ -455,9 +457,9 @@ public class SurfaceControl { nativeReparentChildren(mNativeObject, newParentHandle); } - /** Re-parents a specific child layer to a new parent */ - public void reparentChild(IBinder newParentHandle, IBinder childHandle) { - nativeReparentChild(mNativeObject, newParentHandle, childHandle); + /** Re-parents this layer to a new parent. */ + public void reparent(IBinder newParentHandle) { + nativeReparent(mNativeObject, newParentHandle); } public void detachChildren() { @@ -552,6 +554,15 @@ public class SurfaceControl { nativeSetAlpha(mNativeObject, alpha); } + /** + * Sets a color for the Surface. + * @param color A float array with three values to represent r, g, b in range [0..1] + */ + public void setColor(@Size(3) float[] color) { + checkNotReleased(); + nativeSetColor(mNativeObject, color); + } + public void setMatrix(float dsdx, float dtdx, float dtdy, float dsdy) { checkNotReleased(); nativeSetMatrix(mNativeObject, dsdx, dtdx, dtdy, dsdy); diff --git a/core/java/android/view/SurfaceView.java b/core/java/android/view/SurfaceView.java index cac27afa72cb..462dad3fad7a 100644 --- a/core/java/android/view/SurfaceView.java +++ b/core/java/android/view/SurfaceView.java @@ -231,6 +231,7 @@ public class SurfaceView extends View implements ViewRootImpl.WindowStoppedCallb updateRequestedVisibility(); mAttachedToWindow = true; + mParent.requestTransparentRegion(SurfaceView.this); if (!mGlobalListenersAdded) { ViewTreeObserver observer = getViewTreeObserver(); observer.addOnScrollChangedListener(mScrollChangedListener); @@ -269,8 +270,6 @@ public class SurfaceView extends View implements ViewRootImpl.WindowStoppedCallb if (mPendingReportDraws > 0) { mDrawFinished = true; if (mAttachedToWindow) { - mParent.requestTransparentRegion(SurfaceView.this); - notifyDrawFinished(); invalidate(); } 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/AutofillManager.java b/core/java/android/view/autofill/AutofillManager.java index f888ba298339..e906a1fa7807 100644 --- a/core/java/android/view/autofill/AutofillManager.java +++ b/core/java/android/view/autofill/AutofillManager.java @@ -1342,11 +1342,17 @@ public final class AutofillManager { } } - private void setSessionFinished() { - if (sVerbose) Log.v(TAG, "setSessionFinished()"); + /** + * Marks the state of the session as finished. + * + * @param newState {@link #STATE_FINISHED} (because the autofill service returned a {@code null} + * FillResponse) or {@link #STATE_UNKNOWN} (because the session was removed). + */ + private void setSessionFinished(int newState) { synchronized (mLock) { + if (sVerbose) Log.v(TAG, "setSessionFinished(): from " + mState + " to " + newState); resetSessionLocked(); - mState = STATE_FINISHED; + mState = newState; } } @@ -1413,7 +1419,7 @@ public final class AutofillManager { if (sessionFinished) { // Callback call was "hijacked" to also update the session state. - setSessionFinished(); + setSessionFinished(STATE_FINISHED); } } @@ -1898,10 +1904,10 @@ public final class AutofillManager { } @Override - public void setSessionFinished() { + public void setSessionFinished(int newState) { final AutofillManager afm = mAfm.get(); if (afm != null) { - afm.post(() -> afm.setSessionFinished()); + afm.post(() -> afm.setSessionFinished(newState)); } } } 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/autofill/IAutoFillManagerClient.aidl b/core/java/android/view/autofill/IAutoFillManagerClient.aidl index db6855a4dbf4..3dabcec8636a 100644 --- a/core/java/android/view/autofill/IAutoFillManagerClient.aidl +++ b/core/java/android/view/autofill/IAutoFillManagerClient.aidl @@ -82,8 +82,9 @@ oneway interface IAutoFillManagerClient { void setSaveUiState(int sessionId, boolean shown); /** - * Marks the state of the session as finished (because the AutofillService returned a null - * FillResponse). + * Marks the state of the session as finished. + * @param newState STATE_FINISHED (because the autofill service returned a null + * FillResponse) or STATE_UNKNOWN (because the session was removed). */ - void setSessionFinished(); + void setSessionFinished(int newState); } 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 7903d6fdc614..a5d964951af1 100644 --- a/core/java/android/widget/RemoteViews.java +++ b/core/java/android/widget/RemoteViews.java @@ -2339,20 +2339,12 @@ public class RemoteViews implements Parcelable, Filter { } if (src.mActions != null) { - mActions = new ArrayList<>(); - Parcel p = Parcel.obtain(); - int count = src.mActions.size(); - for (int i = 0; i < count; i++) { - p.setDataPosition(0); - Action a = src.mActions.get(i); - a.writeToParcel( - p, a.hasSameAppInfo(mApplication) ? PARCELABLE_ELIDE_DUPLICATES : 0); - p.setDataPosition(0); - // Since src is already in memory, we do not care about stack overflow as it has - // already been read once. - mActions.add(getActionFromParcel(p, 0)); - } + 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. + readActionsFromParcel(p, 0); p.recycle(); } @@ -2393,13 +2385,7 @@ public class RemoteViews implements Parcelable, Filter { mLayoutId = parcel.readInt(); mIsWidgetCollectionChild = parcel.readInt() == 1; - int count = parcel.readInt(); - if (count > 0) { - mActions = new ArrayList<>(count); - for (int i = 0; i < count; i++) { - mActions.add(getActionFromParcel(parcel, depth)); - } - } + readActionsFromParcel(parcel, depth); } else { // MODE_HAS_LANDSCAPE_AND_PORTRAIT mLandscape = new RemoteViews(parcel, mBitmapCache, info, depth); @@ -2410,6 +2396,16 @@ public class RemoteViews implements Parcelable, Filter { mReapplyDisallowed = parcel.readInt() == 0; } + private void readActionsFromParcel(Parcel parcel, int depth) { + int count = parcel.readInt(); + if (count > 0) { + mActions = new ArrayList<>(count); + for (int i = 0; i < count; i++) { + mActions.add(getActionFromParcel(parcel, depth)); + } + } + } + private Action getActionFromParcel(Parcel parcel, int depth) { int tag = parcel.readInt(); switch (tag) { @@ -3696,18 +3692,7 @@ public class RemoteViews implements Parcelable, Filter { } dest.writeInt(mLayoutId); dest.writeInt(mIsWidgetCollectionChild ? 1 : 0); - int count; - if (mActions != null) { - count = mActions.size(); - } else { - count = 0; - } - dest.writeInt(count); - for (int i=0; i<count; i++) { - Action a = mActions.get(i); - a.writeToParcel(dest, a.hasSameAppInfo(mApplication) - ? PARCELABLE_ELIDE_DUPLICATES : 0); - } + writeActionsToParcel(dest); } else { dest.writeInt(MODE_HAS_LANDSCAPE_AND_PORTRAIT); // We only write the bitmap cache if we are the root RemoteViews, as this cache @@ -3722,6 +3707,21 @@ public class RemoteViews implements Parcelable, Filter { dest.writeInt(mReapplyDisallowed ? 1 : 0); } + private void writeActionsToParcel(Parcel parcel) { + int count; + if (mActions != null) { + count = mActions.size(); + } else { + count = 0; + } + parcel.writeInt(count); + for (int i = 0; i < count; i++) { + Action a = mActions.get(i); + a.writeToParcel(parcel, a.hasSameAppInfo(mApplication) + ? PARCELABLE_ELIDE_DUPLICATES : 0); + } + } + private static ApplicationInfo getApplicationInfo(String packageName, int userId) { if (packageName == null) { return null; 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/android/widget/Switch.java b/core/java/android/widget/Switch.java index 2e1e96365f2a..604575fae463 100644 --- a/core/java/android/widget/Switch.java +++ b/core/java/android/widget/Switch.java @@ -248,10 +248,7 @@ public class Switch extends CompoundButton { com.android.internal.R.styleable.Switch_switchPadding, 0); mSplitTrack = a.getBoolean(com.android.internal.R.styleable.Switch_splitTrack, false); - // TODO: replace CUR_DEVELOPMENT with P once P is added to android.os.Build.VERSION_CODES. - // STOPSHIP if the above TODO is not done. - mUseFallbackLineSpacing = - context.getApplicationInfo().targetSdkVersion >= VERSION_CODES.CUR_DEVELOPMENT; + mUseFallbackLineSpacing = context.getApplicationInfo().targetSdkVersion >= VERSION_CODES.P; ColorStateList thumbTintList = a.getColorStateList( com.android.internal.R.styleable.Switch_thumbTint); diff --git a/core/java/android/widget/TabWidget.java b/core/java/android/widget/TabWidget.java index 05f7c0a1ee08..f8b6837e2d39 100644 --- a/core/java/android/widget/TabWidget.java +++ b/core/java/android/widget/TabWidget.java @@ -61,7 +61,10 @@ public class TabWidget extends LinearLayout implements OnFocusChangeListener { // This value will be set to 0 as soon as the first tab is added to TabHost. private int mSelectedTab = -1; + @Nullable private Drawable mLeftStrip; + + @Nullable private Drawable mRightStrip; private boolean mDrawBottomStrips = true; @@ -374,23 +377,36 @@ public class TabWidget extends LinearLayout implements OnFocusChangeListener { final Drawable leftStrip = mLeftStrip; final Drawable rightStrip = mRightStrip; - leftStrip.setState(selectedChild.getDrawableState()); - rightStrip.setState(selectedChild.getDrawableState()); + if (leftStrip != null) { + leftStrip.setState(selectedChild.getDrawableState()); + } + if (rightStrip != null) { + rightStrip.setState(selectedChild.getDrawableState()); + } if (mStripMoved) { final Rect bounds = mBounds; bounds.left = selectedChild.getLeft(); bounds.right = selectedChild.getRight(); final int myHeight = getHeight(); - leftStrip.setBounds(Math.min(0, bounds.left - leftStrip.getIntrinsicWidth()), - myHeight - leftStrip.getIntrinsicHeight(), bounds.left, myHeight); - rightStrip.setBounds(bounds.right, myHeight - rightStrip.getIntrinsicHeight(), - Math.max(getWidth(), bounds.right + rightStrip.getIntrinsicWidth()), myHeight); + if (leftStrip != null) { + leftStrip.setBounds(Math.min(0, bounds.left - leftStrip.getIntrinsicWidth()), + myHeight - leftStrip.getIntrinsicHeight(), bounds.left, myHeight); + } + if (rightStrip != null) { + rightStrip.setBounds(bounds.right, myHeight - rightStrip.getIntrinsicHeight(), + Math.max(getWidth(), bounds.right + rightStrip.getIntrinsicWidth()), + myHeight); + } mStripMoved = false; } - leftStrip.draw(canvas); - rightStrip.draw(canvas); + if (leftStrip != null) { + leftStrip.draw(canvas); + } + if (rightStrip != null) { + rightStrip.draw(canvas); + } } /** diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java index 2de552777756..791a8fae418f 100644 --- a/core/java/android/widget/TextView.java +++ b/core/java/android/widget/TextView.java @@ -1256,9 +1256,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener final int targetSdkVersion = context.getApplicationInfo().targetSdkVersion; mUseInternationalizedInput = targetSdkVersion >= VERSION_CODES.O; - // TODO: replace CUR_DEVELOPMENT with P once P is added to android.os.Build.VERSION_CODES. - // STOPSHIP if the above TODO is not done. - mUseFallbackLineSpacing = targetSdkVersion >= VERSION_CODES.CUR_DEVELOPMENT; + mUseFallbackLineSpacing = targetSdkVersion >= VERSION_CODES.P; if (inputMethod != null) { Class<?> c; 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_camera2_legacy_LegacyCameraDevice.cpp b/core/jni/android_hardware_camera2_legacy_LegacyCameraDevice.cpp index 863ca8b0bc02..b610b35e45cd 100644 --- a/core/jni/android_hardware_camera2_legacy_LegacyCameraDevice.cpp +++ b/core/jni/android_hardware_camera2_legacy_LegacyCameraDevice.cpp @@ -484,14 +484,14 @@ static jint LegacyCameraDevice_nativeDetectSurfaceUsageFlags(JNIEnv* env, jobjec sp<ANativeWindow> anw; if ((anw = getNativeWindow(env, surface)) == NULL) { - jniThrowException(env, "Ljava/lang/UnsupportedOperationException;", + jniThrowException(env, "java/lang/UnsupportedOperationException;", "Could not retrieve native window from surface."); return BAD_VALUE; } int32_t usage = 0; status_t err = anw->query(anw.get(), NATIVE_WINDOW_CONSUMER_USAGE_BITS, &usage); if(err != NO_ERROR) { - jniThrowException(env, "Ljava/lang/UnsupportedOperationException;", + jniThrowException(env, "java/lang/UnsupportedOperationException;", "Error while querying surface usage bits"); return err; } @@ -511,7 +511,7 @@ static jint LegacyCameraDevice_nativeDisconnectSurface(JNIEnv* env, jobject thiz status_t err = native_window_api_disconnect(anw.get(), NATIVE_WINDOW_API_CAMERA); if(err != NO_ERROR) { - jniThrowException(env, "Ljava/lang/UnsupportedOperationException;", + jniThrowException(env, "java/lang/UnsupportedOperationException;", "Error while disconnecting surface"); return err; } 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_util_Binder.cpp b/core/jni/android_util_Binder.cpp index 883d4db04890..7908c9d2b609 100644 --- a/core/jni/android_util_Binder.cpp +++ b/core/jni/android_util_Binder.cpp @@ -20,8 +20,6 @@ #include "android_os_Parcel.h" #include "android_util_Binder.h" -#include <nativehelper/JNIHelp.h> - #include <fcntl.h> #include <inttypes.h> #include <stdio.h> @@ -44,8 +42,9 @@ #include <utils/SystemClock.h> #include <utils/threads.h> -#include <nativehelper/ScopedUtfChars.h> +#include <nativehelper/JNIHelp.h> #include <nativehelper/ScopedLocalRef.h> +#include <nativehelper/ScopedUtfChars.h> #include "core_jni_helpers.h" @@ -174,8 +173,49 @@ static JNIEnv* javavm_to_jnienv(JavaVM* vm) return vm->GetEnv((void **)&env, JNI_VERSION_1_4) >= 0 ? env : NULL; } -// Report a java.lang.Error (or subclass). This may terminate the runtime. -static void report_java_lang_error(JNIEnv* env, jthrowable error) +// Report a java.lang.Error (or subclass). This will terminate the runtime by +// calling FatalError with a message derived from the given error. +static void report_java_lang_error_fatal_error(JNIEnv* env, jthrowable error, + const char* msg) +{ + // Report an error: reraise the exception and ask the runtime to abort. + + // Try to get the exception string. Sometimes logcat isn't available, + // so try to add it to the abort message. + std::string exc_msg = "(Unknown exception message)"; + { + ScopedLocalRef<jclass> exc_class(env, env->GetObjectClass(error)); + jmethodID method_id = env->GetMethodID(exc_class.get(), "toString", + "()Ljava/lang/String;"); + ScopedLocalRef<jstring> jstr( + env, + reinterpret_cast<jstring>( + env->CallObjectMethod(error, method_id))); + env->ExceptionClear(); // Just for good measure. + if (jstr.get() != nullptr) { + ScopedUtfChars jstr_utf(env, jstr.get()); + if (jstr_utf.c_str() != nullptr) { + exc_msg = jstr_utf.c_str(); + } else { + env->ExceptionClear(); + } + } + } + + env->Throw(error); + ALOGE("java.lang.Error thrown during binder transaction (stack trace follows) : "); + env->ExceptionDescribe(); + + std::string error_msg = base::StringPrintf( + "java.lang.Error thrown during binder transaction: %s", + exc_msg.c_str()); + env->FatalError(error_msg.c_str()); +} + +// Report a java.lang.Error (or subclass). This will terminate the runtime, either by +// the uncaught exception handler, or explicitly by calling +// report_java_lang_error_fatal_error. +static void report_java_lang_error(JNIEnv* env, jthrowable error, const char* msg) { // Try to run the uncaught exception machinery. jobject thread = env->CallStaticObjectMethod(gThreadDispatchOffsets.mClass, @@ -187,77 +227,39 @@ static void report_java_lang_error(JNIEnv* env, jthrowable error) } // Some error occurred that meant that either dispatchUncaughtException could not be // called or that it had an error itself (as this should be unreachable under normal - // conditions). Clear the exception. + // conditions). As the binder code cannot handle Errors, attempt to log the error and + // abort. env->ExceptionClear(); + report_java_lang_error_fatal_error(env, error, msg); } static void report_exception(JNIEnv* env, jthrowable excep, const char* msg) { env->ExceptionClear(); - jstring tagstr = env->NewStringUTF(LOG_TAG); - jstring msgstr = NULL; - if (tagstr != NULL) { - msgstr = env->NewStringUTF(msg); + ScopedLocalRef<jstring> tagstr(env, env->NewStringUTF(LOG_TAG)); + ScopedLocalRef<jstring> msgstr(env); + if (tagstr != nullptr) { + msgstr.reset(env->NewStringUTF(msg)); } - if ((tagstr == NULL) || (msgstr == NULL)) { + if ((tagstr != nullptr) && (msgstr != nullptr)) { + env->CallStaticIntMethod(gLogOffsets.mClass, gLogOffsets.mLogE, + tagstr.get(), msgstr.get(), excep); + if (env->ExceptionCheck()) { + // Attempting to log the failure has failed. + ALOGW("Failed trying to log exception, msg='%s'\n", msg); + env->ExceptionClear(); + } + } else { env->ExceptionClear(); /* assume exception (OOM?) was thrown */ ALOGE("Unable to call Log.e()\n"); ALOGE("%s", msg); - goto bail; - } - - env->CallStaticIntMethod( - gLogOffsets.mClass, gLogOffsets.mLogE, tagstr, msgstr, excep); - if (env->ExceptionCheck()) { - /* attempting to log the failure has failed */ - ALOGW("Failed trying to log exception, msg='%s'\n", msg); - env->ExceptionClear(); } if (env->IsInstanceOf(excep, gErrorOffsets.mClass)) { - // Try to report the error. This should not return under normal circumstances. - report_java_lang_error(env, excep); - // The traditional handling: re-raise and abort. - - /* - * It's an Error: Reraise the exception and ask the runtime to abort. - */ - - // Try to get the exception string. Sometimes logcat isn't available, - // so try to add it to the abort message. - std::string exc_msg = "(Unknown exception message)"; - { - ScopedLocalRef<jclass> exc_class(env, env->GetObjectClass(excep)); - jmethodID method_id = env->GetMethodID(exc_class.get(), - "toString", - "()Ljava/lang/String;"); - ScopedLocalRef<jstring> jstr( - env, - reinterpret_cast<jstring>( - env->CallObjectMethod(excep, method_id))); - env->ExceptionClear(); // Just for good measure. - if (jstr.get() != nullptr) { - ScopedUtfChars jstr_utf(env, jstr.get()); - exc_msg = jstr_utf.c_str(); - } - } - - env->Throw(excep); - ALOGE("java.lang.Error thrown during binder transaction (stack trace follows) : "); - env->ExceptionDescribe(); - - std::string error_msg = base::StringPrintf( - "java.lang.Error thrown during binder transaction: %s", - exc_msg.c_str()); - env->FatalError(error_msg.c_str()); + report_java_lang_error(env, excep, msg); } - -bail: - /* discard local refs created for us by VM */ - env->DeleteLocalRef(tagstr); - env->DeleteLocalRef(msgstr); } class JavaBBinderHolder; @@ -309,14 +311,11 @@ protected: code, reinterpret_cast<jlong>(&data), reinterpret_cast<jlong>(reply), flags); if (env->ExceptionCheck()) { - jthrowable excep = env->ExceptionOccurred(); - report_exception(env, excep, + ScopedLocalRef<jthrowable> excep(env, env->ExceptionOccurred()); + report_exception(env, excep.get(), "*** Uncaught remote exception! " "(Exceptions are not yet supported across processes.)"); res = JNI_FALSE; - - /* clean up JNI local ref -- we don't return to Java code */ - env->DeleteLocalRef(excep); } // Check if the strict mode state changed while processing the @@ -328,11 +327,9 @@ protected: } if (env->ExceptionCheck()) { - jthrowable excep = env->ExceptionOccurred(); - report_exception(env, excep, + ScopedLocalRef<jthrowable> excep(env, env->ExceptionOccurred()); + report_exception(env, excep.get(), "*** Uncaught exception in onBinderStrictModePolicyChange"); - /* clean up JNI local ref -- we don't return to Java code */ - env->DeleteLocalRef(excep); } // Need to always call through the native implementation of @@ -475,9 +472,8 @@ public: if (mObject != NULL) { result = env->IsSameObject(obj, mObject); } else { - jobject me = env->NewLocalRef(mObjectWeak); - result = env->IsSameObject(obj, me); - env->DeleteLocalRef(me); + ScopedLocalRef<jobject> me(env, env->NewLocalRef(mObjectWeak)); + result = env->IsSameObject(obj, me.get()); } return result; } @@ -517,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; }; @@ -590,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) { @@ -605,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); @@ -1281,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/jni/android_view_SurfaceControl.cpp b/core/jni/android_view_SurfaceControl.cpp index 33f1c7d393af..a9b849e7abd9 100644 --- a/core/jni/android_view_SurfaceControl.cpp +++ b/core/jni/android_view_SurfaceControl.cpp @@ -373,6 +373,16 @@ static void nativeSetAlpha(JNIEnv* env, jclass clazz, jlong nativeObject, jfloat } } +static void nativeSetColor(JNIEnv* env, jclass clazz, jlong nativeObject, jfloatArray fColor) { + SurfaceControl* const ctrl = reinterpret_cast<SurfaceControl *>(nativeObject); + float* floatColors = env->GetFloatArrayElements(fColor, 0); + half3 color(floatColors[0], floatColors[1], floatColors[2]); + status_t err = ctrl->setColor(color); + if (err < 0 && err != NO_INIT) { + doThrowIAE(env); + } +} + static void nativeSetMatrix(JNIEnv* env, jclass clazz, jlong nativeObject, jfloat dsdx, jfloat dtdx, jfloat dtdy, jfloat dsdy) { SurfaceControl* const ctrl = reinterpret_cast<SurfaceControl *>(nativeObject); @@ -736,13 +746,11 @@ static void nativeReparentChildren(JNIEnv* env, jclass clazz, jlong nativeObject ctrl->reparentChildren(handle); } -static void nativeReparentChild(JNIEnv* env, jclass clazz, jlong nativeObject, - jobject newParentObject, jobject childObject) { +static void nativeReparent(JNIEnv* env, jclass clazz, jlong nativeObject, + jobject newParentObject) { auto ctrl = reinterpret_cast<SurfaceControl *>(nativeObject); sp<IBinder> parentHandle = ibinderForJavaObject(env, newParentObject); - sp<IBinder> childHandle = ibinderForJavaObject(env, childObject); - - ctrl->reparentChild(parentHandle, childHandle); + ctrl->reparent(parentHandle); } static void nativeSeverChildren(JNIEnv* env, jclass clazz, jlong nativeObject) { @@ -814,6 +822,8 @@ static const JNINativeMethod sSurfaceControlMethods[] = { (void*)nativeSetTransparentRegionHint }, {"nativeSetAlpha", "(JF)V", (void*)nativeSetAlpha }, + {"nativeSetColor", "(J[F)V", + (void*)nativeSetColor }, {"nativeSetMatrix", "(JFFFF)V", (void*)nativeSetMatrix }, {"nativeSetFlags", "(JII)V", @@ -868,8 +878,8 @@ static const JNINativeMethod sSurfaceControlMethods[] = { (void*)nativeDeferTransactionUntilSurface }, {"nativeReparentChildren", "(JLandroid/os/IBinder;)V", (void*)nativeReparentChildren } , - {"nativeReparentChild", "(JLandroid/os/IBinder;Landroid/os/IBinder;)V", - (void*)nativeReparentChild }, + {"nativeReparent", "(JLandroid/os/IBinder;)V", + (void*)nativeReparent }, {"nativeSeverChildren", "(J)V", (void*)nativeSeverChildren } , {"nativeSetOverrideScalingMode", "(JI)V", 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 7331a64789b5..bce10dc2e2fb 100644 --- a/core/proto/android/os/incident.proto +++ b/core/proto/android/os/incident.proto @@ -74,9 +74,12 @@ message IncidentProto { android.service.NetworkStatsServiceDumpProto netstats = 3001; android.providers.settings.SettingsServiceDumpProto settings = 3002; android.service.appwidget.AppWidgetServiceDumpProto appwidget = 3003; + android.service.notification.NotificationServiceDumpProto notification = 3004 [ + (section).type = SECTION_DUMPSYS, + (section).args = "notification --proto" + ]; android.service.battery.BatteryServiceDumpProto battery = 3006; android.service.diskstats.DiskStatsServiceDumpProto diskstats = 3007; - android.service.notification.NotificationServiceDumpProto notification = 3004; android.service.pm.PackageServiceDumpProto package = 3008; android.service.power.PowerServiceDumpProto power = 3009; android.service.print.PrintServiceDumpProto print = 3010; diff --git a/core/proto/android/server/activitymanagerservice.proto b/core/proto/android/server/activitymanagerservice.proto new file mode 100644 index 000000000000..d5ecacc8f72c --- /dev/null +++ b/core/proto/android/server/activitymanagerservice.proto @@ -0,0 +1,84 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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"; + +import "frameworks/base/core/proto/android/server/windowmanagerservice.proto"; +import "frameworks/base/core/proto/android/graphics/rect.proto"; + +package com.android.server.am.proto; + +option java_multiple_files = true; + +message ActivityManagerServiceProto { + ActivityStackSupervisorProto activities = 1; +} + +message ActivityStackSupervisorProto { + .com.android.server.wm.proto.ConfigurationContainerProto configuration_container = 1; + repeated ActivityDisplayProto displays = 2; + KeyguardControllerProto keyguard_controller = 3; + int32 focused_stack_id = 4; + .com.android.server.wm.proto.IdentifierProto resumed_activity = 5; +} + +/* represents ActivityStackSupervisor.ActivityDisplay */ +message ActivityDisplayProto { + .com.android.server.wm.proto.ConfigurationContainerProto configuration_container = 1; + int32 id = 2; + repeated ActivityStackProto stacks = 3; +} + +message ActivityStackProto { + .com.android.server.wm.proto.ConfigurationContainerProto configuration_container = 1; + int32 id = 2; + repeated TaskRecordProto tasks = 3; + .com.android.server.wm.proto.IdentifierProto resumed_activity = 4; + int32 display_id = 5; + bool fullscreen = 6; + .android.graphics.RectProto bounds = 7; +} + +message TaskRecordProto { + .com.android.server.wm.proto.ConfigurationContainerProto configuration_container = 1; + int32 id = 2; + repeated ActivityRecordProto activities = 3; + int32 stack_id = 4; + .android.graphics.RectProto last_non_fullscreen_bounds = 5; + string real_activity = 6; + string orig_activity = 7; + int32 activity_type = 8; + int32 return_to_type = 9; + int32 resize_mode = 10; + bool fullscreen = 11; + .android.graphics.RectProto bounds = 12; + int32 min_width = 13; + int32 min_height = 14; +} + +message ActivityRecordProto { + .com.android.server.wm.proto.ConfigurationContainerProto configuration_container = 1; + .com.android.server.wm.proto.IdentifierProto identifier = 2; + string state = 3; + bool visible = 4; + bool front_of_task = 5; + int32 proc_id = 6; +} + +message KeyguardControllerProto { + bool keyguard_showing = 1; + bool keyguard_occluded = 2; +}
\ No newline at end of file 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 819460e08957..05afe525c1eb 100644 --- a/core/proto/android/service/notification.proto +++ b/core/proto/android/service/notification.proto @@ -21,10 +21,23 @@ 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 { repeated NotificationRecordProto records = 1; ZenModeProto zen = 2; + + ManagedServicesProto notification_listeners = 3; + + int32 listener_hints = 4; + + repeated ListenersDisablingEffectsProto listeners_disabling_effects = 5; + + ManagedServicesProto notification_assistants = 6; + + ManagedServicesProto condition_providers = 7; } message NotificationRecordProto { @@ -40,6 +53,39 @@ message NotificationRecordProto { int32 importance = 10; } +message ListenersDisablingEffectsProto { + int32 hint = 1; + repeated ManagedServiceInfoProto listeners = 2; +} + +message ManagedServiceInfoProto { + android.content.ComponentNameProto component = 1; + int32 user_id = 2; + string service = 3; + bool is_system = 4; + bool is_guest = 5; +} + +message ManagedServicesProto { + string caption = 1; + + message ServiceProto { + repeated string name = 1; + int32 user_id = 2; + bool is_primary = 3; + } + repeated ServiceProto approved = 2; + + // All of this type/caption enabled for current profiles. + repeated android.content.ComponentNameProto enabled = 3; + + + repeated ManagedServiceInfoProto live_services = 4; + + // Snoozed for current profiles. + repeated android.content.ComponentNameProto snoozed = 5; +} + enum State { ENQUEUED = 0; @@ -53,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 { @@ -61,4 +107,4 @@ enum ZenMode { ZEN_MODE_IMPORTANT_INTERRUPTIONS = 1; ZEN_MODE_NO_INTERRUPTIONS = 2; ZEN_MODE_ALARMS = 3; -}
\ No newline at end of file +} 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 d3ba7ef5e25e..164b585de385 100644 --- a/core/res/res/values-af/strings.xml +++ b/core/res/res/values-af/strings.xml @@ -1420,9 +1420,10 @@ <string name="default_audio_route_name" product="tablet" msgid="4617053898167127471">"Tablet"</string> <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_headphones" msgid="8119971843803439110">"Oorfone"</string> <string name="default_audio_route_name_dock_speakers" msgid="6240602982276591864">"Dokluidsprekers"</string> - <string name="default_media_route_name_hdmi" msgid="2450970399023478055">"HDMI"</string> + <string name="default_audio_route_name_hdmi" msgid="1486254205617081251">"HDMI"</string> + <string name="default_audio_route_name_headphones" msgid="8119971843803439110">"Oorfone"</string> + <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 a3c2cab5f78d..9f3bcbbafed5 100644 --- a/core/res/res/values-am/strings.xml +++ b/core/res/res/values-am/strings.xml @@ -1420,9 +1420,10 @@ <string name="default_audio_route_name" product="tablet" msgid="4617053898167127471">"ጡባዊ ተኮ"</string> <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_headphones" msgid="8119971843803439110">"የጆሮ ማዳመጫዎች"</string> <string name="default_audio_route_name_dock_speakers" msgid="6240602982276591864">"የትከል ድምፅ ማጉያዎች"</string> - <string name="default_media_route_name_hdmi" msgid="2450970399023478055">"HDMI"</string> + <string name="default_audio_route_name_hdmi" msgid="1486254205617081251">"ኤችዲኤምአይ"</string> + <string name="default_audio_route_name_headphones" msgid="8119971843803439110">"የጆሮ ማዳመጫዎች"</string> + <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 5ff51f2d1df6..b3aa8bfb2000 100644 --- a/core/res/res/values-ar/strings.xml +++ b/core/res/res/values-ar/strings.xml @@ -1512,9 +1512,10 @@ <string name="default_audio_route_name" product="tablet" msgid="4617053898167127471">"الجهاز اللوحي"</string> <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_headphones" msgid="8119971843803439110">"سماعات رأس"</string> <string name="default_audio_route_name_dock_speakers" msgid="6240602982276591864">"مكبرات صوت للإرساء"</string> - <string name="default_media_route_name_hdmi" msgid="2450970399023478055">"HDMI"</string> + <string name="default_audio_route_name_hdmi" msgid="1486254205617081251">"HDMI"</string> + <string name="default_audio_route_name_headphones" msgid="8119971843803439110">"سماعات رأس"</string> + <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 bd63c27c22b3..61e2c1e4139d 100644 --- a/core/res/res/values-az/strings.xml +++ b/core/res/res/values-az/strings.xml @@ -1420,9 +1420,10 @@ <string name="default_audio_route_name" product="tablet" msgid="4617053898167127471">"Planşet"</string> <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_headphones" msgid="8119971843803439110">"Qulaqlıq"</string> <string name="default_audio_route_name_dock_speakers" msgid="6240602982276591864">"Dok spikerlər"</string> - <string name="default_media_route_name_hdmi" msgid="2450970399023478055">"HDMI"</string> + <string name="default_audio_route_name_hdmi" msgid="1486254205617081251">"HDMI"</string> + <string name="default_audio_route_name_headphones" msgid="8119971843803439110">"Qulaqlıq"</string> + <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 e362a87d959b..f3c25d627f54 100644 --- a/core/res/res/values-b+sr+Latn/strings.xml +++ b/core/res/res/values-b+sr+Latn/strings.xml @@ -1443,9 +1443,10 @@ <string name="default_audio_route_name" product="tablet" msgid="4617053898167127471">"Tablet"</string> <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_headphones" msgid="8119971843803439110">"Slušalice"</string> <string name="default_audio_route_name_dock_speakers" msgid="6240602982276591864">"Zvučnici bazne stanice"</string> - <string name="default_media_route_name_hdmi" msgid="2450970399023478055">"HDMI"</string> + <string name="default_audio_route_name_hdmi" msgid="1486254205617081251">"HDMI"</string> + <string name="default_audio_route_name_headphones" msgid="8119971843803439110">"Slušalice"</string> + <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 fdbe702666d6..bba23aa76458 100644 --- a/core/res/res/values-be/strings.xml +++ b/core/res/res/values-be/strings.xml @@ -1466,9 +1466,10 @@ <string name="default_audio_route_name" product="tablet" msgid="4617053898167127471">"Планшэт"</string> <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_headphones" msgid="8119971843803439110">"Навушнікі"</string> <string name="default_audio_route_name_dock_speakers" msgid="6240602982276591864">"Дынамікі станцыi"</string> - <string name="default_media_route_name_hdmi" msgid="2450970399023478055">"HDMI"</string> + <string name="default_audio_route_name_hdmi" msgid="1486254205617081251">"HDMI"</string> + <string name="default_audio_route_name_headphones" msgid="8119971843803439110">"Навушнікі"</string> + <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 ae4cc61488e3..5b9288810239 100644 --- a/core/res/res/values-bg/strings.xml +++ b/core/res/res/values-bg/strings.xml @@ -1420,9 +1420,10 @@ <string name="default_audio_route_name" product="tablet" msgid="4617053898167127471">"Таблет"</string> <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_headphones" msgid="8119971843803439110">"Слушалки"</string> <string name="default_audio_route_name_dock_speakers" msgid="6240602982276591864">"Докинг станц.: Високогов."</string> - <string name="default_media_route_name_hdmi" msgid="2450970399023478055">"HDMI"</string> + <string name="default_audio_route_name_hdmi" msgid="1486254205617081251">"HDMI"</string> + <string name="default_audio_route_name_headphones" msgid="8119971843803439110">"Слушалки"</string> + <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 e3ecfda94c32..dff5ab608eec 100644 --- a/core/res/res/values-bn/strings.xml +++ b/core/res/res/values-bn/strings.xml @@ -1420,9 +1420,10 @@ <string name="default_audio_route_name" product="tablet" msgid="4617053898167127471">"ট্যাবলেট"</string> <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_headphones" msgid="8119971843803439110">"হেডফোন"</string> <string name="default_audio_route_name_dock_speakers" msgid="6240602982276591864">"ডক স্পিকার"</string> - <string name="default_media_route_name_hdmi" msgid="2450970399023478055">"HDMI"</string> + <string name="default_audio_route_name_hdmi" msgid="1486254205617081251">"HDMI"</string> + <string name="default_audio_route_name_headphones" msgid="8119971843803439110">"হেডফোন"</string> + <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 232a4e17df0b..d1bb0f9c2298 100644 --- a/core/res/res/values-bs/strings.xml +++ b/core/res/res/values-bs/strings.xml @@ -1445,9 +1445,10 @@ <string name="default_audio_route_name" product="tablet" msgid="4617053898167127471">"Tablet"</string> <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_headphones" msgid="8119971843803439110">"Slušalice"</string> <string name="default_audio_route_name_dock_speakers" msgid="6240602982276591864">"Zvučnici priključne stanice"</string> - <string name="default_media_route_name_hdmi" msgid="2450970399023478055">"HDMI"</string> + <string name="default_audio_route_name_hdmi" msgid="1486254205617081251">"HDMI"</string> + <string name="default_audio_route_name_headphones" msgid="8119971843803439110">"Slušalice"</string> + <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 d713c1b00731..60018d93ad38 100644 --- a/core/res/res/values-ca/strings.xml +++ b/core/res/res/values-ca/strings.xml @@ -1285,7 +1285,7 @@ <string name="wallpaper_binding_label" msgid="1240087844304687662">"Fons de pantalla"</string> <string name="chooser_wallpaper" msgid="7873476199295190279">"Canvia el fons de pantalla"</string> <string name="notification_listener_binding_label" msgid="2014162835481906429">"Oient de notificacions"</string> - <string name="vr_listener_binding_label" msgid="4316591939343607306">"Processador de RV"</string> + <string name="vr_listener_binding_label" msgid="4316591939343607306">"Processador d\'RV"</string> <string name="condition_provider_service_binding_label" msgid="1321343352906524564">"Proveïdor de condicions"</string> <string name="notification_ranker_binding_label" msgid="774540592299064747">"Servei de classificació de notificacions"</string> <string name="vpn_title" msgid="19615213552042827">"VPN activada"</string> @@ -1420,9 +1420,10 @@ <string name="default_audio_route_name" product="tablet" msgid="4617053898167127471">"Tauleta"</string> <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_headphones" msgid="8119971843803439110">"Auriculars"</string> <string name="default_audio_route_name_dock_speakers" msgid="6240602982276591864">"Altaveus de la base"</string> - <string name="default_media_route_name_hdmi" msgid="2450970399023478055">"HDMI"</string> + <string name="default_audio_route_name_hdmi" msgid="1486254205617081251">"HDMI"</string> + <string name="default_audio_route_name_headphones" msgid="8119971843803439110">"Auriculars"</string> + <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 31e7487771c9..53ea5860d200 100644 --- a/core/res/res/values-cs/strings.xml +++ b/core/res/res/values-cs/strings.xml @@ -1466,9 +1466,10 @@ <string name="default_audio_route_name" product="tablet" msgid="4617053898167127471">"Tablet"</string> <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_headphones" msgid="8119971843803439110">"Sluchátka"</string> <string name="default_audio_route_name_dock_speakers" msgid="6240602982276591864">"Reproduktory doku"</string> - <string name="default_media_route_name_hdmi" msgid="2450970399023478055">"HDMI"</string> + <string name="default_audio_route_name_hdmi" msgid="1486254205617081251">"HDMI"</string> + <string name="default_audio_route_name_headphones" msgid="8119971843803439110">"Sluchátka"</string> + <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 f1ba1740ca7e..d6e400ba2da0 100644 --- a/core/res/res/values-da/strings.xml +++ b/core/res/res/values-da/strings.xml @@ -1420,9 +1420,10 @@ <string name="default_audio_route_name" product="tablet" msgid="4617053898167127471">"Tablet"</string> <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_headphones" msgid="8119971843803439110">"Hovedtelefoner"</string> <string name="default_audio_route_name_dock_speakers" msgid="6240602982276591864">"Dockstationens højttalere"</string> - <string name="default_media_route_name_hdmi" msgid="2450970399023478055">"HDMI"</string> + <string name="default_audio_route_name_hdmi" msgid="1486254205617081251">"HDMI"</string> + <string name="default_audio_route_name_headphones" msgid="8119971843803439110">"Hovedtelefoner"</string> + <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 cc510d78f591..ff0fe95bf153 100644 --- a/core/res/res/values-de/strings.xml +++ b/core/res/res/values-de/strings.xml @@ -1420,9 +1420,10 @@ <string name="default_audio_route_name" product="tablet" msgid="4617053898167127471">"Tablet"</string> <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_headphones" msgid="8119971843803439110">"Kopfhörer"</string> <string name="default_audio_route_name_dock_speakers" msgid="6240602982276591864">"Dock-Lautsprecher"</string> - <string name="default_media_route_name_hdmi" msgid="2450970399023478055">"HDMI"</string> + <string name="default_audio_route_name_hdmi" msgid="1486254205617081251">"HDMI"</string> + <string name="default_audio_route_name_headphones" msgid="8119971843803439110">"Kopfhörer"</string> + <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 ede305cdb7bd..806d42496458 100644 --- a/core/res/res/values-el/strings.xml +++ b/core/res/res/values-el/strings.xml @@ -1420,9 +1420,10 @@ <string name="default_audio_route_name" product="tablet" msgid="4617053898167127471">"Tablet"</string> <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_headphones" msgid="8119971843803439110">"Ακουστικά"</string> <string name="default_audio_route_name_dock_speakers" msgid="6240602982276591864">"Ηχεία βάσης σύνδεσης"</string> - <string name="default_media_route_name_hdmi" msgid="2450970399023478055">"HDMI"</string> + <string name="default_audio_route_name_hdmi" msgid="1486254205617081251">"HDMI"</string> + <string name="default_audio_route_name_headphones" msgid="8119971843803439110">"Ακουστικά"</string> + <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 fa7f1801a147..8264a28035f3 100644 --- a/core/res/res/values-en-rAU/strings.xml +++ b/core/res/res/values-en-rAU/strings.xml @@ -1420,9 +1420,10 @@ <string name="default_audio_route_name" product="tablet" msgid="4617053898167127471">"Tablet"</string> <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_headphones" msgid="8119971843803439110">"Headphones"</string> <string name="default_audio_route_name_dock_speakers" msgid="6240602982276591864">"Dock speakers"</string> - <string name="default_media_route_name_hdmi" msgid="2450970399023478055">"HDMI"</string> + <string name="default_audio_route_name_hdmi" msgid="1486254205617081251">"HDMI"</string> + <string name="default_audio_route_name_headphones" msgid="8119971843803439110">"Headphones"</string> + <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 fa7f1801a147..8264a28035f3 100644 --- a/core/res/res/values-en-rCA/strings.xml +++ b/core/res/res/values-en-rCA/strings.xml @@ -1420,9 +1420,10 @@ <string name="default_audio_route_name" product="tablet" msgid="4617053898167127471">"Tablet"</string> <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_headphones" msgid="8119971843803439110">"Headphones"</string> <string name="default_audio_route_name_dock_speakers" msgid="6240602982276591864">"Dock speakers"</string> - <string name="default_media_route_name_hdmi" msgid="2450970399023478055">"HDMI"</string> + <string name="default_audio_route_name_hdmi" msgid="1486254205617081251">"HDMI"</string> + <string name="default_audio_route_name_headphones" msgid="8119971843803439110">"Headphones"</string> + <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 fa7f1801a147..8264a28035f3 100644 --- a/core/res/res/values-en-rGB/strings.xml +++ b/core/res/res/values-en-rGB/strings.xml @@ -1420,9 +1420,10 @@ <string name="default_audio_route_name" product="tablet" msgid="4617053898167127471">"Tablet"</string> <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_headphones" msgid="8119971843803439110">"Headphones"</string> <string name="default_audio_route_name_dock_speakers" msgid="6240602982276591864">"Dock speakers"</string> - <string name="default_media_route_name_hdmi" msgid="2450970399023478055">"HDMI"</string> + <string name="default_audio_route_name_hdmi" msgid="1486254205617081251">"HDMI"</string> + <string name="default_audio_route_name_headphones" msgid="8119971843803439110">"Headphones"</string> + <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 fa7f1801a147..8264a28035f3 100644 --- a/core/res/res/values-en-rIN/strings.xml +++ b/core/res/res/values-en-rIN/strings.xml @@ -1420,9 +1420,10 @@ <string name="default_audio_route_name" product="tablet" msgid="4617053898167127471">"Tablet"</string> <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_headphones" msgid="8119971843803439110">"Headphones"</string> <string name="default_audio_route_name_dock_speakers" msgid="6240602982276591864">"Dock speakers"</string> - <string name="default_media_route_name_hdmi" msgid="2450970399023478055">"HDMI"</string> + <string name="default_audio_route_name_hdmi" msgid="1486254205617081251">"HDMI"</string> + <string name="default_audio_route_name_headphones" msgid="8119971843803439110">"Headphones"</string> + <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 353b437fb2c4..44fd405a8961 100644 --- a/core/res/res/values-en-rXC/strings.xml +++ b/core/res/res/values-en-rXC/strings.xml @@ -1420,9 +1420,10 @@ <string name="default_audio_route_name" product="tablet" msgid="4617053898167127471">"Tablet"</string> <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_headphones" msgid="8119971843803439110">"Headphones"</string> <string name="default_audio_route_name_dock_speakers" msgid="6240602982276591864">"Dock speakers"</string> - <string name="default_media_route_name_hdmi" msgid="2450970399023478055">"HDMI"</string> + <string name="default_audio_route_name_hdmi" msgid="1486254205617081251">"HDMI"</string> + <string name="default_audio_route_name_headphones" msgid="8119971843803439110">"Headphones"</string> + <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 4a7a191ea870..e7a18eac324f 100644 --- a/core/res/res/values-es-rUS/strings.xml +++ b/core/res/res/values-es-rUS/strings.xml @@ -1420,9 +1420,10 @@ <string name="default_audio_route_name" product="tablet" msgid="4617053898167127471">"Tablet"</string> <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_headphones" msgid="8119971843803439110">"Auriculares"</string> <string name="default_audio_route_name_dock_speakers" msgid="6240602982276591864">"Altavoces del conector"</string> - <string name="default_media_route_name_hdmi" msgid="2450970399023478055">"HDMI"</string> + <string name="default_audio_route_name_hdmi" msgid="1486254205617081251">"HDMI"</string> + <string name="default_audio_route_name_headphones" msgid="8119971843803439110">"Auriculares"</string> + <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 425e9884dd12..820ab101ca23 100644 --- a/core/res/res/values-es/strings.xml +++ b/core/res/res/values-es/strings.xml @@ -1221,7 +1221,7 @@ <string name="ext_media_unsupported_notification_message" msgid="6121601473787888589">"El dispositivo no admite este medio externo (<xliff:g id="NAME">%s</xliff:g>). Toca para configurarlo con un formato admitido."</string> <string name="ext_media_unsupported_notification_message" product="tv" msgid="3725436899820390906">"El dispositivo no admite esta <xliff:g id="NAME">%s</xliff:g>. Selecciónala para configurarla en un formato admitido."</string> <string name="ext_media_badremoval_notification_title" msgid="3206248947375505416">"Extracción inesperada de <xliff:g id="NAME">%s</xliff:g>"</string> - <string name="ext_media_badremoval_notification_message" msgid="380176703346946313">"Desactiva tu <xliff:g id="NAME">%s</xliff:g> antes de extraer la unidad para evitar pérdidas de datos"</string> + <string name="ext_media_badremoval_notification_message" msgid="380176703346946313">"Desconecta tu <xliff:g id="NAME">%s</xliff:g> antes de extraer la unidad para evitar pérdidas de datos"</string> <string name="ext_media_nomedia_notification_title" msgid="1704840188641749091">"Tu <xliff:g id="NAME">%s</xliff:g> se ha extraído"</string> <string name="ext_media_nomedia_notification_message" msgid="6471542972147056586">"Tu <xliff:g id="NAME">%s</xliff:g> se ha extraído: inserta otra unidad"</string> <string name="ext_media_unmounting_notification_title" msgid="640674168454809372">"Expulsando <xliff:g id="NAME">%s</xliff:g>…"</string> @@ -1420,9 +1420,10 @@ <string name="default_audio_route_name" product="tablet" msgid="4617053898167127471">"Tablet"</string> <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_headphones" msgid="8119971843803439110">"Auriculares"</string> <string name="default_audio_route_name_dock_speakers" msgid="6240602982276591864">"Altavoces de la base"</string> - <string name="default_media_route_name_hdmi" msgid="2450970399023478055">"HDMI"</string> + <string name="default_audio_route_name_hdmi" msgid="1486254205617081251">"HDMI"</string> + <string name="default_audio_route_name_headphones" msgid="8119971843803439110">"Auriculares"</string> + <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 7c57dafdd20e..d6cf28e7b885 100644 --- a/core/res/res/values-et/strings.xml +++ b/core/res/res/values-et/strings.xml @@ -1420,9 +1420,10 @@ <string name="default_audio_route_name" product="tablet" msgid="4617053898167127471">"Tahvelarvuti"</string> <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_headphones" msgid="8119971843803439110">"Kõrvaklapid"</string> <string name="default_audio_route_name_dock_speakers" msgid="6240602982276591864">"Doki kõlarid"</string> - <string name="default_media_route_name_hdmi" msgid="2450970399023478055">"HDMI"</string> + <string name="default_audio_route_name_hdmi" msgid="1486254205617081251">"HDMI"</string> + <string name="default_audio_route_name_headphones" msgid="8119971843803439110">"Kõrvaklapid"</string> + <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 5556a5d44f18..f0414bb0bcac 100644 --- a/core/res/res/values-eu/strings.xml +++ b/core/res/res/values-eu/strings.xml @@ -1420,9 +1420,10 @@ <string name="default_audio_route_name" product="tablet" msgid="4617053898167127471">"Tableta"</string> <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_headphones" msgid="8119971843803439110">"Aurikularrak"</string> <string name="default_audio_route_name_dock_speakers" msgid="6240602982276591864">"Konektatu bozgorailuak oinarrira"</string> - <string name="default_media_route_name_hdmi" msgid="2450970399023478055">"HDMI"</string> + <string name="default_audio_route_name_hdmi" msgid="1486254205617081251">"HDMI"</string> + <string name="default_audio_route_name_headphones" msgid="8119971843803439110">"Aurikularrak"</string> + <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 bb9635a85300..9b974fe3ef06 100644 --- a/core/res/res/values-fa/strings.xml +++ b/core/res/res/values-fa/strings.xml @@ -1420,9 +1420,10 @@ <string name="default_audio_route_name" product="tablet" msgid="4617053898167127471">"رایانهٔ لوحی"</string> <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_headphones" msgid="8119971843803439110">"هدفونها"</string> <string name="default_audio_route_name_dock_speakers" msgid="6240602982276591864">"بلندگوهای جایگاه"</string> - <string name="default_media_route_name_hdmi" msgid="2450970399023478055">"HDMI"</string> + <string name="default_audio_route_name_hdmi" msgid="1486254205617081251">"HDMI"</string> + <string name="default_audio_route_name_headphones" msgid="8119971843803439110">"هدفونها"</string> + <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 a32db2cfcb93..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> @@ -1420,9 +1420,10 @@ <string name="default_audio_route_name" product="tablet" msgid="4617053898167127471">"Tabletti"</string> <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_headphones" msgid="8119971843803439110">"Kuulokkeet"</string> <string name="default_audio_route_name_dock_speakers" msgid="6240602982276591864">"Telineen kaiuttimet"</string> - <string name="default_media_route_name_hdmi" msgid="2450970399023478055">"HDMI"</string> + <string name="default_audio_route_name_hdmi" msgid="1486254205617081251">"HDMI"</string> + <string name="default_audio_route_name_headphones" msgid="8119971843803439110">"Kuulokkeet"</string> + <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 8fe60e3fe483..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> @@ -1420,9 +1420,10 @@ <string name="default_audio_route_name" product="tablet" msgid="4617053898167127471">"Tablette"</string> <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_headphones" msgid="8119971843803439110">"Oreillettes"</string> <string name="default_audio_route_name_dock_speakers" msgid="6240602982276591864">"Haut-parleurs de la station d\'accueil"</string> - <string name="default_media_route_name_hdmi" msgid="2450970399023478055">"HDMI"</string> + <string name="default_audio_route_name_hdmi" msgid="1486254205617081251">"HDMI"</string> + <string name="default_audio_route_name_headphones" msgid="8119971843803439110">"Oreillettes"</string> + <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 52d482482625..5a360a86b0b3 100644 --- a/core/res/res/values-fr/strings.xml +++ b/core/res/res/values-fr/strings.xml @@ -1420,9 +1420,10 @@ <string name="default_audio_route_name" product="tablet" msgid="4617053898167127471">"Tablette"</string> <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_headphones" msgid="8119971843803439110">"Écouteurs"</string> <string name="default_audio_route_name_dock_speakers" msgid="6240602982276591864">"Haut-parleurs de la station d\'accueil"</string> - <string name="default_media_route_name_hdmi" msgid="2450970399023478055">"HDMI"</string> + <string name="default_audio_route_name_hdmi" msgid="1486254205617081251">"HDMI"</string> + <string name="default_audio_route_name_headphones" msgid="8119971843803439110">"Écouteurs"</string> + <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 9a3a83f81fbb..f17f10b261f3 100644 --- a/core/res/res/values-gl/strings.xml +++ b/core/res/res/values-gl/strings.xml @@ -1420,9 +1420,10 @@ <string name="default_audio_route_name" product="tablet" msgid="4617053898167127471">"Tableta"</string> <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_headphones" msgid="8119971843803439110">"Auriculares"</string> <string name="default_audio_route_name_dock_speakers" msgid="6240602982276591864">"Conectar altofalantes á base"</string> - <string name="default_media_route_name_hdmi" msgid="2450970399023478055">"HDMI"</string> + <string name="default_audio_route_name_hdmi" msgid="1486254205617081251">"HDMI"</string> + <string name="default_audio_route_name_headphones" msgid="8119971843803439110">"Auriculares"</string> + <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 ec8023647fbe..4f2e29c806b3 100644 --- a/core/res/res/values-gu/strings.xml +++ b/core/res/res/values-gu/strings.xml @@ -1420,9 +1420,10 @@ <string name="default_audio_route_name" product="tablet" msgid="4617053898167127471">"ટેબ્લેટ"</string> <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_headphones" msgid="8119971843803439110">"હેડફોન"</string> <string name="default_audio_route_name_dock_speakers" msgid="6240602982276591864">"સ્પીકર્સ ડૉક કરો"</string> - <string name="default_media_route_name_hdmi" msgid="2450970399023478055">"HDMI"</string> + <string name="default_audio_route_name_hdmi" msgid="1486254205617081251">"HDMI"</string> + <string name="default_audio_route_name_headphones" msgid="8119971843803439110">"હેડફોન"</string> + <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 217d106cb028..a112be440b14 100644 --- a/core/res/res/values-hi/strings.xml +++ b/core/res/res/values-hi/strings.xml @@ -1420,9 +1420,10 @@ <string name="default_audio_route_name" product="tablet" msgid="4617053898167127471">"टैबलेट"</string> <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_headphones" msgid="8119971843803439110">"हेडफ़ोन"</string> <string name="default_audio_route_name_dock_speakers" msgid="6240602982276591864">"डॉक स्पीकर"</string> - <string name="default_media_route_name_hdmi" msgid="2450970399023478055">"HDMI"</string> + <string name="default_audio_route_name_hdmi" msgid="1486254205617081251">"HDMI"</string> + <string name="default_audio_route_name_headphones" msgid="8119971843803439110">"हेडफ़ोन"</string> + <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 60a0cc2f5085..08a7697bf440 100644 --- a/core/res/res/values-hr/strings.xml +++ b/core/res/res/values-hr/strings.xml @@ -1443,9 +1443,10 @@ <string name="default_audio_route_name" product="tablet" msgid="4617053898167127471">"Tabletno računalo"</string> <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_headphones" msgid="8119971843803439110">"Slušalice"</string> <string name="default_audio_route_name_dock_speakers" msgid="6240602982276591864">"Zvučnici postolja"</string> - <string name="default_media_route_name_hdmi" msgid="2450970399023478055">"HDMI"</string> + <string name="default_audio_route_name_hdmi" msgid="1486254205617081251">"HDMI"</string> + <string name="default_audio_route_name_headphones" msgid="8119971843803439110">"Slušalice"</string> + <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 3c40d569cd0d..2cd1a10d6a8e 100644 --- a/core/res/res/values-hu/strings.xml +++ b/core/res/res/values-hu/strings.xml @@ -1420,9 +1420,10 @@ <string name="default_audio_route_name" product="tablet" msgid="4617053898167127471">"Táblagép"</string> <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_headphones" msgid="8119971843803439110">"Fejhallgató"</string> <string name="default_audio_route_name_dock_speakers" msgid="6240602982276591864">"Dokkolóegység hangszórója"</string> - <string name="default_media_route_name_hdmi" msgid="2450970399023478055">"HDMI"</string> + <string name="default_audio_route_name_hdmi" msgid="1486254205617081251">"HDMI"</string> + <string name="default_audio_route_name_headphones" msgid="8119971843803439110">"Fejhallgató"</string> + <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 190b2d5ea753..b27b257b24c0 100644 --- a/core/res/res/values-hy/strings.xml +++ b/core/res/res/values-hy/strings.xml @@ -1420,9 +1420,10 @@ <string name="default_audio_route_name" product="tablet" msgid="4617053898167127471">"Գրասալիկ"</string> <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_headphones" msgid="8119971843803439110">"Ականջակալներ"</string> <string name="default_audio_route_name_dock_speakers" msgid="6240602982276591864">"Համակցված բարձրախոսներ"</string> - <string name="default_media_route_name_hdmi" msgid="2450970399023478055">"HDMI"</string> + <string name="default_audio_route_name_hdmi" msgid="1486254205617081251">"HDMI"</string> + <string name="default_audio_route_name_headphones" msgid="8119971843803439110">"Ականջակալներ"</string> + <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 b6a8aa28fbd9..dda8877b3785 100644 --- a/core/res/res/values-in/strings.xml +++ b/core/res/res/values-in/strings.xml @@ -1420,9 +1420,10 @@ <string name="default_audio_route_name" product="tablet" msgid="4617053898167127471">"Tablet"</string> <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_headphones" msgid="8119971843803439110">"Headphone"</string> <string name="default_audio_route_name_dock_speakers" msgid="6240602982276591864">"Pengeras suara dok"</string> - <string name="default_media_route_name_hdmi" msgid="2450970399023478055">"HDMI"</string> + <string name="default_audio_route_name_hdmi" msgid="1486254205617081251">"HDMI"</string> + <string name="default_audio_route_name_headphones" msgid="8119971843803439110">"Headphone"</string> + <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 8cc5f97ab7c4..f72f0f640980 100644 --- a/core/res/res/values-is/strings.xml +++ b/core/res/res/values-is/strings.xml @@ -1420,9 +1420,10 @@ <string name="default_audio_route_name" product="tablet" msgid="4617053898167127471">"Spjaldtölva"</string> <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_headphones" msgid="8119971843803439110">"Heyrnartól"</string> <string name="default_audio_route_name_dock_speakers" msgid="6240602982276591864">"Dokkuhátalarar"</string> - <string name="default_media_route_name_hdmi" msgid="2450970399023478055">"HDMI"</string> + <string name="default_audio_route_name_hdmi" msgid="1486254205617081251">"HDMI"</string> + <string name="default_audio_route_name_headphones" msgid="8119971843803439110">"Heyrnartól"</string> + <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 611a9a1a6454..e2c99e7d61d9 100644 --- a/core/res/res/values-it/strings.xml +++ b/core/res/res/values-it/strings.xml @@ -1420,9 +1420,10 @@ <string name="default_audio_route_name" product="tablet" msgid="4617053898167127471">"Tablet"</string> <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_headphones" msgid="8119971843803439110">"Cuffie audio"</string> <string name="default_audio_route_name_dock_speakers" msgid="6240602982276591864">"Altoparlanti dock"</string> - <string name="default_media_route_name_hdmi" msgid="2450970399023478055">"HDMI"</string> + <string name="default_audio_route_name_hdmi" msgid="1486254205617081251">"HDMI"</string> + <string name="default_audio_route_name_headphones" msgid="8119971843803439110">"Cuffie audio"</string> + <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 40aeba43a426..1eb1e6625357 100644 --- a/core/res/res/values-iw/strings.xml +++ b/core/res/res/values-iw/strings.xml @@ -1466,9 +1466,10 @@ <string name="default_audio_route_name" product="tablet" msgid="4617053898167127471">"טאבלט"</string> <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_headphones" msgid="8119971843803439110">"אוזניות"</string> <string name="default_audio_route_name_dock_speakers" msgid="6240602982276591864">"רמקולים של מעגן"</string> - <string name="default_media_route_name_hdmi" msgid="2450970399023478055">"HDMI"</string> + <string name="default_audio_route_name_hdmi" msgid="1486254205617081251">"HDMI"</string> + <string name="default_audio_route_name_headphones" msgid="8119971843803439110">"אוזניות"</string> + <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 aa86db3accac..76caa1c7fc2f 100644 --- a/core/res/res/values-ja/strings.xml +++ b/core/res/res/values-ja/strings.xml @@ -1420,9 +1420,10 @@ <string name="default_audio_route_name" product="tablet" msgid="4617053898167127471">"タブレット"</string> <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_headphones" msgid="8119971843803439110">"ヘッドホン"</string> <string name="default_audio_route_name_dock_speakers" msgid="6240602982276591864">"ホルダーのスピーカー"</string> - <string name="default_media_route_name_hdmi" msgid="2450970399023478055">"HDMI"</string> + <string name="default_audio_route_name_hdmi" msgid="1486254205617081251">"HDMI"</string> + <string name="default_audio_route_name_headphones" msgid="8119971843803439110">"ヘッドホン"</string> + <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 ea993378e5ed..2149ded4fa16 100644 --- a/core/res/res/values-ka/strings.xml +++ b/core/res/res/values-ka/strings.xml @@ -1420,9 +1420,10 @@ <string name="default_audio_route_name" product="tablet" msgid="4617053898167127471">"ტაბლეტი"</string> <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_headphones" msgid="8119971843803439110">"ყურსასმენები"</string> <string name="default_audio_route_name_dock_speakers" msgid="6240602982276591864">"სპიკერების მიმაგრება"</string> - <string name="default_media_route_name_hdmi" msgid="2450970399023478055">"HDMI"</string> + <string name="default_audio_route_name_hdmi" msgid="1486254205617081251">"HDMI"</string> + <string name="default_audio_route_name_headphones" msgid="8119971843803439110">"ყურსასმენები"</string> + <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 d02dc0e4f69a..8e421de5e5b2 100644 --- a/core/res/res/values-kk/strings.xml +++ b/core/res/res/values-kk/strings.xml @@ -1420,9 +1420,10 @@ <string name="default_audio_route_name" product="tablet" msgid="4617053898167127471">"Планшет"</string> <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_headphones" msgid="8119971843803439110">"Құлақаспаптар"</string> <string name="default_audio_route_name_dock_speakers" msgid="6240602982276591864">"Үндеткіштерді қондыру"</string> - <string name="default_media_route_name_hdmi" msgid="2450970399023478055">"HDMI"</string> + <string name="default_audio_route_name_hdmi" msgid="1486254205617081251">"HDMI"</string> + <string name="default_audio_route_name_headphones" msgid="8119971843803439110">"Құлақаспаптар"</string> + <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 38ee22f1e248..910f42cf57ff 100644 --- a/core/res/res/values-km/strings.xml +++ b/core/res/res/values-km/strings.xml @@ -1422,9 +1422,10 @@ <string name="default_audio_route_name" product="tablet" msgid="4617053898167127471">"កុំព្យូទ័របន្ទះ"</string> <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_headphones" msgid="8119971843803439110">"កាស"</string> <string name="default_audio_route_name_dock_speakers" msgid="6240602982276591864">"ភ្ជាប់អូប៉ាល័រ"</string> - <string name="default_media_route_name_hdmi" msgid="2450970399023478055">"HDMI"</string> + <string name="default_audio_route_name_hdmi" msgid="1486254205617081251">"HDMI"</string> + <string name="default_audio_route_name_headphones" msgid="8119971843803439110">"កាស"</string> + <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 5116c5d0810d..5db847f0909e 100644 --- a/core/res/res/values-kn/strings.xml +++ b/core/res/res/values-kn/strings.xml @@ -1420,9 +1420,10 @@ <string name="default_audio_route_name" product="tablet" msgid="4617053898167127471">"ಟ್ಯಾಬ್ಲೆಟ್"</string> <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_headphones" msgid="8119971843803439110">"ಹೆಡ್ಫೋನ್ಗಳು"</string> <string name="default_audio_route_name_dock_speakers" msgid="6240602982276591864">"ಡಾಕ್ ಸ್ಪೀಕರ್ಗಳು"</string> - <string name="default_media_route_name_hdmi" msgid="2450970399023478055">"HDMI"</string> + <string name="default_audio_route_name_hdmi" msgid="1486254205617081251">"HDMI"</string> + <string name="default_audio_route_name_headphones" msgid="8119971843803439110">"ಹೆಡ್ಫೋನ್ಗಳು"</string> + <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 722b25156f0c..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> @@ -1420,9 +1420,10 @@ <string name="default_audio_route_name" product="tablet" msgid="4617053898167127471">"태블릿"</string> <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_headphones" msgid="8119971843803439110">"헤드폰"</string> <string name="default_audio_route_name_dock_speakers" msgid="6240602982276591864">"도크 스피커"</string> - <string name="default_media_route_name_hdmi" msgid="2450970399023478055">"HDMI"</string> + <string name="default_audio_route_name_hdmi" msgid="1486254205617081251">"HDMI"</string> + <string name="default_audio_route_name_headphones" msgid="8119971843803439110">"헤드폰"</string> + <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 9cf927e1ddc7..25958bff8c8a 100644 --- a/core/res/res/values-ky/strings.xml +++ b/core/res/res/values-ky/strings.xml @@ -1421,9 +1421,10 @@ <string name="default_audio_route_name" product="tablet" msgid="4617053898167127471">"Планшет"</string> <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_headphones" msgid="8119971843803439110">"Кулакчын"</string> <string name="default_audio_route_name_dock_speakers" msgid="6240602982276591864">"Аудио док бекет"</string> - <string name="default_media_route_name_hdmi" msgid="2450970399023478055">"HDMI"</string> + <string name="default_audio_route_name_hdmi" msgid="1486254205617081251">"HDMI"</string> + <string name="default_audio_route_name_headphones" msgid="8119971843803439110">"Кулакчын"</string> + <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 27601af1f8a6..8c6b80735a5c 100644 --- a/core/res/res/values-lo/strings.xml +++ b/core/res/res/values-lo/strings.xml @@ -1420,9 +1420,10 @@ <string name="default_audio_route_name" product="tablet" msgid="4617053898167127471">"ແທັບເລັດ"</string> <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_headphones" msgid="8119971843803439110">"ຫູຟັງ"</string> <string name="default_audio_route_name_dock_speakers" msgid="6240602982276591864">"ບ່ອນຕັ້ງລຳໂພງ"</string> - <string name="default_media_route_name_hdmi" msgid="2450970399023478055">"HDMI"</string> + <string name="default_audio_route_name_hdmi" msgid="1486254205617081251">"HDMI"</string> + <string name="default_audio_route_name_headphones" msgid="8119971843803439110">"ຫູຟັງ"</string> + <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 9e807b03ebe5..3f6cddf98616 100644 --- a/core/res/res/values-lt/strings.xml +++ b/core/res/res/values-lt/strings.xml @@ -1466,9 +1466,10 @@ <string name="default_audio_route_name" product="tablet" msgid="4617053898167127471">"Planšetinis kompiuteris"</string> <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_headphones" msgid="8119971843803439110">"Ausinės"</string> <string name="default_audio_route_name_dock_speakers" msgid="6240602982276591864">"Doko garsiakalbiai"</string> - <string name="default_media_route_name_hdmi" msgid="2450970399023478055">"HDMI"</string> + <string name="default_audio_route_name_hdmi" msgid="1486254205617081251">"HDMI"</string> + <string name="default_audio_route_name_headphones" msgid="8119971843803439110">"Ausinės"</string> + <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 5058d43d6393..0afd3e773c86 100644 --- a/core/res/res/values-lv/strings.xml +++ b/core/res/res/values-lv/strings.xml @@ -1443,9 +1443,10 @@ <string name="default_audio_route_name" product="tablet" msgid="4617053898167127471">"Planšetdators"</string> <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_headphones" msgid="8119971843803439110">"Austiņas"</string> <string name="default_audio_route_name_dock_speakers" msgid="6240602982276591864">"Doka skaļruņi"</string> - <string name="default_media_route_name_hdmi" msgid="2450970399023478055">"HDMI"</string> + <string name="default_audio_route_name_hdmi" msgid="1486254205617081251">"HDMI"</string> + <string name="default_audio_route_name_headphones" msgid="8119971843803439110">"Austiņas"</string> + <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 ef5430c3a35d..df755eab834e 100644 --- a/core/res/res/values-mk/strings.xml +++ b/core/res/res/values-mk/strings.xml @@ -1422,9 +1422,10 @@ <string name="default_audio_route_name" product="tablet" msgid="4617053898167127471">"Таблет"</string> <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_headphones" msgid="8119971843803439110">"Слушалки"</string> <string name="default_audio_route_name_dock_speakers" msgid="6240602982276591864">"Приклучи звучници"</string> - <string name="default_media_route_name_hdmi" msgid="2450970399023478055">"ХДМИ"</string> + <string name="default_audio_route_name_hdmi" msgid="1486254205617081251">"HDMI"</string> + <string name="default_audio_route_name_headphones" msgid="8119971843803439110">"Слушалки"</string> + <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 68501191e393..488eba853431 100644 --- a/core/res/res/values-ml/strings.xml +++ b/core/res/res/values-ml/strings.xml @@ -1189,7 +1189,7 @@ <string name="usb_notification_message" msgid="3370903770828407960">"കൂടുതൽ ഓപ്ഷനുകൾക്ക് ടാപ്പുചെയ്യുക."</string> <string name="usb_unsupported_audio_accessory_title" msgid="3529881374464628084">"അനലോഗ് ഓഡിയോ ആക്സസറി കണ്ടെത്തി"</string> <string name="usb_unsupported_audio_accessory_message" msgid="6309553946441565215">"അറ്റാച്ചുചെയ്ത ഉപകരണം ഈ ഫോണിന് അനുയോജ്യമല്ല. കൂടുതലറിയാൻ ടാപ്പുചെയ്യുക."</string> - <string name="adb_active_notification_title" msgid="6729044778949189918">"USB ഡീബഗ്ഗിംഗ് കണക്റ്റുചെയ്തു"</string> + <string name="adb_active_notification_title" msgid="6729044778949189918">"USB ഡീബഗ്ഗിംഗ് കണക്റ്റ് ചെയ്തു"</string> <string name="adb_active_notification_message" msgid="4948470599328424059">"USB ഡീബഗ്ഗിംഗ് പ്രവർത്തനരഹിതമാക്കാൻ ടാപ്പുചെയ്യുക."</string> <string name="adb_active_notification_message" product="tv" msgid="8470296818270110396">"USB ഡീബഗ്ഗുചെയ്യൽ പ്രവർത്തനരഹിതമാക്കാൻ തിരഞ്ഞെടുക്കുക."</string> <string name="taking_remote_bugreport_notification_title" msgid="6742483073875060934">"ബഗ് റിപ്പോർട്ട് എടുക്കുന്നു…"</string> @@ -1420,9 +1420,10 @@ <string name="default_audio_route_name" product="tablet" msgid="4617053898167127471">"ടാബ്ലെറ്റ്"</string> <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_headphones" msgid="8119971843803439110">"ഹെഡ്ഫോണുകൾ"</string> <string name="default_audio_route_name_dock_speakers" msgid="6240602982276591864">"ഡോക്ക് സ്പീക്കറുകൾ"</string> - <string name="default_media_route_name_hdmi" msgid="2450970399023478055">"HDMI"</string> + <string name="default_audio_route_name_hdmi" msgid="1486254205617081251">"HDMI"</string> + <string name="default_audio_route_name_headphones" msgid="8119971843803439110">"ഹെഡ്ഫോണുകൾ"</string> + <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 319ea011874f..e58193216c4c 100644 --- a/core/res/res/values-mn/strings.xml +++ b/core/res/res/values-mn/strings.xml @@ -1420,9 +1420,10 @@ <string name="default_audio_route_name" product="tablet" msgid="4617053898167127471">"Таблет"</string> <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_headphones" msgid="8119971843803439110">"Чихэвч"</string> <string name="default_audio_route_name_dock_speakers" msgid="6240602982276591864">"Чанга яригчийг суулгах"</string> - <string name="default_media_route_name_hdmi" msgid="2450970399023478055">"HDMI"</string> + <string name="default_audio_route_name_hdmi" msgid="1486254205617081251">"HDMI"</string> + <string name="default_audio_route_name_headphones" msgid="8119971843803439110">"Чихэвч"</string> + <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 8436eb454d63..2cf3ec829845 100644 --- a/core/res/res/values-mr/strings.xml +++ b/core/res/res/values-mr/strings.xml @@ -1420,9 +1420,10 @@ <string name="default_audio_route_name" product="tablet" msgid="4617053898167127471">"टॅबलेट"</string> <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_headphones" msgid="8119971843803439110">"हेडफोन"</string> <string name="default_audio_route_name_dock_speakers" msgid="6240602982276591864">"स्पीकर डॉक करा"</string> - <string name="default_media_route_name_hdmi" msgid="2450970399023478055">"HDMI"</string> + <string name="default_audio_route_name_hdmi" msgid="1486254205617081251">"HDMI"</string> + <string name="default_audio_route_name_headphones" msgid="8119971843803439110">"हेडफोन"</string> + <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 67d81d439318..612bc0f7387c 100644 --- a/core/res/res/values-ms/strings.xml +++ b/core/res/res/values-ms/strings.xml @@ -1420,9 +1420,10 @@ <string name="default_audio_route_name" product="tablet" msgid="4617053898167127471">"Tablet"</string> <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_headphones" msgid="8119971843803439110">"Fon kepala"</string> <string name="default_audio_route_name_dock_speakers" msgid="6240602982276591864">"Pembesar suara dok"</string> - <string name="default_media_route_name_hdmi" msgid="2450970399023478055">"HDMI"</string> + <string name="default_audio_route_name_hdmi" msgid="1486254205617081251">"HDMI"</string> + <string name="default_audio_route_name_headphones" msgid="8119971843803439110">"Fon kepala"</string> + <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 d4325057468d..7c2277865daf 100644 --- a/core/res/res/values-my/strings.xml +++ b/core/res/res/values-my/strings.xml @@ -1420,9 +1420,10 @@ <string name="default_audio_route_name" product="tablet" msgid="4617053898167127471">"တက်ဘလက်"</string> <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_headphones" msgid="8119971843803439110">"နားကြပ်"</string> <string name="default_audio_route_name_dock_speakers" msgid="6240602982276591864">"အထိုင်ရှိသော စပီကာများ"</string> - <string name="default_media_route_name_hdmi" msgid="2450970399023478055">"HDMI"</string> + <string name="default_audio_route_name_hdmi" msgid="1486254205617081251">"HDMI"</string> + <string name="default_audio_route_name_headphones" msgid="8119971843803439110">"နားကြပ်"</string> + <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 07a622cddeb3..8b1f80435387 100644 --- a/core/res/res/values-nb/strings.xml +++ b/core/res/res/values-nb/strings.xml @@ -1420,9 +1420,10 @@ <string name="default_audio_route_name" product="tablet" msgid="4617053898167127471">"Nettbrett"</string> <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_headphones" msgid="8119971843803439110">"Hodetelefoner"</string> <string name="default_audio_route_name_dock_speakers" msgid="6240602982276591864">"Dokkhøyttalere"</string> - <string name="default_media_route_name_hdmi" msgid="2450970399023478055">"HDMI"</string> + <string name="default_audio_route_name_hdmi" msgid="1486254205617081251">"HDMI"</string> + <string name="default_audio_route_name_headphones" msgid="8119971843803439110">"Hodetelefoner"</string> + <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 581f34410cda..a0f0065d7041 100644 --- a/core/res/res/values-ne/strings.xml +++ b/core/res/res/values-ne/strings.xml @@ -1426,9 +1426,10 @@ <string name="default_audio_route_name" product="tablet" msgid="4617053898167127471">"ट्याब्लेट"</string> <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_headphones" msgid="8119971843803439110">"हेडफोनहरू"</string> <string name="default_audio_route_name_dock_speakers" msgid="6240602982276591864">"डक स्पिकरहरू"</string> - <string name="default_media_route_name_hdmi" msgid="2450970399023478055">"HDMI"</string> + <string name="default_audio_route_name_hdmi" msgid="1486254205617081251">"HDMI"</string> + <string name="default_audio_route_name_headphones" msgid="8119971843803439110">"हेडफोनहरू"</string> + <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 45dd701bb24c..39810e4ac052 100644 --- a/core/res/res/values-nl/strings.xml +++ b/core/res/res/values-nl/strings.xml @@ -1420,9 +1420,10 @@ <string name="default_audio_route_name" product="tablet" msgid="4617053898167127471">"Tablet"</string> <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_headphones" msgid="8119971843803439110">"Hoofdtelefoon"</string> <string name="default_audio_route_name_dock_speakers" msgid="6240602982276591864">"Dockluidsprekers"</string> - <string name="default_media_route_name_hdmi" msgid="2450970399023478055">"HDMI"</string> + <string name="default_audio_route_name_hdmi" msgid="1486254205617081251">"HDMI"</string> + <string name="default_audio_route_name_headphones" msgid="8119971843803439110">"Hoofdtelefoon"</string> + <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 bc09332a3e38..719eb97cc980 100644 --- a/core/res/res/values-pa/strings.xml +++ b/core/res/res/values-pa/strings.xml @@ -340,7 +340,7 @@ <string name="permdesc_systemAlertWindow" msgid="2393776099672266188">"ਇਹ ਐਪ ਹੋਰ ਐਪਾਂ ਦੇ ਸਿਖਰ \'ਤੇ ਜਾਂ ਸਕ੍ਰੀਨ ਦੇ ਹੋਰ ਭਾਗਾਂ \'ਤੇ ਵਿਖਾਈ ਦੇ ਸਕਦੀ ਹੈ। ਇਹ ਸਧਾਰਨ ਐਪ ਵਰਤੋਂ ਵਿੱਚ ਵਿਘਨ ਪਾ ਸਕਦੀ ਹੈ ਅਤੇ ਹੋਰ ਐਪਾਂ ਦੇ ਵਿਖਾਈ ਦੇਣ ਦੇ ਤਰੀਕੇ ਨੂੰ ਬਦਲ ਸਕਦੀ ਹੈ।"</string> <string name="permlab_runInBackground" msgid="7365290743781858803">"ਬੈਕਗ੍ਰਾਊਂਡ ਵਿੱਚ ਚਲਾਓ"</string> <string name="permdesc_runInBackground" msgid="7370142232209999824">"ਇਹ ਐਪ ਬੈਕਗ੍ਰਾਊਂਡ ਵਿੱਚ ਚੱਲ ਸਕਦੀ ਹੈ। ਇਸ ਨਾਲ ਬੈਟਰੀ ਵਧੇਰੇ ਤੇਜ਼ੀ ਨਾਲ ਖਤਮ ਹੋ ਸਕਦੀ ਹੈ।"</string> - <string name="permlab_useDataInBackground" msgid="8694951340794341809">"ਬੈਕਗ੍ਰਾਊਂਡ ਵਿੱਚ ਡੈਟੇ ਦੀ ਵਰਤੋਂ ਕਰੋ"</string> + <string name="permlab_useDataInBackground" msgid="8694951340794341809">"ਬੈਕਗ੍ਰਾਊਂਡ ਵਿੱਚ ਡਾਟੇ ਦੀ ਵਰਤੋਂ ਕਰੋ"</string> <string name="permdesc_useDataInBackground" msgid="6049514223791806027">"ਇਹ ਐਪ ਬੈਕਗ੍ਰਾਊਂਡ ਵਿੱਚ ਡਾਟੇ ਦੀ ਵਰਤੋਂ ਕਰ ਸਕਦੀ ਹੈ। ਇਸ ਨਾਲ ਡਾਟਾ ਵਰਤੋਂ ਵਧ ਸਕਦੀ ਹੈ।"</string> <string name="permlab_persistentActivity" msgid="8841113627955563938">"ਐਪ ਨੂੰ ਹਮੇਸ਼ਾਂ ਚਲਾਏ ਰੱਖੋ"</string> <string name="permdesc_persistentActivity" product="tablet" msgid="8525189272329086137">"ਐਪ ਨੂੰ ਮੈਮਰੀ ਵਿੱਚ ਖੁਦ ਦੇ ਭਾਗਾਂ ਨੂੰ ਸਥਾਈ ਬਣਾਉਣ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ। ਇਹ ਟੈਬਲੈੱਟ ਨੂੰ ਹੌਲੀ ਕਰਦੇ ਹੋਏ ਹੋਰਾਂ ਐਪਾਂ ਲਈ ਉਪਲਬਧ ਮੈਮਰੀ ਨੂੰ ਸੀਮਿਤ ਕਰ ਸਕਦਾ ਹੈ।"</string> @@ -552,10 +552,10 @@ <string name="policydesc_limitPassword" msgid="2502021457917874968">"ਸਕ੍ਰੀਨ ਲਾਕ ਪਾਸਵਰਡਾਂ ਅਤੇ ਪਿੰਨ ਵਿੱਚ ਆਗਿਆ ਦਿੱਤੀ ਲੰਮਾਈ ਅਤੇ ਅੱਖਰਾਂ ਤੇ ਨਿਯੰਤਰਣ ਪਾਓ।"</string> <string name="policylab_watchLogin" msgid="5091404125971980158">"ਸਕ੍ਰੀਨ ਅਣਲਾਕ ਕਰਨ ਦੀਆਂ ਕੋਸ਼ਿਸ਼ਾਂ \'ਤੇ ਨਿਗਰਾਨੀ ਰੱਖੋ"</string> <string name="policydesc_watchLogin" product="tablet" msgid="3215729294215070072">"ਸਕ੍ਰੀਨ ਨੂੰ ਅਣਲਾਕ ਕਰਦੇ ਹੋਏ ਟਾਈਪ ਕੀਤੇ ਗਲਤ ਪਾਸਵਰਡਾਂ ਦੀ ਸੰਖਿਆ ਦਾ ਨਿਰੀਖਣ ਕਰੋ ਅਤੇ ਟੈਬਲੈੱਟ ਨੂੰ ਲਾਕ ਕਰੋ ਜਾਂ ਟੈਬਲੈੱਟ ਦਾ ਸਾਰਾ ਡਾਟਾ ਮਿਟਾਓ, ਜੇਕਰ ਬਹੁਤ ਜ਼ਿਆਦਾ ਗਲਤ ਪਾਸਵਰਡ ਟਾਈਪ ਕੀਤੇ ਹਨ।"</string> - <string name="policydesc_watchLogin" product="TV" msgid="2707817988309890256">"ਸਕ੍ਰੀਨ ਨੂੰ ਅਨਲੌਕ ਕਰਦੇ ਸਮੇਂ ਟਾਈਪ ਕੀਤੇ ਗ਼ਲਤ ਪਾਸਵਰਡਾਂ ਦੀ ਸੰਖਿਆ ਦਾ ਨਿਰੀਖਣ ਕਰੋ ਅਤੇ TV ਨੂੰ ਲੌਕ ਕਰੋ ਜਾਂ TV ਦਾ ਸਾਰਾ ਡਾਟਾ ਮਿਟਾਓ ਜੇਕਰ ਬਹੁਤ ਜ਼ਿਆਦਾ ਗ਼ਲਤ ਪਾਸਵਰਡ ਟਾਈਪ ਕੀਤੇ ਹਨ।"</string> + <string name="policydesc_watchLogin" product="TV" msgid="2707817988309890256">"ਸਕ੍ਰੀਨ ਨੂੰ ਅਣਲਾਕ ਕਰਦੇ ਸਮੇਂ ਟਾਈਪ ਕੀਤੇ ਗ਼ਲਤ ਪਾਸਵਰਡਾਂ ਦੀ ਸੰਖਿਆ ਦਾ ਨਿਰੀਖਣ ਕਰੋ ਅਤੇ TV ਨੂੰ ਲੌਕ ਕਰੋ ਜਾਂ TV ਦਾ ਸਾਰਾ ਡਾਟਾ ਮਿਟਾਓ ਜੇਕਰ ਬਹੁਤ ਜ਼ਿਆਦਾ ਗ਼ਲਤ ਪਾਸਵਰਡ ਟਾਈਪ ਕੀਤੇ ਹਨ।"</string> <string name="policydesc_watchLogin" product="default" msgid="5712323091846761073">"ਸਕ੍ਰੀਨ ਨੂੰ ਅਣਲਾਕ ਕਰਦੇ ਸਮੇਂ ਟਾਈਪ ਕੀਤੇ ਗਲਤ ਪਾਸਵਰਡਾਂ ਦੀ ਸੰਖਿਆ ਦਾ ਨਿਰੀਖਣ ਕਰੋ ਅਤੇ ਫ਼ੋਨ ਨੂੰ ਲਾਕ ਕਰੋ ਜਾਂ ਫ਼ੋਨ ਦਾ ਸਾਰਾ ਡਾਟਾ ਮਿਟਾਓ ਜੇਕਰ ਬਹੁਤ ਜ਼ਿਆਦਾ ਗਲਤ ਪਾਸਵਰਡ ਟਾਈਪ ਕੀਤੇ ਹਨ।"</string> <string name="policydesc_watchLogin_secondaryUser" product="tablet" msgid="4280246270601044505">"ਸਕ੍ਰੀਨ ਨੂੰ ਅਣਲਾਕ ਕਰਦੇ ਹੋਏ ਟਾਈਪ ਕੀਤੇ ਗਲਤ ਪਾਸਵਰਡਾਂ ਦੀ ਸੰਖਿਆ ਦਾ ਨਿਰੀਖਣ ਕਰੋ ਅਤੇ ਟੈਬਲੈੱਟ ਨੂੰ ਲਾਕ ਕਰੋ ਜਾਂ ਟੈਬਲੈੱਟ ਦਾ ਸਾਰਾ ਡਾਟਾ ਮਿਟਾਓ, ਜੇਕਰ ਬਹੁਤ ਜ਼ਿਆਦਾ ਗਲਤ ਪਾਸਵਰਡ ਟਾਈਪ ਕੀਤੇ ਹਨ।"</string> - <string name="policydesc_watchLogin_secondaryUser" product="TV" msgid="3484832653564483250">"ਸਕ੍ਰੀਨ ਨੂੰ ਅਨਲੌਕ ਕਰਦੇ ਸਮੇਂ ਟਾਈਪ ਕੀਤੇ ਗ਼ਲਤ ਪਾਸਵਰਡਾਂ ਦੀ ਸੰਖਿਆ ਦਾ ਨਿਰੀਖਣ ਕਰੋ ਅਤੇ TV ਨੂੰ ਲੌਕ ਕਰੋ ਜਾਂ TV ਦਾ ਸਾਰਾ ਡਾਟਾ ਮਿਟਾਓ ਜੇਕਰ ਬਹੁਤ ਜ਼ਿਆਦਾ ਗ਼ਲਤ ਪਾਸਵਰਡ ਟਾਈਪ ਕੀਤੇ ਹਨ।"</string> + <string name="policydesc_watchLogin_secondaryUser" product="TV" msgid="3484832653564483250">"ਸਕ੍ਰੀਨ ਨੂੰ ਅਣਲਾਕ ਕਰਦੇ ਸਮੇਂ ਟਾਈਪ ਕੀਤੇ ਗ਼ਲਤ ਪਾਸਵਰਡਾਂ ਦੀ ਸੰਖਿਆ ਦਾ ਨਿਰੀਖਣ ਕਰੋ ਅਤੇ TV ਨੂੰ ਲੌਕ ਕਰੋ ਜਾਂ TV ਦਾ ਸਾਰਾ ਡਾਟਾ ਮਿਟਾਓ ਜੇਕਰ ਬਹੁਤ ਜ਼ਿਆਦਾ ਗ਼ਲਤ ਪਾਸਵਰਡ ਟਾਈਪ ਕੀਤੇ ਹਨ।"</string> <string name="policydesc_watchLogin_secondaryUser" product="default" msgid="2185480427217127147">"ਸਕ੍ਰੀਨ ਨੂੰ ਅਣਲਾਕ ਕਰਦੇ ਸਮੇਂ ਟਾਈਪ ਕੀਤੇ ਗਲਤ ਪਾਸਵਰਡਾਂ ਦੀ ਸੰਖਿਆ ਦਾ ਨਿਰੀਖਣ ਕਰੋ ਅਤੇ ਫ਼ੋਨ ਨੂੰ ਲਾਕ ਕਰੋ ਜਾਂ ਫ਼ੋਨ ਦਾ ਸਾਰਾ ਡਾਟਾ ਮਿਟਾਓ ਜੇਕਰ ਬਹੁਤ ਜ਼ਿਆਦਾ ਗਲਤ ਪਾਸਵਰਡ ਟਾਈਪ ਕੀਤੇ ਹਨ।"</string> <string name="policylab_resetPassword" msgid="4934707632423915395">"ਸਕ੍ਰੀਨ ਲੌਕ ਬਦਲੋ"</string> <string name="policydesc_resetPassword" msgid="1278323891710619128">"ਸਕ੍ਰੀਨ ਲੌਕ ਬਦਲੋ।"</string> @@ -735,7 +735,7 @@ <string name="lockscreen_sim_puk_locked_message" msgid="7441797339976230">"SIM ਕਾਰਡ PUK-ਲੌਕਡ ਹੈ।"</string> <string name="lockscreen_sim_puk_locked_instructions" msgid="8127916255245181063">"ਵਰਤੋਂਕਾਰ ਗਾਈਡ ਦੇਖੋ ਜਾਂ ਗਾਹਕ ਸੇਵਾ ਨੂੰ ਫ਼ੋਨ ਕਰੋ।"</string> <string name="lockscreen_sim_locked_message" msgid="8066660129206001039">"SIM ਕਾਰਡ ਲੌਕ ਕੀਤਾ ਹੋਇਆ ਹੈ।"</string> - <string name="lockscreen_sim_unlock_progress_dialog_message" msgid="595323214052881264">"SIM ਕਾਰਡ ਅਨਲੌਕ ਕਰ ਰਿਹਾ ਹੈ…"</string> + <string name="lockscreen_sim_unlock_progress_dialog_message" msgid="595323214052881264">"SIM ਕਾਰਡ ਅਣਲਾਕ ਕਰ ਰਿਹਾ ਹੈ…"</string> <string name="lockscreen_too_many_failed_attempts_dialog_message" msgid="6481623830344107222">"ਤੁਸੀਂ <xliff:g id="NUMBER_0">%1$d</xliff:g> ਵਾਰ ਆਪਣਾ ਅਣਲਾਕ ਪੈਟਰਨ ਗਲਤ ਢੰਗ ਨਾਲ ਉਲੀਕਿਆ ਹੈ। \n\n<xliff:g id="NUMBER_1">%2$d</xliff:g> ਸਕਿੰਟਾਂ ਵਿੱਚ ਦੁਬਾਰਾ ਕੋਸ਼ਿਸ਼ ਕਰੋ।"</string> <string name="lockscreen_too_many_failed_password_attempts_dialog_message" msgid="2725973286239344555">"ਤੁਸੀਂ <xliff:g id="NUMBER_0">%1$d</xliff:g> ਵਾਰ ਆਪਣਾ ਪਾਸਵਰਡ ਗਲਤ ਢੰਗ ਨਾਲ ਟਾਈਪ ਕੀਤਾ ਹੈ।\n\n<xliff:g id="NUMBER_1">%2$d</xliff:g> ਸਕਿੰਟਾਂ ਵਿੱਚ ਦੁਬਾਰਾ ਕੋਸ਼ਿਸ਼ ਕਰੋ।"</string> <string name="lockscreen_too_many_failed_pin_attempts_dialog_message" msgid="6216672706545696955">"ਤੁਸੀਂ ਆਪਣਾ ਪਿੰਨ <xliff:g id="NUMBER_0">%1$d</xliff:g> ਵਾਰ ਗਲਤ ਢੰਗ ਨਾਲ ਟਾਈਪ ਕੀਤਾ ਹੈ। \n\n<xliff:g id="NUMBER_1">%2$d</xliff:g> ਸਕਿੰਟਾਂ ਵਿੱਚ ਦੁਬਾਰਾ ਕੋਸ਼ਿਸ਼ ਕਰੋ।"</string> @@ -1420,9 +1420,10 @@ <string name="default_audio_route_name" product="tablet" msgid="4617053898167127471">"ਟੈਬਲੈੱਟ"</string> <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_headphones" msgid="8119971843803439110">"ਹੈੱਡਫ਼ੋਨ"</string> <string name="default_audio_route_name_dock_speakers" msgid="6240602982276591864">"ਡੌਕ ਸਪੀਕਰਸ"</string> - <string name="default_media_route_name_hdmi" msgid="2450970399023478055">"HDMI"</string> + <string name="default_audio_route_name_hdmi" msgid="1486254205617081251">"HDMI"</string> + <string name="default_audio_route_name_headphones" msgid="8119971843803439110">"ਹੈੱਡਫ਼ੋਨ"</string> + <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> @@ -1457,7 +1458,7 @@ <string name="kg_puk_enter_puk_hint" msgid="453227143861735537">"ਸਿਮ ਹੁਣ ਬੰਦ ਕੀਤਾ ਗਿਆ ਹੈ। ਜਾਰੀ ਰੱਖਣ ਲਈ PUK ਕੋਡ ਦਾਖਲ ਕਰੋ। ਵੇਰਵਿਆਂ ਲਈ ਕੈਰੀਅਰ ਨਾਲ ਸੰਪਰਕ ਕਰੋ।"</string> <string name="kg_puk_enter_pin_hint" msgid="7871604527429602024">"ਇੱਛਤ ਪਿੰਨ ਕੋਡ ਦਾਖਲ ਕਰੋ"</string> <string name="kg_enter_confirm_pin_hint" msgid="325676184762529976">"ਇੱਛਤ ਪਿੰਨ ਕੋਡ ਦੀ ਪੁਸ਼ਟੀ ਕਰੋ"</string> - <string name="kg_sim_unlock_progress_dialog_message" msgid="8950398016976865762">"SIM ਕਾਰਡ ਅਨਲੌਕ ਕਰ ਰਿਹਾ ਹੈ…"</string> + <string name="kg_sim_unlock_progress_dialog_message" msgid="8950398016976865762">"SIM ਕਾਰਡ ਅਣਲਾਕ ਕਰ ਰਿਹਾ ਹੈ…"</string> <string name="kg_password_wrong_pin_code" msgid="1139324887413846912">"ਗਲਤ ਪਿੰਨ ਕੋਡ।"</string> <string name="kg_invalid_sim_pin_hint" msgid="8795159358110620001">"ਕੋਈ ਪਿੰਨ ਟਾਈਪ ਕਰੋ ਜੋ 4 ਤੋਂ 8 ਨੰਬਰਾਂ ਦਾ ਹੋਵੇ।"</string> <string name="kg_invalid_sim_puk_hint" msgid="6025069204539532000">"PUK ਕੋਡ 8 ਸੰਖਿਆਵਾਂ ਦਾ ਹੋਣਾ ਚਾਹੀਦਾ ਹੈ।"</string> diff --git a/core/res/res/values-pl/strings.xml b/core/res/res/values-pl/strings.xml index 5bca5a95dd13..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> @@ -1466,9 +1466,10 @@ <string name="default_audio_route_name" product="tablet" msgid="4617053898167127471">"Tablet"</string> <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_headphones" msgid="8119971843803439110">"Słuchawki"</string> <string name="default_audio_route_name_dock_speakers" msgid="6240602982276591864">"Głośniki stacji dokującej"</string> - <string name="default_media_route_name_hdmi" msgid="2450970399023478055">"HDMI"</string> + <string name="default_audio_route_name_hdmi" msgid="1486254205617081251">"HDMI"</string> + <string name="default_audio_route_name_headphones" msgid="8119971843803439110">"Słuchawki"</string> + <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 43c0bb177f7c..276add6425be 100644 --- a/core/res/res/values-pt-rBR/strings.xml +++ b/core/res/res/values-pt-rBR/strings.xml @@ -1420,9 +1420,10 @@ <string name="default_audio_route_name" product="tablet" msgid="4617053898167127471">"Tablet"</string> <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_headphones" msgid="8119971843803439110">"Fones de ouvido"</string> <string name="default_audio_route_name_dock_speakers" msgid="6240602982276591864">"Alto-falantes da dock"</string> - <string name="default_media_route_name_hdmi" msgid="2450970399023478055">"HDMI"</string> + <string name="default_audio_route_name_hdmi" msgid="1486254205617081251">"HDMI"</string> + <string name="default_audio_route_name_headphones" msgid="8119971843803439110">"Fones de ouvido"</string> + <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 d130f978c3e6..ac81366a6bd5 100644 --- a/core/res/res/values-pt-rPT/strings.xml +++ b/core/res/res/values-pt-rPT/strings.xml @@ -1420,9 +1420,10 @@ <string name="default_audio_route_name" product="tablet" msgid="4617053898167127471">"Tablet"</string> <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_headphones" msgid="8119971843803439110">"Auscultadores"</string> <string name="default_audio_route_name_dock_speakers" msgid="6240602982276591864">"Altif. estação ancoragem"</string> - <string name="default_media_route_name_hdmi" msgid="2450970399023478055">"HDMI"</string> + <string name="default_audio_route_name_hdmi" msgid="1486254205617081251">"HDMI"</string> + <string name="default_audio_route_name_headphones" msgid="8119971843803439110">"Auscultadores"</string> + <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 43c0bb177f7c..276add6425be 100644 --- a/core/res/res/values-pt/strings.xml +++ b/core/res/res/values-pt/strings.xml @@ -1420,9 +1420,10 @@ <string name="default_audio_route_name" product="tablet" msgid="4617053898167127471">"Tablet"</string> <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_headphones" msgid="8119971843803439110">"Fones de ouvido"</string> <string name="default_audio_route_name_dock_speakers" msgid="6240602982276591864">"Alto-falantes da dock"</string> - <string name="default_media_route_name_hdmi" msgid="2450970399023478055">"HDMI"</string> + <string name="default_audio_route_name_hdmi" msgid="1486254205617081251">"HDMI"</string> + <string name="default_audio_route_name_headphones" msgid="8119971843803439110">"Fones de ouvido"</string> + <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 d49694152cc2..6f310b3d0155 100644 --- a/core/res/res/values-ro/strings.xml +++ b/core/res/res/values-ro/strings.xml @@ -1443,9 +1443,10 @@ <string name="default_audio_route_name" product="tablet" msgid="4617053898167127471">"Tabletă"</string> <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_headphones" msgid="8119971843803439110">"Căști"</string> <string name="default_audio_route_name_dock_speakers" msgid="6240602982276591864">"Difuz. dispozit. andocare"</string> - <string name="default_media_route_name_hdmi" msgid="2450970399023478055">"HDMI"</string> + <string name="default_audio_route_name_hdmi" msgid="1486254205617081251">"HDMI"</string> + <string name="default_audio_route_name_headphones" msgid="8119971843803439110">"Căști"</string> + <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 564dbbb23dbb..1960663f0ab9 100644 --- a/core/res/res/values-ru/strings.xml +++ b/core/res/res/values-ru/strings.xml @@ -1466,9 +1466,10 @@ <string name="default_audio_route_name" product="tablet" msgid="4617053898167127471">"Планшетный ПК"</string> <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_headphones" msgid="8119971843803439110">"Наушники"</string> <string name="default_audio_route_name_dock_speakers" msgid="6240602982276591864">"Динамики док-станции"</string> - <string name="default_media_route_name_hdmi" msgid="2450970399023478055">"HDMI"</string> + <string name="default_audio_route_name_hdmi" msgid="1486254205617081251">"HDMI"</string> + <string name="default_audio_route_name_headphones" msgid="8119971843803439110">"Наушники"</string> + <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 39caed3a91bf..63f2c50c0a78 100644 --- a/core/res/res/values-si/strings.xml +++ b/core/res/res/values-si/strings.xml @@ -1422,9 +1422,10 @@ <string name="default_audio_route_name" product="tablet" msgid="4617053898167127471">"ටැබ්ලට්ය"</string> <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_headphones" msgid="8119971843803439110">"ඉස් බණු"</string> <string name="default_audio_route_name_dock_speakers" msgid="6240602982276591864">"නාදක ඩොක් කරන්න"</string> - <string name="default_media_route_name_hdmi" msgid="2450970399023478055">"HDMI"</string> + <string name="default_audio_route_name_hdmi" msgid="1486254205617081251">"HDMI"</string> + <string name="default_audio_route_name_headphones" msgid="8119971843803439110">"ඉස් බණු"</string> + <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 11b9c88d3a71..9f37618bfc8f 100644 --- a/core/res/res/values-sk/strings.xml +++ b/core/res/res/values-sk/strings.xml @@ -1466,9 +1466,10 @@ <string name="default_audio_route_name" product="tablet" msgid="4617053898167127471">"Tablet"</string> <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_headphones" msgid="8119971843803439110">"Slúchadlá"</string> <string name="default_audio_route_name_dock_speakers" msgid="6240602982276591864">"Reproduktory doku"</string> - <string name="default_media_route_name_hdmi" msgid="2450970399023478055">"HDMI"</string> + <string name="default_audio_route_name_hdmi" msgid="1486254205617081251">"HDMI"</string> + <string name="default_audio_route_name_headphones" msgid="8119971843803439110">"Slúchadlá"</string> + <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 71b7126ab8f7..349e5b1901eb 100644 --- a/core/res/res/values-sl/strings.xml +++ b/core/res/res/values-sl/strings.xml @@ -1466,9 +1466,10 @@ <string name="default_audio_route_name" product="tablet" msgid="4617053898167127471">"Tablični računalnik"</string> <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_headphones" msgid="8119971843803439110">"Slušalke"</string> <string name="default_audio_route_name_dock_speakers" msgid="6240602982276591864">"Zvočniki stojala"</string> - <string name="default_media_route_name_hdmi" msgid="2450970399023478055">"HDMI"</string> + <string name="default_audio_route_name_hdmi" msgid="1486254205617081251">"HDMI"</string> + <string name="default_audio_route_name_headphones" msgid="8119971843803439110">"Slušalke"</string> + <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 3ad574a1bfca..f67c889e34e9 100644 --- a/core/res/res/values-sq/strings.xml +++ b/core/res/res/values-sq/strings.xml @@ -1420,9 +1420,10 @@ <string name="default_audio_route_name" product="tablet" msgid="4617053898167127471">"Tablet"</string> <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_headphones" msgid="8119971843803439110">"Kufjet"</string> <string name="default_audio_route_name_dock_speakers" msgid="6240602982276591864">"Altoparlantët e stacionit"</string> - <string name="default_media_route_name_hdmi" msgid="2450970399023478055">"HDMI"</string> + <string name="default_audio_route_name_hdmi" msgid="1486254205617081251">"HDMI"</string> + <string name="default_audio_route_name_headphones" msgid="8119971843803439110">"Kufjet"</string> + <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 f9b865d2fff2..579a60199e71 100644 --- a/core/res/res/values-sr/strings.xml +++ b/core/res/res/values-sr/strings.xml @@ -1443,9 +1443,10 @@ <string name="default_audio_route_name" product="tablet" msgid="4617053898167127471">"Таблет"</string> <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_headphones" msgid="8119971843803439110">"Слушалице"</string> <string name="default_audio_route_name_dock_speakers" msgid="6240602982276591864">"Звучници базне станице"</string> - <string name="default_media_route_name_hdmi" msgid="2450970399023478055">"HDMI"</string> + <string name="default_audio_route_name_hdmi" msgid="1486254205617081251">"HDMI"</string> + <string name="default_audio_route_name_headphones" msgid="8119971843803439110">"Слушалице"</string> + <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 3f7cecb94fc6..619d498349bb 100644 --- a/core/res/res/values-sv/strings.xml +++ b/core/res/res/values-sv/strings.xml @@ -1420,9 +1420,10 @@ <string name="default_audio_route_name" product="tablet" msgid="4617053898167127471">"Surfplatta"</string> <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_headphones" msgid="8119971843803439110">"Hörlurar"</string> <string name="default_audio_route_name_dock_speakers" msgid="6240602982276591864">"Dockningsstationens högtalare"</string> - <string name="default_media_route_name_hdmi" msgid="2450970399023478055">"HDMI"</string> + <string name="default_audio_route_name_hdmi" msgid="1486254205617081251">"HDMI"</string> + <string name="default_audio_route_name_headphones" msgid="8119971843803439110">"Hörlurar"</string> + <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 8bda7f84f55f..236e467c0db8 100644 --- a/core/res/res/values-sw/strings.xml +++ b/core/res/res/values-sw/strings.xml @@ -1418,9 +1418,10 @@ <string name="default_audio_route_name" product="tablet" msgid="4617053898167127471">"Kompyuta kibao"</string> <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_headphones" msgid="8119971843803439110">"Vipokeasauti"</string> <string name="default_audio_route_name_dock_speakers" msgid="6240602982276591864">"Vipasa sauti vya kituo"</string> - <string name="default_media_route_name_hdmi" msgid="2450970399023478055">"HDMI"</string> + <string name="default_audio_route_name_hdmi" msgid="1486254205617081251">"HDMI"</string> + <string name="default_audio_route_name_headphones" msgid="8119971843803439110">"Vipokeasauti"</string> + <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 9405608cf48a..9c81d0ec49bb 100644 --- a/core/res/res/values-ta/strings.xml +++ b/core/res/res/values-ta/strings.xml @@ -1420,9 +1420,10 @@ <string name="default_audio_route_name" product="tablet" msgid="4617053898167127471">"டேப்லெட்"</string> <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_headphones" msgid="8119971843803439110">"ஹெட்ஃபோன்கள்"</string> <string name="default_audio_route_name_dock_speakers" msgid="6240602982276591864">"மொபைல் வைக்கும் கருவியின் ஸ்பீக்கர்கள்"</string> - <string name="default_media_route_name_hdmi" msgid="2450970399023478055">"HDMI"</string> + <string name="default_audio_route_name_hdmi" msgid="1486254205617081251">"HDMI"</string> + <string name="default_audio_route_name_headphones" msgid="8119971843803439110">"ஹெட்ஃபோன்கள்"</string> + <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 bd984c534cef..5b05a254d1fb 100644 --- a/core/res/res/values-te/strings.xml +++ b/core/res/res/values-te/strings.xml @@ -1420,9 +1420,10 @@ <string name="default_audio_route_name" product="tablet" msgid="4617053898167127471">"టాబ్లెట్"</string> <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_headphones" msgid="8119971843803439110">"హెడ్ఫోన్లు"</string> <string name="default_audio_route_name_dock_speakers" msgid="6240602982276591864">"డాక్ స్పీకర్లు"</string> - <string name="default_media_route_name_hdmi" msgid="2450970399023478055">"HDMI"</string> + <string name="default_audio_route_name_hdmi" msgid="1486254205617081251">"HDMI"</string> + <string name="default_audio_route_name_headphones" msgid="8119971843803439110">"హెడ్ఫోన్లు"</string> + <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 2653dea7f729..05a8b92a6286 100644 --- a/core/res/res/values-th/strings.xml +++ b/core/res/res/values-th/strings.xml @@ -1420,9 +1420,10 @@ <string name="default_audio_route_name" product="tablet" msgid="4617053898167127471">"แท็บเล็ต"</string> <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_headphones" msgid="8119971843803439110">"หูฟัง"</string> <string name="default_audio_route_name_dock_speakers" msgid="6240602982276591864">"ลำโพงแท่นชาร์จ"</string> - <string name="default_media_route_name_hdmi" msgid="2450970399023478055">"HDMI"</string> + <string name="default_audio_route_name_hdmi" msgid="1486254205617081251">"HDMI"</string> + <string name="default_audio_route_name_headphones" msgid="8119971843803439110">"หูฟัง"</string> + <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 da41b9e87ef3..227a28749c2e 100644 --- a/core/res/res/values-tl/strings.xml +++ b/core/res/res/values-tl/strings.xml @@ -1420,9 +1420,10 @@ <string name="default_audio_route_name" product="tablet" msgid="4617053898167127471">"Tablet"</string> <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_headphones" msgid="8119971843803439110">"Mga Headphone"</string> <string name="default_audio_route_name_dock_speakers" msgid="6240602982276591864">"Mga speaker ng dock"</string> - <string name="default_media_route_name_hdmi" msgid="2450970399023478055">"HDMI"</string> + <string name="default_audio_route_name_hdmi" msgid="1486254205617081251">"HDMI"</string> + <string name="default_audio_route_name_headphones" msgid="8119971843803439110">"Mga Headphone"</string> + <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 41a3eae12eca..918d9d670da9 100644 --- a/core/res/res/values-tr/strings.xml +++ b/core/res/res/values-tr/strings.xml @@ -1420,9 +1420,10 @@ <string name="default_audio_route_name" product="tablet" msgid="4617053898167127471">"Tablet"</string> <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_headphones" msgid="8119971843803439110">"Kulaklıklar"</string> <string name="default_audio_route_name_dock_speakers" msgid="6240602982276591864">"Yuva hoparlörleri"</string> - <string name="default_media_route_name_hdmi" msgid="2450970399023478055">"HDMI"</string> + <string name="default_audio_route_name_hdmi" msgid="1486254205617081251">"HDMI"</string> + <string name="default_audio_route_name_headphones" msgid="8119971843803439110">"Kulaklıklar"</string> + <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 f0e2c1dd3bdd..08fdf012cc5f 100644 --- a/core/res/res/values-uk/strings.xml +++ b/core/res/res/values-uk/strings.xml @@ -1466,9 +1466,10 @@ <string name="default_audio_route_name" product="tablet" msgid="4617053898167127471">"Планшетний ПК"</string> <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_headphones" msgid="8119971843803439110">"Навушники"</string> <string name="default_audio_route_name_dock_speakers" msgid="6240602982276591864">"Динаміки док-станції"</string> - <string name="default_media_route_name_hdmi" msgid="2450970399023478055">"HDMI"</string> + <string name="default_audio_route_name_hdmi" msgid="1486254205617081251">"HDMI"</string> + <string name="default_audio_route_name_headphones" msgid="8119971843803439110">"Навушники"</string> + <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 2d9717d4861e..073f7a6948e0 100644 --- a/core/res/res/values-ur/strings.xml +++ b/core/res/res/values-ur/strings.xml @@ -1420,9 +1420,10 @@ <string name="default_audio_route_name" product="tablet" msgid="4617053898167127471">"ٹیبلیٹ"</string> <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_headphones" msgid="8119971843803439110">"ہیڈ فونز"</string> <string name="default_audio_route_name_dock_speakers" msgid="6240602982276591864">"ڈاک اسپیکرز"</string> - <string name="default_media_route_name_hdmi" msgid="2450970399023478055">"HDMI"</string> + <string name="default_audio_route_name_hdmi" msgid="1486254205617081251">"HDMI"</string> + <string name="default_audio_route_name_headphones" msgid="8119971843803439110">"ہیڈ فونز"</string> + <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 f639e800d054..2ad9bd1f02b4 100644 --- a/core/res/res/values-uz/strings.xml +++ b/core/res/res/values-uz/strings.xml @@ -1420,9 +1420,10 @@ <string name="default_audio_route_name" product="tablet" msgid="4617053898167127471">"Planshet"</string> <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_headphones" msgid="8119971843803439110">"Quloq karnaychalari"</string> <string name="default_audio_route_name_dock_speakers" msgid="6240602982276591864">"Taglik karnaylar"</string> - <string name="default_media_route_name_hdmi" msgid="2450970399023478055">"HDMI"</string> + <string name="default_audio_route_name_hdmi" msgid="1486254205617081251">"HDMI"</string> + <string name="default_audio_route_name_headphones" msgid="8119971843803439110">"Quloq karnaychalari"</string> + <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 58e0e34a24eb..e585f77b50da 100644 --- a/core/res/res/values-vi/strings.xml +++ b/core/res/res/values-vi/strings.xml @@ -1420,9 +1420,10 @@ <string name="default_audio_route_name" product="tablet" msgid="4617053898167127471">"Máy tính bảng"</string> <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_headphones" msgid="8119971843803439110">"Tai nghe"</string> <string name="default_audio_route_name_dock_speakers" msgid="6240602982276591864">"Loa đế"</string> - <string name="default_media_route_name_hdmi" msgid="2450970399023478055">"HDMI"</string> + <string name="default_audio_route_name_hdmi" msgid="1486254205617081251">"HDMI"</string> + <string name="default_audio_route_name_headphones" msgid="8119971843803439110">"Tai nghe"</string> + <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 e87f76cdc5ac..5f8d072c446e 100644 --- a/core/res/res/values-zh-rCN/strings.xml +++ b/core/res/res/values-zh-rCN/strings.xml @@ -1420,9 +1420,10 @@ <string name="default_audio_route_name" product="tablet" msgid="4617053898167127471">"平板电脑"</string> <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_headphones" msgid="8119971843803439110">"耳机"</string> <string name="default_audio_route_name_dock_speakers" msgid="6240602982276591864">"基座扬声器"</string> - <string name="default_media_route_name_hdmi" msgid="2450970399023478055">"HDMI"</string> + <string name="default_audio_route_name_hdmi" msgid="1486254205617081251">"HDMI"</string> + <string name="default_audio_route_name_headphones" msgid="8119971843803439110">"耳机"</string> + <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 56ea6a05dc16..d4b3b394055b 100644 --- a/core/res/res/values-zh-rHK/strings.xml +++ b/core/res/res/values-zh-rHK/strings.xml @@ -1420,9 +1420,10 @@ <string name="default_audio_route_name" product="tablet" msgid="4617053898167127471">"平板電腦"</string> <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_headphones" msgid="8119971843803439110">"耳機"</string> <string name="default_audio_route_name_dock_speakers" msgid="6240602982276591864">"插座喇叭"</string> - <string name="default_media_route_name_hdmi" msgid="2450970399023478055">"HDMI"</string> + <string name="default_audio_route_name_hdmi" msgid="1486254205617081251">"HDMI"</string> + <string name="default_audio_route_name_headphones" msgid="8119971843803439110">"耳機"</string> + <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 17c80b5c15f4..de12340f6be5 100644 --- a/core/res/res/values-zh-rTW/strings.xml +++ b/core/res/res/values-zh-rTW/strings.xml @@ -1420,9 +1420,10 @@ <string name="default_audio_route_name" product="tablet" msgid="4617053898167127471">"平板電腦"</string> <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_headphones" msgid="8119971843803439110">"耳機"</string> <string name="default_audio_route_name_dock_speakers" msgid="6240602982276591864">"座架喇叭"</string> - <string name="default_media_route_name_hdmi" msgid="2450970399023478055">"HDMI"</string> + <string name="default_audio_route_name_hdmi" msgid="1486254205617081251">"HDMI"</string> + <string name="default_audio_route_name_headphones" msgid="8119971843803439110">"耳機"</string> + <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 88fb1d78aa86..9178ed785ae1 100644 --- a/core/res/res/values-zu/strings.xml +++ b/core/res/res/values-zu/strings.xml @@ -1420,9 +1420,10 @@ <string name="default_audio_route_name" product="tablet" msgid="4617053898167127471">"Ithebulethi"</string> <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_headphones" msgid="8119971843803439110">"Ama-headphone"</string> <string name="default_audio_route_name_dock_speakers" msgid="6240602982276591864">"Izipikha ze-Dock"</string> - <string name="default_media_route_name_hdmi" msgid="2450970399023478055">"HDMI"</string> + <string name="default_audio_route_name_hdmi" msgid="1486254205617081251">"HDMI"</string> + <string name="default_audio_route_name_headphones" msgid="8119971843803439110">"Ama-headphone"</string> + <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 83bb443e1b72..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 @@ -1363,7 +1368,7 @@ <!-- The package of the time zone rules updater application. Expected to be the same for all Android devices that support APK-based time zone rule updates. - A package-targeted android.intent.action.timezone.TRIGGER_RULES_UPDATE_CHECK intent + A package-targeted com.android.intent.action.timezone.TRIGGER_RULES_UPDATE_CHECK intent will be sent to the updater app if the system server detects an update to the updater or data app packages. The package referenced here must have the android.permission.UPDATE_TIME_ZONE_RULES @@ -1374,7 +1379,7 @@ <!-- The package of the time zone rules data application. Expected to be configured by OEMs to reference their own priv-app APK package. - A package-targeted android.intent.action.timezone.TRIGGER_RULES_UPDATE_CHECK intent + A package-targeted com.android.intent.action.timezone.TRIGGER_RULES_UPDATE_CHECK intent will be sent to the updater app if the system server detects an update to the updater or data app packages. [This is only used if config_enableUpdateableTimeZoneRules and diff --git a/core/res/res/values/dimens.xml b/core/res/res/values/dimens.xml index 2c64789f2121..16c857894d05 100644 --- a/core/res/res/values/dimens.xml +++ b/core/res/res/values/dimens.xml @@ -346,11 +346,6 @@ <dimen name="notification_text_size">14sp</dimen> <!-- Size of notification text titles (see TextAppearance.StatusBar.EventContent.Title) --> <dimen name="notification_title_text_size">14sp</dimen> - - <!-- Size of notification text (see TextAppearance.StatusBar.EventContent) when colorized --> - <dimen name="notification_text_size_colorized">16sp</dimen> - <!-- Size of notification text titles (see TextAppearance.StatusBar.EventContent.Title) when colorized --> - <dimen name="notification_title_text_size_colorized">20sp</dimen> <!-- Size of smaller notification text (see TextAppearance.StatusBar.EventContent.Line2, Info, Time) --> <dimen name="notification_subtext_size">12sp</dimen> diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml index c4a45ee11098..4f03e7b06d97 100644 --- a/core/res/res/values/symbols.xml +++ b/core/res/res/values/symbols.xml @@ -3027,6 +3027,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" /> @@ -3058,9 +3060,6 @@ <java-symbol type="array" name="config_allowedSystemInstantAppSettings" /> <java-symbol type="array" name="config_allowedSecureInstantAppSettings" /> - <java-symbol type="dimen" name="notification_text_size_colorized" /> - <java-symbol type="dimen" name="notification_title_text_size_colorized" /> - <java-symbol type="bool" name="config_handleVolumeKeysInWindowManager" /> <java-symbol type="dimen" name="config_inCallNotificationVolume" /> <java-symbol type="string" name="config_inCallNotificationSound" /> diff --git a/core/tests/coretests/src/android/text/DynamicLayoutTest.java b/core/tests/coretests/src/android/text/DynamicLayoutTest.java index ed6bfbfa3491..639cefbcf26b 100644 --- a/core/tests/coretests/src/android/text/DynamicLayoutTest.java +++ b/core/tests/coretests/src/android/text/DynamicLayoutTest.java @@ -259,4 +259,21 @@ public class DynamicLayoutTest { assertEquals(2 * textSize, layout.getLineDescent(2)); } } + + @Test + public void testBuilder_defaultTextDirection() { + final DynamicLayout.Builder builder = DynamicLayout.Builder + .obtain("", new TextPaint(), WIDTH); + final DynamicLayout layout = builder.build(); + assertEquals(TextDirectionHeuristics.FIRSTSTRONG_LTR, layout.getTextDirectionHeuristic()); + } + + @Test + public void testBuilder_setTextDirection() { + final DynamicLayout.Builder builder = DynamicLayout.Builder + .obtain("", new TextPaint(), WIDTH) + .setTextDirection(TextDirectionHeuristics.ANYRTL_LTR); + final DynamicLayout layout = builder.build(); + assertEquals(TextDirectionHeuristics.ANYRTL_LTR, layout.getTextDirectionHeuristic()); + } } diff --git a/core/tests/coretests/src/android/text/StaticLayoutTest.java b/core/tests/coretests/src/android/text/StaticLayoutTest.java index defb44ad64d0..078ed76844ac 100644 --- a/core/tests/coretests/src/android/text/StaticLayoutTest.java +++ b/core/tests/coretests/src/android/text/StaticLayoutTest.java @@ -72,7 +72,7 @@ public class StaticLayoutTest { } @Test - public void testBuilder() { + public void testBuilder_textDirection() { { // Obtain. final StaticLayout.Builder builder = StaticLayout.Builder.obtain(LAYOUT_TEXT, 0, @@ -88,8 +88,7 @@ public class StaticLayoutTest { LAYOUT_TEXT.length(), mDefaultPaint, DEFAULT_OUTER_WIDTH); builder.setTextDirection(TextDirectionHeuristics.RTL); final StaticLayout layout = builder.build(); - // Always returns TextDirectionHeuristics.FIRSTSTRONG_LTR. - assertEquals(TextDirectionHeuristics.FIRSTSTRONG_LTR, + assertEquals(TextDirectionHeuristics.RTL, layout.getTextDirectionHeuristic()); } } diff --git a/core/tests/coretests/src/android/widget/RemoteViewsTest.java b/core/tests/coretests/src/android/widget/RemoteViewsTest.java index d26437eafa07..ddf9876d3dae 100644 --- a/core/tests/coretests/src/android/widget/RemoteViewsTest.java +++ b/core/tests/coretests/src/android/widget/RemoteViewsTest.java @@ -20,7 +20,9 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertSame; import static org.junit.Assert.assertTrue; +import android.app.PendingIntent; import android.content.Context; +import android.content.Intent; import android.graphics.Bitmap; import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.Drawable; @@ -382,4 +384,19 @@ public class RemoteViewsTest { RemoteViews.CREATOR.createFromParcel(p); p.recycle(); } + + @Test + public void copyWithBinders() throws Exception { + RemoteViews views = new RemoteViews(mPackage, R.layout.remote_views_test); + for (int i = 1; i < 10; i++) { + PendingIntent pi = PendingIntent.getBroadcast(mContext, 0, + new Intent("android.widget.RemoteViewsTest_" + i), PendingIntent.FLAG_ONE_SHOT); + views.setOnClickPendingIntent(i, pi); + } + try { + new RemoteViews(views); + } catch (Throwable t) { + throw new Exception(t); + } + } } diff --git a/data/etc/platform.xml b/data/etc/platform.xml index 7e245309e756..2333feceb1db 100644 --- a/data/etc/platform.xml +++ b/data/etc/platform.xml @@ -160,6 +160,9 @@ <assign-permission name="android.permission.ACCESS_SURFACE_FLINGER" uid="graphics" /> + <assign-permission name="android.permission.ACCESS_LOWPAN_STATE" uid="lowpan" /> + <assign-permission name="android.permission.MANAGE_LOWPAN_INTERFACES" uid="lowpan" /> + <!-- This is a list of all the libraries available for application code to link against. --> 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/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/OpenGLReadback.cpp b/libs/hwui/OpenGLReadback.cpp index f9a1cc5296d5..2687410897ac 100644 --- a/libs/hwui/OpenGLReadback.cpp +++ b/libs/hwui/OpenGLReadback.cpp @@ -280,6 +280,11 @@ CopyResult OpenGLReadbackImpl::copyImageInto(EGLImageKHR eglImage, bool OpenGLReadbackImpl::copyLayerInto(renderthread::RenderThread& renderThread, GlLayer& layer, SkBitmap* bitmap) { + if (!layer.isRenderable()) { + // layer has never been updated by DeferredLayerUpdater, abort copy + return false; + } + return CopyResult::Success == copyTextureInto(Caches::getInstance(), renderThread.renderState(), layer.getTexture(), layer.getTexTransform(), Rect(), bitmap); 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/RenderNodeDrawable.cpp b/libs/hwui/pipeline/skia/RenderNodeDrawable.cpp index 4ee47afe87fd..47dee9d4e9d8 100644 --- a/libs/hwui/pipeline/skia/RenderNodeDrawable.cpp +++ b/libs/hwui/pipeline/skia/RenderNodeDrawable.cpp @@ -19,6 +19,7 @@ #include "SkiaDisplayList.h" #include "SkiaPipeline.h" #include "utils/TraceUtils.h" +#include <SkPaintFilterCanvas.h> namespace android { namespace uirenderer { @@ -151,6 +152,27 @@ static bool layerNeedsPaint(const LayerProperties& properties, return false; } +class AlphaFilterCanvas : public SkPaintFilterCanvas { +public: + AlphaFilterCanvas(SkCanvas* canvas, float alpha) : SkPaintFilterCanvas(canvas), mAlpha(alpha) {} +protected: + bool onFilter(SkTCopyOnFirstWrite<SkPaint>* paint, Type t) const override { + SkTLazy<SkPaint> defaultPaint; + if (!*paint) { + paint->init(*defaultPaint.init()); + } + paint->writable()->setAlpha((uint8_t)(*paint)->getAlpha()*mAlpha); + return true; + } + void onDrawDrawable(SkDrawable* drawable, const SkMatrix* matrix) override { + // We unroll the drawable using "this" canvas, so that draw calls contained inside will + // get their alpha applied. THe default SkPaintFilterCanvas::onDrawDrawable does not unroll. + drawable->draw(this, matrix); + } +private: + float mAlpha; +}; + void RenderNodeDrawable::drawContent(SkCanvas* canvas) const { RenderNode* renderNode = mRenderNode.get(); float alphaMultiplier = 1.0f; @@ -211,7 +233,14 @@ void RenderNodeDrawable::drawContent(SkCanvas* canvas) const { canvas->restore(); } } else { - displayList->draw(canvas); + if (alphaMultiplier < 1.0f) { + // Non-layer draw for a view with getHasOverlappingRendering=false, will apply + // the alpha to the paint of each nested draw. + AlphaFilterCanvas alphaCanvas(canvas, alphaMultiplier); + displayList->draw(&alphaCanvas); + } else { + displayList->draw(canvas); + } } } } diff --git a/libs/hwui/tests/common/scenes/TvApp.cpp b/libs/hwui/tests/common/scenes/TvApp.cpp new file mode 100644 index 000000000000..04fc2d46f946 --- /dev/null +++ b/libs/hwui/tests/common/scenes/TvApp.cpp @@ -0,0 +1,274 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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 "TestSceneBase.h" +#include "tests/common/BitmapAllocationTestUtils.h" +#include "SkBlendMode.h" + +class TvApp; +class TvAppNoRoundedCorner; +class TvAppColorFilter; +class TvAppNoRoundedCornerColorFilter; + +static bool _TvApp( + BitmapAllocationTestUtils::registerBitmapAllocationScene<TvApp>( + "tvapp", "A dense grid of cards:" + "with rounded corner, using overlay RenderNode for dimming.")); + +static bool _TvAppNoRoundedCorner( + BitmapAllocationTestUtils::registerBitmapAllocationScene<TvAppNoRoundedCorner>( + "tvapp_norc", "A dense grid of cards:" + "no rounded corner, using overlay RenderNode for dimming")); + +static bool _TvAppColorFilter( + BitmapAllocationTestUtils::registerBitmapAllocationScene<TvAppColorFilter>( + "tvapp_cf", "A dense grid of cards:" + "with rounded corner, using ColorFilter for dimming")); + +static bool _TvAppNoRoundedCornerColorFilter( + BitmapAllocationTestUtils::registerBitmapAllocationScene<TvAppNoRoundedCornerColorFilter>( + "tvapp_norc_cf", "A dense grid of cards:" + "no rounded corner, using ColorFilter for dimming")); + +class TvApp : public TestScene { +public: + TvApp(BitmapAllocationTestUtils::BitmapAllocator allocator) + : TestScene() + , mAllocator(allocator) { } + + sp<RenderNode> mBg; + std::vector<sp<RenderNode>> mCards; + std::vector<sp<RenderNode>> mInfoAreas; + std::vector<sp<RenderNode>> mImages; + std::vector<sp<RenderNode>> mOverlays; + std::vector<sk_sp<Bitmap>> mCachedBitmaps; + BitmapAllocationTestUtils::BitmapAllocator mAllocator; + sk_sp<Bitmap> mSingleBitmap; + int mSeed = 0; + int mSeed2 = 0; + + void createContent(int width, int height, Canvas& canvas) override { + mBg = createBitmapNode(canvas, 0xFF9C27B0, 0, 0, width, height); + canvas.drawRenderNode(mBg.get()); + + canvas.insertReorderBarrier(true); + mSingleBitmap = mAllocator(dp(160), dp(120), kRGBA_8888_SkColorType, + [](SkBitmap& skBitmap) { + skBitmap.eraseColor(0xFF0000FF); + }); + + for (int y = dp(18) - dp(178); y < height - dp(18); y += dp(178)) { + bool isFirstCard = true; + for (int x = dp(18); x < width - dp(18); x += dp(178)) { + sp<RenderNode> card = createCard(x, y, dp(160), dp(160), isFirstCard); + isFirstCard = false; + canvas.drawRenderNode(card.get()); + mCards.push_back(card); + } + } + canvas.insertReorderBarrier(false); + } + + void doFrame(int frameNr) override { + size_t numCards = mCards.size(); + for (size_t ci = 0; ci < numCards; ci++) { + updateCard(ci, frameNr); + } + } + +private: + sp<RenderNode> createBitmapNode(Canvas& canvas, SkColor color, int left, int top, + int width, int height) { + return TestUtils::createNode(left, top, left + width , top + height, + [this, width, height, color](RenderProperties& props, Canvas& canvas) { + sk_sp<Bitmap> bitmap = mAllocator(width, height, kRGBA_8888_SkColorType, + [color](SkBitmap& skBitmap) { + skBitmap.eraseColor(color); + }); + canvas.drawBitmap(*bitmap, 0, 0, nullptr); + }); + } + + sp<RenderNode> createSharedBitmapNode(Canvas& canvas, int left, int top, + int width, int height, sk_sp<Bitmap>bitmap) { + return TestUtils::createNode(left, top, left + width , top + height, + [bitmap](RenderProperties& props, Canvas& canvas) { + canvas.drawBitmap(*bitmap, 0, 0, nullptr); + }); + } + + sp<RenderNode> createInfoNode(Canvas& canvas, int left, int top, + int width, int height, const char* text, const char* text2) { + return TestUtils::createNode(left, top, left + width , top + height, + [text, text2](RenderProperties& props, Canvas& canvas) { + canvas.drawColor(0xFFFFEEEE, SkBlendMode::kSrcOver); + + SkPaint paint; + paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding); + paint.setAntiAlias(true); + paint.setTextSize(24); + + paint.setColor(Color::Black); + TestUtils::drawUtf8ToCanvas(&canvas, text, paint, 10, 30); + paint.setTextSize(20); + TestUtils::drawUtf8ToCanvas(&canvas, text2, paint, 10, 54); + + }); + } + + sp<RenderNode> createColorNode(Canvas& canvas, int left, int top, + int width, int height, SkColor color) { + return TestUtils::createNode(left, top, left + width , top + height, + [color](RenderProperties& props, Canvas& canvas) { + canvas.drawColor(color, SkBlendMode::kSrcOver); + }); + } + + virtual bool useSingleBitmap() { + return false; + } + + virtual float roundedCornerRadius() { + return dp(2); + } + + // when true, use overlay RenderNode for dimming, otherwise apply a ColorFilter to dim image + virtual bool useOverlay() { + return true; + } + + sp<RenderNode> createCard(int x, int y, int width, int height, bool selected) { + return TestUtils::createNode(x, y, x + width, y + height, + [width, height, selected, this](RenderProperties& props, Canvas& canvas) { + if (selected) { + props.setElevation(dp(16)); + props.setScaleX(1.2); + props.setScaleY(1.2); + } + props.mutableOutline().setRoundRect(0, 0, width, height, roundedCornerRadius(), 1); + props.mutableOutline().setShouldClip(true); + + sk_sp<Bitmap> bitmap = useSingleBitmap() ? mSingleBitmap + : mAllocator(width, dp(120), kRGBA_8888_SkColorType, [this](SkBitmap& skBitmap) { + skBitmap.eraseColor(0xFF000000 | ((mSeed << 3) & 0xFF)); + }); + sp<RenderNode> cardImage = createSharedBitmapNode(canvas, 0, 0, width, dp(120), + bitmap); + canvas.drawRenderNode(cardImage.get()); + mCachedBitmaps.push_back(bitmap); + mImages.push_back(cardImage); + + char buffer[128]; + sprintf(buffer, "Video %d-%d", mSeed, mSeed + 1); + mSeed++; + char buffer2[128]; + sprintf(buffer2, "Studio %d", mSeed2++); + sp<RenderNode> infoArea = createInfoNode(canvas, 0, dp(120), width, height, buffer, buffer2); + canvas.drawRenderNode(infoArea.get()); + mInfoAreas.push_back(infoArea); + + if (useOverlay()) { + sp<RenderNode> overlayColor = createColorNode(canvas, 0, 0, width, height, 0x00000000); + canvas.drawRenderNode(overlayColor.get()); + mOverlays.push_back(overlayColor); + } + }); + } + + void updateCard(int ci, int curFrame) { + // updating card's translation Y + sp<RenderNode> card = mCards[ci]; + card->setPropertyFieldsDirty(RenderNode::Y); + card->mutateStagingProperties().setTranslationY(curFrame % 150); + + // re-recording card's canvas, not necessary but to add some burden to CPU + std::unique_ptr<Canvas> cardcanvas(Canvas::create_recording_canvas( + card->stagingProperties().getWidth(), + card->stagingProperties().getHeight())); + sp<RenderNode> image = mImages[ci]; + sp<RenderNode> infoArea = mInfoAreas[ci]; + cardcanvas->drawRenderNode(infoArea.get()); + + if (useOverlay()) { + cardcanvas->drawRenderNode(image.get()); + // re-recording card overlay's canvas, animating overlay color alpha + sp<RenderNode> overlay = mOverlays[ci]; + std::unique_ptr<Canvas> canvas(Canvas::create_recording_canvas( + overlay->stagingProperties().getWidth(), + overlay->stagingProperties().getHeight())); + canvas->drawColor((curFrame % 150) << 24, SkBlendMode::kSrcOver); + overlay->setStagingDisplayList(canvas->finishRecording()); + cardcanvas->drawRenderNode(overlay.get()); + } else { + // re-recording image node's canvas, animating ColorFilter + std::unique_ptr<Canvas> canvas(Canvas::create_recording_canvas( + image->stagingProperties().getWidth(), + image->stagingProperties().getHeight())); + SkPaint paint; + sk_sp<SkColorFilter> filter(SkColorFilter::MakeModeFilter((curFrame % 150) << 24, + SkBlendMode::kSrcATop)); + paint.setColorFilter(filter); + sk_sp<Bitmap> bitmap = mCachedBitmaps[ci]; + canvas->drawBitmap(*bitmap, 0, 0, &paint); + image->setStagingDisplayList(canvas->finishRecording()); + cardcanvas->drawRenderNode(image.get()); + } + + card->setStagingDisplayList(cardcanvas->finishRecording()); + } +}; + +class TvAppNoRoundedCorner : public TvApp { +public: + TvAppNoRoundedCorner(BitmapAllocationTestUtils::BitmapAllocator allocator) + : TvApp(allocator) { } + +private: + + virtual float roundedCornerRadius() override { + return dp(0); + } +}; + +class TvAppColorFilter : public TvApp { +public: + TvAppColorFilter(BitmapAllocationTestUtils::BitmapAllocator allocator) + : TvApp(allocator) { } + +private: + + virtual bool useOverlay() override { + return false; + } +}; + +class TvAppNoRoundedCornerColorFilter : public TvApp { +public: + TvAppNoRoundedCornerColorFilter(BitmapAllocationTestUtils::BitmapAllocator allocator) + : TvApp(allocator) { } + +private: + + virtual float roundedCornerRadius() override { + return dp(0); + } + + virtual bool useOverlay() override { + return false; + } +}; + + 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/java/android/media/IMediaRouterService.aidl b/media/java/android/media/IMediaRouterService.aidl index dc7fa8c00f82..3308fc929b03 100644 --- a/media/java/android/media/IMediaRouterService.aidl +++ b/media/java/android/media/IMediaRouterService.aidl @@ -28,7 +28,6 @@ interface IMediaRouterService { MediaRouterClientState getState(IMediaRouterClient client); boolean isPlaybackActive(IMediaRouterClient client); - boolean isGlobalBluetoothA2doOn(); void setDiscoveryRequest(IMediaRouterClient client, int routeTypes, boolean activeScan); void setSelectedRoute(IMediaRouterClient client, String routeId, boolean explicit); diff --git a/media/java/android/media/MediaRouter.java b/media/java/android/media/MediaRouter.java index 8707ad017f51..d733ad9085d1 100644 --- a/media/java/android/media/MediaRouter.java +++ b/media/java/android/media/MediaRouter.java @@ -184,13 +184,15 @@ public class MediaRouter { void updateAudioRoutes(AudioRoutesInfo newRoutes) { boolean audioRoutesChanged = false; + boolean forceUseDefaultRoute = false; + if (newRoutes.mainType != mCurAudioRoutesInfo.mainType) { mCurAudioRoutesInfo.mainType = newRoutes.mainType; int name; - if ((newRoutes.mainType&AudioRoutesInfo.MAIN_HEADPHONES) != 0 - || (newRoutes.mainType&AudioRoutesInfo.MAIN_HEADSET) != 0) { + if ((newRoutes.mainType & AudioRoutesInfo.MAIN_HEADPHONES) != 0 + || (newRoutes.mainType & AudioRoutesInfo.MAIN_HEADSET) != 0) { name = com.android.internal.R.string.default_audio_route_name_headphones; - } else if ((newRoutes.mainType&AudioRoutesInfo.MAIN_DOCK_SPEAKERS) != 0) { + } else if ((newRoutes.mainType & AudioRoutesInfo.MAIN_DOCK_SPEAKERS) != 0) { name = com.android.internal.R.string.default_audio_route_name_dock_speakers; } else if ((newRoutes.mainType&AudioRoutesInfo.MAIN_HDMI) != 0) { name = com.android.internal.R.string.default_audio_route_name_hdmi; @@ -201,10 +203,16 @@ public class MediaRouter { } mDefaultAudioVideo.mNameResId = name; dispatchRouteChanged(mDefaultAudioVideo); + + if ((newRoutes.mainType & (AudioRoutesInfo.MAIN_HEADSET + | AudioRoutesInfo.MAIN_HEADPHONES | AudioRoutesInfo.MAIN_USB)) != 0) { + forceUseDefaultRoute = true; + } audioRoutesChanged = true; } if (!TextUtils.equals(newRoutes.bluetoothName, mCurAudioRoutesInfo.bluetoothName)) { + forceUseDefaultRoute = false; mCurAudioRoutesInfo.bluetoothName = newRoutes.bluetoothName; if (mCurAudioRoutesInfo.bluetoothName != null) { if (mBluetoothA2dpRoute == null) { @@ -233,30 +241,18 @@ public class MediaRouter { Log.v(TAG, "Audio routes updated: " + newRoutes + ", a2dp=" + isBluetoothA2dpOn()); if (mSelectedRoute == null || mSelectedRoute == mDefaultAudioVideo || mSelectedRoute == mBluetoothA2dpRoute) { - selectRouteStatic(ROUTE_TYPE_LIVE_AUDIO, getDefaultSystemAudioRoute(), false); + if (forceUseDefaultRoute || mBluetoothA2dpRoute == null) { + selectRouteStatic(ROUTE_TYPE_LIVE_AUDIO, mDefaultAudioVideo, false); + } else { + selectRouteStatic(ROUTE_TYPE_LIVE_AUDIO, mBluetoothA2dpRoute, false); + } } } } - RouteInfo getDefaultSystemAudioRoute() { - boolean globalBluetoothA2doOn = false; - try { - globalBluetoothA2doOn = mMediaRouterService.isGlobalBluetoothA2doOn(); - } catch (RemoteException ex) { - Log.e(TAG, "Unable to call isSystemBluetoothA2doOn.", ex); - } - return (globalBluetoothA2doOn && mBluetoothA2dpRoute != null) - ? mBluetoothA2dpRoute : mDefaultAudioVideo; - } - - RouteInfo getCurrentSystemAudioRoute() { - return (isBluetoothA2dpOn() && mBluetoothA2dpRoute != null) - ? mBluetoothA2dpRoute : mDefaultAudioVideo; - } - boolean isBluetoothA2dpOn() { try { - return mAudioService.isBluetoothA2dpOn(); + return mBluetoothA2dpRoute != null && mAudioService.isBluetoothA2dpOn(); } catch (RemoteException e) { Log.e(TAG, "Error querying Bluetooth A2DP state", e); return false; @@ -610,6 +606,7 @@ public class MediaRouter { || mSelectedRoute == null) { return; } + Log.v(TAG, "onRestoreRoute() : a2dp=" + isBluetoothA2dpOn()); mSelectedRoute.select(); } } @@ -942,10 +939,12 @@ public class MediaRouter { Log.v(TAG, "Selecting route: " + route); assert(route != null); final RouteInfo oldRoute = sStatic.mSelectedRoute; + final RouteInfo currentSystemRoute = sStatic.isBluetoothA2dpOn() + ? sStatic.mBluetoothA2dpRoute : sStatic.mDefaultAudioVideo; boolean wasDefaultOrBluetoothRoute = (oldRoute == sStatic.mDefaultAudioVideo || oldRoute == sStatic.mBluetoothA2dpRoute); if (oldRoute == route - && (!wasDefaultOrBluetoothRoute || route == sStatic.getCurrentSystemAudioRoute())) { + && (!wasDefaultOrBluetoothRoute || route == currentSystemRoute)) { return; } if (!route.matchesTypes(types)) { @@ -1016,8 +1015,7 @@ public class MediaRouter { static void selectDefaultRouteStatic() { // TODO: Be smarter about the route types here; this selects for all valid. - if (sStatic.mSelectedRoute != sStatic.mBluetoothA2dpRoute - && sStatic.mBluetoothA2dpRoute != null && sStatic.isBluetoothA2dpOn()) { + if (sStatic.mSelectedRoute != sStatic.mBluetoothA2dpRoute && sStatic.isBluetoothA2dpOn()) { selectRouteStatic(ROUTE_TYPE_ANY, sStatic.mBluetoothA2dpRoute, false); } else { selectRouteStatic(ROUTE_TYPE_ANY, sStatic.mDefaultAudioVideo, false); 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/layout/preference_two_target.xml b/packages/SettingsLib/res/layout/preference_two_target.xml index 2309ec6f1f8d..c2167f3e608d 100644 --- a/packages/SettingsLib/res/layout/preference_two_target.xml +++ b/packages/SettingsLib/res/layout/preference_two_target.xml @@ -33,6 +33,7 @@ android:background="?android:attr/selectableItemBackground" android:gravity="start|center_vertical" android:clipToPadding="false" + android:layout_marginStart="4dp" android:paddingStart="?android:attr/listPreferredItemPaddingStart" android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"> 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/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 cd62bc363c26..4ca5beff8eb2 100644 --- a/packages/SettingsLib/src/com/android/settingslib/wrapper/PackageManagerWrapper.java +++ b/packages/SettingsLib/src/com/android/settingslib/wrapper/PackageManagerWrapper.java @@ -60,6 +60,13 @@ public class PackageManagerWrapper { } /** + * Calls {@code PackageManager.getInstalledPackagesAsUser} + */ + public List<PackageInfo> getInstalledPackagesAsUser(int flags, int userId) { + return mPm.getInstalledPackagesAsUser(flags, userId); + } + + /** * Calls {@code PackageManager.hasSystemFeature()}. * * @see android.content.pm.PackageManager#hasSystemFeature @@ -132,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); @@ -144,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. */ @@ -154,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 */ @@ -190,4 +199,34 @@ public class PackageManagerWrapper { throws PackageManager.NameNotFoundException { return mPm.getPackageUidAsUser(pkg, userId); } + + /** + * Calls {@code PackageManager.setApplicationEnabledSetting} + */ + public void setApplicationEnabledSetting(String packageName, int newState, int flags) { + mPm.setApplicationEnabledSetting(packageName, newState, flags); + } + + /** + * Calls {@code PackageManager.getApplicationEnabledSetting} + */ + 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-keyguard/values-pa/strings.xml b/packages/SystemUI/res-keyguard/values-pa/strings.xml index 82f7227c7411..00f0ccbd5e51 100644 --- a/packages/SystemUI/res-keyguard/values-pa/strings.xml +++ b/packages/SystemUI/res-keyguard/values-pa/strings.xml @@ -45,7 +45,7 @@ <string name="keyguard_permanent_disabled_sim_instructions" msgid="4683178224791318347">"ਤੁਹਾਡਾ ਸਿਮ ਕਾਰਡ ਸਥਾਈ ਤੌਰ \'ਤੇ ਅਯੋਗ ਬਣਾ ਦਿੱਤਾ ਗਿਆ ਹੈ।\n ਇੱਕ ਹੋਰ ਸਿਮ ਕਾਰਡ ਲਈ ਆਪਣੇ ਵਾਇਰਲੈੱਸ ਸੇਵਾ ਪ੍ਰਦਾਨਕ ਨੂੰ ਸੰਪਰਕ ਕਰੋ।"</string> <string name="keyguard_sim_locked_message" msgid="953766009432168127">"SIM ਕਾਰਡ ਲੌਕ ਕੀਤਾ ਹੋਇਆ ਹੈ।"</string> <string name="keyguard_sim_puk_locked_message" msgid="1772789643694942073">"SIM ਕਾਰਡ PUK-ਲੌਕ ਕੀਤਾ ਹੋਇਆ ਹੈ।"</string> - <string name="keyguard_sim_unlock_progress_dialog_message" msgid="3586601150825821675">"SIM ਕਾਰਡ ਨੂੰ ਅਨਲੌਕ ਕੀਤਾ ਜਾ ਰਿਹਾ ਹੈ…"</string> + <string name="keyguard_sim_unlock_progress_dialog_message" msgid="3586601150825821675">"SIM ਕਾਰਡ ਨੂੰ ਅਣਲਾਕ ਕੀਤਾ ਜਾ ਰਿਹਾ ਹੈ…"</string> <string name="keyguard_accessibility_pin_area" msgid="703175752097279029">"ਪਿੰਨ ਖੇਤਰ"</string> <string name="keyguard_accessibility_sim_pin_area" msgid="912702510825058921">"ਸਿਮ ਪਿੰਨ ਖੇਤਰ"</string> <string name="keyguard_accessibility_sim_puk_area" msgid="136979425761438705">"SIM PUK ਖੇਤਰ"</string> @@ -71,7 +71,7 @@ <string name="kg_puk_enter_puk_hint_multi" msgid="1373131883510840794">"ਸਿਮ \"<xliff:g id="CARRIER">%1$s</xliff:g>\" ਹੁਣ ਬੰਦ ਕੀਤਾ ਗਿਆ ਹੈ। ਜਾਰੀ ਰੱਖਣ ਲਈ PUK ਕੋਡ ਦਾਖਲ ਕਰੋ। ਵੇਰਵਿਆਂ ਲਈ ਕੈਰੀਅਰ ਨਾਲ ਸੰਪਰਕ ਕਰੋ।"</string> <string name="kg_puk_enter_pin_hint" msgid="3137789674920391087">"ਇੱਛਤ ਪਿੰਨ ਕੋਡ ਦਾਖਲ ਕਰੋ"</string> <string name="kg_enter_confirm_pin_hint" msgid="3089485999116759671">"ਇੱਛਤ ਪਿੰਨ ਕੋਡ ਦੀ ਪੁਸ਼ਟੀ ਕਰੋ"</string> - <string name="kg_sim_unlock_progress_dialog_message" msgid="4471738151810900114">"SIM ਕਾਰਡ ਨੂੰ ਅਨਲੌਕ ਕੀਤਾ ਜਾ ਰਿਹਾ ਹੈ…"</string> + <string name="kg_sim_unlock_progress_dialog_message" msgid="4471738151810900114">"SIM ਕਾਰਡ ਨੂੰ ਅਣਲਾਕ ਕੀਤਾ ਜਾ ਰਿਹਾ ਹੈ…"</string> <string name="kg_invalid_sim_pin_hint" msgid="3057533256729513335">"ਕੋਈ ਪਿੰਨ ਟਾਈਪ ਕਰੋ ਜੋ 4 ਤੋਂ 8 ਨੰਬਰਾਂ ਦਾ ਹੋਵੇ।"</string> <string name="kg_invalid_sim_puk_hint" msgid="6003602401368264144">"PUK ਕੋਡ 8 ਜਾਂ ਵੱਧ ਨੰਬਰਾਂ ਦਾ ਹੋਣਾ ਚਾਹੀਦਾ ਹੈ।"</string> <string name="kg_invalid_puk" msgid="5399287873762592502">"ਸਹੀ PUK ਕੋਡ ਮੁੜ-ਦਾਖਲ ਕਰੋ। ਬਾਰ-ਬਾਰ ਕੀਤੀਆਂ ਕੋਸ਼ਿਸ਼ਾਂ ਸਿਮ ਨੂੰ ਸਥਾਈ ਤੌਰ \'ਤੇ ਬੰਦ ਕਰ ਦੇਣਗੀਆਂ।"</string> 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 166e0cb0a5c8..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> @@ -468,7 +468,7 @@ <string name="branded_monitoring_description_app_personal" msgid="2669518213949202599">"ਤੁਸੀਂ <xliff:g id="APPLICATION">%1$s</xliff:g> ਨਾਲ ਕਨੈਕਟ ਹੋ, ਜੋ ਈਮੇਲਾਂ, ਐਪਾਂ, ਅਤੇ ਵੈੱਬਸਾਈਟਾਂ ਸਮੇਤ ਤੁਹਾਡੀ ਨਿੱਜੀ ਨੈੱਟਵਰਕ ਸਰਗਰਮੀ ਦੀ ਨਿਗਰਾਨੀ ਕਰ ਸਕਦੀ ਹੈ।"</string> <string name="monitoring_description_app_work" msgid="4612997849787922906">"ਤੁਹਾਡੇ ਕਾਰਜ ਪ੍ਰੋਫਾਈਲ ਦਾ ਪ੍ਰਬੰਧਨ <xliff:g id="ORGANIZATION">%1$s</xliff:g> ਵੱਲੋਂ ਕੀਤਾ ਜਾਂਦਾ ਹੈ। ਇਹ ਪ੍ਰੋਫਾਈਲ <xliff:g id="APPLICATION">%2$s</xliff:g> ਨਾਲ ਕਨੈਕਟ ਹੈ, ਜੋ ਈਮੇਲਾਂ, ਐਪਾਂ, ਅਤੇ ਵੈੱਬਸਾਈਟਾਂ ਸਮੇਤ ਤੁਹਾਡੀ ਕਾਰਜ ਨੈੱਟਵਰਕ ਸਰਗਰਮੀ ਦੀ ਨਿਗਰਾਨੀ ਕਰ ਸਕਦੀ ਹੈ।\n\nਹੋਰ ਜਾਣਕਾਰੀ ਲਈ, ਆਪਣੇ ਪ੍ਰਸ਼ਾਸਕ ਨਾਲ ਸੰਪਰਕ ਕਰੋ।"</string> <string name="monitoring_description_app_personal_work" msgid="5664165460056859391">"ਤੁਹਾਡੇ ਕਾਰਜ ਪ੍ਰੋਫਾਈਲ ਦਾ ਪ੍ਰਬੰਧਨ <xliff:g id="ORGANIZATION">%1$s</xliff:g> ਵੱਲੋਂ ਕੀਤਾ ਜਾਂਦਾ ਹੈ। ਪ੍ਰੋਫਾਈਲ <xliff:g id="APPLICATION_WORK">%2$s</xliff:g> ਨਾਲ ਕਨੈਕਟ ਕੀਤਾ ਗਿਆ ਹੈ, ਜੋ ਈਮੇਲਾਂ, ਐਪਾਂ, ਅਤੇ ਵੈੱਬਸਾਈਟਾਂ ਸਮੇਤ ਤੁਹਾਡੀ ਕਾਰਜ ਨੈੱਟਵਰਕ ਸਰਗਰਮੀ ਦੀ ਨਿਗਰਾਨੀ ਕਰ ਸਕਦੀ ਹੈ।\n\nਤੁਸੀਂ <xliff:g id="APPLICATION_PERSONAL">%3$s</xliff:g> ਨਾਲ ਵੀ ਕਨੈਕਟ ਹੋਂ, ਜੋ ਤੁਹਾਡੀ ਨਿੱਜੀ ਨੈੱਟਵਰਕ ਸਰਗਰਮੀ ਦੀ ਨਿਗਰਾਨੀ ਕਰ ਸਕਦੀ ਹੈ।"</string> - <string name="keyguard_indication_trust_granted" msgid="4985003749105182372">"<xliff:g id="USER_NAME">%1$s</xliff:g> ਲਈ ਅਨਲੌਕ ਕੀਤੀ ਗਈ"</string> + <string name="keyguard_indication_trust_granted" msgid="4985003749105182372">"<xliff:g id="USER_NAME">%1$s</xliff:g> ਲਈ ਅਣਲਾਕ ਕੀਤੀ ਗਈ"</string> <string name="keyguard_indication_trust_managed" msgid="8319646760022357585">"<xliff:g id="TRUST_AGENT">%1$s</xliff:g> ਚੱਲ ਰਿਹਾ ਹੈ"</string> <string name="keyguard_indication_trust_disabled" msgid="7412534203633528135">"ਡੀਵਾਈਸ ਲਾਕ ਰਹੇਗਾ ਜਦੋਂ ਤੱਕ ਤੁਸੀਂ ਮੈਨੂਅਲੀ ਅਣਲਾਕ ਨਹੀਂ ਕਰਦੇ"</string> <string name="hidden_notifications_title" msgid="7139628534207443290">"ਤੇਜ਼ੀ ਨਾਲ ਸੂਚਨਾਵਾਂ ਪ੍ਰਾਪਤ ਕਰੋ"</string> @@ -587,7 +587,7 @@ <string name="battery_panel_title" msgid="7944156115535366613">"ਬੈਟਰੀ ਵਰਤੋਂ"</string> <string name="battery_detail_charging_summary" msgid="4055327085770378335">"ਬੈਟਰੀ ਸੇਵਰ ਚਾਰਜਿੰਗ ਦੌਰਾਨ ਉਪਲਬਧ ਨਹੀਂ ਹੈ"</string> <string name="battery_detail_switch_title" msgid="8763441006881907058">"ਬੈਟਰੀ ਸੇਵਰ"</string> - <string name="battery_detail_switch_summary" msgid="9049111149407626804">"ਕਾਰਗੁਜ਼ਾਰੀ ਅਤੇ ਬੈਕਗ੍ਰਾਊਂਡ ਡੈਟੇ ਨੂੰ ਘਟਾਉਂਦਾ ਹੈ"</string> + <string name="battery_detail_switch_summary" msgid="9049111149407626804">"ਕਾਰਗੁਜ਼ਾਰੀ ਅਤੇ ਬੈਕਗ੍ਰਾਊਂਡ ਡਾਟੇ ਨੂੰ ਘਟਾਉਂਦਾ ਹੈ"</string> <string name="keyboard_key_button_template" msgid="6230056639734377300">"ਬਟਨ <xliff:g id="NAME">%1$s</xliff:g>"</string> <string name="keyboard_key_home" msgid="2243500072071305073">"Home"</string> <string name="keyboard_key_back" msgid="2337450286042721351">"Back"</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/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml index e6a357fc7be8..9901f6ff8fda 100644 --- a/packages/SystemUI/res/values/dimens.xml +++ b/packages/SystemUI/res/values/dimens.xml @@ -80,12 +80,6 @@ <!-- Height of a small notification in the status bar which was used before android N --> <dimen name="notification_min_height_legacy">64dp</dimen> - <!-- The increase in minHeight that is allowed when the notification is colorized --> - <dimen name="notification_height_increase_colorized">11sp</dimen> - - <!-- The increase in minHeight that is allowed when the notification is colorized and has increased height (i.e messages) --> - <dimen name="notification_height_increase_colorized_increased">13sp</dimen> - <!-- Height of a large notification in the status bar --> <dimen name="notification_max_height">284dp</dimen> diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java index d95402cdb5dc..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(); } /** @@ -1069,6 +1070,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener { cb.onDreamingStateChanged(mIsDreaming); } } + 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/pip/phone/PipManager.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipManager.java index b3f992db1b6b..bae9ef8abfba 100644 --- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipManager.java +++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipManager.java @@ -30,6 +30,7 @@ import android.graphics.Rect; import android.os.Handler; import android.os.RemoteException; import android.util.Log; +import android.util.Pair; import android.view.IPinnedStackController; import android.view.IPinnedStackListener; import android.view.IWindowManager; @@ -70,11 +71,11 @@ public class PipManager implements BasePipManager { */ TaskStackListener mTaskStackListener = new TaskStackListener() { @Override - public void onActivityPinned(String packageName, int taskId) { + public void onActivityPinned(String packageName, int userId, int taskId) { mTouchHandler.onActivityPinned(); mMediaController.onActivityPinned(); mMenuController.onActivityPinned(); - mNotificationController.onActivityPinned(packageName, + mNotificationController.onActivityPinned(packageName, userId, true /* deferUntilAnimationEnds */); SystemServicesProxy.getInstance(mContext).setPipVisibility(true); @@ -82,13 +83,15 @@ public class PipManager implements BasePipManager { @Override public void onActivityUnpinned() { - ComponentName topPipActivity = PipUtils.getTopPinnedActivity(mContext, - mActivityManager); - mMenuController.onActivityUnpinned(topPipActivity); - mTouchHandler.onActivityUnpinned(topPipActivity); - mNotificationController.onActivityUnpinned(topPipActivity); - - SystemServicesProxy.getInstance(mContext).setPipVisibility(topPipActivity != null); + final Pair<ComponentName, Integer> topPipActivityInfo = PipUtils.getTopPinnedActivity( + mContext, mActivityManager); + final ComponentName topActivity = topPipActivityInfo.first; + final int userId = topActivity != null ? topPipActivityInfo.second : 0; + mMenuController.onActivityUnpinned(); + mTouchHandler.onActivityUnpinned(topActivity); + mNotificationController.onActivityUnpinned(topActivity, userId); + + SystemServicesProxy.getInstance(mContext).setPipVisibility(topActivity != null); } @Override diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipMediaController.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipMediaController.java index b3a0794f742f..174a7ef19cbd 100644 --- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipMediaController.java +++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipMediaController.java @@ -230,7 +230,7 @@ public class PipMediaController { private void resolveActiveMediaController(List<MediaController> controllers) { if (controllers != null) { final ComponentName topActivity = PipUtils.getTopPinnedActivity(mContext, - mActivityManager); + mActivityManager).first; if (topActivity != null) { for (int i = 0; i < controllers.size(); i++) { final MediaController controller = controllers.get(i); diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivityController.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivityController.java index 34666fb30689..68743b34884d 100644 --- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivityController.java +++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivityController.java @@ -223,7 +223,7 @@ public class PipMenuActivityController { } } - public void onActivityUnpinned(ComponentName topPipActivity) { + public void onActivityUnpinned() { hideMenu(); setStartActivityRequested(false); } diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipNotificationController.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipNotificationController.java index 696fdbc811e7..6d083e9d601d 100644 --- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipNotificationController.java +++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipNotificationController.java @@ -35,10 +35,15 @@ import android.content.Intent; import android.content.pm.ApplicationInfo; import android.content.pm.PackageManager; import android.content.pm.PackageManager.NameNotFoundException; -import android.content.res.Resources; -import android.graphics.drawable.Icon; +import android.graphics.Bitmap; +import android.graphics.Bitmap.Config; +import android.graphics.Canvas; +import android.graphics.drawable.Drawable; import android.net.Uri; +import android.os.UserHandle; +import android.util.IconDrawableFactory; import android.util.Log; +import android.util.Pair; import com.android.systemui.R; import com.android.systemui.SystemUI; @@ -57,22 +62,29 @@ public class PipNotificationController { private IActivityManager mActivityManager; private AppOpsManager mAppOpsManager; private NotificationManager mNotificationManager; + private IconDrawableFactory mIconDrawableFactory; private PipMotionHelper mMotionHelper; // Used when building a deferred notification private String mDeferredNotificationPackageName; + private int mDeferredNotificationUserId; private AppOpsManager.OnOpChangedListener mAppOpsChangedListener = new OnOpChangedListener() { @Override public void onOpChanged(String op, String packageName) { try { // Dismiss the PiP once the user disables the app ops setting for that package - final ApplicationInfo appInfo = mContext.getPackageManager().getApplicationInfo( - packageName, 0); - if (mAppOpsManager.checkOpNoThrow(OP_PICTURE_IN_PICTURE, appInfo.uid, packageName) - != MODE_ALLOWED) { - mMotionHelper.dismissPip(); + final Pair<ComponentName, Integer> topPipActivityInfo = + PipUtils.getTopPinnedActivity(mContext, mActivityManager); + if (topPipActivityInfo.first != null) { + final ApplicationInfo appInfo = mContext.getPackageManager() + .getApplicationInfoAsUser(packageName, 0, topPipActivityInfo.second); + if (appInfo.packageName.equals(topPipActivityInfo.first.getPackageName()) && + mAppOpsManager.checkOpNoThrow(OP_PICTURE_IN_PICTURE, appInfo.uid, + packageName) != MODE_ALLOWED) { + mMotionHelper.dismissPip(); + } } } catch (NameNotFoundException e) { // Unregister the listener if the package can't be found @@ -88,16 +100,18 @@ public class PipNotificationController { mAppOpsManager = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE); mNotificationManager = NotificationManager.from(context); mMotionHelper = motionHelper; + mIconDrawableFactory = IconDrawableFactory.newInstance(context); } - public void onActivityPinned(String packageName, boolean deferUntilAnimationEnds) { + public void onActivityPinned(String packageName, int userId, boolean deferUntilAnimationEnds) { // Clear any existing notification mNotificationManager.cancel(NOTIFICATION_TAG, NOTIFICATION_ID); if (deferUntilAnimationEnds) { mDeferredNotificationPackageName = packageName; + mDeferredNotificationUserId = userId; } else { - showNotificationForApp(mDeferredNotificationPackageName); + showNotificationForApp(packageName, userId); } // Register for changes to the app ops setting for this package while it is in PiP @@ -106,22 +120,25 @@ public class PipNotificationController { public void onPinnedStackAnimationEnded() { if (mDeferredNotificationPackageName != null) { - showNotificationForApp(mDeferredNotificationPackageName); + showNotificationForApp(mDeferredNotificationPackageName, mDeferredNotificationUserId); mDeferredNotificationPackageName = null; + mDeferredNotificationUserId = 0; } } - public void onActivityUnpinned(ComponentName topPipActivity) { + public void onActivityUnpinned(ComponentName topPipActivity, int userId) { // Unregister for changes to the previously PiP'ed package unregisterAppOpsListener(); // Reset the deferred notification package mDeferredNotificationPackageName = null; + mDeferredNotificationUserId = 0; if (topPipActivity != null) { // onActivityUnpinned() is only called after the transition is complete, so we don't // need to defer until the animation ends to update the notification - onActivityPinned(topPipActivity.getPackageName(), false /* deferUntilAnimationEnds */); + onActivityPinned(topPipActivity.getPackageName(), userId, + false /* deferUntilAnimationEnds */); } else { mNotificationManager.cancel(NOTIFICATION_TAG, NOTIFICATION_ID); } @@ -130,20 +147,27 @@ public class PipNotificationController { /** * Builds and shows the notification for the given app. */ - private void showNotificationForApp(String packageName) { + private void showNotificationForApp(String packageName, int userId) { // Build a new notification - final Notification.Builder builder = - new Notification.Builder(mContext, NotificationChannels.GENERAL) - .setLocalOnly(true) - .setOngoing(true) - .setSmallIcon(R.drawable.pip_notification_icon) - .setColor(mContext.getColor( - com.android.internal.R.color.system_notification_accent_color)); - if (updateNotificationForApp(builder, packageName)) { - SystemUI.overrideNotificationAppName(mContext, builder); - - // Show the new notification - mNotificationManager.notify(NOTIFICATION_TAG, NOTIFICATION_ID, builder.build()); + try { + final UserHandle user = UserHandle.of(userId); + final Context userContext = mContext.createPackageContextAsUser( + mContext.getPackageName(), 0, user); + final Notification.Builder builder = + new Notification.Builder(userContext, NotificationChannels.GENERAL) + .setLocalOnly(true) + .setOngoing(true) + .setSmallIcon(R.drawable.pip_notification_icon) + .setColor(mContext.getColor( + com.android.internal.R.color.system_notification_accent_color)); + if (updateNotificationForApp(builder, packageName, user)) { + SystemUI.overrideNotificationAppName(mContext, builder); + + // Show the new notification + mNotificationManager.notify(NOTIFICATION_TAG, NOTIFICATION_ID, builder.build()); + } + } catch (NameNotFoundException e) { + Log.e(TAG, "Could not show notification for application", e); } } @@ -151,33 +175,33 @@ public class PipNotificationController { * Updates the notification builder with app-specific information, returning whether it was * successful. */ - private boolean updateNotificationForApp(Notification.Builder builder, String packageName) { + private boolean updateNotificationForApp(Notification.Builder builder, String packageName, + UserHandle user) throws NameNotFoundException { final PackageManager pm = mContext.getPackageManager(); final ApplicationInfo appInfo; try { - appInfo = pm.getApplicationInfo(packageName, 0); + appInfo = pm.getApplicationInfoAsUser(packageName, 0, user.getIdentifier()); } catch (NameNotFoundException e) { Log.e(TAG, "Could not update notification for application", e); return false; } if (appInfo != null) { - final String appName = pm.getApplicationLabel(appInfo).toString(); + final String appName = pm.getUserBadgedLabel(pm.getApplicationLabel(appInfo), user) + .toString(); final String message = mContext.getString(R.string.pip_notification_message, appName); final Intent settingsIntent = new Intent(ACTION_PICTURE_IN_PICTURE_SETTINGS, Uri.fromParts("package", packageName, null)); + settingsIntent.putExtra(Intent.EXTRA_USER_HANDLE, user); settingsIntent.setFlags(FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK); - final Icon appIcon = appInfo.icon != 0 - ? Icon.createWithResource(packageName, appInfo.icon) - : Icon.createWithResource(Resources.getSystem(), - com.android.internal.R.drawable.sym_def_app_icon); + final Drawable iconDrawable = mIconDrawableFactory.getBadgedIcon(appInfo); builder.setContentTitle(mContext.getString(R.string.pip_notification_title, appName)) .setContentText(message) - .setContentIntent(PendingIntent.getActivity(mContext, packageName.hashCode(), - settingsIntent, FLAG_CANCEL_CURRENT)) + .setContentIntent(PendingIntent.getActivityAsUser(mContext, packageName.hashCode(), + settingsIntent, FLAG_CANCEL_CURRENT, null, user)) .setStyle(new Notification.BigTextStyle().bigText(message)) - .setLargeIcon(appIcon); + .setLargeIcon(createBitmap(iconDrawable).createAshmemBitmap()); return true; } return false; @@ -191,4 +215,17 @@ public class PipNotificationController { private void unregisterAppOpsListener() { mAppOpsManager.stopWatchingMode(mAppOpsChangedListener); } + + /** + * Bakes a drawable into a bitmap. + */ + private Bitmap createBitmap(Drawable d) { + Bitmap bitmap = Bitmap.createBitmap(d.getIntrinsicWidth(), d.getIntrinsicHeight(), + Config.ARGB_8888); + Canvas c = new Canvas(bitmap); + d.setBounds(0, 0, d.getIntrinsicWidth(), d.getIntrinsicHeight()); + d.draw(c); + c.setBitmap(null); + return bitmap; + } } diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipUtils.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipUtils.java index a8cdd1bdb802..56275fd043cf 100644 --- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipUtils.java +++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipUtils.java @@ -24,16 +24,17 @@ import android.content.ComponentName; import android.content.Context; import android.os.RemoteException; import android.util.Log; +import android.util.Pair; public class PipUtils { private static final String TAG = "PipUtils"; /** - * @return the ComponentName of the top non-SystemUI activity in the pinned stack, or null if - * none exists. + * @return the ComponentName and user id of the top non-SystemUI activity in the pinned stack. + * The component name may be null if no such activity exists. */ - public static ComponentName getTopPinnedActivity(Context context, + public static Pair<ComponentName, Integer> getTopPinnedActivity(Context context, IActivityManager activityManager) { try { final String sysUiPackageName = context.getPackageName(); @@ -44,13 +45,13 @@ public class PipUtils { ComponentName cn = ComponentName.unflattenFromString( pinnedStackInfo.taskNames[i]); if (cn != null && !cn.getPackageName().equals(sysUiPackageName)) { - return cn; + return new Pair<>(cn, pinnedStackInfo.taskUserIds[i]); } } } } catch (RemoteException e) { Log.w(TAG, "Unable to get pinned stack."); } - return null; + return new Pair<>(null, 0); } } diff --git a/packages/SystemUI/src/com/android/systemui/pip/tv/PipManager.java b/packages/SystemUI/src/com/android/systemui/pip/tv/PipManager.java index e8c129521010..186de5c4e121 100644 --- a/packages/SystemUI/src/com/android/systemui/pip/tv/PipManager.java +++ b/packages/SystemUI/src/com/android/systemui/pip/tv/PipManager.java @@ -654,7 +654,7 @@ public class PipManager implements BasePipManager { } @Override - public void onActivityPinned(String packageName, int taskId) { + public void onActivityPinned(String packageName, int userId, int taskId) { if (DEBUG) Log.d(TAG, "onActivityPinned()"); if (!checkCurrentUserId(mContext, DEBUG)) { return; diff --git a/packages/SystemUI/src/com/android/systemui/qs/AlphaControlledSignalTileView.java b/packages/SystemUI/src/com/android/systemui/qs/AlphaControlledSignalTileView.java new file mode 100644 index 000000000000..2c7ec70a5fff --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/qs/AlphaControlledSignalTileView.java @@ -0,0 +1,86 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.qs; + +import android.content.Context; +import android.content.res.ColorStateList; +import android.graphics.drawable.Drawable; +import com.android.systemui.qs.tileimpl.SlashImageView; + + +/** + * Creates AlphaControlledSlashImageView instead of SlashImageView + */ +public class AlphaControlledSignalTileView extends SignalTileView { + public AlphaControlledSignalTileView(Context context) { + super(context); + } + + @Override + protected SlashImageView createSlashImageView(Context context) { + return new AlphaControlledSlashImageView(context); + } + + /** + * Creates AlphaControlledSlashDrawable instead of regular SlashDrawables + */ + public static class AlphaControlledSlashImageView extends SlashImageView { + public AlphaControlledSlashImageView(Context context) { + super(context); + } + + public void setFinalImageTintList(ColorStateList tint) { + super.setImageTintList(tint); + final SlashDrawable slash = getSlash(); + if (slash != null) { + ((AlphaControlledSlashDrawable)slash).setFinalTintList(tint); + } + } + + @Override + protected void ensureSlashDrawable() { + if (getSlash() == null) { + final SlashDrawable slash = new AlphaControlledSlashDrawable(getDrawable()); + setSlash(slash); + slash.setAnimationEnabled(getAnimationEnabled()); + setImageViewDrawable(slash); + } + } + } + + /** + * SlashDrawable that disobeys orders to change its drawable's tint except when you tell + * it not to disobey. The slash still will animate its alpha. + */ + public static class AlphaControlledSlashDrawable extends SlashDrawable { + AlphaControlledSlashDrawable(Drawable d) { + super(d); + } + + @Override + protected void setDrawableTintList(ColorStateList tint) { + } + + /** + * Set a target tint list instead of + */ + public void setFinalTintList(ColorStateList tint) { + super.setDrawableTintList(tint); + } + } +} + diff --git a/packages/SystemUI/src/com/android/systemui/qs/SignalTileView.java b/packages/SystemUI/src/com/android/systemui/qs/SignalTileView.java index b300e4a35a5a..9ee40ccf8893 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/SignalTileView.java +++ b/packages/SystemUI/src/com/android/systemui/qs/SignalTileView.java @@ -63,13 +63,17 @@ public class SignalTileView extends QSIconViewImpl { @Override protected View createIcon() { mIconFrame = new FrameLayout(mContext); - mSignal = new SlashImageView(mContext); + mSignal = createSlashImageView(mContext); mIconFrame.addView(mSignal); mOverlay = new ImageView(mContext); mIconFrame.addView(mOverlay, LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT); return mIconFrame; } + protected SlashImageView createSlashImageView(Context context) { + return new SlashImageView(context); + } + @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); diff --git a/packages/SystemUI/src/com/android/systemui/qs/SlashDrawable.java b/packages/SystemUI/src/com/android/systemui/qs/SlashDrawable.java index c35614893098..a9b2376e46e5 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/SlashDrawable.java +++ b/packages/SystemUI/src/com/android/systemui/qs/SlashDrawable.java @@ -197,11 +197,15 @@ public class SlashDrawable extends Drawable { public void setTintList(@Nullable ColorStateList tint) { mTintList = tint; super.setTintList(tint); - mDrawable.setTintList(tint); + setDrawableTintList(tint); mPaint.setColor(tint.getDefaultColor()); invalidateSelf(); } + protected void setDrawableTintList(@Nullable ColorStateList tint) { + mDrawable.setTintList(tint); + } + @Override public void setTintMode(@NonNull Mode tintMode) { mTintMode = tintMode; diff --git a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSIconViewImpl.java b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSIconViewImpl.java index 8074cb9b0443..e8c8b9075792 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSIconViewImpl.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSIconViewImpl.java @@ -33,6 +33,7 @@ import com.android.systemui.plugins.qs.QSIconView; import com.android.systemui.plugins.qs.QSTile; import com.android.systemui.plugins.qs.QSTile.State; +import com.android.systemui.qs.AlphaControlledSignalTileView.AlphaControlledSlashImageView; import java.util.Objects; public class QSIconViewImpl extends QSIconView { @@ -138,7 +139,12 @@ public class QSIconViewImpl extends QSIconView { animateGrayScale(mTint, color, iv); mTint = color; } else { - setTint(iv, color); + if (iv instanceof AlphaControlledSlashImageView) { + ((AlphaControlledSlashImageView)iv) + .setFinalImageTintList(ColorStateList.valueOf(color)); + } else { + setTint(iv, color); + } mTint = color; } } @@ -149,6 +155,10 @@ public class QSIconViewImpl extends QSIconView { } public static void animateGrayScale(int fromColor, int toColor, ImageView iv) { + if (iv instanceof AlphaControlledSlashImageView) { + ((AlphaControlledSlashImageView)iv) + .setFinalImageTintList(ColorStateList.valueOf(toColor)); + } if (ValueAnimator.areAnimatorsEnabled()) { final float fromAlpha = Color.alpha(fromColor); final float toAlpha = Color.alpha(toColor); diff --git a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/SlashImageView.java b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/SlashImageView.java index 97e9c3dfd82c..63d6f82ce9e6 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/SlashImageView.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/SlashImageView.java @@ -34,7 +34,15 @@ public class SlashImageView extends ImageView { super(context); } - private void ensureSlashDrawable() { + protected SlashDrawable getSlash() { + return mSlash; + } + + protected void setSlash(SlashDrawable slash) { + mSlash = slash; + } + + protected void ensureSlashDrawable() { if (mSlash == null) { mSlash = new SlashDrawable(getDrawable()); mSlash.setAnimationEnabled(mAnimationEnabled); @@ -56,10 +64,18 @@ public class SlashImageView extends ImageView { } } + protected void setImageViewDrawable(SlashDrawable slash) { + super.setImageDrawable(slash); + } + public void setAnimationEnabled(boolean enabled) { mAnimationEnabled = enabled; } + public boolean getAnimationEnabled() { + return mAnimationEnabled; + } + private void setSlashState(@NonNull SlashState slashState) { ensureSlashDrawable(); mSlash.setRotation(slashState.rotation); diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java index 33b15121b47e..23702736b0db 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java @@ -37,10 +37,10 @@ import com.android.systemui.plugins.qs.DetailAdapter; import com.android.systemui.plugins.qs.QSIconView; import com.android.systemui.plugins.qs.QSTile; import com.android.systemui.plugins.qs.QSTile.SignalState; +import com.android.systemui.qs.AlphaControlledSignalTileView; import com.android.systemui.qs.QSDetailItems; import com.android.systemui.qs.QSDetailItems.Item; import com.android.systemui.qs.QSHost; -import com.android.systemui.qs.SignalTileView; import com.android.systemui.qs.tileimpl.QSTileImpl; import com.android.systemui.statusbar.policy.NetworkController; import com.android.systemui.statusbar.policy.NetworkController.AccessPointController; @@ -104,7 +104,7 @@ public class WifiTile extends QSTileImpl<SignalState> { @Override public QSIconView createTileView(Context context) { - return new SignalTileView(context); + return new AlphaControlledSignalTileView(context); } @Override diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java index c4e870135a6d..43227ab4f313 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java +++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java @@ -173,7 +173,7 @@ public class RecentsImpl implements ActivityOptions.OnAnimationFinishedListener } @Override - public void onActivityPinned(String packageName, int taskId) { + public void onActivityPinned(String packageName, int userId, int taskId) { // Check this is for the right user if (!checkCurrentUserId(mContext, false /* debug */)) { return; diff --git a/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java b/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java index 366a908f15bd..5a5251e19337 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java +++ b/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java @@ -176,7 +176,7 @@ public class SystemServicesProxy { public void onTaskStackChangedBackground() { } public void onTaskStackChanged() { } public void onTaskSnapshotChanged(int taskId, TaskSnapshot snapshot) { } - public void onActivityPinned(String packageName, int taskId) { } + public void onActivityPinned(String packageName, int userId, int taskId) { } public void onActivityUnpinned() { } public void onPinnedActivityRestartAttempt(boolean clearedTask) { } public void onPinnedStackAnimationStarted() { } @@ -231,9 +231,10 @@ public class SystemServicesProxy { } @Override - public void onActivityPinned(String packageName, int taskId) throws RemoteException { + public void onActivityPinned(String packageName, int userId, int taskId) + throws RemoteException { mHandler.removeMessages(H.ON_ACTIVITY_PINNED); - mHandler.obtainMessage(H.ON_ACTIVITY_PINNED, taskId, 0, packageName).sendToTarget(); + mHandler.obtainMessage(H.ON_ACTIVITY_PINNED, userId, taskId, packageName).sendToTarget(); } @Override @@ -1356,7 +1357,8 @@ public class SystemServicesProxy { } case ON_ACTIVITY_PINNED: { for (int i = mTaskStackListeners.size() - 1; i >= 0; i--) { - mTaskStackListeners.get(i).onActivityPinned((String) msg.obj, msg.arg1); + mTaskStackListeners.get(i).onActivityPinned((String) msg.obj, msg.arg1, + msg.arg2); } break; } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java index 8fa904e10b4a..966e78997244 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java @@ -64,10 +64,10 @@ import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin; import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin.MenuItem; import com.android.systemui.statusbar.NotificationGuts.GutsContent; import com.android.systemui.statusbar.notification.AboveShelfChangedListener; +import com.android.systemui.statusbar.notification.AboveShelfObserver; import com.android.systemui.statusbar.notification.HybridNotificationView; import com.android.systemui.statusbar.notification.NotificationInflater; import com.android.systemui.statusbar.notification.NotificationUtils; -import com.android.systemui.statusbar.notification.NotificationViewWrapper; import com.android.systemui.statusbar.notification.VisualStabilityManager; import com.android.systemui.statusbar.phone.NotificationGroupManager; import com.android.systemui.statusbar.phone.StatusBar; @@ -436,9 +436,6 @@ public class ExpandableNotificationRow extends ActivatableNotificationView } else { minHeight = mNotificationMinHeight; } - NotificationViewWrapper collapsedWrapper = layout.getVisibleWrapper( - NotificationContentView.VISIBLE_TYPE_CONTRACTED); - minHeight += collapsedWrapper.getMinHeightIncrease(mUseIncreasedCollapsedHeight); boolean headsUpCustom = layout.getHeadsUpChild() != null && layout.getHeadsUpChild().getId() != com.android.internal.R.id.status_bar_latest_event_content; @@ -450,11 +447,6 @@ public class ExpandableNotificationRow extends ActivatableNotificationView } else { headsUpheight = mMaxHeadsUpHeight; } - NotificationViewWrapper headsUpWrapper = layout.getVisibleWrapper( - NotificationContentView.VISIBLE_TYPE_HEADSUP); - if (headsUpWrapper != null) { - headsUpheight += headsUpWrapper.getMinHeightIncrease(mUseIncreasedCollapsedHeight); - } layout.setHeights(minHeight, headsUpheight, mNotificationMaxHeight, mNotificationAmbientHeight); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/KeyboardShortcuts.java b/packages/SystemUI/src/com/android/systemui/statusbar/KeyboardShortcuts.java index d370a6331ea1..2d16d2209c9e 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/KeyboardShortcuts.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/KeyboardShortcuts.java @@ -433,24 +433,27 @@ public final class KeyboardShortcuts { // Assist. final AssistUtils assistUtils = new AssistUtils(mContext); final ComponentName assistComponent = assistUtils.getAssistComponentForUser(userId); - PackageInfo assistPackageInfo = null; - try { - assistPackageInfo = mPackageManager.getPackageInfo( - assistComponent.getPackageName(), 0, userId); - } catch (RemoteException e) { - Log.e(TAG, "PackageManagerService is dead"); - } + // Not all devices have an assist component. + if (assistComponent != null) { + PackageInfo assistPackageInfo = null; + try { + assistPackageInfo = mPackageManager.getPackageInfo( + assistComponent.getPackageName(), 0, userId); + } catch (RemoteException e) { + Log.e(TAG, "PackageManagerService is dead"); + } - if (assistPackageInfo != null) { - final Icon assistIcon = Icon.createWithResource( - assistPackageInfo.applicationInfo.packageName, - assistPackageInfo.applicationInfo.icon); + if (assistPackageInfo != null) { + final Icon assistIcon = Icon.createWithResource( + assistPackageInfo.applicationInfo.packageName, + assistPackageInfo.applicationInfo.icon); - keyboardShortcutInfoAppItems.add(new KeyboardShortcutInfo( - mContext.getString(R.string.keyboard_shortcut_group_applications_assist), - assistIcon, - KeyEvent.KEYCODE_UNKNOWN, - KeyEvent.META_META_ON)); + keyboardShortcutInfoAppItems.add(new KeyboardShortcutInfo( + mContext.getString(R.string.keyboard_shortcut_group_applications_assist), + assistIcon, + KeyEvent.KEYCODE_UNKNOWN, + KeyEvent.META_META_ON)); + } } // Browser. 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/notification/NotificationTemplateViewWrapper.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationTemplateViewWrapper.java index 9bfa7a9752a8..bb979ebd1288 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationTemplateViewWrapper.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationTemplateViewWrapper.java @@ -25,7 +25,6 @@ import android.widget.ImageView; import android.widget.ProgressBar; import android.widget.TextView; -import com.android.systemui.R; import com.android.systemui.statusbar.CrossFadeHelper; import com.android.systemui.statusbar.ExpandableNotificationRow; import com.android.systemui.statusbar.TransformableView; @@ -48,7 +47,6 @@ public class NotificationTemplateViewWrapper extends NotificationHeaderViewWrapp private int mContentHeight; private int mMinHeightHint; - private boolean mColorized; protected NotificationTemplateViewWrapper(Context ctx, View view, ExpandableNotificationRow row) { @@ -164,9 +162,7 @@ public class NotificationTemplateViewWrapper extends NotificationHeaderViewWrapp public void onContentUpdated(ExpandableNotificationRow row) { // Reinspect the notification. Before the super call, because the super call also updates // the transformation types and we need to have our values set by then. - StatusBarNotification sbn = row.getStatusBarNotification(); - resolveTemplateViews(sbn); - mColorized = sbn.getNotification().isColorized(); + resolveTemplateViews(row.getStatusBarNotification()); super.onContentUpdated(row); } @@ -269,17 +265,6 @@ public class NotificationTemplateViewWrapper extends NotificationHeaderViewWrapp updateActionOffset(); } - @Override - public int getMinHeightIncrease(boolean useIncreasedCollapsedHeight) { - if (mColorized) { - int dimen = useIncreasedCollapsedHeight - ? R.dimen.notification_height_increase_colorized_increased - : R.dimen.notification_height_increase_colorized; - return mRow.getResources().getDimensionPixelSize(dimen); - } - return super.getMinHeightIncrease(useIncreasedCollapsedHeight); - } - private void updateActionOffset() { if (mActionsContainer != null) { // We should never push the actions higher than they are in the headsup view. diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationViewWrapper.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationViewWrapper.java index 085bce971ffc..5200d6962ed5 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationViewWrapper.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationViewWrapper.java @@ -190,14 +190,4 @@ public abstract class NotificationViewWrapper implements TransformableView { public boolean disallowSingleClick(float x, float y) { return false; } - - /** - * Get the amount that the minheight is allowed to be increased based on this layout. - * - * @param increasedHeight is the view allowed to show even bigger, i.e for messaging layouts - * @return - */ - public int getMinHeightIncrease(boolean increasedHeight) { - return 0; - } } 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 4739a2eed6de..67500bf4217d 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java @@ -2624,8 +2624,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/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/src/com/android/systemui/volume/ZenModePanel.java b/packages/SystemUI/src/com/android/systemui/volume/ZenModePanel.java index a3aca6e1b649..7bb987ca7cf0 100644 --- a/packages/SystemUI/src/com/android/systemui/volume/ZenModePanel.java +++ b/packages/SystemUI/src/com/android/systemui/volume/ZenModePanel.java @@ -524,18 +524,17 @@ public class ZenModePanel extends FrameLayout { bindGenericCountdown(); bindNextAlarm(getTimeUntilNextAlarmCondition()); } else if (isForever(c)) { + getConditionTagAt(FOREVER_CONDITION_INDEX).rb.setChecked(true); bindGenericCountdown(); bindNextAlarm(getTimeUntilNextAlarmCondition()); } else { if (isAlarm(c)) { bindGenericCountdown(); - bindNextAlarm(c); getConditionTagAt(COUNTDOWN_ALARM_CONDITION_INDEX).rb.setChecked(true); } else if (isCountdown(c)) { bindNextAlarm(getTimeUntilNextAlarmCondition()); - bind(c, mZenRadioGroupContent.getChildAt(COUNTDOWN_CONDITION_INDEX), COUNTDOWN_CONDITION_INDEX); getConditionTagAt(COUNTDOWN_CONDITION_INDEX).rb.setChecked(true); @@ -568,8 +567,8 @@ public class ZenModePanel extends FrameLayout { tag = (ConditionTag) alarmContent.getTag(); boolean showAlarm = tag != null && tag.condition != null; mZenRadioGroup.getChildAt(COUNTDOWN_ALARM_CONDITION_INDEX).setVisibility( - showAlarm ? View.VISIBLE : View.GONE); - alarmContent.setVisibility(showAlarm ? View.VISIBLE : View.GONE); + showAlarm ? View.VISIBLE : View.INVISIBLE); + alarmContent.setVisibility(showAlarm ? View.VISIBLE : View.INVISIBLE); } private Condition forever() { diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/AlphaControlledSignalTileViewTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/AlphaControlledSignalTileViewTest.java new file mode 100644 index 000000000000..3e677c01fd57 --- /dev/null +++ b/packages/SystemUI/tests/src/com/android/systemui/qs/AlphaControlledSignalTileViewTest.java @@ -0,0 +1,93 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.qs; + + +import static org.junit.Assert.assertTrue; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.atLeastOnce; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.verify; + +import android.content.Context; +import android.content.res.ColorStateList; +import android.graphics.drawable.Drawable; +import android.test.suitebuilder.annotation.SmallTest; +import com.android.systemui.SysuiTestCase; +import com.android.systemui.qs.AlphaControlledSignalTileView.AlphaControlledSlashDrawable; +import com.android.systemui.qs.AlphaControlledSignalTileView.AlphaControlledSlashImageView; +import org.junit.Test; + +@SmallTest +public class AlphaControlledSignalTileViewTest extends SysuiTestCase { + + private AlphaControlledSignalTileView mTileView; + + @Test + public void testTileView_createsAlphaControlledSlashImageView() { + mTileView = new AlphaControlledSignalTileView(mContext); + + assertTrue(mTileView.createSlashImageView(mContext) + instanceof AlphaControlledSlashImageView); + } + + /// AlphaControlledSlashImageView tests + @Test + public void testSlashImageView_createsAlphaControlledSlashDrawable() { + TestableSlashImageView iv = new TestableSlashImageView(mContext); + + iv.ensureSlashDrawable(); + assertTrue(iv.getSlashDrawable() instanceof AlphaControlledSlashDrawable); + } + + /// AlphaControlledSlashDrawable tests + @Test + public void testSlashDrawable_doesNotSetTintList() { + Drawable mockDrawable = mock(Drawable.class); + AlphaControlledSlashDrawable drawable = new AlphaControlledSlashDrawable(mockDrawable); + ColorStateList list = ColorStateList.valueOf(0xffffff); + drawable.setTintList(list); + verify(mockDrawable, never()).setTintList(any()); + } + + @Test + public void testSlashDrawable_setsFinalTintList() { + Drawable mockDrawable = mock(Drawable.class); + AlphaControlledSlashDrawable drawable = new AlphaControlledSlashDrawable(mockDrawable); + ColorStateList list = ColorStateList.valueOf(0xffffff); + drawable.setFinalTintList(list); + verify(mockDrawable, atLeastOnce()).setTintList(list); + } + + // Expose getSlashDrawable + private static class TestableSlashImageView extends AlphaControlledSlashImageView { + TestableSlashImageView(Context c) { + super(c); + } + + private SlashDrawable getSlashDrawable() { + return mSlash; + } + + @Override + protected void setSlash(SlashDrawable slash) { + super.setSlash(slash); + } + } +} 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 07302706d134..1b0ff216636b 100644 --- a/proto/src/metrics_constants.proto +++ b/proto/src/metrics_constants.proto @@ -4527,6 +4527,17 @@ message MetricsEvent { // Type TYPE_FAILURE: An invalid opperation was reported by the app's AutofillManager AUTOFILL_PENDING_SAVE_UI_OPERATION = 1134; + // Autofill service called API that disables itself + // Package: Package of the autofill service + // OS: O MR + AUTOFILL_SERVICE_DISABLED_SELF = 1135; + + // Counter showing how long it took (in ms) to show the autofill UI after a field was focused + // Tag FIELD_AUTOFILL_SERVICE: Package of service that processed the request + // Package: Package of the autofill service + // OS: O MR + AUTOFILL_UI_LATENCY = 1136; + // ---- End O-MR1 Constants, all O-MR1 constants go above this line ---- // OPEN: Settings > Network & Internet > Mobile network @@ -4610,6 +4621,16 @@ message MetricsEvent { // OS: P DIALOG_ENABLE_DEVELOPMENT_OPTIONS = 1158; + // OPEN: Settings > Developer options > OEM unlocking > Info dialog + // CATEGORY: SETTINGS + // 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/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java b/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java index 80b54770e4b7..a6aaaa673013 100644 --- a/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java +++ b/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java @@ -2427,14 +2427,14 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku out.attribute(null, "p", Integer.toHexString(widget.provider.tag)); } if (widget.options != null) { - out.attribute(null, "min_width", Integer.toHexString(widget.options.getInt( - AppWidgetManager.OPTION_APPWIDGET_MIN_WIDTH))); - out.attribute(null, "min_height", Integer.toHexString(widget.options.getInt( - AppWidgetManager.OPTION_APPWIDGET_MIN_HEIGHT))); - out.attribute(null, "max_width", Integer.toHexString(widget.options.getInt( - AppWidgetManager.OPTION_APPWIDGET_MAX_WIDTH))); - out.attribute(null, "max_height", Integer.toHexString(widget.options.getInt( - AppWidgetManager.OPTION_APPWIDGET_MAX_HEIGHT))); + int minWidth = widget.options.getInt(AppWidgetManager.OPTION_APPWIDGET_MIN_WIDTH); + int minHeight = widget.options.getInt(AppWidgetManager.OPTION_APPWIDGET_MIN_HEIGHT); + int maxWidth = widget.options.getInt(AppWidgetManager.OPTION_APPWIDGET_MAX_WIDTH); + int maxHeight = widget.options.getInt(AppWidgetManager.OPTION_APPWIDGET_MAX_HEIGHT); + out.attribute(null, "min_width", Integer.toHexString((minWidth > 0) ? minWidth : 0)); + out.attribute(null, "min_height", Integer.toHexString((minHeight > 0) ? minHeight : 0)); + out.attribute(null, "max_width", Integer.toHexString((maxWidth > 0) ? maxWidth : 0)); + out.attribute(null, "max_height", Integer.toHexString((maxHeight > 0) ? maxHeight : 0)); out.attribute(null, "host_category", Integer.toHexString(widget.options.getInt( AppWidgetManager.OPTION_APPWIDGET_HOST_CATEGORY))); } diff --git a/services/autofill/java/com/android/server/autofill/AutofillManagerService.java b/services/autofill/java/com/android/server/autofill/AutofillManagerService.java index a1c75bfc16c0..1f4161ac54d4 100644 --- a/services/autofill/java/com/android/server/autofill/AutofillManagerService.java +++ b/services/autofill/java/com/android/server/autofill/AutofillManagerService.java @@ -115,11 +115,24 @@ public final class AutofillManagerService extends SystemService { private final SparseBooleanArray mDisabledUsers = new SparseBooleanArray(); private final LocalLog mRequestsHistory = new LocalLog(20); + private final LocalLog mUiLatencyHistory = new LocalLog(20); private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { if (Intent.ACTION_CLOSE_SYSTEM_DIALOGS.equals(intent.getAction())) { + if (sDebug) Slog.d(TAG, "Close system dialogs"); + + // TODO(b/64940307): we need to destroy all sessions that are finished but showing + // Save UI because there is no way to show the Save UI back when the activity + // beneath it is brought back to top. Ideally, we should just hide the UI and + // bring it back when the activity resumes. + synchronized (mLock) { + for (int i = 0; i < mServicesCache.size(); i++) { + mServicesCache.valueAt(i).destroyFinishedSessionsLocked(); + } + } + mUi.hideAll(null); } } @@ -294,7 +307,7 @@ public final class AutofillManagerService extends SystemService { AutofillManagerServiceImpl service = mServicesCache.get(resolvedUserId); if (service == null) { service = new AutofillManagerServiceImpl(mContext, mLock, mRequestsHistory, - resolvedUserId, mUi, mDisabledUsers.get(resolvedUserId)); + mUiLatencyHistory, resolvedUserId, mUi, mDisabledUsers.get(resolvedUserId)); mServicesCache.put(userId, service); } return service; @@ -724,6 +737,8 @@ public final class AutofillManagerService extends SystemService { if (showHistory) { pw.println("Requests history:"); mRequestsHistory.reverseDump(fd, pw, args); + pw.println("UI latency history:"); + mUiLatencyHistory.reverseDump(fd, pw, args); } } finally { setDebugLocked(oldDebug); diff --git a/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java b/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java index 7212b2335a47..862070adbeee 100644 --- a/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java +++ b/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java @@ -35,6 +35,7 @@ import android.content.pm.PackageManager; import android.content.pm.ServiceInfo; import android.graphics.Rect; import android.graphics.drawable.Drawable; +import android.metrics.LogMaker; import android.os.AsyncTask; import android.os.Binder; import android.os.Bundle; @@ -63,6 +64,8 @@ import android.view.autofill.IAutoFillManagerClient; import com.android.internal.R; import com.android.internal.annotations.GuardedBy; +import com.android.internal.logging.MetricsLogger; +import com.android.internal.logging.nano.MetricsProto.MetricsEvent; import com.android.internal.os.HandlerCaller; import com.android.server.autofill.ui.AutoFillUI; @@ -89,6 +92,7 @@ final class AutofillManagerServiceImpl { private final Context mContext; private final Object mLock; private final AutoFillUI mUi; + private final MetricsLogger mMetricsLogger = new MetricsLogger(); private RemoteCallbackList<IAutoFillManagerClient> mClients; private AutofillServiceInfo mInfo; @@ -96,6 +100,8 @@ final class AutofillManagerServiceImpl { private static final Random sRandom = new Random(); private final LocalLog mRequestsHistory; + private final LocalLog mUiLatencyHistory; + /** * Whether service was disabled for user due to {@link UserManager} restrictions. */ @@ -137,10 +143,11 @@ final class AutofillManagerServiceImpl { private long mLastPrune = 0; AutofillManagerServiceImpl(Context context, Object lock, LocalLog requestsHistory, - int userId, AutoFillUI ui, boolean disabled) { + LocalLog uiLatencyHistory, int userId, AutoFillUI ui, boolean disabled) { mContext = context; mLock = lock; mRequestsHistory = requestsHistory; + mUiLatencyHistory = uiLatencyHistory; mUserId = userId; mUi = ui; updateLocked(disabled); @@ -218,8 +225,10 @@ final class AutofillManagerServiceImpl { if (serviceInfo != null) { mInfo = new AutofillServiceInfo(mContext.getPackageManager(), serviceComponent, mUserId); + if (sDebug) Slog.d(TAG, "Set component for user " + mUserId + " as " + mInfo); } else { mInfo = null; + if (sDebug) Slog.d(TAG, "Reset component for user " + mUserId); } final boolean isEnabled = isEnabled(); if (wasEnabled != isEnabled) { @@ -345,17 +354,31 @@ final class AutofillManagerServiceImpl { } void disableOwnedAutofillServicesLocked(int uid) { - if (mInfo == null || mInfo.getServiceInfo().applicationInfo.uid != uid) { + Slog.i(TAG, "disableOwnedServices(" + uid + "): " + mInfo); + if (mInfo == null) return; + + final ServiceInfo serviceInfo = mInfo.getServiceInfo(); + if (serviceInfo.applicationInfo.uid != uid) { + Slog.w(TAG, "disableOwnedServices(): ignored when called by UID " + uid + + " instead of " + serviceInfo.applicationInfo.uid + + " for service " + mInfo); return; } + + final long identity = Binder.clearCallingIdentity(); try { final String autoFillService = getComponentNameFromSettings(); - if (mInfo.getServiceInfo().getComponentName().equals( - ComponentName.unflattenFromString(autoFillService))) { + final ComponentName componentName = serviceInfo.getComponentName(); + if (componentName.equals(ComponentName.unflattenFromString(autoFillService))) { + mMetricsLogger.action(MetricsEvent.AUTOFILL_SERVICE_DISABLED_SELF, + componentName.getPackageName()); Settings.Secure.putStringForUser(mContext.getContentResolver(), Settings.Secure.AUTOFILL_SERVICE, null, mUserId); destroySessionsLocked(); + } else { + Slog.w(TAG, "disableOwnedServices(): ignored because current service (" + + serviceInfo + ") does not match Settings (" + autoFillService + ")"); } } finally { Binder.restoreCallingIdentity(identity); @@ -379,7 +402,7 @@ final class AutofillManagerServiceImpl { final Session newSession = new Session(this, mUi, mContext, mHandlerCaller, mUserId, mLock, sessionId, uid, activityToken, appCallbackToken, hasCallback, - mInfo.getServiceInfo().getComponentName(), packageName); + mUiLatencyHistory, mInfo.getServiceInfo().getComponentName(), packageName); mSessions.put(newSession.id, newSession); return newSession; @@ -452,7 +475,7 @@ final class AutofillManagerServiceImpl { final int sessionCount = mSessions.size(); for (int i = sessionCount - 1; i >= 0; i--) { final Session session = mSessions.valueAt(i); - if (session.isSaveUiPendingForToken(token)) { + if (session.isSaveUiPendingForTokenLocked(token)) { session.onPendingSaveUi(operation, token); return; } @@ -646,6 +669,18 @@ final class AutofillManagerServiceImpl { } } + // TODO(b/64940307): remove this method if SaveUI is refactored to be attached on activities + void destroyFinishedSessionsLocked() { + final int sessionCount = mSessions.size(); + for (int i = sessionCount - 1; i >= 0; i--) { + final Session session = mSessions.valueAt(i); + if (session.isSavingLocked()) { + if (sDebug) Slog.d(TAG, "destroyFinishedSessionsLocked(): " + session.id); + session.forceRemoveSelfLocked(); + } + } + } + void listSessionsLocked(ArrayList<String> output) { final int numSessions = mSessions.size(); for (int i = 0; i < numSessions; i++) { diff --git a/services/autofill/java/com/android/server/autofill/Session.java b/services/autofill/java/com/android/server/autofill/Session.java index ed3441ff7328..11478fe4f31a 100644 --- a/services/autofill/java/com/android/server/autofill/Session.java +++ b/services/autofill/java/com/android/server/autofill/Session.java @@ -50,6 +50,7 @@ import android.os.Bundle; import android.os.IBinder; import android.os.Parcelable; import android.os.RemoteException; +import android.os.SystemClock; import android.service.autofill.AutofillService; import android.service.autofill.Dataset; import android.service.autofill.FillContext; @@ -61,8 +62,10 @@ import android.service.autofill.SaveRequest; import android.service.autofill.ValueFinder; import android.util.ArrayMap; import android.util.ArraySet; +import android.util.LocalLog; import android.util.Slog; import android.util.SparseArray; +import android.util.TimeUtils; import android.view.autofill.AutofillId; import android.view.autofill.AutofillManager; import android.view.autofill.AutofillValue; @@ -183,6 +186,20 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState private ArrayList<String> mSelectedDatasetIds; /** + * When the session started (using elapsed time since boot). + */ + private final long mStartTime; + + /** + * When the UI was shown for the first time (using elapsed time since boot). + */ + @GuardedBy("mLock") + private long mUiShownTime; + + @GuardedBy("mLock") + private final LocalLog mUiLatencyHistory; + + /** * Receiver of assist data from the app's {@link Activity}. */ private final IResultReceiver mAssistReceiver = new IResultReceiver.Stub() { @@ -403,10 +420,11 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState Session(@NonNull AutofillManagerServiceImpl service, @NonNull AutoFillUI ui, @NonNull Context context, @NonNull HandlerCaller handlerCaller, int userId, @NonNull Object lock, int sessionId, int uid, @NonNull IBinder activityToken, - @NonNull IBinder client, boolean hasCallback, + @NonNull IBinder client, boolean hasCallback, @NonNull LocalLog uiLatencyHistory, @NonNull ComponentName componentName, @NonNull String packageName) { id = sessionId; this.uid = uid; + mStartTime = SystemClock.elapsedRealtime(); mService = service; mLock = lock; mUi = ui; @@ -414,6 +432,7 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState mRemoteFillService = new RemoteFillService(context, componentName, userId, this); mActivityToken = activityToken; mHasCallback = hasCallback; + mUiLatencyHistory = uiLatencyHistory; mPackageName = packageName; mClient = IAutoFillManagerClient.Stub.asInterface(client); @@ -1355,6 +1374,31 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState getUiForShowing().showFillUi(filledId, response, filterText, mService.getServicePackageName(), mPackageName, this); + + synchronized (mLock) { + if (mUiShownTime == 0) { + // Log first time UI is shown. + mUiShownTime = SystemClock.elapsedRealtime(); + final long duration = mUiShownTime - mStartTime; + if (sDebug) { + final StringBuilder msg = new StringBuilder("1st UI for ") + .append(mActivityToken) + .append(" shown in "); + TimeUtils.formatDuration(duration, msg); + Slog.d(TAG, msg.toString()); + } + final StringBuilder historyLog = new StringBuilder("id=").append(id) + .append(" app=").append(mActivityToken) + .append(" svc=").append(mService.getServicePackageName()) + .append(" latency="); + TimeUtils.formatDuration(duration, historyLog); + mUiLatencyHistory.log(historyLog.toString()); + + final LogMaker metricsLog = newLogMaker(MetricsEvent.AUTOFILL_UI_LATENCY) + .setCounterValue((int) duration); + mMetricsLogger.write(metricsLog); + } + } } boolean isDestroyed() { @@ -1376,7 +1420,7 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState if (mHasCallback) { mClient.notifyNoFillUi(id, mCurrentViewId, sessionFinished); } else if (sessionFinished) { - mClient.setSessionFinished(); + mClient.setSessionFinished(AutofillManager.STATE_FINISHED); } } catch (RemoteException e) { Slog.e(TAG, "Error notifying client no fill UI: id=" + mCurrentViewId, e); @@ -1663,6 +1707,14 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState pw.print(prefix); pw.print("uid: "); pw.println(uid); pw.print(prefix); pw.print("mPackagename: "); pw.println(mPackageName); pw.print(prefix); pw.print("mActivityToken: "); pw.println(mActivityToken); + pw.print(prefix); pw.print("mStartTime: "); pw.println(mStartTime); + pw.print(prefix); pw.print("Time to show UI: "); + if (mUiShownTime == 0) { + pw.println("N/A"); + } else { + TimeUtils.formatDuration(mUiShownTime - mStartTime, pw); + pw.println(); + } pw.print(prefix); pw.print("mResponses: "); if (mResponses == null) { pw.println("null"); @@ -1795,18 +1847,17 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState void forceRemoveSelfLocked() { if (sVerbose) Slog.v(TAG, "forceRemoveSelfLocked(): " + mPendingSaveUi); + final boolean isPendingSaveUi = isSaveUiPendingLocked(); mPendingSaveUi = null; removeSelfLocked(); - - mHandlerCaller.getHandler().post(() -> { + mUi.destroyAll(mPendingSaveUi, this, false); + if (!isPendingSaveUi) { try { - mClient.setState(mService.isEnabled(), true, false); + mClient.setSessionFinished(AutofillManager.STATE_UNKNOWN); } catch (RemoteException e) { - Slog.w(TAG, "error updating client state: " + e); + Slog.e(TAG, "Error notifying client to finish session", e); } - }); - - mUi.destroyAll(mPendingSaveUi, this, false); + } } /** @@ -1829,7 +1880,7 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState + id + " destroyed"); return; } - if (isSaveUiPending()) { + if (isSaveUiPendingLocked()) { Slog.i(TAG, "removeSelfLocked() ignored, waiting for pending save ui"); return; } @@ -1850,14 +1901,14 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState * a specific {@code token} created by * {@link PendingUi#PendingUi(IBinder, int, IAutoFillManagerClient)}. */ - boolean isSaveUiPendingForToken(@NonNull IBinder token) { - return isSaveUiPending() && token.equals(mPendingSaveUi.getToken()); + boolean isSaveUiPendingForTokenLocked(@NonNull IBinder token) { + return isSaveUiPendingLocked() && token.equals(mPendingSaveUi.getToken()); } /** * Checks whether this session is hiding the Save UI to handle a custom description link. */ - private boolean isSaveUiPending() { + private boolean isSaveUiPendingLocked() { return mPendingSaveUi != null && mPendingSaveUi.getState() == PendingUi.STATE_PENDING; } 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 32f4d69fc3e3..d48f23caedaa 100644 --- a/services/autofill/java/com/android/server/autofill/ui/SaveUi.java +++ b/services/autofill/java/com/android/server/autofill/ui/SaveUi.java @@ -263,9 +263,7 @@ final class SaveUi { } else { noButton.setText(R.string.autofill_save_no); } - final View.OnClickListener cancelListener = - (v) -> mListener.onCancel(info.getNegativeActionListener()); - noButton.setOnClickListener(cancelListener); + noButton.setOnClickListener((v) -> mListener.onCancel(info.getNegativeActionListener())); final View yesButton = view.findViewById(R.id.autofill_save_yes); yesButton.setOnClickListener((v) -> mListener.onSave()); @@ -273,8 +271,9 @@ final class SaveUi { mDialog = new Dialog(context, R.style.Theme_DeviceDefault_Light_Panel); mDialog.setContentView(view); - // Dialog can be dismissed when touched outside. - mDialog.setOnDismissListener((d) -> mListener.onCancel(info.getNegativeActionListener())); + // 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); @@ -305,7 +304,7 @@ final class SaveUi { if (actualWidth <= maxWidth && actualHeight <= maxHeight) { if (sDebug) { - Slog.d(TAG, "Addingservice icon " + Slog.d(TAG, "Adding service icon " + "(" + actualWidth + "x" + actualHeight + ") as it's less than maximum " + "(" + maxWidth + "x" + maxHeight + ")."); } 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 bfe50404a26a..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; @@ -128,7 +130,6 @@ import com.android.server.connectivity.DataConnectionStats; import com.android.server.connectivity.KeepaliveTracker; import com.android.server.connectivity.LingerMonitor; import com.android.server.connectivity.MockableSystemProperties; -import com.android.server.connectivity.Nat464Xlat; import com.android.server.connectivity.NetworkAgentInfo; import com.android.server.connectivity.NetworkDiagnostics; import com.android.server.connectivity.NetworkMonitor; @@ -781,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>(); @@ -2205,7 +2213,7 @@ public class ConnectivityService extends IConnectivityManager.Stub // A network factory has connected. Send it all current NetworkRequests. for (NetworkRequestInfo nri : mNetworkRequests.values()) { if (nri.request.isListen()) continue; - NetworkAgentInfo nai = mNetworkForRequestId.get(nri.request.requestId); + NetworkAgentInfo nai = getNetworkForRequest(nri.request.requestId); ac.sendMessage(android.net.NetworkFactory.CMD_REQUEST_NETWORK, (nai != null ? nai.getCurrentScore() : 0), 0, nri.request); } @@ -2282,9 +2290,9 @@ public class ConnectivityService extends IConnectivityManager.Stub // Remove all previously satisfied requests. for (int i = 0; i < nai.numNetworkRequests(); i++) { NetworkRequest request = nai.requestAt(i); - NetworkAgentInfo currentNetwork = mNetworkForRequestId.get(request.requestId); + NetworkAgentInfo currentNetwork = getNetworkForRequest(request.requestId); if (currentNetwork != null && currentNetwork.network.netId == nai.network.netId) { - mNetworkForRequestId.remove(request.requestId); + clearNetworkForRequest(request.requestId); sendUpdatedScoreToFactories(request, 0); } } @@ -2360,7 +2368,7 @@ public class ConnectivityService extends IConnectivityManager.Stub } } rematchAllNetworksAndRequests(null, 0); - if (nri.request.isRequest() && mNetworkForRequestId.get(nri.request.requestId) == null) { + if (nri.request.isRequest() && getNetworkForRequest(nri.request.requestId) == null) { sendUpdatedScoreToFactories(nri.request, 0); } } @@ -2415,7 +2423,7 @@ public class ConnectivityService extends IConnectivityManager.Stub // 2. Unvalidated WiFi will not be reaped when validated cellular // is currently satisfying the request. This is desirable when // WiFi ends up validating and out scoring cellular. - mNetworkForRequestId.get(nri.request.requestId).getCurrentScore() < + getNetworkForRequest(nri.request.requestId).getCurrentScore() < nai.getCurrentScoreAsValidated())) { return false; } @@ -2442,7 +2450,7 @@ public class ConnectivityService extends IConnectivityManager.Stub if (mNetworkRequests.get(nri.request) == null) { return; } - if (mNetworkForRequestId.get(nri.request.requestId) != null) { + if (getNetworkForRequest(nri.request.requestId) != null) { return; } if (VDBG || (DBG && nri.request.isRequest())) { @@ -2482,7 +2490,7 @@ public class ConnectivityService extends IConnectivityManager.Stub mNetworkRequestInfoLogs.log("RELEASE " + nri); if (nri.request.isRequest()) { boolean wasKept = false; - NetworkAgentInfo nai = mNetworkForRequestId.get(nri.request.requestId); + NetworkAgentInfo nai = getNetworkForRequest(nri.request.requestId); if (nai != null) { boolean wasBackgroundNetwork = nai.isBackgroundNetwork(); nai.removeRequest(nri.request.requestId); @@ -2499,7 +2507,7 @@ public class ConnectivityService extends IConnectivityManager.Stub } else { wasKept = true; } - mNetworkForRequestId.remove(nri.request.requestId); + clearNetworkForRequest(nri.request.requestId); if (!wasBackgroundNetwork && nai.isBackgroundNetwork()) { // Went from foreground to background. updateCapabilities(nai.getCurrentScore(), nai, nai.networkCapabilities); @@ -4296,7 +4304,8 @@ public class ConnectivityService extends IConnectivityManager.Stub * and the are the highest scored network available. * the are keyed off the Requests requestId. */ - // TODO: Yikes, this is accessed on multiple threads: add synchronization. + // NOTE: Accessed on multiple threads, must be synchronized on itself. + @GuardedBy("mNetworkForRequestId") private final SparseArray<NetworkAgentInfo> mNetworkForRequestId = new SparseArray<NetworkAgentInfo>(); @@ -4326,8 +4335,26 @@ public class ConnectivityService extends IConnectivityManager.Stub // priority networks like Wi-Fi are active. private final NetworkRequest mDefaultMobileDataRequest; + private NetworkAgentInfo getNetworkForRequest(int requestId) { + synchronized (mNetworkForRequestId) { + return mNetworkForRequestId.get(requestId); + } + } + + private void clearNetworkForRequest(int requestId) { + synchronized (mNetworkForRequestId) { + mNetworkForRequestId.remove(requestId); + } + } + + private void setNetworkForRequest(int requestId, NetworkAgentInfo nai) { + synchronized (mNetworkForRequestId) { + mNetworkForRequestId.put(requestId, nai); + } + } + private NetworkAgentInfo getDefaultNetwork() { - return mNetworkForRequestId.get(mDefaultRequest.requestId); + return getNetworkForRequest(mDefaultRequest.requestId); } private boolean isDefaultNetwork(NetworkAgentInfo nai) { @@ -4881,7 +4908,7 @@ public class ConnectivityService extends IConnectivityManager.Stub // requests or not, and doesn't affect the network's score. if (nri.request.isListen()) continue; - final NetworkAgentInfo currentNetwork = mNetworkForRequestId.get(nri.request.requestId); + final NetworkAgentInfo currentNetwork = getNetworkForRequest(nri.request.requestId); final boolean satisfies = newNetwork.satisfies(nri.request); if (newNetwork == currentNetwork && satisfies) { if (VDBG) { @@ -4913,7 +4940,7 @@ public class ConnectivityService extends IConnectivityManager.Stub if (VDBG) log(" accepting network in place of null"); } newNetwork.unlingerRequest(nri.request); - mNetworkForRequestId.put(nri.request.requestId, newNetwork); + setNetworkForRequest(nri.request.requestId, newNetwork); if (!newNetwork.addRequest(nri.request)) { Slog.wtf(TAG, "BUG: " + newNetwork.name() + " already has " + nri.request); } @@ -4947,7 +4974,7 @@ public class ConnectivityService extends IConnectivityManager.Stub } newNetwork.removeRequest(nri.request.requestId); if (currentNetwork == newNetwork) { - mNetworkForRequestId.remove(nri.request.requestId); + clearNetworkForRequest(nri.request.requestId); sendUpdatedScoreToFactories(nri.request, 0); } else { Slog.wtf(TAG, "BUG: Removing request " + nri.request.requestId + " from " + @@ -5522,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 8ae592f7978a..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))) { @@ -5285,7 +5299,7 @@ public class AccountManagerService == PackageManager.PERMISSION_GRANTED) { // Checks runtime permission revocation. final int opCode = AppOpsManager.permissionToOpCode(perm); - if (opCode == AppOpsManager.OP_NONE || mAppOpsManager.noteOp( + if (opCode == AppOpsManager.OP_NONE || mAppOpsManager.noteOpNoThrow( opCode, uid, packageName) == AppOpsManager.MODE_ALLOWED) { return true; } @@ -5306,7 +5320,7 @@ public class AccountManagerService Log.v(TAG, " caller uid " + callingUid + " has " + perm); } final int opCode = AppOpsManager.permissionToOpCode(perm); - if (opCode == AppOpsManager.OP_NONE || mAppOpsManager.noteOp( + if (opCode == AppOpsManager.OP_NONE || mAppOpsManager.noteOpNoThrow( opCode, callingUid, opPackageName) == AppOpsManager.MODE_ALLOWED) { return true; } 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/ActivityDisplay.java b/services/core/java/com/android/server/am/ActivityDisplay.java new file mode 100644 index 000000000000..5da9fb2ee8ee --- /dev/null +++ b/services/core/java/com/android/server/am/ActivityDisplay.java @@ -0,0 +1,201 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License + */ + +package com.android.server.am; + +import static android.view.Display.FLAG_PRIVATE; +import static android.view.Display.REMOVE_MODE_DESTROY_CONTENT; +import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_STACK; +import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_STACK; +import static com.android.server.am.ActivityManagerDebugConfig.TAG_AM; +import static com.android.server.am.ActivityManagerDebugConfig.TAG_WITH_CLASS_NAME; +import static com.android.server.am.proto.ActivityDisplayProto.CONFIGURATION_CONTAINER; +import static com.android.server.am.proto.ActivityDisplayProto.STACKS; +import static com.android.server.am.proto.ActivityDisplayProto.ID; + +import android.app.ActivityManagerInternal; +import android.util.IntArray; +import android.util.Slog; +import android.util.proto.ProtoOutputStream; +import android.view.Display; +import com.android.server.wm.ConfigurationContainer; + +import java.util.ArrayList; + +/** + * Exactly one of these classes per Display in the system. Capable of holding zero or more + * attached {@link ActivityStack}s. + */ +class ActivityDisplay extends ConfigurationContainer { + private static final String TAG = TAG_WITH_CLASS_NAME ? "ActivityDisplay" : TAG_AM; + private static final String TAG_STACK = TAG + POSTFIX_STACK; + + static final int POSITION_TOP = Integer.MAX_VALUE; + static final int POSITION_BOTTOM = Integer.MIN_VALUE; + + private ActivityStackSupervisor mSupervisor; + /** Actual Display this object tracks. */ + int mDisplayId; + Display mDisplay; + + /** All of the stacks on this display. Order matters, topmost stack is in front of all other + * stacks, bottommost behind. Accessed directly by ActivityManager package classes */ + final ArrayList<ActivityStack> mStacks = new ArrayList<>(); + + /** Array of all UIDs that are present on the display. */ + private IntArray mDisplayAccessUIDs = new IntArray(); + + /** All tokens used to put activities on this stack to sleep (including mOffToken) */ + final ArrayList<ActivityManagerInternal.SleepToken> mAllSleepTokens = new ArrayList<>(); + /** The token acquired by ActivityStackSupervisor to put stacks on the display to sleep */ + ActivityManagerInternal.SleepToken mOffToken; + + private boolean mSleeping; + + ActivityDisplay(ActivityStackSupervisor supervisor, int displayId) { + mSupervisor = supervisor; + mDisplayId = displayId; + final Display display = supervisor.mDisplayManager.getDisplay(displayId); + if (display == null) { + throw new IllegalStateException("Display does not exist displayId=" + displayId); + } + mDisplay = display; + } + + void addChild(ActivityStack stack, int position) { + if (position == POSITION_BOTTOM) { + position = 0; + } else if (position == POSITION_TOP) { + position = mStacks.size(); + } + if (DEBUG_STACK) Slog.v(TAG_STACK, "addChild: attaching " + stack + + " to displayId=" + mDisplayId + " position=" + position); + positionChildAt(stack, position); + mSupervisor.mService.updateSleepIfNeededLocked(); + } + + void removeChild(ActivityStack stack) { + if (DEBUG_STACK) Slog.v(TAG_STACK, "removeChild: detaching " + stack + + " from displayId=" + mDisplayId); + mStacks.remove(stack); + mSupervisor.mService.updateSleepIfNeededLocked(); + } + + void positionChildAtTop(ActivityStack stack) { + positionChildAt(stack, mStacks.size()); + } + + void positionChildAtBottom(ActivityStack stack) { + positionChildAt(stack, 0); + } + + private void positionChildAt(ActivityStack stack, int position) { + mStacks.remove(stack); + mStacks.add(getTopInsertPosition(stack, position), stack); + } + + private int getTopInsertPosition(ActivityStack stack, int candidatePosition) { + int position = mStacks.size(); + if (position > 0) { + final ActivityStack topStack = mStacks.get(position - 1); + if (topStack.getWindowConfiguration().isAlwaysOnTop() && topStack != stack) { + // If the top stack is always on top, we move this stack just below it. + position--; + } + } + return Math.min(position, candidatePosition); + } + + <T extends ActivityStack> T getStack(int stackId) { + for (int i = mStacks.size() - 1; i >= 0; --i) { + final ActivityStack stack = mStacks.get(i); + if (stack.mStackId == stackId) { + return (T) stack; + } + } + return null; + } + + @Override + public String toString() { + return "ActivityDisplay={" + mDisplayId + " numStacks=" + mStacks.size() + "}"; + } + + @Override + protected int getChildCount() { + return mStacks.size(); + } + + @Override + protected ConfigurationContainer getChildAt(int index) { + return mStacks.get(index); + } + + @Override + protected ConfigurationContainer getParent() { + return mSupervisor; + } + + boolean isPrivate() { + return (mDisplay.getFlags() & FLAG_PRIVATE) != 0; + } + + boolean isUidPresent(int uid) { + for (ActivityStack stack : mStacks) { + if (stack.isUidPresent(uid)) { + return true; + } + } + return false; + } + + /** Update and get all UIDs that are present on the display and have access to it. */ + IntArray getPresentUIDs() { + mDisplayAccessUIDs.clear(); + for (ActivityStack stack : mStacks) { + stack.getPresentUIDs(mDisplayAccessUIDs); + } + return mDisplayAccessUIDs; + } + + boolean shouldDestroyContentOnRemove() { + return mDisplay.getRemoveMode() == REMOVE_MODE_DESTROY_CONTENT; + } + + boolean shouldSleep() { + return (mStacks.isEmpty() || !mAllSleepTokens.isEmpty()) + && (mSupervisor.mService.mRunningVoice == null); + } + + boolean isSleeping() { + return mSleeping; + } + + void setIsSleeping(boolean asleep) { + mSleeping = asleep; + } + + public void writeToProto(ProtoOutputStream proto, long fieldId) { + final long token = proto.start(fieldId); + super.writeToProto(proto, CONFIGURATION_CONTAINER); + proto.write(ID, mDisplayId); + for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) { + final ActivityStack stack = mStacks.get(stackNdx); + stack.writeToProto(proto, STACKS); + } + proto.end(token); + } +} diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java index 5d200ae91e25..57bcda7a5646 100644 --- a/services/core/java/com/android/server/am/ActivityManagerService.java +++ b/services/core/java/com/android/server/am/ActivityManagerService.java @@ -145,7 +145,6 @@ import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_CLEANUP; import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_CONFIGURATION; import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_FOCUS; import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_IMMERSIVE; -import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_LOCKSCREEN; import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_LOCKTASK; import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_LRU; import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_MU; @@ -163,7 +162,6 @@ import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_SWITCH; import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_UID_OBSERVERS; import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_URI_PERMISSION; import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_VISIBILITY; -import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_VISIBLE_BEHIND; import static com.android.server.am.ActivityManagerDebugConfig.TAG_AM; import static com.android.server.am.ActivityManagerDebugConfig.TAG_WITH_CLASS_NAME; import static com.android.server.am.ActivityStackSupervisor.CREATE_IF_NEEDED; @@ -177,6 +175,7 @@ import static com.android.server.am.TaskRecord.INVALID_TASK_ID; import static com.android.server.am.TaskRecord.LOCK_TASK_AUTH_DONT_LOCK; import static com.android.server.am.TaskRecord.REPARENT_KEEP_STACK_AT_FRONT; import static com.android.server.am.TaskRecord.REPARENT_LEAVE_STACK_IN_PLACE; +import static com.android.server.am.proto.ActivityManagerServiceProto.ACTIVITIES; import static com.android.server.wm.AppTransition.TRANSIT_ACTIVITY_OPEN; import static com.android.server.wm.AppTransition.TRANSIT_ACTIVITY_RELAUNCH; import static com.android.server.wm.AppTransition.TRANSIT_NONE; @@ -349,6 +348,7 @@ import android.util.SparseArray; import android.util.SparseIntArray; import android.util.TimeUtils; import android.util.Xml; +import android.util.proto.ProtoOutputStream; import android.view.Gravity; import android.view.LayoutInflater; import android.view.View; @@ -402,6 +402,7 @@ import com.android.server.firewall.IntentFirewall; import com.android.server.job.JobSchedulerInternal; import com.android.server.pm.Installer; import com.android.server.pm.Installer.InstallerException; +import com.android.server.utils.PriorityDump; import com.android.server.vr.VrManagerInternal; import com.android.server.wm.PinnedStackWindowController; import com.android.server.wm.WindowManagerService; @@ -707,6 +708,42 @@ public class ActivityManagerService extends IActivityManager.Stub @VisibleForTesting long mWaitForNetworkTimeoutMs; + /** + * Helper class which parses out priority arguments and dumps sections according to their + * priority. If priority arguments are omitted, function calls the legacy dump command. + */ + private final PriorityDump.PriorityDumper mPriorityDumper = new PriorityDump.PriorityDumper() { + @Override + public void dumpCritical(FileDescriptor fd, PrintWriter pw, String[] args) { + doDump(fd, pw, new String[] {"activities"}); + } + + @Override + public void dumpNormal(FileDescriptor fd, PrintWriter pw, String[] args) { + doDump(fd, pw, new String[] {"settings"}); + doDump(fd, pw, new String[] {"intents"}); + doDump(fd, pw, new String[] {"broadcasts"}); + doDump(fd, pw, new String[] {"providers"}); + doDump(fd, pw, new String[] {"permissions"}); + doDump(fd, pw, new String[] {"services"}); + doDump(fd, pw, new String[] {"recents"}); + doDump(fd, pw, new String[] {"lastanr"}); + doDump(fd, pw, new String[] {"starter"}); + if (mAssociations.size() > 0) { + doDump(fd, pw, new String[] {"associations"}); + } + doDump(fd, pw, new String[] {"processes"}); + doDump(fd, pw, new String[] {"-v", "all"}); + doDump(fd, pw, new String[] {"service", "all"}); + doDump(fd, pw, new String[] {"provider", "all"}); + } + + @Override + public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { + doDump(fd, pw, args); + } + }; + public boolean canShowErrorDialogs() { return mShowDialogs && !mSleeping && !mShuttingDown && !mKeyguardController.isKeyguardShowing(DEFAULT_DISPLAY) @@ -2482,10 +2519,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) { @@ -2503,6 +2542,14 @@ public class ActivityManagerService extends IActivityManager.Stub static class MemBinder extends Binder { ActivityManagerService mActivityManagerService; + private final PriorityDump.PriorityDumper mPriorityDumper = + new PriorityDump.PriorityDumper() { + @Override + public void dumpNormal(FileDescriptor fd, PrintWriter pw, String[] args) { + mActivityManagerService.dumpApplicationMemoryUsage(fd, pw, " ", args, false, null); + } + }; + MemBinder(ActivityManagerService activityManagerService) { mActivityManagerService = activityManagerService; } @@ -2511,7 +2558,7 @@ public class ActivityManagerService extends IActivityManager.Stub protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { if (!DumpUtils.checkDumpAndUsageStatsPermission(mActivityManagerService.mContext, "meminfo", pw)) return; - mActivityManagerService.dumpApplicationMemoryUsage(fd, pw, " ", args, false, null); + PriorityDump.dump(mPriorityDumper, fd, pw, args); } } @@ -2545,19 +2592,27 @@ public class ActivityManagerService extends IActivityManager.Stub static class CpuBinder extends Binder { ActivityManagerService mActivityManagerService; + private final PriorityDump.PriorityDumper mPriorityDumper = + new PriorityDump.PriorityDumper() { + @Override + public void dumpCritical(FileDescriptor fd, PrintWriter pw, String[] args) { + if (!DumpUtils.checkDumpAndUsageStatsPermission(mActivityManagerService.mContext, + "cpuinfo", pw)) return; + synchronized (mActivityManagerService.mProcessCpuTracker) { + pw.print(mActivityManagerService.mProcessCpuTracker.printCurrentLoad()); + pw.print(mActivityManagerService.mProcessCpuTracker.printCurrentState( + SystemClock.uptimeMillis())); + } + } + }; + CpuBinder(ActivityManagerService activityManagerService) { mActivityManagerService = activityManagerService; } @Override protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { - if (!DumpUtils.checkDumpAndUsageStatsPermission(mActivityManagerService.mContext, - "cpuinfo", pw)) return; - synchronized (mActivityManagerService.mProcessCpuTracker) { - pw.print(mActivityManagerService.mProcessCpuTracker.printCurrentLoad()); - pw.print(mActivityManagerService.mProcessCpuTracker.printCurrentState( - SystemClock.uptimeMillis())); - } + PriorityDump.dump(mPriorityDumper, fd, pw, args); } } @@ -6097,7 +6152,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); } @@ -7255,33 +7310,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(); } } @@ -10996,7 +11050,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; @@ -11384,7 +11438,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 " @@ -12014,9 +12068,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(); @@ -12434,7 +12486,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); @@ -14014,9 +14066,8 @@ public class ActivityManagerService extends IActivityManager.Stub } retrieveSettings(); - final int currentUserId; + final int currentUserId = mUserController.getCurrentUserId(); synchronized (this) { - currentUserId = mUserController.getCurrentUserIdLocked(); readGrantedUriPermissionsLocked(); } @@ -14095,7 +14146,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 } @@ -14793,6 +14844,13 @@ public class ActivityManagerService extends IActivityManager.Stub @Override protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { + PriorityDump.dump(mPriorityDumper, fd, pw, args); + } + + /** + * Wrapper function to print out debug data filtered by specified arguments. + */ + private void doDump(FileDescriptor fd, PrintWriter pw, String[] args) { if (!DumpUtils.checkDumpAndUsageStatsPermission(mContext, TAG, pw)) return; boolean dumpAll = false; @@ -14801,6 +14859,7 @@ public class ActivityManagerService extends IActivityManager.Stub boolean dumpCheckinFormat = false; boolean dumpVisibleStacksOnly = false; boolean dumpFocusedStackOnly = false; + boolean useProto = false; String dumpPackage = null; int opti = 0; @@ -14834,12 +14893,26 @@ public class ActivityManagerService extends IActivityManager.Stub } else if ("-h".equals(opt)) { ActivityManagerShellCommand.dumpHelp(pw, true); return; + } else if ("--proto".equals(opt)) { + useProto = true; } else { pw.println("Unknown argument: " + opt + "; use -h for help"); } } long origId = Binder.clearCallingIdentity(); + + if (useProto) { + //TODO: Options when dumping proto + final ProtoOutputStream proto = new ProtoOutputStream(fd); + synchronized (this) { + writeActivitiesToProtoLocked(proto); + } + proto.flush(); + Binder.restoreCallingIdentity(origId); + return; + } + boolean more = false; // Is the caller requesting to dump a particular piece of data? if (opti < args.length) { @@ -15183,6 +15256,10 @@ public class ActivityManagerService extends IActivityManager.Stub Binder.restoreCallingIdentity(origId); } + private void writeActivitiesToProtoLocked(ProtoOutputStream proto) { + mStackSupervisor.writeToProto(proto, ACTIVITIES); + } + private void dumpLastANRLocked(PrintWriter pw) { pw.println("ACTIVITY MANAGER LAST ANR (dumpsys activity lastanr)"); if (mLastANRState == null) { @@ -18897,7 +18974,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())) { @@ -19316,7 +19393,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}; @@ -19981,7 +20058,10 @@ public class ActivityManagerService extends IActivityManager.Stub synchronized (this) { final long origId = Binder.clearCallingIdentity(); try { - mStackSupervisor.moveTasksToFullscreenStackLocked(fromStackId, onTop); + final ActivityStack stack = mStackSupervisor.getStack(fromStackId); + if (stack != null){ + mStackSupervisor.moveTasksToFullscreenStackLocked(stack, onTop); + } } finally { Binder.restoreCallingIdentity(origId); } @@ -20079,7 +20159,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 */, @@ -20190,7 +20270,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); @@ -22121,7 +22201,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); @@ -23430,10 +23510,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 @@ -23448,9 +23526,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 @@ -23464,9 +23540,7 @@ public class ActivityManagerService extends IActivityManager.Stub Slog.w(TAG, msg); throw new SecurityException(msg); } - synchronized (this) { - return mUserController.getStartedUserArrayLocked(); - } + return mUserController.getStartedUserArray(); } @Override @@ -23487,9 +23561,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) { @@ -24077,7 +24149,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/ActivityManagerShellCommand.java b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java index 0aca9ea6d748..5e0724e94b41 100644 --- a/services/core/java/com/android/server/am/ActivityManagerShellCommand.java +++ b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java @@ -2675,6 +2675,7 @@ final class ActivityManagerShellCommand extends ShellCommand { pw.println(" -p: limit output to given package."); pw.println(" --checkin: output checkin format, resetting data."); pw.println(" --C: output checkin format, not resetting data."); + pw.println(" --proto: output dump in protocol buffer format."); } else { pw.println("Activity manager (activity) commands:"); pw.println(" help"); diff --git a/services/core/java/com/android/server/am/ActivityRecord.java b/services/core/java/com/android/server/am/ActivityRecord.java index 49082334db8c..193443691ee5 100644 --- a/services/core/java/com/android/server/am/ActivityRecord.java +++ b/services/core/java/com/android/server/am/ActivityRecord.java @@ -112,6 +112,16 @@ import static com.android.server.am.EventLogTags.AM_RELAUNCH_RESUME_ACTIVITY; import static com.android.server.am.TaskPersister.DEBUG; import static com.android.server.am.TaskPersister.IMAGE_EXTENSION; import static com.android.server.am.TaskRecord.INVALID_TASK_ID; +import static com.android.server.am.proto.ActivityRecordProto.CONFIGURATION_CONTAINER; +import static com.android.server.am.proto.ActivityRecordProto.FRONT_OF_TASK; +import static com.android.server.am.proto.ActivityRecordProto.IDENTIFIER; +import static com.android.server.am.proto.ActivityRecordProto.PROC_ID; +import static com.android.server.am.proto.ActivityRecordProto.STATE; +import static com.android.server.am.proto.ActivityRecordProto.VISIBLE; +import static com.android.server.wm.proto.IdentifierProto.HASH_CODE; +import static com.android.server.wm.proto.IdentifierProto.TITLE; +import static com.android.server.wm.proto.IdentifierProto.USER_ID; + import static org.xmlpull.v1.XmlPullParser.END_DOCUMENT; import static org.xmlpull.v1.XmlPullParser.END_TAG; import static org.xmlpull.v1.XmlPullParser.START_TAG; @@ -149,6 +159,7 @@ import android.util.Log; import android.util.MergedConfiguration; import android.util.Slog; import android.util.TimeUtils; +import android.util.proto.ProtoOutputStream; import android.view.AppTransitionAnimationSpec; import android.view.IAppTransitionAnimationSpecsFuture; import android.view.IApplicationToken; @@ -1937,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 */)); } /** @@ -2301,7 +2312,7 @@ final class ActivityRecord extends ConfigurationContainer implements AppWindowCo // be visible based on the stack, task, and lockscreen state and use that here instead. The // method should be based on the logic in ActivityStack.ensureActivitiesVisibleLocked(). // Skip updating configuration for activity is a stack that shouldn't be visible. - if (stack.shouldBeVisible(null /* starting */) == STACK_INVISIBLE) { + if (!stack.shouldBeVisible(null /* starting */)) { if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION, "Skipping config check invisible stack: " + this); return true; @@ -2773,4 +2784,25 @@ final class ActivityRecord extends ConfigurationContainer implements AppWindowCo stringName = sb.toString(); return toString(); } + + void writeIdentifierToProto(ProtoOutputStream proto, long fieldId) { + final long token = proto.start(fieldId); + proto.write(HASH_CODE, System.identityHashCode(this)); + proto.write(USER_ID, userId); + proto.write(TITLE, intent.getComponent().flattenToShortString()); + proto.end(token); + } + + public void writeToProto(ProtoOutputStream proto, long fieldId) { + final long token = proto.start(fieldId); + super.writeToProto(proto, CONFIGURATION_CONTAINER); + writeIdentifierToProto(proto, IDENTIFIER); + proto.write(STATE, state.toString()); + proto.write(VISIBLE, visible); + proto.write(FRONT_OF_TASK, frontOfTask); + if (app != null) { + proto.write(PROC_ID, app.pid); + } + proto.end(token); + } } diff --git a/services/core/java/com/android/server/am/ActivityStack.java b/services/core/java/com/android/server/am/ActivityStack.java index 6140c266f96b..829669327bf4 100644 --- a/services/core/java/com/android/server/am/ActivityStack.java +++ b/services/core/java/com/android/server/am/ActivityStack.java @@ -29,6 +29,7 @@ import static android.app.WindowConfiguration.ACTIVITY_TYPE_ASSISTANT; import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME; import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD; import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED; +import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY; import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED; import static android.content.pm.ActivityInfo.CONFIG_SCREEN_LAYOUT; import static android.content.pm.ActivityInfo.FLAG_RESUME_WHILE_PAUSING; @@ -37,6 +38,8 @@ import static android.view.Display.DEFAULT_DISPLAY; import static android.view.Display.FLAG_CAN_SHOW_WITH_INSECURE_KEYGUARD; import static android.view.Display.INVALID_DISPLAY; +import static com.android.server.am.ActivityDisplay.POSITION_BOTTOM; +import static com.android.server.am.ActivityDisplay.POSITION_TOP; import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_ADD_REMOVE; import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_ALL; import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_APP; @@ -78,6 +81,13 @@ import static com.android.server.am.ActivityStackSupervisor.ON_TOP; import static com.android.server.am.ActivityStackSupervisor.PAUSE_IMMEDIATELY; import static com.android.server.am.ActivityStackSupervisor.PRESERVE_WINDOWS; import static com.android.server.am.ActivityStackSupervisor.REMOVE_FROM_RECENTS; +import static com.android.server.am.proto.ActivityStackProto.BOUNDS; +import static com.android.server.am.proto.ActivityStackProto.CONFIGURATION_CONTAINER; +import static com.android.server.am.proto.ActivityStackProto.DISPLAY_ID; +import static com.android.server.am.proto.ActivityStackProto.FULLSCREEN; +import static com.android.server.am.proto.ActivityStackProto.ID; +import static com.android.server.am.proto.ActivityStackProto.RESUMED_ACTIVITY; +import static com.android.server.am.proto.ActivityStackProto.TASKS; import static com.android.server.wm.AppTransition.TRANSIT_ACTIVITY_CLOSE; import static com.android.server.wm.AppTransition.TRANSIT_ACTIVITY_OPEN; import static com.android.server.wm.AppTransition.TRANSIT_NONE; @@ -86,6 +96,7 @@ import static com.android.server.wm.AppTransition.TRANSIT_TASK_OPEN; import static com.android.server.wm.AppTransition.TRANSIT_TASK_OPEN_BEHIND; import static com.android.server.wm.AppTransition.TRANSIT_TASK_TO_BACK; import static com.android.server.wm.AppTransition.TRANSIT_TASK_TO_FRONT; + import static java.lang.Integer.MAX_VALUE; import android.app.Activity; @@ -122,6 +133,7 @@ import android.util.IntArray; import android.util.Log; import android.util.Slog; import android.util.SparseArray; +import android.util.proto.ProtoOutputStream; import android.view.Display; import com.android.internal.annotations.VisibleForTesting; @@ -258,7 +270,6 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai final ActivityManagerService mService; private final WindowManagerService mWindowManager; T mWindowContainerController; - private final RecentTasks mRecentTasks; /** * The back history of all previous (and possibly still @@ -341,9 +352,6 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai int mCurrentUser; final int mStackId; - /** The other stacks, in order, on the attached display. Updated at attach/detach time. */ - // TODO: This list doesn't belong here... - ArrayList<ActivityStack> mStacks; /** The attached Display's unique identifier, or -1 if detached */ int mDisplayId; @@ -452,22 +460,20 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai return count; } - ActivityStack(ActivityStackSupervisor.ActivityDisplay display, int stackId, - ActivityStackSupervisor supervisor, RecentTasks recentTasks, boolean onTop) { + ActivityStack(ActivityDisplay display, int stackId, ActivityStackSupervisor supervisor, + boolean onTop) { mStackSupervisor = supervisor; mService = supervisor.mService; mHandler = new ActivityStackHandler(mService.mHandler.getLooper()); mWindowManager = mService.mWindowManager; mStackId = stackId; - mCurrentUser = mService.mUserController.getCurrentUserIdLocked(); - mRecentTasks = recentTasks; + mCurrentUser = mService.mUserController.getCurrentUserId(); mTaskPositioner = mStackId == FREEFORM_WORKSPACE_STACK_ID ? new LaunchingTaskPositioner() : null; mTmpRect2.setEmpty(); updateOverrideConfiguration(); mWindowContainerController = createStackWindowController(display.mDisplayId, onTop, mTmpRect2); - mStackSupervisor.mStacks.put(mStackId, this); postAddToDisplay(display, mTmpRect2.isEmpty() ? null : mTmpRect2, onTop); } @@ -494,7 +500,7 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai } /** Adds the stack to specified display and calls WindowManager to do the same. */ - void reparent(ActivityStackSupervisor.ActivityDisplay activityDisplay, boolean onTop) { + void reparent(ActivityDisplay activityDisplay, boolean onTop) { removeFromDisplay(); mTmpRect2.setEmpty(); postAddToDisplay(activityDisplay, mTmpRect2.isEmpty() ? null : mTmpRect2, onTop); @@ -512,10 +518,9 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai * @param activityDisplay New display to which this stack was attached. * @param bounds Updated bounds. */ - private void postAddToDisplay(ActivityStackSupervisor.ActivityDisplay activityDisplay, + private void postAddToDisplay(ActivityDisplay activityDisplay, Rect bounds, boolean onTop) { mDisplayId = activityDisplay.mDisplayId; - mStacks = activityDisplay.mStacks; mBounds = bounds != null ? new Rect(bounds) : null; mFullscreen = mBounds == null; if (mTaskPositioner != null) { @@ -524,7 +529,7 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai } onParentChanged(); - activityDisplay.attachStack(this, findStackInsertIndex(onTop)); + activityDisplay.addChild(this, onTop ? POSITION_TOP : POSITION_BOTTOM); if (mStackId == DOCKED_STACK_ID) { // If we created a docked stack we want to resize it so it resizes all other stacks // in the system. @@ -538,33 +543,31 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai * either destroyed completely or re-parented. */ private void removeFromDisplay() { - final ActivityStackSupervisor.ActivityDisplay display = getDisplay(); + if (getWindowingMode() == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY) { + // If we removed a docked stack we want to resize it so it resizes all other stacks + // in the system to fullscreen. + mStackSupervisor.resizeDockedStackLocked( + null, null, null, null, null, PRESERVE_WINDOWS); + } + final ActivityDisplay display = getDisplay(); if (display != null) { - display.detachStack(this); + display.removeChild(this); } mDisplayId = INVALID_DISPLAY; - mStacks = null; if (mTaskPositioner != null) { mTaskPositioner.reset(); } - if (mStackId == DOCKED_STACK_ID) { - // If we removed a docked stack we want to resize it so it resizes all other stacks - // in the system to fullscreen. - mStackSupervisor.resizeDockedStackLocked( - null, null, null, null, null, PRESERVE_WINDOWS); - } } /** Removes the stack completely. Also calls WindowManager to do the same on its side. */ void remove() { removeFromDisplay(); - mStackSupervisor.mStacks.remove(mStackId); mWindowContainerController.removeContainer(); mWindowContainerController = null; onParentChanged(); } - ActivityStackSupervisor.ActivityDisplay getDisplay() { + ActivityDisplay getDisplay() { return mStackSupervisor.getActivityDisplay(mDisplayId); } @@ -849,7 +852,7 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai } final boolean isOnHomeDisplay() { - return isAttached() && mDisplayId == DEFAULT_DISPLAY; + return mDisplayId == DEFAULT_DISPLAY; } void moveToFront(String reason) { @@ -865,8 +868,7 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai return; } - mStacks.remove(this); - mStacks.add(findStackInsertIndex(ON_TOP), this); + getDisplay().positionChildAtTop(this); mStackSupervisor.setFocusStackUnchecked(reason, this); if (task != null) { insertTaskAtTop(task, null); @@ -880,45 +882,6 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai } } - /** - * @param task If non-null, the task will be moved to the back of the stack. - * */ - private void moveToBack(TaskRecord task) { - if (!isAttached()) { - return; - } - - mStacks.remove(this); - mStacks.add(0, this); - - if (task != null) { - mTaskHistory.remove(task); - mTaskHistory.add(0, task); - updateTaskMovement(task, false); - mWindowContainerController.positionChildAtBottom(task.getWindowContainerController()); - } - } - - /** - * @return the index to insert a new stack into, taking the always-on-top stacks into account. - */ - private int findStackInsertIndex(boolean onTop) { - if (onTop) { - int addIndex = mStacks.size(); - if (addIndex > 0) { - final ActivityStack topStack = mStacks.get(addIndex - 1); - if (topStack.getWindowConfiguration().isAlwaysOnTop() - && topStack != this) { - // If the top stack is always on top, we move this stack just below it. - addIndex--; - } - } - return addIndex; - } else { - return 0; - } - } - boolean isFocusable() { if (getWindowConfiguration().canReceiveKeys()) { return true; @@ -930,7 +893,7 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai } final boolean isAttached() { - return mStacks != null; + return getParent() != null; } /** @@ -1105,13 +1068,6 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai "Launch completed; removing icicle of " + r.icicle); } - void addRecentActivityLocked(ActivityRecord r) { - if (r != null) { - final TaskRecord task = r.getTask(); - mRecentTasks.addLocked(task); - task.touchActiveTime(); - } - } private void startLaunchTraces(String packageName) { if (mFullyDrawnStartTime != 0) { @@ -1559,54 +1515,6 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai } } - // Find the first visible activity above the passed activity and if it is translucent return it - // otherwise return null; - ActivityRecord findNextTranslucentActivity(ActivityRecord r) { - TaskRecord task = r.getTask(); - if (task == null) { - return null; - } - - final ActivityStack stack = task.getStack(); - if (stack == null) { - return null; - } - - int stackNdx = mStacks.indexOf(stack); - - ArrayList<TaskRecord> tasks = stack.mTaskHistory; - int taskNdx = tasks.indexOf(task); - - ArrayList<ActivityRecord> activities = task.mActivities; - int activityNdx = activities.indexOf(r) + 1; - - final int numStacks = mStacks.size(); - while (stackNdx < numStacks) { - final ActivityStack historyStack = mStacks.get(stackNdx); - tasks = historyStack.mTaskHistory; - final int numTasks = tasks.size(); - while (taskNdx < numTasks) { - final TaskRecord currentTask = tasks.get(taskNdx); - activities = currentTask.mActivities; - final int numActivities = activities.size(); - while (activityNdx < numActivities) { - final ActivityRecord activity = activities.get(activityNdx); - if (!activity.finishing) { - return historyStack.mFullscreen - && currentTask.mFullscreen && activity.fullscreen ? null : activity; - } - ++activityNdx; - } - activityNdx = 0; - ++taskNdx; - } - taskNdx = 0; - ++stackNdx; - } - - return null; - } - /** Returns true if the stack contains a fullscreen task. */ private boolean hasFullscreenTask() { for (int i = mTaskHistory.size() - 1; i >= 0; --i) { @@ -1670,26 +1578,26 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai } /** - * Returns what the stack visibility should be: {@link #STACK_INVISIBLE} or - * {@link #STACK_VISIBLE}. + * Returns true if the stack should be visible. * * @param starting The currently starting activity or null if there is none. */ - int shouldBeVisible(ActivityRecord starting) { + boolean shouldBeVisible(ActivityRecord starting) { if (!isAttached() || mForceHidden) { - return STACK_INVISIBLE; + return false; } if (mStackSupervisor.isFrontStackOnDisplay(this) || mStackSupervisor.isFocusedStack(this)) { - return STACK_VISIBLE; + return true; } - final int stackIndex = mStacks.indexOf(this); + final ArrayList<ActivityStack> displayStacks = getDisplay().mStacks; + final int stackIndex = displayStacks.indexOf(this); - if (stackIndex == mStacks.size() - 1) { + if (stackIndex == displayStacks.size() - 1) { Slog.wtf(TAG, "Stack=" + this + " isn't front stack but is at the top of the stack list"); - return STACK_INVISIBLE; + return false; } // Check position and visibility of this stack relative to the front stack on its display. @@ -1700,43 +1608,43 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai // If the assistant stack is focused and translucent, then the docked stack is always // visible if (topStack.isActivityTypeAssistant()) { - return (topStack.isStackTranslucent(starting, DOCKED_STACK_ID)) ? STACK_VISIBLE - : STACK_INVISIBLE; + return topStack.isStackTranslucent(starting, DOCKED_STACK_ID); } - return STACK_VISIBLE; + return true; } // Set home stack to invisible when it is below but not immediately below the docked stack // A case would be if recents stack exists but has no tasks and is below the docked stack // and home stack is below recents if (mStackId == HOME_STACK_ID) { - int dockedStackIndex = mStacks.indexOf(mStackSupervisor.getStack(DOCKED_STACK_ID)); + int dockedStackIndex = displayStacks.indexOf + (mStackSupervisor.getStack(DOCKED_STACK_ID)); if (dockedStackIndex > stackIndex && stackIndex != dockedStackIndex - 1) { - return STACK_INVISIBLE; + return false; } } // Find the first stack behind front stack that actually got something visible. - int stackBehindTopIndex = mStacks.indexOf(topStack) - 1; + int stackBehindTopIndex = displayStacks.indexOf(topStack) - 1; while (stackBehindTopIndex >= 0 && - mStacks.get(stackBehindTopIndex).topRunningActivityLocked() == null) { + displayStacks.get(stackBehindTopIndex).topRunningActivityLocked() == null) { stackBehindTopIndex--; } final int stackBehindTopId = (stackBehindTopIndex >= 0) - ? mStacks.get(stackBehindTopIndex).mStackId : INVALID_STACK_ID; + ? displayStacks.get(stackBehindTopIndex).mStackId : INVALID_STACK_ID; final boolean alwaysOnTop = topStack.getWindowConfiguration().isAlwaysOnTop(); if (topStackId == DOCKED_STACK_ID || alwaysOnTop) { if (stackIndex == stackBehindTopIndex) { // Stacks directly behind the docked or pinned stack are always visible. - return STACK_VISIBLE; + return true; } else if (alwaysOnTop && stackIndex == stackBehindTopIndex - 1) { // Otherwise, this stack can also be visible if it is directly behind a docked stack // or translucent assistant stack behind an always-on-top top-most stack if (stackBehindTopId == DOCKED_STACK_ID) { - return STACK_VISIBLE; + return true; } else if (stackBehindTopId == ASSISTANT_STACK_ID) { - return mStacks.get(stackBehindTopIndex).isStackTranslucent(starting, mStackId) - ? STACK_VISIBLE : STACK_INVISIBLE; + return displayStacks.get(stackBehindTopIndex).isStackTranslucent( + starting, mStackId); } } } @@ -1747,7 +1655,7 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai // always visible so they can act as a backdrop to the translucent activity. // For example, dialog activities if (stackIndex == stackBehindTopIndex) { - return STACK_VISIBLE; + return true; } if (stackBehindTopIndex >= 0) { if ((stackBehindTopId == DOCKED_STACK_ID @@ -1755,18 +1663,18 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai && stackIndex == (stackBehindTopIndex - 1)) { // The stack behind the docked or pinned stack is also visible so we can have a // complete backdrop to the translucent activity when the docked stack is up. - return STACK_VISIBLE; + return true; } } } if (StackId.isStaticStack(mStackId)) { // Visibility of any static stack should have been determined by the conditions above. - return STACK_INVISIBLE; + return false; } - for (int i = stackIndex + 1; i < mStacks.size(); i++) { - final ActivityStack stack = mStacks.get(i); + for (int i = stackIndex + 1; i < displayStacks.size(); i++) { + final ActivityStack stack = displayStacks.get(i); if (!stack.mFullscreen && !stack.hasFullscreenTask()) { continue; @@ -1774,15 +1682,15 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai if (!StackId.isDynamicStacksVisibleBehindAllowed(stack.mStackId)) { // These stacks can't have any dynamic stacks visible behind them. - return STACK_INVISIBLE; + return false; } if (!stack.isStackTranslucent(starting, INVALID_STACK_ID)) { - return STACK_INVISIBLE; + return false; } } - return STACK_VISIBLE; + return true; } final int rankTaskLayers(int baseLayer) { @@ -1819,12 +1727,10 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai // If the top activity is not fullscreen, then we need to // make sure any activities under it are now visible. boolean aboveTop = top != null; - final int stackVisibility = shouldBeVisible(starting); - final boolean stackInvisible = stackVisibility != STACK_VISIBLE; - boolean behindFullscreenActivity = stackInvisible; + final boolean stackVisible = shouldBeVisible(starting); + boolean behindFullscreenActivity = !stackVisible; boolean resumeNextActivity = mStackSupervisor.isFocusedStack(this) && (isInStackLocked(starting) == null); - boolean behindTranslucentActivity = false; for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) { final TaskRecord task = mTaskHistory.get(taskNdx); final ArrayList<ActivityRecord> activities = task.mActivities; @@ -1848,11 +1754,8 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai final boolean reallyVisible = checkKeyguardVisibility(r, visibleIgnoringKeyguard, isTop); if (visibleIgnoringKeyguard) { - behindFullscreenActivity = updateBehindFullscreen(stackInvisible, + behindFullscreenActivity = updateBehindFullscreen(!stackVisible, behindFullscreenActivity, task, r); - if (behindFullscreenActivity && !r.fullscreen) { - behindTranslucentActivity = true; - } } if (reallyVisible) { if (DEBUG_VISIBILITY) Slog.v(TAG_VISIBILITY, "Make visible? " + r @@ -1888,10 +1791,10 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai configChanges |= r.configChangeFlags; } else { if (DEBUG_VISIBILITY) Slog.v(TAG_VISIBILITY, "Make invisible? " + r - + " finishing=" + r.finishing + " state=" + r.state + " stackInvisible=" - + stackInvisible + " behindFullscreenActivity=" - + behindFullscreenActivity + " mLaunchTaskBehind=" - + r.mLaunchTaskBehind); + + " finishing=" + r.finishing + " state=" + r.state + + " stackVisible=" + stackVisible + + " behindFullscreenActivity=" + behindFullscreenActivity + + " mLaunchTaskBehind=" + r.mLaunchTaskBehind); makeInvisible(r); } } @@ -1899,10 +1802,10 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai // The visibility of tasks and the activities they contain in freeform stack are // determined individually unlike other stacks where the visibility or fullscreen // status of an activity in a previous task affects other. - behindFullscreenActivity = stackVisibility == STACK_INVISIBLE; + behindFullscreenActivity = !stackVisible; } else if (mStackId == HOME_STACK_ID) { if (DEBUG_VISIBILITY) Slog.v(TAG_VISIBILITY, "Home task: at " + task - + " stackInvisible=" + stackInvisible + + " stackVisible=" + stackVisible + " behindFullscreenActivity=" + behindFullscreenActivity); // No other task in the home stack should be visible behind the home activity. // Home activities is usually a translucent activity with the wallpaper behind @@ -2003,7 +1906,7 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai * {@link Display#FLAG_CAN_SHOW_WITH_INSECURE_KEYGUARD} applied. */ private boolean canShowWithInsecureKeyguard() { - final ActivityStackSupervisor.ActivityDisplay activityDisplay = getDisplay(); + final ActivityDisplay activityDisplay = getDisplay(); if (activityDisplay == null) { throw new IllegalStateException("Stack is not attached to any display, stackId=" + mStackId); @@ -2183,7 +2086,7 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai // activities as we need to display their starting window until they are done initializing. boolean behindFullscreenActivity = false; - if (shouldBeVisible(null) == STACK_INVISIBLE) { + if (!shouldBeVisible(null)) { // The stack is not visible, so no activity in it should be displaying a starting // window. Mark all activities below top and behind fullscreen. aboveTop = false; @@ -2233,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; } @@ -2259,9 +2169,7 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai mResumedActivity = r; r.state = ActivityState.RESUMED; mService.setResumedActivityUncheckLocked(r, reason); - final TaskRecord task = r.getTask(); - task.touchActiveTime(); - mRecentTasks.addLocked(task); + mStackSupervisor.addRecentActivity(r); } private boolean resumeTopActivityInnerLocked(ActivityRecord prev, ActivityOptions options) { @@ -4549,7 +4457,7 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai // Don't refocus if invisible to current user final ActivityRecord top = tr.getTopActivity(); if (top == null || !top.okToShowLocked()) { - addRecentActivityLocked(top); + mStackSupervisor.addRecentActivity(top); ActivityOptions.abort(options); return; } @@ -4602,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; } @@ -5153,8 +5061,7 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai if (task.autoRemoveFromRecents() || isVoiceSession) { // Task creator asked to remove this when done, or this task was a voice // interaction, so it should not remain on the recent tasks list. - mRecentTasks.remove(task); - task.removedFromRecents(); + mStackSupervisor.removeTaskFromRecents(task); } task.removeWindowContainer(); @@ -5171,9 +5078,8 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai mStackSupervisor.moveHomeStackToFront(myReason); } } - if (mStacks != null) { - mStacks.remove(this); - mStacks.add(0, this); + if (isAttached()) { + getDisplay().positionChildAtBottom(this); } if (!isHomeOrRecentsStack()) { remove(); @@ -5350,11 +5256,30 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai } boolean shouldSleepActivities() { - final ActivityStackSupervisor.ActivityDisplay display = getDisplay(); + final ActivityDisplay display = getDisplay(); return display != null ? display.isSleeping() : mService.isSleepingLocked(); } boolean shouldSleepOrShutDownActivities() { return shouldSleepActivities() || mService.isShuttingDownLocked(); } + + public void writeToProto(ProtoOutputStream proto, long fieldId) { + final long token = proto.start(fieldId); + super.writeToProto(proto, CONFIGURATION_CONTAINER); + proto.write(ID, mStackId); + for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) { + final TaskRecord task = mTaskHistory.get(taskNdx); + task.writeToProto(proto, TASKS); + } + if (mResumedActivity != null) { + mResumedActivity.writeIdentifierToProto(proto, RESUMED_ACTIVITY); + } + proto.write(DISPLAY_ID, mDisplayId); + if (mBounds != null) { + mBounds.writeToProto(proto, BOUNDS); + } + proto.write(FULLSCREEN, mFullscreen); + proto.end(token); + } } diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java index ffe5fd48706a..f423ce81bd75 100644 --- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java +++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java @@ -52,9 +52,7 @@ import static android.os.PowerManager.PARTIAL_WAKE_LOCK; import static android.os.Process.SYSTEM_UID; import static android.os.Trace.TRACE_TAG_ACTIVITY_MANAGER; import static android.view.Display.DEFAULT_DISPLAY; -import static android.view.Display.FLAG_PRIVATE; import static android.view.Display.INVALID_DISPLAY; -import static android.view.Display.REMOVE_MODE_DESTROY_CONTENT; import static android.view.Display.TYPE_VIRTUAL; import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.ACTION_PICTURE_IN_PICTURE_EXPANDED_TO_FULLSCREEN; import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_ALL; @@ -97,6 +95,13 @@ import static com.android.server.am.TaskRecord.LOCK_TASK_AUTH_LAUNCHABLE_PRIV; import static com.android.server.am.TaskRecord.REPARENT_KEEP_STACK_AT_FRONT; import static com.android.server.am.TaskRecord.REPARENT_LEAVE_STACK_IN_PLACE; import static com.android.server.am.TaskRecord.REPARENT_MOVE_STACK_TO_FRONT; +import static com.android.server.am.proto.ActivityStackSupervisorProto.DISPLAYS; +import static com.android.server.am.proto.ActivityStackSupervisorProto.FOCUSED_STACK_ID; +import static com.android.server.am.proto.ActivityStackSupervisorProto.KEYGUARD_CONTROLLER; +import static com.android.server.am.proto.ActivityStackSupervisorProto.RESUMED_ACTIVITY; +import static com.android.server.am.proto.ActivityStackSupervisorProto.CONFIGURATION_CONTAINER; +import static com.android.server.am.proto.ActivityDisplayProto.STACKS; +import static com.android.server.am.proto.ActivityDisplayProto.ID; import static com.android.server.wm.AppTransition.TRANSIT_DOCK_TASK_FROM_RECENTS; import static java.lang.Integer.MAX_VALUE; @@ -157,6 +162,7 @@ import android.util.Slog; import android.util.SparseArray; import android.util.SparseIntArray; import android.util.TimeUtils; +import android.util.proto.ProtoOutputStream; import android.view.Display; import com.android.internal.annotations.VisibleForTesting; @@ -166,6 +172,7 @@ import com.android.internal.os.TransferPipe; import com.android.internal.util.ArrayUtils; import com.android.server.LocalServices; import com.android.server.am.ActivityStack.ActivityState; +import com.android.server.am.proto.ActivityDisplayProto; import com.android.server.wm.ConfigurationContainer; import com.android.server.wm.PinnedStackWindowController; import com.android.server.wm.WindowManagerService; @@ -384,15 +391,11 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D * They are used by components that may hide and block interaction with underlying * activities. */ - final ArrayList<SleepToken> mSleepTokens = new ArrayList<SleepToken>(); + final ArrayList<SleepToken> mSleepTokens = new ArrayList<>(); /** Stack id of the front stack when user switched, indexed by userId. */ SparseIntArray mUserStackInFront = new SparseIntArray(2); - // TODO: Add listener for removal of references. - /** Mapping from (ActivityStack/TaskStack).mStackId to their current state */ - SparseArray<ActivityStack> mStacks = new SparseArray<>(); - // TODO: There should be an ActivityDisplayController coordinating am/wm interaction. /** Mapping from displayId to display current state */ private final SparseArray<ActivityDisplay> mActivityDisplays = new SparseArray<>(); @@ -611,10 +614,7 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D Display[] displays = mDisplayManager.getDisplays(); for (int displayNdx = displays.length - 1; displayNdx >= 0; --displayNdx) { final int displayId = displays[displayNdx].getDisplayId(); - ActivityDisplay activityDisplay = new ActivityDisplay(displayId); - if (activityDisplay.mDisplay == null) { - throw new IllegalStateException("Default Display does not exist"); - } + ActivityDisplay activityDisplay = new ActivityDisplay(this, displayId); mActivityDisplays.put(displayId, activityDisplay); calculateDefaultMinimalSizeOfResizeableTasks(activityDisplay); } @@ -2151,12 +2151,18 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D } protected <T extends ActivityStack> T getStack(int stackId) { - return getStack(stackId, !CREATE_IF_NEEDED, !ON_TOP); + for (int i = mActivityDisplays.size() - 1; i >= 0; --i) { + final T stack = mActivityDisplays.valueAt(i).getStack(stackId); + if (stack != null) { + return stack; + } + } + return null; } protected <T extends ActivityStack> T getStack(int stackId, boolean createStaticStackIfNeeded, boolean createOnTop) { - final ActivityStack stack = mStacks.get(stackId); + final ActivityStack stack = getStack(stackId); if (stack != null) { return (T) stack; } @@ -2434,8 +2440,7 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D final List<ActivityStack> stacks = getActivityDisplayOrCreateLocked(displayId).mStacks; for (int j = stacks.size() - 1; j >= 0; --j) { final ActivityStack stack = stacks.get(j); - if (stack != currentFocus && stack.isFocusable() - && stack.shouldBeVisible(null) != STACK_INVISIBLE) { + if (stack != currentFocus && stack.isFocusable() && stack.shouldBeVisible(null)) { return stack; } } @@ -2562,16 +2567,12 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D mResizingTasksDuringAnimation.clear(); } - private void moveTasksToFullscreenStackInSurfaceTransaction(int fromStackId, + private void moveTasksToFullscreenStackInSurfaceTransaction(ActivityStack fromStack, boolean onTop) { - final ActivityStack stack = getStack(fromStackId); - if (stack == null) { - return; - } - mWindowManager.deferSurfaceLayout(); try { + final int fromStackId = fromStack.mStackId; if (fromStackId == DOCKED_STACK_ID) { // We are moving all tasks from the docked stack to the fullscreen stack, // which is dismissing the docked stack, so resize all other stacks to @@ -2601,12 +2602,12 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D } } ActivityStack fullscreenStack = getStack(FULLSCREEN_WORKSPACE_STACK_ID); - final boolean isFullscreenStackVisible = fullscreenStack != null && - fullscreenStack.shouldBeVisible(null) == STACK_VISIBLE; + final boolean isFullscreenStackVisible = fullscreenStack != null + && fullscreenStack.shouldBeVisible(null); // If we are moving from the pinned stack, then the animation takes care of updating // the picture-in-picture mode. final boolean schedulePictureInPictureModeChange = (fromStackId == PINNED_STACK_ID); - final ArrayList<TaskRecord> tasks = stack.getAllTasks(); + final ArrayList<TaskRecord> tasks = fromStack.getAllTasks(); final int size = tasks.size(); if (onTop) { for (int i = 0; i < size; i++) { @@ -2646,9 +2647,9 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D } } - void moveTasksToFullscreenStackLocked(int fromStackId, boolean onTop) { + void moveTasksToFullscreenStackLocked(ActivityStack fromStack, boolean onTop) { mWindowManager.inSurfaceTransaction( - () -> moveTasksToFullscreenStackInSurfaceTransaction(fromStackId, onTop)); + () -> moveTasksToFullscreenStackInSurfaceTransaction(fromStack, onTop)); } void resizeDockedStackLocked(Rect dockedBounds, Rect tempDockedTaskBounds, @@ -2688,7 +2689,7 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D // The dock stack either was dismissed or went fullscreen, which is kinda the same. // In this case we make all other static stacks fullscreen and move all // docked stack tasks to the fullscreen stack. - moveTasksToFullscreenStackLocked(DOCKED_STACK_ID, ON_TOP); + moveTasksToFullscreenStackLocked(stack, ON_TOP); // stack shouldn't contain anymore activities, so nothing to resume. r = null; @@ -2780,9 +2781,9 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D ActivityStack createStack(int stackId, ActivityDisplay display, boolean onTop) { switch (stackId) { case PINNED_STACK_ID: - return new PinnedActivityStack(display, stackId, this, mRecentTasks, onTop); + return new PinnedActivityStack(display, stackId, this, onTop); default: - return new ActivityStack(display, stackId, this, mRecentTasks, onTop); + return new ActivityStack(display, stackId, this, onTop); } } @@ -2811,7 +2812,7 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D true /* processPausingActivites */, null /* configuration */); // Move all the tasks to the bottom of the fullscreen stack - moveTasksToFullscreenStackLocked(PINNED_STACK_ID, !ON_TOP); + moveTasksToFullscreenStackLocked(pinnedStack, !ON_TOP); } else { for (int i = tasks.size() - 1; i >= 0; i--) { removeTaskByIdLocked(tasks.get(i).taskId, true /* killProcess */, @@ -2862,10 +2863,23 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D return false; } + void addRecentActivity(ActivityRecord r) { + if (r == null) { + return; + } + final TaskRecord task = r.getTask(); + mRecentTasks.addLocked(task); + task.touchActiveTime(); + } + + void removeTaskFromRecents(TaskRecord task) { + mRecentTasks.remove(task); + task.removedFromRecents(); + } + void cleanUpRemovedTaskLocked(TaskRecord tr, boolean killProcess, boolean removeFromRecents) { if (removeFromRecents) { - mRecentTasks.remove(tr); - tr.removedFromRecents(); + removeTaskFromRecents(tr); } ComponentName component = tr.getBaseIntent().getComponent(); if (component == null) { @@ -2991,7 +3005,7 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D throw new IllegalArgumentException("moveStackToDisplayLocked: Unknown displayId=" + displayId); } - final ActivityStack stack = mStacks.get(stackId); + final ActivityStack stack = getStack(stackId); if (stack == null) { throw new IllegalArgumentException("moveStackToDisplayLocked: Unknown stackId=" + stackId); @@ -3100,12 +3114,16 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D mWindowManager.deferSurfaceLayout(); + PinnedActivityStack stack = getStack(PINNED_STACK_ID); + // This will clear the pinned stack by moving an existing task to the full screen stack, // ensuring only one task is present. - moveTasksToFullscreenStackLocked(PINNED_STACK_ID, !ON_TOP); + if (stack != null) { + moveTasksToFullscreenStackLocked(stack, !ON_TOP); + } // Need to make sure the pinned stack exist so we can resize it below... - final PinnedActivityStack stack = getStack(PINNED_STACK_ID, CREATE_IF_NEEDED, ON_TOP); + stack = getStack(PINNED_STACK_ID, CREATE_IF_NEEDED, ON_TOP); try { final TaskRecord task = r.getTask(); @@ -3171,7 +3189,7 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS); resumeFocusedStackTopActivityLocked(); - mService.mTaskChangeNotificationController.notifyActivityPinned(r.packageName, + mService.mTaskChangeNotificationController.notifyActivityPinned(r.packageName, r.userId, r.getTask().taskId); } @@ -3232,6 +3250,9 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D // tasks should always have lower priority than any affinity-matching tasks // in the fullscreen stacks affinityMatch = mTmpFindTaskResult.r; + } else if (DEBUG_TASKS && mTmpFindTaskResult.matchedByRootAffinity) { + Slog.d(TAG_TASKS, "Skipping match on different display " + + mTmpFindTaskResult.r.getDisplayId() + " " + displayId); } } } @@ -3596,7 +3617,10 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D boolean switchUserLocked(int userId, UserState uss) { final int focusStackId = mFocusedStack.getStackId(); // We dismiss the docked stack whenever we switch users. - moveTasksToFullscreenStackLocked(DOCKED_STACK_ID, focusStackId == DOCKED_STACK_ID); + final ActivityStack dockedStack = getStack(DOCKED_STACK_ID); + if (dockedStack != null) { + moveTasksToFullscreenStackLocked(dockedStack, mFocusedStack == dockedStack); + } // Also dismiss the pinned stack whenever we switch users. Removing the pinned stack will // also cause all tasks to be moved to the fullscreen stack at a position that is // appropriate. @@ -3636,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); } /** @@ -3743,7 +3767,10 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D pw.print(prefix); pw.println("mCurTaskIdForUser=" + mCurTaskIdForUser); pw.print(prefix); pw.println("mUserStackInFront=" + mUserStackInFront); - pw.print(prefix); pw.println("mStacks=" + mStacks); + for (int i = mActivityDisplays.size() - 1; i >= 0; --i) { + final ActivityDisplay display = mActivityDisplays.valueAt(i); + pw.println(prefix + "displayId=" + display.mDisplayId + " mStacks=" + display.mStacks); + } if (!mWaitingForActivityVisible.isEmpty()) { pw.print(prefix); pw.println("mWaitingForActivityVisible="); for (int i = 0; i < mWaitingForActivityVisible.size(); ++i) { @@ -3755,6 +3782,26 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D mService.mLockTaskController.dump(pw, prefix); } + public void writeToProto(ProtoOutputStream proto, long fieldId) { + final long token = proto.start(fieldId); + super.writeToProto(proto, CONFIGURATION_CONTAINER); + for (int displayNdx = 0; displayNdx < mActivityDisplays.size(); ++displayNdx) { + ActivityDisplay activityDisplay = mActivityDisplays.valueAt(displayNdx); + activityDisplay.writeToProto(proto, DISPLAYS); + } + mKeyguardController.writeToProto(proto, KEYGUARD_CONTROLLER); + if (mFocusedStack != null) { + proto.write(FOCUSED_STACK_ID, mFocusedStack.mStackId); + ActivityRecord focusedActivity = getResumedActivityLocked(); + if (focusedActivity != null) { + focusedActivity.writeIdentifierToProto(proto, RESUMED_ACTIVITY); + } + } else { + proto.write(FOCUSED_STACK_ID, INVALID_STACK_ID); + } + proto.end(token); + } + /** * Dump all connected displays' configurations. * @param prefix Prefix to apply to each line of the dump. @@ -3784,8 +3831,7 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks; for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) { ActivityStack stack = stacks.get(stackNdx); - if (!dumpVisibleStacksOnly || - stack.shouldBeVisible(null) == STACK_VISIBLE) { + if (!dumpVisibleStacksOnly || stack.shouldBeVisible(null)) { activities.addAll(stack.getDumpActivitiesLocked(name)); } } @@ -4034,17 +4080,18 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D return null; } // The display hasn't been added to ActivityManager yet, create a new record now. - activityDisplay = new ActivityDisplay(displayId); - if (activityDisplay.mDisplay == null) { - Slog.w(TAG, "Display " + displayId + " gone before initialization complete"); - return null; - } - mActivityDisplays.put(displayId, activityDisplay); + activityDisplay = new ActivityDisplay(this, displayId); + attachDisplay(activityDisplay); calculateDefaultMinimalSizeOfResizeableTasks(activityDisplay); mWindowManager.onDisplayAdded(displayId); return activityDisplay; } + @VisibleForTesting + void attachDisplay(ActivityDisplay display) { + mActivityDisplays.put(display.mDisplayId, display); + } + private void calculateDefaultMinimalSizeOfResizeableTasks(ActivityDisplay display) { mDefaultMinSizeOfResizeableTask = mService.mContext.getResources().getDimensionPixelSize( @@ -4072,7 +4119,7 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D // Moving all tasks to fullscreen stack, because it's guaranteed to be // a valid launch stack for all activities. This way the task history from // external display will be preserved on primary after move. - moveTasksToFullscreenStackLocked(stack.getStackId(), true /* onTop */); + moveTasksToFullscreenStackLocked(stack, true /* onTop */); } } @@ -4134,7 +4181,7 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D if (display.mAllSleepTokens.isEmpty()) { return; } - for (SleepTokenImpl token : display.mAllSleepTokens) { + for (SleepToken token : display.mAllSleepTokens) { mSleepTokens.remove(token); } display.mAllSleepTokens.clear(); @@ -4150,7 +4197,7 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D info.displayId = displayId; info.stackId = stack.mStackId; info.userId = stack.mCurrentUser; - info.visible = stack.shouldBeVisible(null) == STACK_VISIBLE; + info.visible = stack.shouldBeVisible(null); // A stack might be not attached to a display. info.position = display != null ? display.mStacks.indexOf(stack) @@ -4257,7 +4304,11 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D // Dismiss docked stack. If task appeared to be in docked stack but is not resizable - // we need to move it to top of fullscreen stack, otherwise it will be covered. - moveTasksToFullscreenStackLocked(DOCKED_STACK_ID, actualStackId == DOCKED_STACK_ID); + final ActivityStack dockedStack = getStack(DOCKED_STACK_ID); + if (dockedStack != null) { + moveTasksToFullscreenStackLocked(dockedStack, + actualStackId == dockedStack.getStackId()); + } } else if (topActivity != null && topActivity.isNonResizableOrForcedResizable() && !topActivity.noDisplay) { final String packageName = topActivity.appInfo.packageName; @@ -4462,122 +4513,6 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D } } - // TODO: Move to its own file. - /** Exactly one of these classes per Display in the system. Capable of holding zero or more - * attached {@link ActivityStack}s */ - class ActivityDisplay extends ConfigurationContainer { - /** Actual Display this object tracks. */ - int mDisplayId; - Display mDisplay; - - /** All of the stacks on this display. Order matters, topmost stack is in front of all other - * stacks, bottommost behind. Accessed directly by ActivityManager package classes */ - final ArrayList<ActivityStack> mStacks = new ArrayList<>(); - - /** Array of all UIDs that are present on the display. */ - private IntArray mDisplayAccessUIDs = new IntArray(); - - /** All tokens used to put activities on this stack to sleep (including mOffToken) */ - final ArrayList<SleepTokenImpl> mAllSleepTokens = new ArrayList<>(); - /** The token acquired by ActivityStackSupervisor to put stacks on the display to sleep */ - SleepToken mOffToken; - - private boolean mSleeping; - - @VisibleForTesting - ActivityDisplay() { - mActivityDisplays.put(mDisplayId, this); - } - - // After instantiation, check that mDisplay is not null before using this. The alternative - // is for this to throw an exception if mDisplayManager.getDisplay() returns null. - ActivityDisplay(int displayId) { - final Display display = mDisplayManager.getDisplay(displayId); - if (display == null) { - return; - } - init(display); - } - - void init(Display display) { - mDisplay = display; - mDisplayId = display.getDisplayId(); - } - - void attachStack(ActivityStack stack, int position) { - if (DEBUG_STACK) Slog.v(TAG_STACK, "attachStack: attaching " + stack - + " to displayId=" + mDisplayId + " position=" + position); - mStacks.add(position, stack); - mService.updateSleepIfNeededLocked(); - } - - void detachStack(ActivityStack stack) { - if (DEBUG_STACK) Slog.v(TAG_STACK, "detachStack: detaching " + stack - + " from displayId=" + mDisplayId); - mStacks.remove(stack); - mService.updateSleepIfNeededLocked(); - } - - @Override - public String toString() { - return "ActivityDisplay={" + mDisplayId + " numStacks=" + mStacks.size() + "}"; - } - - @Override - protected int getChildCount() { - return mStacks.size(); - } - - @Override - protected ConfigurationContainer getChildAt(int index) { - return mStacks.get(index); - } - - @Override - protected ConfigurationContainer getParent() { - return ActivityStackSupervisor.this; - } - - boolean isPrivate() { - return (mDisplay.getFlags() & FLAG_PRIVATE) != 0; - } - - boolean isUidPresent(int uid) { - for (ActivityStack stack : mStacks) { - if (stack.isUidPresent(uid)) { - return true; - } - } - return false; - } - - /** Update and get all UIDs that are present on the display and have access to it. */ - private IntArray getPresentUIDs() { - mDisplayAccessUIDs.clear(); - for (ActivityStack stack : mStacks) { - stack.getPresentUIDs(mDisplayAccessUIDs); - } - return mDisplayAccessUIDs; - } - - boolean shouldDestroyContentOnRemove() { - return mDisplay.getRemoveMode() == REMOVE_MODE_DESTROY_CONTENT; - } - - boolean shouldSleep() { - return (mStacks.isEmpty() || !mAllSleepTokens.isEmpty()) - && (mService.mRunningVoice == null); - } - - boolean isSleeping() { - return mSleeping; - } - - void setIsSleeping(boolean asleep) { - mSleeping = asleep; - } - } - ActivityStack findStackBehind(ActivityStack stack) { // TODO(multi-display): We are only looking for stacks on the default display. final ActivityDisplay display = mActivityDisplays.get(DEFAULT_DISPLAY); @@ -4713,8 +4648,7 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D for (int j = display.mStacks.size() - 1; j >= 0; j--) { final ActivityStack stack = display.mStacks.get(j); // Get top activity from a visible stack and add it to the list. - if (stack.shouldBeVisible(null /* starting */) - == ActivityStack.STACK_VISIBLE) { + if (stack.shouldBeVisible(null /* starting */)) { final ActivityRecord top = stack.topActivity(); if (top != null) { if (stack == mFocusedStack) { diff --git a/services/core/java/com/android/server/am/ActivityStarter.java b/services/core/java/com/android/server/am/ActivityStarter.java index d94e866b312b..1a2b46c9b948 100644 --- a/services/core/java/com/android/server/am/ActivityStarter.java +++ b/services/core/java/com/android/server/am/ActivityStarter.java @@ -39,7 +39,6 @@ import static android.app.ActivityManager.StackId.isDynamicStack; import static android.app.WindowConfiguration.ACTIVITY_TYPE_ASSISTANT; import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME; import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD; -import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED; import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED; import static android.content.Intent.FLAG_ACTIVITY_CLEAR_TASK; import static android.content.Intent.FLAG_ACTIVITY_CLEAR_TOP; @@ -78,7 +77,6 @@ import static com.android.server.am.ActivityManagerDebugConfig.TAG_AM; import static com.android.server.am.ActivityManagerDebugConfig.TAG_WITH_CLASS_NAME; import static com.android.server.am.ActivityManagerService.ANIMATE; import static com.android.server.am.ActivityStack.ActivityState.RESUMED; -import static com.android.server.am.ActivityStack.STACK_INVISIBLE; import static com.android.server.am.ActivityStackSupervisor.CREATE_IF_NEEDED; import static com.android.server.am.ActivityStackSupervisor.DEFER_RESUME; import static com.android.server.am.ActivityStackSupervisor.ON_TOP; @@ -169,7 +167,8 @@ class ActivityStarter { private boolean mDoResume; private int mStartFlags; private ActivityRecord mSourceRecord; - private int mSourceDisplayId; + // The display to launch the activity onto, barring any strong reason to do otherwise. + private int mPreferredDisplayId; private TaskRecord mInTask; private boolean mAddingToTask; @@ -224,7 +223,7 @@ class ActivityStarter { mDoResume = false; mStartFlags = 0; mSourceRecord = null; - mSourceDisplayId = INVALID_DISPLAY; + mPreferredDisplayId = INVALID_DISPLAY; mInTask = null; mAddingToTask = false; @@ -1240,7 +1239,7 @@ class ActivityStarter { mOptions); } } else { - mTargetStack.addRecentActivityLocked(mStartActivity); + mSupervisor.addRecentActivity(mStartActivity); } mSupervisor.updateUserStackLocked(mStartActivity.userId, mTargetStack); @@ -1263,7 +1262,7 @@ class ActivityStarter { mVoiceSession = voiceSession; mVoiceInteractor = voiceInteractor; - mSourceDisplayId = getSourceDisplayId(mSourceRecord, mStartActivity); + mPreferredDisplayId = getPreferedDisplayId(mSourceRecord, mStartActivity, options); mLaunchBounds = getOverrideBounds(r, options, inTask); @@ -1518,7 +1517,7 @@ class ActivityStarter { !mLaunchSingleTask); } else { // Otherwise find the best task to put the activity in. - intentActivity = mSupervisor.findTaskLocked(mStartActivity, mSourceDisplayId); + intentActivity = mSupervisor.findTaskLocked(mStartActivity, mPreferredDisplayId); } } return intentActivity; @@ -1526,10 +1525,12 @@ class ActivityStarter { /** * Returns the ID of the display to use for a new activity. If the device is in VR mode, - * then return the Vr mode's virtual display ID. If not, if the source activity has - * a explicit display ID set, use that to launch the activity. + * then return the Vr mode's virtual display ID. If not, if the activity was started with + * a launchDisplayId, use that. Otherwise, if the source activity has a explicit display ID + * set, use that to launch the activity. */ - private int getSourceDisplayId(ActivityRecord sourceRecord, ActivityRecord startingActivity) { + private int getPreferedDisplayId( + ActivityRecord sourceRecord, ActivityRecord startingActivity, ActivityOptions options) { // Check if the Activity is a VR activity. If so, the activity should be launched in // main display. if (startingActivity != null && startingActivity.requestedVrComponent != null) { @@ -1546,6 +1547,13 @@ class ActivityStarter { return displayId; } + // If the caller requested a display, prefer that display. + final int launchDisplayId = + (options != null) ? options.getLaunchDisplayId() : INVALID_DISPLAY; + if (launchDisplayId != INVALID_DISPLAY) { + return launchDisplayId; + } + displayId = sourceRecord != null ? sourceRecord.getDisplayId() : INVALID_DISPLAY; // If the activity has a displayId set explicitly, launch it on the same displayId. if (displayId != INVALID_DISPLAY) { @@ -2084,20 +2092,21 @@ class ActivityStarter { return mSupervisor.mFocusedStack; } - if (mSourceDisplayId != DEFAULT_DISPLAY) { + if (mPreferredDisplayId != DEFAULT_DISPLAY) { // Try to put the activity in a stack on a secondary display. - stack = mSupervisor.getValidLaunchStackOnDisplay(mSourceDisplayId, r); + stack = mSupervisor.getValidLaunchStackOnDisplay(mPreferredDisplayId, r); if (stack == null) { // If source display is not suitable - look for topmost valid stack in the system. if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG_FOCUS, - "computeStackFocus: Can't launch on mSourceDisplayId=" + mSourceDisplayId - + ", looking on all displays."); - stack = mSupervisor.getNextValidLaunchStackLocked(r, mSourceDisplayId); + "computeStackFocus: Can't launch on mPreferredDisplayId=" + + mPreferredDisplayId + ", looking on all displays."); + stack = mSupervisor.getNextValidLaunchStackLocked(r, mPreferredDisplayId); } } if (stack == null) { // We first try to put the task in the first dynamic stack on home display. - final ArrayList<ActivityStack> homeDisplayStacks = mSupervisor.mHomeStack.mStacks; + final ArrayList<ActivityStack> homeDisplayStacks = + mSupervisor.getStacksOnDefaultDisplay(); for (int stackNdx = homeDisplayStacks.size() - 1; stackNdx >= 0; --stackNdx) { stack = homeDisplayStacks.get(stackNdx); if (isDynamicStack(stack.mStackId)) { @@ -2148,8 +2157,8 @@ class ActivityStarter { } return canUseFocusedStack && !newTask - // We strongly prefer to launch activities on the same display as their source. - && (mSourceDisplayId == focusedStack.mDisplayId); + // Using the focus stack isn't important enough to override the prefered display. + && (mPreferredDisplayId == focusedStack.mDisplayId); } private ActivityStack getLaunchStack(ActivityRecord r, int launchFlags, TaskRecord task, @@ -2175,7 +2184,7 @@ class ActivityStarter { int launchStackId = INVALID_STACK_ID; if (aOptions != null) { launchDisplayId = aOptions.getLaunchDisplayId(); - final int vrDisplayId = mUsingVr2dDisplay ? mSourceDisplayId : INVALID_DISPLAY; + final int vrDisplayId = mUsingVr2dDisplay ? mPreferredDisplayId : INVALID_DISPLAY; launchStackId = mSupervisor.getLaunchStackId(r, aOptions, task, vrDisplayId); } @@ -2197,7 +2206,7 @@ class ActivityStarter { // If we are using Vr2d display, find the virtual display stack. // TODO: Can be removed. if (mUsingVr2dDisplay) { - ActivityStack as = mSupervisor.getValidLaunchStackOnDisplay(mSourceDisplayId, r); + ActivityStack as = mSupervisor.getValidLaunchStackOnDisplay(mPreferredDisplayId, r); if (DEBUG_STACK) { Slog.v(TAG, "Launch stack for app: " + r.toString() + ", on virtual display stack:" + as.toString()); @@ -2206,7 +2215,7 @@ class ActivityStarter { } if (((launchFlags & FLAG_ACTIVITY_LAUNCH_ADJACENT) == 0) - || mSourceDisplayId != DEFAULT_DISPLAY) { + || mPreferredDisplayId != DEFAULT_DISPLAY) { return null; } // Otherwise handle adjacent launch. @@ -2235,8 +2244,7 @@ class ActivityStarter { // and if yes, we will launch into that stack. If not, we just put the new // activity into parent's stack, because we can't find a better place. final ActivityStack dockedStack = mSupervisor.getStack(DOCKED_STACK_ID); - if (dockedStack != null - && dockedStack.shouldBeVisible(r) == STACK_INVISIBLE) { + if (dockedStack != null && !dockedStack.shouldBeVisible(r)) { // There is a docked stack, but it isn't visible, so we can't launch into that. return null; } else { 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/BatteryStatsService.java b/services/core/java/com/android/server/am/BatteryStatsService.java index 3105e37f618f..e839003b957e 100644 --- a/services/core/java/com/android/server/am/BatteryStatsService.java +++ b/services/core/java/com/android/server/am/BatteryStatsService.java @@ -300,10 +300,10 @@ public final class BatteryStatsService extends IBatteryStats.Stub // TODO: remove this once we figure out properly where and how // PROCESS_EVENT = 1112 - // EVENT SUBTYPE: START = 1 - // KEY_NAME: 1 + // KEY_STATE = 1 + // KEY_PACKAGE_NAME: 1002 // KEY_UID: 2 - StatsLog.writeArray(1112, 1, 1, name, 2, uid); + StatsLog.writeArray(1112, 1, 1, 1002, name, 2, uid); } } @@ -313,10 +313,10 @@ public final class BatteryStatsService extends IBatteryStats.Stub // TODO: remove this once we figure out properly where and how // PROCESS_EVENT = 1112 - // EVENT SUBTYPE: CRASH = 2 - // KEY_NAME: 1 + // KEY_STATE = 1 + // KEY_PACKAGE_NAME: 1002 // KEY_UID: 2 - StatsLog.writeArray(1112, 2, 1, name, 2, uid); + StatsLog.writeArray(1112, 1, 2, 1002, name, 2, uid); } } @@ -550,10 +550,10 @@ public final class BatteryStatsService extends IBatteryStats.Stub synchronized (mStats) { mStats.noteScreenStateLocked(state); // TODO: remove this once we figure out properly where and how - // SCREEN_EVENT = 1003 - // State key: 1 + // SCREEN_EVENT = 2 + // KEY_STATE: 1 // State value: state. We can change this to our own def later. - StatsLog.writeArray(1003, 1, state); + StatsLog.writeArray(2, 1, state); } if (DBG) Slog.d(TAG, "end noteScreenState"); } @@ -564,14 +564,14 @@ public final class BatteryStatsService extends IBatteryStats.Stub mStats.noteScreenBrightnessLocked(brightness); } } - + public void noteUserActivity(int uid, int event) { enforceCallingPermission(); synchronized (mStats) { mStats.noteUserActivityLocked(uid, event); } } - + public void noteWakeUp(String reason, int reasonUid) { enforceCallingPermission(); synchronized (mStats) { diff --git a/services/core/java/com/android/server/am/KeyguardController.java b/services/core/java/com/android/server/am/KeyguardController.java index 85961135d84f..7101fc4eb93c 100644 --- a/services/core/java/com/android/server/am/KeyguardController.java +++ b/services/core/java/com/android/server/am/KeyguardController.java @@ -26,6 +26,8 @@ import static android.view.WindowManagerPolicy.KEYGUARD_GOING_AWAY_FLAG_WITH_WAL import static com.android.server.am.ActivityManagerDebugConfig.TAG_AM; import static com.android.server.am.ActivityManagerDebugConfig.TAG_WITH_CLASS_NAME; import static com.android.server.am.ActivityStackSupervisor.PRESERVE_WINDOWS; +import static com.android.server.am.proto.KeyguardControllerProto.KEYGUARD_OCCLUDED; +import static com.android.server.am.proto.KeyguardControllerProto.KEYGUARD_SHOWING; import static com.android.server.wm.AppTransition.TRANSIT_FLAG_KEYGUARD_GOING_AWAY_NO_ANIMATION; import static com.android.server.wm.AppTransition.TRANSIT_FLAG_KEYGUARD_GOING_AWAY_TO_SHADE; import static com.android.server.wm.AppTransition.TRANSIT_FLAG_KEYGUARD_GOING_AWAY_WITH_WALLPAPER; @@ -39,6 +41,7 @@ import android.os.IBinder; import android.os.RemoteException; import android.os.Trace; import android.util.Slog; +import android.util.proto.ProtoOutputStream; import com.android.internal.policy.IKeyguardDismissCallback; import com.android.server.wm.WindowManagerService; @@ -339,8 +342,12 @@ class KeyguardController { // show on top of the lock screen. In this can we want to dismiss the docked // stack since it will be complicated/risky to try to put the activity on top // of the lock screen in the right fullscreen configuration. - mStackSupervisor.moveTasksToFullscreenStackLocked(DOCKED_STACK_ID, - mStackSupervisor.mFocusedStack.getStackId() == DOCKED_STACK_ID); + final ActivityStack stack = mStackSupervisor.getStack(DOCKED_STACK_ID); + if (stack == null) { + return; + } + mStackSupervisor.moveTasksToFullscreenStackLocked(stack, + mStackSupervisor.mFocusedStack == stack); } } @@ -362,4 +369,11 @@ class KeyguardController { pw.println(prefix + " mDismissalRequested=" + mDismissalRequested); pw.println(prefix + " mVisibilityTransactionDepth=" + mVisibilityTransactionDepth); } + + void writeToProto(ProtoOutputStream proto, long fieldId) { + final long token = proto.start(fieldId); + proto.write(KEYGUARD_SHOWING, mKeyguardShowing); + proto.write(KEYGUARD_OCCLUDED, mOccluded); + proto.end(token); + } } 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/PinnedActivityStack.java b/services/core/java/com/android/server/am/PinnedActivityStack.java index a601ee1c0c89..33f56644a3f6 100644 --- a/services/core/java/com/android/server/am/PinnedActivityStack.java +++ b/services/core/java/com/android/server/am/PinnedActivityStack.java @@ -32,9 +32,9 @@ import java.util.List; class PinnedActivityStack extends ActivityStack<PinnedStackWindowController> implements PinnedStackWindowListener { - PinnedActivityStack(ActivityStackSupervisor.ActivityDisplay display, int stackId, - ActivityStackSupervisor supervisor, RecentTasks recentTasks, boolean onTop) { - super(display, stackId, supervisor, recentTasks, onTop); + PinnedActivityStack(ActivityDisplay display, int stackId, ActivityStackSupervisor supervisor, + boolean onTop) { + super(display, stackId, supervisor, onTop); } @Override diff --git a/services/core/java/com/android/server/am/TaskChangeNotificationController.java b/services/core/java/com/android/server/am/TaskChangeNotificationController.java index 82971696d670..6a986bb8a684 100644 --- a/services/core/java/com/android/server/am/TaskChangeNotificationController.java +++ b/services/core/java/com/android/server/am/TaskChangeNotificationController.java @@ -95,7 +95,7 @@ class TaskChangeNotificationController { }; private final TaskStackConsumer mNotifyActivityPinned = (l, m) -> { - l.onActivityPinned((String) m.obj, m.arg1); + l.onActivityPinned((String) m.obj, m.arg1, m.arg2); }; private final TaskStackConsumer mNotifyActivityUnpinned = (l, m) -> { @@ -278,10 +278,10 @@ class TaskChangeNotificationController { } /** Notifies all listeners when an Activity is pinned. */ - void notifyActivityPinned(String packageName, int taskId) { + void notifyActivityPinned(String packageName, int userId, int taskId) { mHandler.removeMessages(NOTIFY_ACTIVITY_PINNED_LISTENERS_MSG); final Message msg = mHandler.obtainMessage(NOTIFY_ACTIVITY_PINNED_LISTENERS_MSG, - taskId, 0, packageName); + userId, taskId, packageName); forAllLocalListeners(mNotifyActivityPinned, msg); msg.sendToTarget(); } diff --git a/services/core/java/com/android/server/am/TaskRecord.java b/services/core/java/com/android/server/am/TaskRecord.java index 28b71d9c978d..fb8b034ab064 100644 --- a/services/core/java/com/android/server/am/TaskRecord.java +++ b/services/core/java/com/android/server/am/TaskRecord.java @@ -66,6 +66,20 @@ import static com.android.server.am.ActivityStack.REMOVE_TASK_MODE_MOVING; import static com.android.server.am.ActivityStack.REMOVE_TASK_MODE_MOVING_TO_TOP; import static com.android.server.am.ActivityStackSupervisor.PAUSE_IMMEDIATELY; import static com.android.server.am.ActivityStackSupervisor.PRESERVE_WINDOWS; +import static com.android.server.am.proto.TaskRecordProto.ACTIVITIES; +import static com.android.server.am.proto.TaskRecordProto.BOUNDS; +import static com.android.server.am.proto.TaskRecordProto.CONFIGURATION_CONTAINER; +import static com.android.server.am.proto.TaskRecordProto.FULLSCREEN; +import static com.android.server.am.proto.TaskRecordProto.ID; +import static com.android.server.am.proto.TaskRecordProto.LAST_NON_FULLSCREEN_BOUNDS; +import static com.android.server.am.proto.TaskRecordProto.MIN_HEIGHT; +import static com.android.server.am.proto.TaskRecordProto.MIN_WIDTH; +import static com.android.server.am.proto.TaskRecordProto.ORIG_ACTIVITY; +import static com.android.server.am.proto.TaskRecordProto.REAL_ACTIVITY; +import static com.android.server.am.proto.TaskRecordProto.RESIZE_MODE; +import static com.android.server.am.proto.TaskRecordProto.RETURN_TO_TYPE; +import static com.android.server.am.proto.TaskRecordProto.STACK_ID; +import static com.android.server.am.proto.TaskRecordProto.ACTIVITY_TYPE; import static java.lang.Integer.MAX_VALUE; @@ -95,6 +109,7 @@ import android.provider.Settings; import android.service.voice.IVoiceInteractionSession; import android.util.DisplayMetrics; import android.util.Slog; +import android.util.proto.ProtoOutputStream; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.app.IVoiceInteractor; @@ -2237,4 +2252,34 @@ class TaskRecord extends ConfigurationContainer implements TaskWindowContainerLi stringName = sb.toString(); return toString(); } + + public void writeToProto(ProtoOutputStream proto, long fieldId) { + final long token = proto.start(fieldId); + super.writeToProto(proto, CONFIGURATION_CONTAINER); + proto.write(ID, taskId); + for (int i = mActivities.size() - 1; i >= 0; i--) { + ActivityRecord activity = mActivities.get(i); + activity.writeToProto(proto, ACTIVITIES); + } + proto.write(STACK_ID, mStack.mStackId); + if (mLastNonFullscreenBounds != null) { + mLastNonFullscreenBounds.writeToProto(proto, LAST_NON_FULLSCREEN_BOUNDS); + } + if (realActivity != null) { + proto.write(REAL_ACTIVITY, realActivity.flattenToShortString()); + } + if (origActivity != null) { + proto.write(ORIG_ACTIVITY, origActivity.flattenToShortString()); + } + proto.write(ACTIVITY_TYPE, getActivityType()); + proto.write(RETURN_TO_TYPE, mTaskToReturnTo); + proto.write(RESIZE_MODE, mResizeMode); + proto.write(FULLSCREEN, mFullscreen); + if (mBounds != null) { + mBounds.writeToProto(proto, BOUNDS); + } + proto.write(MIN_WIDTH, mMinWidth); + proto.write(MIN_HEIGHT, mMinHeight); + proto.end(token); + } } 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 e6585ad194ec..fceacba4239c 100644 --- a/services/core/java/com/android/server/connectivity/Nat464Xlat.java +++ b/services/core/java/com/android/server/connectivity/Nat464Xlat.java @@ -20,6 +20,7 @@ import android.net.InterfaceConfiguration; import android.net.ConnectivityManager; import android.net.LinkAddress; import android.net.LinkProperties; +import android.net.NetworkInfo; import android.net.RouteInfo; import android.os.INetworkManagementService; import android.os.RemoteException; @@ -44,12 +45,18 @@ public class Nat464Xlat extends BaseNetworkObserver { // This must match the interface prefix in clatd.c. private static final String CLAT_PREFIX = "v4-"; - // The network types we will start clatd on, + // The network types on which we will start clatd, // allowing clat only on networks for which we can support IPv6-only. private static final int[] NETWORK_TYPES = { - ConnectivityManager.TYPE_MOBILE, - ConnectivityManager.TYPE_WIFI, - ConnectivityManager.TYPE_ETHERNET, + ConnectivityManager.TYPE_MOBILE, + ConnectivityManager.TYPE_WIFI, + ConnectivityManager.TYPE_ETHERNET, + }; + + // The network states in which running clatd is supported. + private static final NetworkInfo.State[] NETWORK_STATES = { + NetworkInfo.State.CONNECTED, + NetworkInfo.State.SUSPENDED, }; private final INetworkManagementService mNMService; @@ -81,11 +88,8 @@ public class Nat464Xlat extends BaseNetworkObserver { */ public static boolean requiresClat(NetworkAgentInfo nai) { // TODO: migrate to NetworkCapabilities.TRANSPORT_*. - final int netType = nai.networkInfo.getType(); final boolean supported = ArrayUtils.contains(NETWORK_TYPES, nai.networkInfo.getType()); - // TODO: this should also consider if the network is in SUSPENDED state to avoid stopping - // clatd in SUSPENDED state. - final boolean connected = nai.networkInfo.isConnected(); + final boolean connected = ArrayUtils.contains(NETWORK_STATES, nai.networkInfo.getState()); // We only run clat on networks that don't have a native IPv4 address. final boolean hasIPv4Address = (nai.linkProperties != null) && nai.linkProperties.hasIPv4Address(); @@ -148,7 +152,6 @@ public class Nat464Xlat extends BaseNetworkObserver { * turn ND offload off if on WiFi. */ private void enterRunningState() { - maybeSetIpv6NdOffload(mBaseIface, false); mState = State.RUNNING; } @@ -156,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) { @@ -275,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/connectivity/tethering/OffloadController.java b/services/core/java/com/android/server/connectivity/tethering/OffloadController.java index 5eafe5f9f64f..057704a56c4c 100644 --- a/services/core/java/com/android/server/connectivity/tethering/OffloadController.java +++ b/services/core/java/com/android/server/connectivity/tethering/OffloadController.java @@ -52,6 +52,7 @@ import java.net.Inet4Address; import java.net.Inet6Address; import java.net.InetAddress; import java.util.ArrayList; +import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.List; @@ -73,6 +74,8 @@ public class OffloadController { private static final String ANYIP = "0.0.0.0"; private static final ForwardedStats EMPTY_STATS = new ForwardedStats(); + private static enum UpdateType { IF_NEEDED, FORCE }; + private final Handler mHandler; private final OffloadHardwareInterface mHwInterface; private final ContentResolver mContentResolver; @@ -185,8 +188,8 @@ public class OffloadController { updateStatsForAllUpstreams(); forceTetherStatsPoll(); // [2] (Re)Push all state. - // TODO: computeAndPushLocalPrefixes() - // TODO: push all downstream state. + computeAndPushLocalPrefixes(UpdateType.FORCE); + pushAllDownstreamState(); pushUpstreamParameters(null); } @@ -319,7 +322,7 @@ public class OffloadController { } private boolean maybeUpdateDataLimit(String iface) { - // setDataLimit may only be called while offload is occuring on this upstream. + // setDataLimit may only be called while offload is occurring on this upstream. if (!started() || !TextUtils.equals(iface, currentUpstreamInterface())) { return true; } @@ -368,15 +371,15 @@ public class OffloadController { // upstream parameters fails (probably just wait for a subsequent // onOffloadEvent() callback to tell us offload is available again and // then reapply all state). - computeAndPushLocalPrefixes(); + computeAndPushLocalPrefixes(UpdateType.IF_NEEDED); pushUpstreamParameters(prevUpstream); } public void setLocalPrefixes(Set<IpPrefix> localPrefixes) { - if (!started()) return; - mExemptPrefixes = localPrefixes; - computeAndPushLocalPrefixes(); + + if (!started()) return; + computeAndPushLocalPrefixes(UpdateType.IF_NEEDED); } public void notifyDownstreamLinkProperties(LinkProperties lp) { @@ -385,27 +388,38 @@ public class OffloadController { if (Objects.equals(oldLp, lp)) return; if (!started()) return; + pushDownstreamState(oldLp, lp); + } - final List<RouteInfo> oldRoutes = (oldLp != null) ? oldLp.getRoutes() : new ArrayList<>(); - final List<RouteInfo> newRoutes = lp.getRoutes(); + private void pushDownstreamState(LinkProperties oldLp, LinkProperties newLp) { + final String ifname = newLp.getInterfaceName(); + final List<RouteInfo> oldRoutes = + (oldLp != null) ? oldLp.getRoutes() : Collections.EMPTY_LIST; + final List<RouteInfo> newRoutes = newLp.getRoutes(); // For each old route, if not in new routes: remove. - for (RouteInfo oldRoute : oldRoutes) { - if (shouldIgnoreDownstreamRoute(oldRoute)) continue; - if (!newRoutes.contains(oldRoute)) { - mHwInterface.removeDownstreamPrefix(ifname, oldRoute.getDestination().toString()); + for (RouteInfo ri : oldRoutes) { + if (shouldIgnoreDownstreamRoute(ri)) continue; + if (!newRoutes.contains(ri)) { + mHwInterface.removeDownstreamPrefix(ifname, ri.getDestination().toString()); } } // For each new route, if not in old routes: add. - for (RouteInfo newRoute : newRoutes) { - if (shouldIgnoreDownstreamRoute(newRoute)) continue; - if (!oldRoutes.contains(newRoute)) { - mHwInterface.addDownstreamPrefix(ifname, newRoute.getDestination().toString()); + for (RouteInfo ri : newRoutes) { + if (shouldIgnoreDownstreamRoute(ri)) continue; + if (!oldRoutes.contains(ri)) { + mHwInterface.addDownstreamPrefix(ifname, ri.getDestination().toString()); } } } + private void pushAllDownstreamState() { + for (LinkProperties lp : mDownstreams.values()) { + pushDownstreamState(null, lp); + } + } + public void removeDownstreamInterface(String ifname) { final LinkProperties lp = mDownstreams.remove(ifname); if (lp == null) return; @@ -484,10 +498,11 @@ public class OffloadController { return success; } - private boolean computeAndPushLocalPrefixes() { + private boolean computeAndPushLocalPrefixes(UpdateType how) { + final boolean force = (how == UpdateType.FORCE); final Set<String> localPrefixStrs = computeLocalPrefixStrings( mExemptPrefixes, mUpstreamLinkProperties); - if (mLastLocalPrefixStrs.equals(localPrefixStrs)) return true; + if (!force && mLastLocalPrefixStrs.equals(localPrefixStrs)) return true; mLastLocalPrefixStrs = localPrefixStrs; return mHwInterface.setLocalPrefixes(new ArrayList<>(localPrefixStrs)); diff --git a/services/core/java/com/android/server/content/SyncManager.java b/services/core/java/com/android/server/content/SyncManager.java index 2f3b55960c13..205e8283cc55 100644 --- a/services/core/java/com/android/server/content/SyncManager.java +++ b/services/core/java/com/android/server/content/SyncManager.java @@ -143,6 +143,7 @@ public class SyncManager { private static final boolean DEBUG_ACCOUNT_ACCESS = false; + // Only do the check on a debuggable build. private static final boolean ENABLE_SUSPICIOUS_CHECK = Build.IS_DEBUGGABLE; /** Delay a sync due to local changes this long. In milliseconds */ @@ -537,9 +538,11 @@ public class SyncManager { * @return whether the device most likely has some periodic syncs. */ private boolean likelyHasPeriodicSyncs() { - // STOPSHIP Remove the google specific string. try { - return AccountManager.get(mContext).getAccountsByType("com.google").length > 0; + // Each sync adapter has a daily periodic sync by default, but sync adapters can remove + // them by themselves. So here, we use an arbitrary threshold. If there are more than + // this many sync endpoints, surely one of them should have a periodic sync... + return mSyncStorageEngine.getAuthorityCount() >= 6; } catch (Throwable th) { // Just in case. } @@ -3775,48 +3778,10 @@ public class SyncManager { } if (op.isPeriodic) { mLogger.log("Removing periodic sync ", op, " for ", why); - - if (ENABLE_SUSPICIOUS_CHECK && isSuspiciousPeriodicSyncRemoval(op)) { - wtfWithLog("Suspicious removal of " + op + " for " + why); - } } getJobScheduler().cancel(op.jobId); } - private boolean isSuspiciousPeriodicSyncRemoval(SyncOperation op) { - // STOPSHIP Remove the google specific string. - if (!op.isPeriodic){ - return false; - } - boolean found = false; - for (UserInfo user : UserManager.get(mContext).getUsers(/*excludeDying=*/ true)) { - if (op.target.userId == user.id) { - found = true; - break; - } - } - if (!found) { - return false; // User is being removed, okay. - } - switch (op.target.provider) { - case "gmail-ls": - case "com.android.contacts.metadata": - break; - default: - return false; - } - final Account account = op.target.account; - final Account[] accounts = AccountManager.get(mContext) - .getAccountsByTypeAsUser(account.type, UserHandle.of(op.target.userId)); - for (Account a : accounts) { - if (a.equals(account)) { - return true; // Account still exists. Suspicious! - } - } - // Account no longer exists. Makes sense... - return false; - } - private void wtfWithLog(String message) { Slog.wtf(TAG, message); mLogger.log("WTF: ", message); diff --git a/services/core/java/com/android/server/content/SyncStorageEngine.java b/services/core/java/com/android/server/content/SyncStorageEngine.java index 7b277c06328e..3591871f5386 100644 --- a/services/core/java/com/android/server/content/SyncStorageEngine.java +++ b/services/core/java/com/android/server/content/SyncStorageEngine.java @@ -911,6 +911,12 @@ public class SyncStorageEngine extends Handler { } } + public int getAuthorityCount() { + synchronized (mAuthorities) { + return mAuthorities.size(); + } + } + public AuthorityInfo getAuthority(int authorityId) { synchronized (mAuthorities) { return mAuthorities.get(authorityId); diff --git a/services/core/java/com/android/server/fingerprint/FingerprintService.java b/services/core/java/com/android/server/fingerprint/FingerprintService.java index b1c165ef048d..0e1252eea88e 100644 --- a/services/core/java/com/android/server/fingerprint/FingerprintService.java +++ b/services/core/java/com/android/server/fingerprint/FingerprintService.java @@ -1338,6 +1338,8 @@ public class FingerprintService extends SystemService implements IHwBinder.Death set.put("rejectCrypto", (cryptoStats != null) ? cryptoStats.reject : 0); set.put("acquireCrypto", (cryptoStats != null) ? cryptoStats.acquire : 0); set.put("lockoutCrypto", (cryptoStats != null) ? cryptoStats.lockout : 0); + set.put("permanentLockoutCrypto", + (cryptoStats != null) ? cryptoStats.permanentLockout : 0); sets.put(set); } @@ -1367,7 +1369,7 @@ public class FingerprintService extends SystemService implements IHwBinder.Death proto.write(FingerprintActionStatsProto.REJECT, normal.reject); proto.write(FingerprintActionStatsProto.ACQUIRE, normal.acquire); proto.write(FingerprintActionStatsProto.LOCKOUT, normal.lockout); - proto.write(FingerprintActionStatsProto.LOCKOUT_PERMANENT, normal.lockout); + proto.write(FingerprintActionStatsProto.LOCKOUT_PERMANENT, normal.permanentLockout); proto.end(countsToken); } @@ -1380,7 +1382,7 @@ public class FingerprintService extends SystemService implements IHwBinder.Death proto.write(FingerprintActionStatsProto.REJECT, crypto.reject); proto.write(FingerprintActionStatsProto.ACQUIRE, crypto.acquire); proto.write(FingerprintActionStatsProto.LOCKOUT, crypto.lockout); - proto.write(FingerprintActionStatsProto.LOCKOUT_PERMANENT, crypto.lockout); + proto.write(FingerprintActionStatsProto.LOCKOUT_PERMANENT, crypto.permanentLockout); proto.end(countsToken); } diff --git a/services/core/java/com/android/server/locksettings/LockSettingsService.java b/services/core/java/com/android/server/locksettings/LockSettingsService.java index 11043bd16648..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, @@ -2366,6 +2367,13 @@ public class LockSettingsService extends ILockSettings.Stub { Slog.w(TAG, "Invalid escrow token supplied"); return false; } + if (result.gkResponse.getResponseCode() != VerifyCredentialResponse.RESPONSE_OK) { + // Most likely, an untrusted credential reset happened in the past which + // changed the synthetic password + Slog.e(TAG, "Obsolete token: synthetic password derived but it fails GK " + + "verification."); + return false; + } // Update PASSWORD_TYPE_KEY since it's needed by notifyActivePasswordMetricsAvailable() // called by setLockCredentialWithAuthTokenLocked(). // TODO: refactor usage of PASSWORD_TYPE_KEY b/65239740 @@ -2497,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 @@ -2526,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/media/MediaRouterService.java b/services/core/java/com/android/server/media/MediaRouterService.java index 3795b7f3091c..1cfd5f02e810 100644 --- a/services/core/java/com/android/server/media/MediaRouterService.java +++ b/services/core/java/com/android/server/media/MediaRouterService.java @@ -271,14 +271,6 @@ public final class MediaRouterService extends IMediaRouterService.Stub // Binder call @Override - public boolean isGlobalBluetoothA2doOn() { - synchronized (mLock) { - return mGlobalBluetoothA2dpOn; - } - } - - // Binder call - @Override public void setDiscoveryRequest(IMediaRouterClient client, int routeTypes, boolean activeScan) { if (client == null) { @@ -383,7 +375,7 @@ public final class MediaRouterService extends IMediaRouterService.Stub synchronized (mLock) { a2dpOn = mGlobalBluetoothA2dpOn; } - Slog.v(TAG, "restoreBluetoothA2dp( " + a2dpOn + ")"); + Slog.v(TAG, "restoreBluetoothA2dp(" + a2dpOn + ")"); mAudioService.setBluetoothA2dpOn(a2dpOn); } catch (RemoteException e) { Slog.w(TAG, "RemoteException while calling setBluetoothA2dpOn."); diff --git a/services/core/java/com/android/server/media/MediaSessionRecord.java b/services/core/java/com/android/server/media/MediaSessionRecord.java index 89e10503fcf3..0b11479a162a 100644 --- a/services/core/java/com/android/server/media/MediaSessionRecord.java +++ b/services/core/java/com/android/server/media/MediaSessionRecord.java @@ -462,18 +462,25 @@ public class MediaSessionRecord implements IBinder.DeathRecipient { mHandler.post(new Runnable() { @Override public void run() { - if (useSuggested) { - if (AudioSystem.isStreamActive(stream, 0)) { - mAudioManagerInternal.adjustSuggestedStreamVolumeForUid(stream, direction, - flags, packageName, uid); + try { + if (useSuggested) { + if (AudioSystem.isStreamActive(stream, 0)) { + mAudioManagerInternal.adjustSuggestedStreamVolumeForUid(stream, + direction, flags, packageName, uid); + } else { + mAudioManagerInternal.adjustSuggestedStreamVolumeForUid( + AudioManager.USE_DEFAULT_STREAM_TYPE, direction, + flags | previousFlagPlaySound, packageName, uid); + } } else { - mAudioManagerInternal.adjustSuggestedStreamVolumeForUid( - AudioManager.USE_DEFAULT_STREAM_TYPE, direction, - flags | previousFlagPlaySound, packageName, uid); + mAudioManagerInternal.adjustStreamVolumeForUid(stream, direction, flags, + packageName, uid); } - } else { - mAudioManagerInternal.adjustStreamVolumeForUid(stream, direction, flags, - packageName, uid); + } catch (IllegalArgumentException e) { + Log.e(TAG, "Cannot adjust volume: direction=" + direction + ", stream=" + + stream + ", flags=" + flags + ", packageName=" + packageName + + ", uid=" + uid + ", useSuggested=" + useSuggested + + ", previousFlagPlaySound=" + previousFlagPlaySound, e); } } }); diff --git a/services/core/java/com/android/server/media/MediaSessionService.java b/services/core/java/com/android/server/media/MediaSessionService.java index b77ed913cd12..b9a2d184aade 100644 --- a/services/core/java/com/android/server/media/MediaSessionService.java +++ b/services/core/java/com/android/server/media/MediaSessionService.java @@ -1363,6 +1363,10 @@ public class MediaSessionService extends SystemService implements Monitor { flags, packageName, TAG); } catch (RemoteException e) { Log.e(TAG, "Error adjusting default volume.", e); + } catch (IllegalArgumentException e) { + Log.e(TAG, "Cannot adjust volume: direction=" + direction + + ", suggestedStream=" + suggestedStream + ", flags=" + flags, + e); } } }); diff --git a/services/core/java/com/android/server/notification/ConditionProviders.java b/services/core/java/com/android/server/notification/ConditionProviders.java index 3444ef3ec2fa..c0fbfbb20b95 100644 --- a/services/core/java/com/android/server/notification/ConditionProviders.java +++ b/services/core/java/com/android/server/notification/ConditionProviders.java @@ -186,6 +186,11 @@ public class ConditionProviders extends ManagedServices { super.onPackagesChanged(removingPackage, pkgList, uid); } + @Override + protected boolean isValidEntry(String packageOrComponent, int userId) { + return true; + } + public ManagedServiceInfo checkServiceToken(IConditionProvider provider) { synchronized(mMutex) { return checkServiceTokenLocked(provider); 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/ManagedServices.java b/services/core/java/com/android/server/notification/ManagedServices.java index add4184fc129..c1d7059d0e3d 100644 --- a/services/core/java/com/android/server/notification/ManagedServices.java +++ b/services/core/java/com/android/server/notification/ManagedServices.java @@ -45,12 +45,16 @@ import android.os.RemoteException; import android.os.UserHandle; import android.os.UserManager; import android.provider.Settings; +import android.service.notification.ManagedServiceInfoProto; +import android.service.notification.ManagedServicesProto; +import android.service.notification.ManagedServicesProto.ServiceProto; import android.text.TextUtils; import android.util.ArrayMap; import android.util.ArraySet; import android.util.Log; import android.util.Slog; import android.util.SparseArray; +import android.util.proto.ProtoOutputStream; import com.android.internal.util.XmlUtils; import com.android.server.notification.NotificationManagerService.DumpFilter; @@ -214,6 +218,53 @@ abstract public class ManagedServices { } } + public void dump(ProtoOutputStream proto, DumpFilter filter) { + proto.write(ManagedServicesProto.CAPTION, getCaption()); + final int N = mApproved.size(); + for (int i = 0 ; i < N; i++) { + final int userId = mApproved.keyAt(i); + final ArrayMap<Boolean, ArraySet<String>> approvedByType = mApproved.valueAt(i); + if (approvedByType != null) { + final int M = approvedByType.size(); + for (int j = 0; j < M; j++) { + final boolean isPrimary = approvedByType.keyAt(j); + final ArraySet<String> approved = approvedByType.valueAt(j); + if (approvedByType != null && approvedByType.size() > 0) { + final long sToken = proto.start(ManagedServicesProto.APPROVED); + for (String s : approved) { + proto.write(ServiceProto.NAME, s); + } + proto.write(ServiceProto.USER_ID, userId); + proto.write(ServiceProto.IS_PRIMARY, isPrimary); + proto.end(sToken); + } + } + } + } + + for (ComponentName cmpt : mEnabledServicesForCurrentProfiles) { + if (filter != null && !filter.matches(cmpt)) continue; + + final long cToken = proto.start(ManagedServicesProto.ENABLED); + cmpt.toProto(proto); + proto.end(cToken); + } + + for (ManagedServiceInfo info : mServices) { + if (filter != null && !filter.matches(info.component)) continue; + + final long lToken = proto.start(ManagedServicesProto.LIVE_SERVICES); + info.toProto(proto, this); + proto.end(lToken); + } + + for (ComponentName name : mSnoozingForCurrentProfiles) { + final long cToken = proto.start(ManagedServicesProto.SNOOZED); + name.toProto(proto); + proto.end(cToken); + } + } + protected void onSettingRestored(String element, String value, int backupSdkInt, int userId) { if (!mUseXml) { Slog.d(TAG, "Restored managed service setting: " + element); @@ -294,6 +345,7 @@ abstract public class ManagedServices { } if (type == XmlPullParser.START_TAG) { if (TAG_MANAGED_SERVICES.equals(tag)) { + Slog.i(TAG, "Read " + mConfig.caption + " permissions from xml"); final String approved = XmlUtils.readStringAttribute(parser, ATT_APPROVED_LIST); final int userId = XmlUtils.readIntAttribute(parser, ATT_USER_ID, 0); final boolean isPrimary = @@ -353,6 +405,8 @@ abstract public class ManagedServices { protected void setPackageOrComponentEnabled(String pkgOrComponent, int userId, boolean isPrimary, boolean enabled) { + Slog.i(TAG, + (enabled ? " Allowing " : "Disallowing ") + mConfig.caption + " " + pkgOrComponent); ArrayMap<Boolean, ArraySet<String>> allowedByType = mApproved.get(userId); if (allowedByType == null) { allowedByType = new ArrayMap<>(); @@ -460,6 +514,7 @@ abstract public class ManagedServices { } public void onUserRemoved(int user) { + Slog.i(TAG, "Removing approved services for removed user " + user); mApproved.remove(user); rebindServices(true); } @@ -543,10 +598,8 @@ abstract public class ManagedServices { } // State changed - if (DEBUG) { - Slog.d(TAG, ((enabled) ? "Enabling " : "Disabling ") + "component " + - component.flattenToShortString()); - } + Slog.d(TAG, ((enabled) ? "Enabling " : "Disabling ") + "component " + + component.flattenToShortString()); synchronized (mMutex) { final int[] userIds = mUserProfiles.getCurrentProfileIds(); @@ -628,12 +681,10 @@ abstract public class ManagedServices { int P = approved.size(); for (int k = P - 1; k >= 0; k--) { final String approvedPackageOrComponent = approved.valueAt(k); - if (!hasMatchingServices(approvedPackageOrComponent, userId)){ + if (!isValidEntry(approvedPackageOrComponent, userId)){ approved.removeAt(k); - if (DEBUG) { - Slog.v(TAG, "Removing " + approvedPackageOrComponent - + " from approved list; no matching services found"); - } + Slog.v(TAG, "Removing " + approvedPackageOrComponent + + " from approved list; no matching services found"); } else { if (DEBUG) { Slog.v(TAG, "Keeping " + approvedPackageOrComponent @@ -678,6 +729,10 @@ abstract public class ManagedServices { } } + protected boolean isValidEntry(String packageOrComponent, int userId) { + return hasMatchingServices(packageOrComponent, userId); + } + private boolean hasMatchingServices(String packageOrComponent, int userId) { if (!TextUtils.isEmpty(packageOrComponent)) { final String packageName = getPackageName(packageOrComponent); @@ -830,8 +885,7 @@ abstract public class ManagedServices { if (name.equals(info.component) && info.userid == userid) { // cut old connections - if (DEBUG) Slog.v(TAG, " disconnecting old " + getCaption() + ": " - + info.service); + Slog.v(TAG, " disconnecting old " + getCaption() + ": " + info.service); removeServiceLocked(i); if (info.connection != null) { mContext.unbindService(info.connection); @@ -859,7 +913,7 @@ abstract public class ManagedServices { appInfo != null ? appInfo.targetSdkVersion : Build.VERSION_CODES.BASE; try { - if (DEBUG) Slog.v(TAG, "binding: " + intent); + Slog.v(TAG, "binding: " + intent); ServiceConnection serviceConnection = new ServiceConnection() { IInterface mService; @@ -917,8 +971,7 @@ abstract public class ManagedServices { final int N = mServices.size(); for (int i = N - 1; i >= 0; i--) { final ManagedServiceInfo info = mServices.get(i); - if (name.equals(info.component) - && info.userid == userid) { + if (name.equals(info.component) && info.userid == userid) { removeServiceLocked(i); if (info.connection != null) { try { @@ -945,9 +998,8 @@ abstract public class ManagedServices { final int N = mServices.size(); for (int i = N - 1; i >= 0; i--) { final ManagedServiceInfo info = mServices.get(i); - if (info.service.asBinder() == service.asBinder() - && info.userid == userid) { - if (DEBUG) Slog.d(TAG, "Removing active service " + info.component); + if (info.service.asBinder() == service.asBinder() && info.userid == userid) { + Slog.d(TAG, "Removing active service " + info.component); serviceInfo = removeServiceLocked(i); } } @@ -1035,6 +1087,16 @@ abstract public class ManagedServices { .append(']').toString(); } + public void toProto(ProtoOutputStream proto, ManagedServices host) { + final long cToken = proto.start(ManagedServiceInfoProto.COMPONENT); + component.toProto(proto); + proto.end(cToken); + proto.write(ManagedServiceInfoProto.USER_ID, userid); + proto.write(ManagedServiceInfoProto.SERVICE, service.getClass().getName()); + proto.write(ManagedServiceInfoProto.IS_SYSTEM, isSystem); + proto.write(ManagedServiceInfoProto.IS_GUEST, isGuest(host)); + } + public boolean enabledAndUserMatches(int nid) { if (!isEnabledForCurrentProfiles()) { return false; 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 fe39fccbc781..1f0c14517e62 100644 --- a/services/core/java/com/android/server/notification/NotificationManagerService.java +++ b/services/core/java/com/android/server/notification/NotificationManagerService.java @@ -16,8 +16,10 @@ package com.android.server.notification; +import static android.app.NotificationManager.IMPORTANCE_LOW; import static android.app.NotificationManager.IMPORTANCE_MIN; import static android.app.NotificationManager.IMPORTANCE_NONE; +import static android.app.NotificationManager.IMPORTANCE_UNSPECIFIED; import static android.content.pm.PackageManager.FEATURE_LEANBACK; import static android.content.pm.PackageManager.FEATURE_TELEVISION; import static android.content.pm.PackageManager.PERMISSION_GRANTED; @@ -125,6 +127,7 @@ import android.service.notification.Condition; import android.service.notification.IConditionProvider; import android.service.notification.INotificationListener; import android.service.notification.IStatusBarNotificationHolder; +import android.service.notification.ListenersDisablingEffectsProto; import android.service.notification.NotificationAssistantService; import android.service.notification.NotificationListenerService; import android.service.notification.NotificationRankingUpdate; @@ -1142,6 +1145,12 @@ public class NotificationManagerService extends SystemService { } @VisibleForTesting + NotificationRecord getNotificationRecord(String key) { + return mNotificationsByKey.get(key); + } + + + @VisibleForTesting void setSystemReady(boolean systemReady) { mSystemReady = systemReady; } @@ -1216,7 +1225,7 @@ public class NotificationManagerService extends SystemService { mUsageStats = usageStats; mRankingHandler = new RankingHandlerWorker(mRankingThread.getLooper()); mRankingHelper = new RankingHelper(getContext(), - getContext().getPackageManager(), + mPackageManagerClient, mRankingHandler, mUsageStats, extractorNames); @@ -1476,7 +1485,7 @@ public class NotificationManagerService extends SystemService { } } } - mRankingHelper.updateNotificationChannel(pkg, uid, channel); + mRankingHelper.updateNotificationChannel(pkg, uid, channel, true); if (!fromListener) { final NotificationChannel modifiedChannel = @@ -3239,14 +3248,47 @@ public class NotificationManagerService extends SystemService { } } proto.end(records); - } - long zenLog = proto.start(NotificationServiceDumpProto.ZEN); - mZenModeHelper.dump(proto); - for (ComponentName suppressor : mEffectsSuppressors) { - proto.write(ZenModeProto.SUPPRESSORS, suppressor.toString()); + long zenLog = proto.start(NotificationServiceDumpProto.ZEN); + mZenModeHelper.dump(proto); + for (ComponentName suppressor : mEffectsSuppressors) { + proto.write(ZenModeProto.SUPPRESSORS, suppressor.toString()); + } + proto.end(zenLog); + + long listenersToken = proto.start(NotificationServiceDumpProto.NOTIFICATION_LISTENERS); + mListeners.dump(proto, filter); + proto.end(listenersToken); + + proto.write(NotificationServiceDumpProto.LISTENER_HINTS, mListenerHints); + + for (int i = 0; i < mListenersDisablingEffects.size(); ++i) { + long effectsToken = proto.start( + NotificationServiceDumpProto.LISTENERS_DISABLING_EFFECTS); + + proto.write( + ListenersDisablingEffectsProto.HINT, mListenersDisablingEffects.keyAt(i)); + final ArraySet<ManagedServiceInfo> listeners = + mListenersDisablingEffects.valueAt(i); + for (int j = 0; j < listeners.size(); j++) { + final ManagedServiceInfo listener = listeners.valueAt(i); + listenersToken = proto.start(ListenersDisablingEffectsProto.LISTENERS); + listener.toProto(proto, null); + proto.end(listenersToken); + } + + proto.end(effectsToken); + } + + long assistantsToken = proto.start( + NotificationServiceDumpProto.NOTIFICATION_ASSISTANTS); + mAssistants.dump(proto, filter); + proto.end(assistantsToken); + + long conditionsToken = proto.start(NotificationServiceDumpProto.CONDITION_PROVIDERS); + mConditionProviders.dump(proto, filter); + proto.end(conditionsToken); } - proto.end(zenLog); proto.flush(); } @@ -3519,6 +3561,21 @@ public class NotificationManagerService extends SystemService { user, null, System.currentTimeMillis()); final NotificationRecord r = new NotificationRecord(getContext(), n, channel); + if ((notification.flags & Notification.FLAG_FOREGROUND_SERVICE) != 0 + && (channel.getUserLockedFields() & NotificationChannel.USER_LOCKED_IMPORTANCE) == 0 + && (r.getImportance() == IMPORTANCE_MIN || r.getImportance() == IMPORTANCE_NONE)) { + // Increase the importance of foreground service notifications unless the user had an + // opinion otherwise + if (TextUtils.isEmpty(channelId) + || NotificationChannel.DEFAULT_CHANNEL_ID.equals(channelId)) { + r.setImportance(IMPORTANCE_LOW, "Bumped for foreground service"); + } else { + channel.setImportance(IMPORTANCE_LOW); + mRankingHelper.updateNotificationChannel(pkg, notificationUid, channel, false); + r.updateNotificationChannel(channel); + } + } + if (!checkDisqualifyingFeatures(userId, notificationUid, id, tag, r, r.sbn.getOverrideGroupKey() != null)) { return; @@ -4028,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) { @@ -4137,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/RankingConfig.java b/services/core/java/com/android/server/notification/RankingConfig.java index b5ef1c60f607..b9c0d90741f3 100644 --- a/services/core/java/com/android/server/notification/RankingConfig.java +++ b/services/core/java/com/android/server/notification/RankingConfig.java @@ -39,7 +39,7 @@ public interface RankingConfig { int uid, boolean includeDeleted); void createNotificationChannel(String pkg, int uid, NotificationChannel channel, boolean fromTargetApp); - void updateNotificationChannel(String pkg, int uid, NotificationChannel channel); + void updateNotificationChannel(String pkg, int uid, NotificationChannel channel, boolean fromUser); NotificationChannel getNotificationChannel(String pkg, int uid, String channelId, boolean includeDeleted); void deleteNotificationChannel(String pkg, int uid, String channelId); void permanentlyDeleteNotificationChannel(String pkg, int uid, String channelId); diff --git a/services/core/java/com/android/server/notification/RankingHelper.java b/services/core/java/com/android/server/notification/RankingHelper.java index fc24581f148f..fea2464ba5b8 100644 --- a/services/core/java/com/android/server/notification/RankingHelper.java +++ b/services/core/java/com/android/server/notification/RankingHelper.java @@ -613,7 +613,8 @@ public class RankingHelper implements RankingConfig { } @Override - public void updateNotificationChannel(String pkg, int uid, NotificationChannel updatedChannel) { + public void updateNotificationChannel(String pkg, int uid, NotificationChannel updatedChannel, + boolean fromUser) { Preconditions.checkNotNull(updatedChannel); Preconditions.checkNotNull(updatedChannel.getId()); Record r = getOrCreateRecord(pkg, uid); @@ -627,7 +628,11 @@ public class RankingHelper implements RankingConfig { if (updatedChannel.getLockscreenVisibility() == Notification.VISIBILITY_PUBLIC) { updatedChannel.setLockscreenVisibility(Ranking.VISIBILITY_NO_OVERRIDE); } - lockFieldsForUpdate(channel, updatedChannel); + updatedChannel.unlockFields(updatedChannel.getUserLockedFields()); + updatedChannel.lockFields(channel.getUserLockedFields()); + if (fromUser) { + lockFieldsForUpdate(channel, updatedChannel); + } r.channels.put(updatedChannel.getId(), updatedChannel); if (NotificationChannel.DEFAULT_CHANNEL_ID.equals(updatedChannel.getId())) { @@ -874,8 +879,6 @@ public class RankingHelper implements RankingConfig { @VisibleForTesting void lockFieldsForUpdate(NotificationChannel original, NotificationChannel update) { - update.unlockFields(update.getUserLockedFields()); - update.lockFields(original.getUserLockedFields()); if (original.canBypassDnd() != update.canBypassDnd()) { update.lockFields(NotificationChannel.USER_LOCKED_PRIORITY); } diff --git a/services/core/java/com/android/server/notification/ScheduleCalendar.java b/services/core/java/com/android/server/notification/ScheduleCalendar.java index 9e8b2e34520b..40230bd2ba82 100644 --- a/services/core/java/com/android/server/notification/ScheduleCalendar.java +++ b/services/core/java/com/android/server/notification/ScheduleCalendar.java @@ -42,7 +42,8 @@ public class ScheduleCalendar { public void maybeSetNextAlarm(long now, long nextAlarm) { if (mSchedule != null) { - if (mSchedule.exitAtAlarm && now > mSchedule.nextAlarm) { + if (mSchedule.exitAtAlarm + && (now > mSchedule.nextAlarm || nextAlarm < mSchedule.nextAlarm)) { mSchedule.nextAlarm = nextAlarm; } } 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/BackgroundDexOptService.java b/services/core/java/com/android/server/pm/BackgroundDexOptService.java index 415c9a9cba10..6d8cac0c661b 100644 --- a/services/core/java/com/android/server/pm/BackgroundDexOptService.java +++ b/services/core/java/com/android/server/pm/BackgroundDexOptService.java @@ -342,8 +342,7 @@ public class BackgroundDexOptService extends JobService { DexoptOptions.DEXOPT_BOOT_COMPLETE | (downgrade ? DexoptOptions.DEXOPT_DOWNGRADE : 0); if (is_for_primary_dex) { - int result = pm.performDexOptWithStatus(new DexoptOptions(pkg, - PackageManagerService.REASON_BACKGROUND_DEXOPT, + int result = pm.performDexOptWithStatus(new DexoptOptions(pkg, reason, dexoptFlags)); success = result != PackageDexOptimizer.DEX_OPT_FAILED; if (result == PackageDexOptimizer.DEX_OPT_PERFORMED) { @@ -351,8 +350,7 @@ public class BackgroundDexOptService extends JobService { } } else { success = pm.performDexOpt(new DexoptOptions(pkg, - PackageManagerService.REASON_BACKGROUND_DEXOPT, - dexoptFlags | DexoptOptions.DEXOPT_ONLY_SECONDARY_DEX)); + reason, dexoptFlags | DexoptOptions.DEXOPT_ONLY_SECONDARY_DEX)); } if (success) { // Dexopt succeeded, remove package from the list of failing ones. 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 8852a4db0cfe..bbb58ac7886c 100644 --- a/services/core/java/com/android/server/pm/PackageManagerService.java +++ b/services/core/java/com/android/server/pm/PackageManagerService.java @@ -9796,19 +9796,6 @@ public class PackageManagerService extends IPackageManager.Stub } } - // 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(compilerFilter) && - !Environment.getReferenceProfile(pkg.packageName).exists()) { - compilerFilter = getNonProfileGuidedCompilerFilter(compilerFilter); - } - // checkProfiles is false to avoid merging profiles during boot which // might interfere with background compilation (b/28612421). // Unfortunately this will also means that "pm.dexopt.boot=speed-profile" will @@ -10691,6 +10678,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()); @@ -25233,6 +25226,37 @@ Slog.v(TAG, ":: stepped forward, applying functor at tag " + parser.getName()); } return results; } + + // NB: this differentiates between preloads and sideloads + @Override + public String getInstallerForPackage(String packageName) throws RemoteException { + final String installerName = getInstallerPackageName(packageName); + if (!TextUtils.isEmpty(installerName)) { + return installerName; + } + // differentiate between preload and sideload + int callingUser = UserHandle.getUserId(Binder.getCallingUid()); + ApplicationInfo appInfo = getApplicationInfo(packageName, + /*flags*/ 0, + /*userId*/ callingUser); + if (appInfo != null && (appInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0) { + return "preload"; + } + return ""; + } + + @Override + public int getVersionCodeForPackage(String packageName) throws RemoteException { + try { + int callingUser = UserHandle.getUserId(Binder.getCallingUid()); + PackageInfo pInfo = getPackageInfo(packageName, 0, callingUser); + if (pInfo != null) { + return pInfo.versionCode; + } + } catch (Exception e) { + } + return 0; + } } private class PackageManagerInternalImpl extends PackageManagerInternal { 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/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java index d19bf445ef04..578429a1d05c 100644 --- a/services/core/java/com/android/server/policy/PhoneWindowManager.java +++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java @@ -2627,18 +2627,15 @@ public class PhoneWindowManager implements WindowManagerPolicy { attrs.privateFlags &= ~WindowManager.LayoutParams.PRIVATE_FLAG_KEYGUARD; } - if (ActivityManager.isHighEndGfx()) { - if ((attrs.flags & FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) != 0) { - attrs.subtreeSystemUiVisibility |= View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION; - } - final boolean forceWindowDrawsStatusBarBackground = - (attrs.privateFlags & PRIVATE_FLAG_FORCE_DRAW_STATUS_BAR_BACKGROUND) - != 0; - if ((attrs.flags & FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) != 0 - || forceWindowDrawsStatusBarBackground - && attrs.height == MATCH_PARENT && attrs.width == MATCH_PARENT) { - attrs.subtreeSystemUiVisibility |= View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN; - } + if ((attrs.flags & FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) != 0) { + attrs.subtreeSystemUiVisibility |= View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION; + } + final boolean forceWindowDrawsStatusBarBackground = + (attrs.privateFlags & PRIVATE_FLAG_FORCE_DRAW_STATUS_BAR_BACKGROUND) != 0; + if ((attrs.flags & FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) != 0 + || forceWindowDrawsStatusBarBackground + && attrs.height == MATCH_PARENT && attrs.width == MATCH_PARENT) { + attrs.subtreeSystemUiVisibility |= View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN; } } diff --git a/services/core/java/com/android/server/power/PowerManagerService.java b/services/core/java/com/android/server/power/PowerManagerService.java index 12ca89a93d02..b917dae2adf8 100644 --- a/services/core/java/com/android/server/power/PowerManagerService.java +++ b/services/core/java/com/android/server/power/PowerManagerService.java @@ -120,7 +120,7 @@ public final class PowerManagerService extends SystemService implements Watchdog.Monitor { private static final String TAG = "PowerManagerService"; - private static final boolean DEBUG = true; + private static final boolean DEBUG = false; private static final boolean DEBUG_SPEW = DEBUG && true; // Message: Sent when a user activity timeout occurs to update the power state. @@ -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/stats/StatsCompanionService.java b/services/core/java/com/android/server/stats/StatsCompanionService.java index 5b77b1ed5269..11ae2129c339 100644 --- a/services/core/java/com/android/server/stats/StatsCompanionService.java +++ b/services/core/java/com/android/server/stats/StatsCompanionService.java @@ -21,12 +21,15 @@ import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.os.Binder; +import android.os.IBinder; import android.os.IStatsCompanionService; import android.os.IStatsManager; import android.os.Process; +import android.os.RemoteException; import android.os.ServiceManager; import android.util.Slog; +import com.android.internal.annotations.GuardedBy; import com.android.server.SystemService; /** @@ -39,29 +42,13 @@ public class StatsCompanionService extends IStatsCompanionService.Stub { private final Context mContext; private final AlarmManager mAlarmManager; - private final IStatsManager mStatsd; + @GuardedBy("sStatsdLock") + private static IStatsManager sStatsd; + private static final Object sStatsdLock = new Object(); private final PendingIntent mAnomalyAlarmIntent; private final PendingIntent mPollingAlarmIntent; - public final static class AnomalyAlarmReceiver extends BroadcastReceiver { - @Override - public void onReceive(Context context, Intent intent) { - Slog.i(TAG, "StatsCompanionService believes an anomaly has occurred."); - // TODO: mStatsd.informAlarm(); // should be twoway so device won't sleep before acting? - // AlarmManager releases its own wakelock here. - } - }; - - public final static class PollingAlarmReceiver extends BroadcastReceiver { - @Override - public void onReceive(Context context, Intent intent) { - if (DEBUG) Slog.d(TAG, "Time to poll something."); - // TODO: mStatsd.poll(); // should be twoway so device won't sleep before acting? - // AlarmManager releases its own wakelock here. - } - }; - public StatsCompanionService(Context context) { super(); mContext = context; @@ -71,33 +58,47 @@ public class StatsCompanionService extends IStatsCompanionService.Stub { new Intent(mContext, AnomalyAlarmReceiver.class), 0); mPollingAlarmIntent = PendingIntent.getBroadcast(mContext, 0, new Intent(mContext, PollingAlarmReceiver.class), 0); - - mStatsd = getStatsdService(); } - /** Returns the statsd IBinder service */ - public static IStatsManager getStatsdService() { - return IStatsManager.Stub.asInterface(ServiceManager.getService("statsd")); - } - - public static final class Lifecycle extends SystemService { - private StatsCompanionService mStatsCompanionService; - - public Lifecycle(Context context) { - super(context); + public final static class AnomalyAlarmReceiver extends BroadcastReceiver { + @Override + public void onReceive(Context context, Intent intent) { + Slog.i(TAG, "StatsCompanionService believes an anomaly has occurred."); + synchronized (sStatsdLock) { + if (sStatsd == null) { + Slog.w(TAG, "Could not access statsd to inform it of anomaly alarm firing"); + return; + } + try { + // Two-way call to statsd to retain AlarmManager wakelock + sStatsd.informAnomalyAlarmFired(); + } catch (RemoteException e) { + Slog.w(TAG, "Failed to inform statsd of anomaly alarm firing", e); + } + } + // AlarmManager releases its own wakelock here. } + }; + public final static class PollingAlarmReceiver extends BroadcastReceiver { @Override - public void onStart() { - mStatsCompanionService = new StatsCompanionService(getContext()); - try { - publishBinderService(Context.STATS_COMPANION_SERVICE, mStatsCompanionService); - if (DEBUG) Slog.d(TAG, "Published " + Context.STATS_COMPANION_SERVICE); - } catch (Exception e) { - Slog.e(TAG, "Failed to publishBinderService", e); + public void onReceive(Context context, Intent intent) { + if (DEBUG) Slog.d(TAG, "Time to poll something."); + synchronized (sStatsdLock) { + if (sStatsd == null) { + Slog.w(TAG, "Could not access statsd to inform it of polling alarm firing"); + return; + } + try { + // Two-way call to statsd to retain AlarmManager wakelock + sStatsd.informPollAlarmFired(); + } catch (RemoteException e) { + Slog.w(TAG, "Failed to inform statsd of polling alarm firing", e); + } } + // AlarmManager releases its own wakelock here. } - } + }; @Override // Binder call public void setAnomalyAlarm(long timestampMs) { @@ -155,6 +156,13 @@ public class StatsCompanionService extends IStatsCompanionService.Stub { } } + @Override + public void statsdReady() { + enforceCallingPermission(); + if (DEBUG) Slog.d(TAG, "learned that statsdReady"); + sayHiToStatsd(); // tell statsd that we're ready too and link to it + } + private void enforceCallingPermission() { if (Binder.getCallingPid() == Process.myPid()) { return; @@ -162,4 +170,90 @@ public class StatsCompanionService extends IStatsCompanionService.Stub { mContext.enforceCallingPermission(android.Manifest.permission.STATSCOMPANION, null); } + // Lifecycle and related code + + /** Fetches the statsd IBinder service */ + private static IStatsManager fetchStatsdService() { + return IStatsManager.Stub.asInterface(ServiceManager.getService("stats")); + } + + public static final class Lifecycle extends SystemService { + private StatsCompanionService mStatsCompanionService; + + public Lifecycle(Context context) { + super(context); + } + + @Override + public void onStart() { + mStatsCompanionService = new StatsCompanionService(getContext()); + try { + publishBinderService(Context.STATS_COMPANION_SERVICE, mStatsCompanionService); + if (DEBUG) Slog.d(TAG, "Published " + Context.STATS_COMPANION_SERVICE); + } catch (Exception e) { + Slog.e(TAG, "Failed to publishBinderService", e); + } + } + + @Override + public void onBootPhase(int phase) { + super.onBootPhase(phase); + if (phase == PHASE_THIRD_PARTY_APPS_CAN_START) { + mStatsCompanionService.systemReady(); + } + } + } + + /** Now that the android system is ready, StatsCompanion is ready too, so inform statsd. */ + private void systemReady() { + if (DEBUG) Slog.d(TAG, "Learned that systemReady"); + sayHiToStatsd(); + } + + /** Tells statsd that statscompanion is ready. If the binder call returns, link to statsd. */ + private void sayHiToStatsd() { + synchronized (sStatsdLock) { + if (sStatsd != null) { + Slog.e(TAG, "Trying to fetch statsd, but it was already fetched", + new IllegalStateException("sStatsd is not null when being fetched")); + return; + } + sStatsd = fetchStatsdService(); + if (sStatsd == null) { + Slog.w(TAG, "Could not access statsd"); + return; + } + if (DEBUG) Slog.d(TAG, "Saying hi to statsd"); + try { + sStatsd.statsCompanionReady(); + // If the statsCompanionReady two-way binder call returns, link to statsd. + try { + sStatsd.asBinder().linkToDeath(new StatsdDeathRecipient(), 0); + } catch (RemoteException e) { + Slog.e(TAG, "linkToDeath(StatsdDeathRecipient) failed", e); + forgetEverything(); + } + } catch (RemoteException e) { + Slog.e(TAG, "Failed to inform statsd that statscompanion is ready", e); + forgetEverything(); + } + } + } + + private class StatsdDeathRecipient implements IBinder.DeathRecipient { + @Override + public void binderDied() { + Slog.i(TAG, "Statsd is dead - erase all my knowledge."); + forgetEverything(); + } + } + + private void forgetEverything() { + synchronized (sStatsdLock) { + sStatsd = null; + cancelAnomalyAlarm(); + cancelPollingAlarms(); + } + } + } 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/utils/ManagedApplicationService.java b/services/core/java/com/android/server/utils/ManagedApplicationService.java index 0f251fd83822..1ea70585aa5f 100644 --- a/services/core/java/com/android/server/utils/ManagedApplicationService.java +++ b/services/core/java/com/android/server/utils/ManagedApplicationService.java @@ -44,6 +44,7 @@ public class ManagedApplicationService { private final int mClientLabel; private final String mSettingsAction; private final BinderChecker mChecker; + private final boolean mIsImportant; private final DeathRecipient mDeathRecipient = new DeathRecipient() { @Override @@ -64,13 +65,14 @@ public class ManagedApplicationService { private ManagedApplicationService(final Context context, final ComponentName component, final int userId, int clientLabel, String settingsAction, - BinderChecker binderChecker) { + BinderChecker binderChecker, boolean isImportant) { mContext = context; mComponent = component; mUserId = userId; mClientLabel = clientLabel; mSettingsAction = settingsAction; mChecker = binderChecker; + mIsImportant = isImportant; } /** @@ -99,13 +101,15 @@ public class ManagedApplicationService { * @param settingsAction an action that can be used to open the Settings UI to enable/disable * binding to these services. * @param binderChecker an interface used to validate the returned binder object. + * @param isImportant bind the user service with BIND_IMPORTANT. * @return a ManagedApplicationService instance. */ public static ManagedApplicationService build(@NonNull final Context context, @NonNull final ComponentName component, final int userId, @NonNull int clientLabel, - @NonNull String settingsAction, @NonNull BinderChecker binderChecker) { + @NonNull String settingsAction, @NonNull BinderChecker binderChecker, + boolean isImportant) { return new ManagedApplicationService(context, component, userId, clientLabel, - settingsAction, binderChecker); + settingsAction, binderChecker, isImportant); } /** @@ -248,9 +252,12 @@ public class ManagedApplicationService { mPendingConnection = serviceConnection; + int flags = Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE; + if (mIsImportant) { + flags |= Context.BIND_IMPORTANT; + } try { - if (!mContext.bindServiceAsUser(intent, serviceConnection, - Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE, + if (!mContext.bindServiceAsUser(intent, serviceConnection, flags, new UserHandle(mUserId))) { Slog.w(TAG, "Unable to bind service: " + intent); } diff --git a/services/core/java/com/android/server/utils/PriorityDump.java b/services/core/java/com/android/server/utils/PriorityDump.java index c05cc3ff8827..054f1564730e 100644 --- a/services/core/java/com/android/server/utils/PriorityDump.java +++ b/services/core/java/com/android/server/utils/PriorityDump.java @@ -59,10 +59,10 @@ public class SpringfieldNuclearPowerPlant extends Binder { Donuts in the box: 1 Nuclear reactor status: DANGER - MELTDOWN IMMINENT - $ adb shell dumpsys snpp --dump_priority CRITICAL + $ adb shell dumpsys snpp --dump-priority CRITICAL Donuts in the box: 1 - $ adb shell dumpsys snpp --dump_priority NORMAL + $ adb shell dumpsys snpp --dump-priority NORMAL Nuclear reactor status: DANGER - MELTDOWN IMMINENT * </code></pre> @@ -84,7 +84,7 @@ public class SpringfieldNuclearPowerPlant extends Binder { */ public final class PriorityDump { - public static final String PRIORITY_ARG = "--dump_priority"; + public static final String PRIORITY_ARG = "--dump-priority"; private PriorityDump() { throw new UnsupportedOperationException(); @@ -92,12 +92,12 @@ public final class PriorityDump { /** * Parses {@code} and call the proper {@link PriorityDumper} method when the first argument is - * {@code --dump_priority}, stripping the priority and its type. + * {@code --dump-priority}, stripping the priority and its type. * <p> - * For example, if called as {@code --dump_priority HIGH arg1 arg2 arg3}, it will call + * For example, if called as {@code --dump-priority HIGH arg1 arg2 arg3}, it will call * <code>dumper.dumpHigh(fd, pw, {"arg1", "arg2", "arg3"}) </code> * <p> - * If the {@code --dump_priority} is not set, it calls + * If the {@code --dump-priority} is not set, it calls * {@link PriorityDumper#dump(FileDescriptor, PrintWriter, String[])} passing the whole * {@code args} instead. */ @@ -124,7 +124,7 @@ public final class PriorityDump { } /** - * Gets an array without the {@code --dump_priority PRIORITY} prefix. + * Gets an array without the {@code --dump-priority PRIORITY} prefix. */ private static String[] getStrippedArgs(String[] args) { final String[] stripped = new String[args.length - 2]; diff --git a/services/core/java/com/android/server/vr/VrManagerService.java b/services/core/java/com/android/server/vr/VrManagerService.java index 1f0b2f000be1..830ebda0b9c1 100644 --- a/services/core/java/com/android/server/vr/VrManagerService.java +++ b/services/core/java/com/android/server/vr/VrManagerService.java @@ -1026,7 +1026,7 @@ public class VrManagerService extends SystemService implements EnabledComponentC @NonNull ComponentName component, int userId) { return ManagedApplicationService.build(context, component, userId, R.string.vr_listener_binding_label, Settings.ACTION_VR_LISTENER_SETTINGS, - sBinderChecker); + sBinderChecker, /*isImportant*/true); } /** diff --git a/services/core/java/com/android/server/wm/AppWindowToken.java b/services/core/java/com/android/server/wm/AppWindowToken.java index 2d1fc912fcfc..78f81574c5bc 100644 --- a/services/core/java/com/android/server/wm/AppWindowToken.java +++ b/services/core/java/com/android/server/wm/AppWindowToken.java @@ -16,8 +16,7 @@ package com.android.server.wm; -import static android.app.ActivityManager.StackId; -import static android.app.ActivityManager.StackId.PINNED_STACK_ID; +import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED; import static android.content.pm.ActivityInfo.CONFIG_ORIENTATION; import static android.content.pm.ActivityInfo.CONFIG_SCREEN_SIZE; import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_BEHIND; @@ -1312,7 +1311,8 @@ class AppWindowToken extends WindowToken implements WindowManagerService.AppFree // Notify the pinned stack upon all windows drawn. If there was an animation in // progress then this signal will resume that animation. - final TaskStack pinnedStack = mDisplayContent.getStackById(PINNED_STACK_ID); + final TaskStack pinnedStack = + mDisplayContent.getStack(WINDOWING_MODE_PINNED); if (pinnedStack != null) { pinnedStack.onAllWindowsDrawn(); } diff --git a/services/core/java/com/android/server/wm/ConfigurationContainer.java b/services/core/java/com/android/server/wm/ConfigurationContainer.java index 1da94da1b3b6..dc5a81443b96 100644 --- a/services/core/java/com/android/server/wm/ConfigurationContainer.java +++ b/services/core/java/com/android/server/wm/ConfigurationContainer.java @@ -225,9 +225,37 @@ public abstract class ConfigurationContainer<E extends ConfigurationContainer> { /*@WindowConfiguration.ActivityType*/ int thisType = getActivityType(); /*@WindowConfiguration.ActivityType*/ int otherType = other.getActivityType(); - return thisType == otherType - || thisType == ACTIVITY_TYPE_UNDEFINED - || otherType == ACTIVITY_TYPE_UNDEFINED; + if (thisType == otherType) { + return true; + } + if (thisType == ACTIVITY_TYPE_ASSISTANT) { + // Assistant activities are only compatible with themselves... + return false; + } + // Otherwise we are compatible if us or other is not currently defined. + return thisType == ACTIVITY_TYPE_UNDEFINED || otherType == ACTIVITY_TYPE_UNDEFINED; + } + + /** + * Returns true if this container is compatible with the input windowing mode and activity type. + */ + public boolean isCompatible(int windowingMode, int activityType) { + final int thisActivityType = getActivityType(); + final int thisWindowingMode = getWindowingMode(); + final boolean sameActivityType = thisActivityType == activityType; + final boolean sameWindowingMode = thisWindowingMode == windowingMode; + + if (sameActivityType && sameWindowingMode) { + return true; + } + + if (activityType != ACTIVITY_TYPE_UNDEFINED && activityType != ACTIVITY_TYPE_STANDARD) { + // Only activity type need to match for non-standard activity types that are defined. + return sameActivityType; + } + + // Otherwise we are compatible if the windowing mode is the same. + return sameWindowingMode; } public void registerConfigurationChangeListener(ConfigurationContainerListener listener) { diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java index 98a1bd359b55..7ae5d1a872de 100644 --- a/services/core/java/com/android/server/wm/DisplayContent.java +++ b/services/core/java/com/android/server/wm/DisplayContent.java @@ -19,8 +19,10 @@ package com.android.server.wm; import static android.app.ActivityManager.StackId.DOCKED_STACK_ID; import static android.app.ActivityManager.StackId.FREEFORM_WORKSPACE_STACK_ID; import static android.app.ActivityManager.StackId.HOME_STACK_ID; -import static android.app.ActivityManager.StackId.PINNED_STACK_ID; +import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED; import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN; +import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED; +import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY; import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_BEHIND; import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSET; import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED; @@ -117,7 +119,6 @@ import static com.android.server.wm.proto.DisplayProto.WINDOW_CONTAINER; import android.annotation.CallSuper; import android.annotation.NonNull; import android.app.ActivityManager.StackId; -import android.app.WindowConfiguration; import android.content.res.CompatibilityInfo; import android.content.res.Configuration; import android.graphics.Bitmap; @@ -1457,6 +1458,28 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo return null; } + /** + * Returns the topmost stack on the display that is compatible with the input windowing mode. + * Null is no compatible stack on the display. + */ + TaskStack getStack(int windowingMode) { + return getStack(windowingMode, ACTIVITY_TYPE_UNDEFINED); + } + + /** + * Returns the topmost stack on the display that is compatible with the input windowing mode and + * activity type. Null is no compatible stack on the display. + */ + private TaskStack getStack(int windowingMode, int activityType) { + for (int i = mTaskStackContainers.size() - 1; i >= 0; --i) { + final TaskStack stack = mTaskStackContainers.get(i); + if (stack.isCompatible(windowingMode, activityType)) { + return stack; + } + } + return null; + } + @VisibleForTesting int getStackCount() { return mTaskStackContainers.size(); @@ -1501,7 +1524,7 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo // If there was no pinned stack, we still need to notify the controller of the display info // update as a result of the config change. We do this here to consolidate the flow between // changes when there is and is not a stack. - if (getStackById(PINNED_STACK_ID) == null) { + if (getStack(WINDOWING_MODE_PINNED) == null) { mPinnedStackControllerLocked.onDisplayInfoChanged(); } } @@ -2238,7 +2261,7 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo * @return The docked stack, but only if it is visible, and {@code null} otherwise. */ TaskStack getDockedStackLocked() { - final TaskStack stack = getStackById(DOCKED_STACK_ID); + final TaskStack stack = getStack(WINDOWING_MODE_SPLIT_SCREEN_PRIMARY); return (stack != null && stack.isVisible()) ? stack : null; } @@ -2247,7 +2270,7 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo * visible. */ TaskStack getDockedStackIgnoringVisibility() { - return getStackById(DOCKED_STACK_ID); + return getStack(WINDOWING_MODE_SPLIT_SCREEN_PRIMARY); } /** Find the visible, touch-deliverable window under the given point */ @@ -3421,11 +3444,11 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo : requestedPosition >= topChildPosition; int targetPosition = requestedPosition; - if (toTop && stack.mStackId != PINNED_STACK_ID - && getStackById(PINNED_STACK_ID) != null) { + if (toTop && stack.getWindowingMode() != WINDOWING_MODE_PINNED + && getStack(WINDOWING_MODE_PINNED) != null) { // The pinned stack is always the top most stack (always-on-top) when it is present. TaskStack topStack = mChildren.get(topChildPosition); - if (topStack.mStackId != PINNED_STACK_ID) { + if (topStack.getWindowingMode() != WINDOWING_MODE_PINNED) { throw new IllegalStateException("Pinned stack isn't top stack??? " + mChildren); } diff --git a/services/core/java/com/android/server/wm/DockedStackDividerController.java b/services/core/java/com/android/server/wm/DockedStackDividerController.java index 030b986ef0e9..e0a46666bd76 100644 --- a/services/core/java/com/android/server/wm/DockedStackDividerController.java +++ b/services/core/java/com/android/server/wm/DockedStackDividerController.java @@ -17,8 +17,9 @@ package com.android.server.wm; import static android.app.ActivityManager.StackId.DOCKED_STACK_ID; -import static android.app.ActivityManager.StackId.FULLSCREEN_WORKSPACE_STACK_ID; import static android.app.ActivityManager.StackId.INVALID_STACK_ID; +import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY; +import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_SECONDARY; import static android.content.res.Configuration.ORIENTATION_LANDSCAPE; import static android.content.res.Configuration.ORIENTATION_PORTRAIT; import static android.view.Surface.ROTATION_270; @@ -456,7 +457,8 @@ public class DockedStackDividerController implements DimLayerUser { boolean isHomeStackResizable) { long animDuration = 0; if (animate) { - final TaskStack stack = mDisplayContent.getStackById(DOCKED_STACK_ID); + final TaskStack stack = + mDisplayContent.getStack(WINDOWING_MODE_SPLIT_SCREEN_PRIMARY); final long transitionDuration = isAnimationMaximizing() ? mService.mAppTransition.getLastClipRevealTransitionDuration() : DEFAULT_APP_TRANSITION_DURATION; @@ -605,8 +607,8 @@ public class DockedStackDividerController implements DimLayerUser { if (mMinimizedDock && mService.mPolicy.isKeyguardShowingAndNotOccluded()) { return; } - final TaskStack fullscreenStack = - mDisplayContent.getStackById(FULLSCREEN_WORKSPACE_STACK_ID); + final TaskStack fullscreenStack = mDisplayContent.getStack( + WINDOWING_MODE_SPLIT_SCREEN_SECONDARY); final boolean homeVisible = homeTask.getTopVisibleAppToken() != null; final boolean homeBehind = fullscreenStack != null && fullscreenStack.isVisible(); setMinimizedDockedStack(homeVisible && !homeBehind, animate); @@ -801,7 +803,8 @@ public class DockedStackDividerController implements DimLayerUser { } private boolean animateForMinimizedDockedStack(long now) { - final TaskStack stack = mDisplayContent.getStackById(DOCKED_STACK_ID); + final TaskStack stack = + mDisplayContent.getStack(WINDOWING_MODE_SPLIT_SCREEN_PRIMARY); if (!mAnimationStarted) { mAnimationStarted = true; mAnimationStartTime = now; diff --git a/services/core/java/com/android/server/wm/PinnedStackController.java b/services/core/java/com/android/server/wm/PinnedStackController.java index 1e7140a12d01..4c9326dbba86 100644 --- a/services/core/java/com/android/server/wm/PinnedStackController.java +++ b/services/core/java/com/android/server/wm/PinnedStackController.java @@ -17,6 +17,7 @@ package com.android.server.wm; import static android.app.ActivityManager.StackId.PINNED_STACK_ID; +import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED; import static android.util.TypedValue.COMPLEX_UNIT_DIP; import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME; @@ -404,27 +405,29 @@ class PinnedStackController { */ private void notifyMovementBoundsChanged(boolean fromImeAdjustement) { synchronized (mService.mWindowMap) { - if (mPinnedStackListener != null) { - try { - final Rect insetBounds = new Rect(); - getInsetBounds(insetBounds); - final Rect normalBounds = getDefaultBounds(); - if (isValidPictureInPictureAspectRatio(mAspectRatio)) { - transformBoundsToAspectRatio(normalBounds, mAspectRatio, - false /* useCurrentMinEdgeSize */); - } - final Rect animatingBounds = mTmpAnimatingBoundsRect; - final TaskStack pinnedStack = mDisplayContent.getStackById(PINNED_STACK_ID); - if (pinnedStack != null) { - pinnedStack.getAnimationOrCurrentBounds(animatingBounds); - } else { - animatingBounds.set(normalBounds); - } - mPinnedStackListener.onMovementBoundsChanged(insetBounds, normalBounds, - animatingBounds, fromImeAdjustement, mDisplayInfo.rotation); - } catch (RemoteException e) { - Slog.e(TAG_WM, "Error delivering actions changed event.", e); + if (mPinnedStackListener == null) { + return; + } + try { + final Rect insetBounds = new Rect(); + getInsetBounds(insetBounds); + final Rect normalBounds = getDefaultBounds(); + if (isValidPictureInPictureAspectRatio(mAspectRatio)) { + transformBoundsToAspectRatio(normalBounds, mAspectRatio, + false /* useCurrentMinEdgeSize */); + } + final Rect animatingBounds = mTmpAnimatingBoundsRect; + final TaskStack pinnedStack = + mDisplayContent.getStack(WINDOWING_MODE_PINNED); + if (pinnedStack != null) { + pinnedStack.getAnimationOrCurrentBounds(animatingBounds); + } else { + animatingBounds.set(normalBounds); } + mPinnedStackListener.onMovementBoundsChanged(insetBounds, normalBounds, + animatingBounds, fromImeAdjustement, mDisplayInfo.rotation); + } catch (RemoteException e) { + Slog.e(TAG_WM, "Error delivering actions changed event.", e); } } } diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java index 6f796481cc08..10adc5a65388 100644 --- a/services/core/java/com/android/server/wm/WindowManagerService.java +++ b/services/core/java/com/android/server/wm/WindowManagerService.java @@ -247,6 +247,7 @@ import com.android.server.Watchdog; import com.android.server.input.InputManagerService; import com.android.server.power.BatterySaverPolicy.ServiceType; import com.android.server.power.ShutdownThread; +import com.android.server.utils.PriorityDump; import java.io.BufferedWriter; import java.io.DataInputStream; @@ -391,6 +392,18 @@ public class WindowManagerService extends IWindowManager.Stub }; final WindowSurfacePlacer mWindowPlacerLocked; + private final PriorityDump.PriorityDumper mPriorityDumper = new PriorityDump.PriorityDumper() { + @Override + public void dumpCritical(FileDescriptor fd, PrintWriter pw, String[] args) { + doDump(fd, pw, new String[] {"-a"}); + } + + @Override + public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { + doDump(fd, pw, args); + } + }; + /** * Current user when multi-user is enabled. Don't show windows of * non-current user. Also see mCurrentProfileIds. @@ -2180,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); @@ -6794,8 +6817,11 @@ public class WindowManagerService extends IWindowManager.Stub @Override public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { - if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return; + PriorityDump.dump(mPriorityDumper, fd, pw, args); + } + private void doDump(FileDescriptor fd, PrintWriter pw, String[] args) { + if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return; boolean dumpAll = false; boolean useProto = false; 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/notification/src/com/android/server/notification/NotificationManagerServiceTest.java b/services/tests/notification/src/com/android/server/notification/NotificationManagerServiceTest.java index ddd21df78e85..71a024c5be07 100644 --- a/services/tests/notification/src/com/android/server/notification/NotificationManagerServiceTest.java +++ b/services/tests/notification/src/com/android/server/notification/NotificationManagerServiceTest.java @@ -16,12 +16,15 @@ package com.android.server.notification; +import static android.app.NotificationManager.IMPORTANCE_HIGH; import static android.app.NotificationManager.IMPORTANCE_LOW; import static android.app.NotificationManager.IMPORTANCE_NONE; +import static android.app.NotificationManager.IMPORTANCE_UNSPECIFIED; import static android.content.pm.PackageManager.PERMISSION_DENIED; import static junit.framework.Assert.assertEquals; import static junit.framework.Assert.assertFalse; +import static junit.framework.Assert.assertNull; import static junit.framework.Assert.assertTrue; import static junit.framework.Assert.fail; @@ -56,6 +59,7 @@ import android.content.pm.ParceledListSlice; import android.graphics.Color; import android.media.AudioManager; import android.os.Binder; +import android.os.Build; import android.os.Process; import android.os.UserHandle; import android.provider.Settings.Secure; @@ -241,6 +245,7 @@ public class NotificationManagerServiceTest extends NotificationTestCase { nb.build(), new UserHandle(mUid), null, 0); return new NotificationRecord(mContext, sbn, channel); } + private NotificationRecord generateNotificationRecord(NotificationChannel channel) { return generateNotificationRecord(channel, null); } @@ -342,7 +347,7 @@ public class NotificationManagerServiceTest extends NotificationTestCase { // Recreating the channel doesn't throw, but ignores importance. final NotificationChannel dupeChannel = - new NotificationChannel("id", "name", NotificationManager.IMPORTANCE_HIGH); + new NotificationChannel("id", "name", IMPORTANCE_HIGH); mBinderService.createNotificationChannels(PKG, new ParceledListSlice(Arrays.asList(dupeChannel))); final NotificationChannel createdChannel = @@ -378,7 +383,7 @@ public class NotificationManagerServiceTest extends NotificationTestCase { // The user modifies importance directly, can no longer be changed by the app. final NotificationChannel updatedChannel = - new NotificationChannel("id", "name", NotificationManager.IMPORTANCE_HIGH); + new NotificationChannel("id", "name", IMPORTANCE_HIGH); mBinderService.updateNotificationChannelForPackage(PKG, mUid, updatedChannel); // Recreating with a lower importance leaves channel unchanged. @@ -388,7 +393,7 @@ public class NotificationManagerServiceTest extends NotificationTestCase { new ParceledListSlice(Arrays.asList(dupeChannel))); final NotificationChannel createdChannel = mBinderService.getNotificationChannel(PKG, "id"); - assertEquals(NotificationManager.IMPORTANCE_HIGH, createdChannel.getImportance()); + assertEquals(IMPORTANCE_HIGH, createdChannel.getImportance()); } @Test @@ -397,7 +402,7 @@ public class NotificationManagerServiceTest extends NotificationTestCase { final NotificationChannel channel1 = new NotificationChannel("id", "name", NotificationManager.IMPORTANCE_DEFAULT); final NotificationChannel channel2 = - new NotificationChannel("id", "name", NotificationManager.IMPORTANCE_HIGH); + new NotificationChannel("id", "name", IMPORTANCE_HIGH); mBinderService.createNotificationChannels(PKG, new ParceledListSlice(Arrays.asList(channel1, channel2))); final NotificationChannel createdChannel = @@ -410,7 +415,7 @@ public class NotificationManagerServiceTest extends NotificationTestCase { when(mPackageManager.isPackageSuspendedForUser(anyString(), anyInt())).thenReturn(true); NotificationChannel channel = new NotificationChannel("id", "name", - NotificationManager.IMPORTANCE_HIGH); + IMPORTANCE_HIGH); NotificationRecord r = generateNotificationRecord(channel); assertTrue(mNotificationManagerService.isBlocked(r, mUsageStats)); verify(mUsageStats, times(1)).registerSuspendedByAdmin(eq(r)); @@ -421,11 +426,68 @@ public class NotificationManagerServiceTest extends NotificationTestCase { when(mPackageManager.isPackageSuspendedForUser(anyString(), anyInt())).thenReturn(false); NotificationChannel channel = new NotificationChannel("id", "name", - NotificationManager.IMPORTANCE_HIGH); - channel.setImportance(IMPORTANCE_NONE); + NotificationManager.IMPORTANCE_NONE); NotificationRecord r = generateNotificationRecord(channel); assertTrue(mNotificationManagerService.isBlocked(r, mUsageStats)); verify(mUsageStats, times(1)).registerBlocked(eq(r)); + + mBinderService.createNotificationChannels( + PKG, new ParceledListSlice(Arrays.asList(channel))); + final StatusBarNotification sbn = generateNotificationRecord(channel).sbn; + mBinderService.enqueueNotificationWithTag(PKG, "opPkg", "tag", + sbn.getId(), sbn.getNotification(), sbn.getUserId()); + waitForIdle(); + assertEquals(0, mBinderService.getActiveNotifications(sbn.getPackageName()).length); + } + + @Test + public void testEnqueuedBlockedNotifications_appBlockedChannelForegroundService() + throws Exception { + when(mPackageManager.isPackageSuspendedForUser(anyString(), anyInt())).thenReturn(false); + + NotificationChannel channel = new NotificationChannel("blocked", "name", + NotificationManager.IMPORTANCE_NONE); + mBinderService.createNotificationChannels( + PKG, new ParceledListSlice(Arrays.asList(channel))); + + final StatusBarNotification sbn = generateNotificationRecord(channel).sbn; + sbn.getNotification().flags |= Notification.FLAG_FOREGROUND_SERVICE; + mBinderService.enqueueNotificationWithTag(PKG, "opPkg", "tag", + sbn.getId(), sbn.getNotification(), sbn.getUserId()); + waitForIdle(); + assertEquals(1, mBinderService.getActiveNotifications(sbn.getPackageName()).length); + assertEquals(IMPORTANCE_LOW, + mNotificationManagerService.getNotificationRecord(sbn.getKey()).getImportance()); + assertEquals(IMPORTANCE_LOW, + mBinderService.getNotificationChannel(PKG, channel.getId()).getImportance()); + } + + @Test + public void testEnqueuedBlockedNotifications_userBlockedChannelForegroundService() + throws Exception { + when(mPackageManager.isPackageSuspendedForUser(anyString(), anyInt())).thenReturn(false); + + NotificationChannel channel = + new NotificationChannel("blockedbyuser", "name", IMPORTANCE_HIGH); + mBinderService.createNotificationChannels( + PKG, new ParceledListSlice(Arrays.asList(channel))); + + NotificationChannel update = + new NotificationChannel("blockedbyuser", "name", IMPORTANCE_NONE); + mBinderService.updateNotificationChannelForPackage(PKG, mUid, update); + waitForIdle(); + assertEquals(IMPORTANCE_NONE, + mBinderService.getNotificationChannel(PKG, channel.getId()).getImportance()); + + final StatusBarNotification sbn = generateNotificationRecord(channel).sbn; + sbn.getNotification().flags |= Notification.FLAG_FOREGROUND_SERVICE; + mBinderService.enqueueNotificationWithTag(PKG, "opPkg", "tag", + sbn.getId(), sbn.getNotification(), sbn.getUserId()); + waitForIdle(); + assertEquals(0, mBinderService.getActiveNotifications(sbn.getPackageName()).length); + assertNull(mNotificationManagerService.getNotificationRecord(sbn.getKey())); + assertEquals(IMPORTANCE_NONE, + mBinderService.getNotificationChannel(PKG, channel.getId()).getImportance()); } @Test @@ -456,6 +518,21 @@ public class NotificationManagerServiceTest extends NotificationTestCase { } @Test + public void testEnqueuedBlockedNotifications_blockedAppForegroundService() throws Exception { + when(mPackageManager.isPackageSuspendedForUser(anyString(), anyInt())).thenReturn(false); + + mBinderService.setNotificationsEnabledForPackage(PKG, mUid, false); + + final StatusBarNotification sbn = generateNotificationRecord(null).sbn; + sbn.getNotification().flags |= Notification.FLAG_FOREGROUND_SERVICE; + mBinderService.enqueueNotificationWithTag(PKG, "opPkg", "tag", + sbn.getId(), sbn.getNotification(), sbn.getUserId()); + waitForIdle(); + assertEquals(0, mBinderService.getActiveNotifications(sbn.getPackageName()).length); + assertNull(mNotificationManagerService.getNotificationRecord(sbn.getKey())); + } + + @Test public void testEnqueueNotificationWithTag_PopulatesGetActiveNotifications() throws Exception { mBinderService.enqueueNotificationWithTag(PKG, "opPkg", "tag", 0, generateNotificationRecord(null).getNotification(), 0); @@ -812,7 +889,7 @@ public class NotificationManagerServiceTest extends NotificationTestCase { mNotificationManagerService.setRankingHelper(mRankingHelper); when(mRankingHelper.getNotificationChannel( anyString(), anyInt(), eq("foo"), anyBoolean())).thenReturn( - new NotificationChannel("foo", "foo", NotificationManager.IMPORTANCE_HIGH)); + new NotificationChannel("foo", "foo", IMPORTANCE_HIGH)); Notification.TvExtender tv = new Notification.TvExtender().setChannelId("foo"); mBinderService.enqueueNotificationWithTag(PKG, "opPkg", "tag", 0, @@ -941,7 +1018,8 @@ public class NotificationManagerServiceTest extends NotificationTestCase { mBinderService.updateNotificationChannelFromPrivilegedListener( null, PKG, Process.myUserHandle(), mTestNotificationChannel); - verify(mRankingHelper, times(1)).updateNotificationChannel(anyString(), anyInt(), any()); + verify(mRankingHelper, times(1)).updateNotificationChannel( + anyString(), anyInt(), any(), anyBoolean()); verify(mListeners, never()).notifyNotificationChannelChanged(eq(PKG), eq(Process.myUserHandle()), eq(mTestNotificationChannel), @@ -962,7 +1040,8 @@ public class NotificationManagerServiceTest extends NotificationTestCase { // pass } - verify(mRankingHelper, never()).updateNotificationChannel(anyString(), anyInt(), any()); + verify(mRankingHelper, never()).updateNotificationChannel( + anyString(), anyInt(), any(), anyBoolean()); verify(mListeners, never()).notifyNotificationChannelChanged(eq(PKG), eq(Process.myUserHandle()), eq(mTestNotificationChannel), @@ -988,7 +1067,8 @@ public class NotificationManagerServiceTest extends NotificationTestCase { // pass } - verify(mRankingHelper, never()).updateNotificationChannel(anyString(), anyInt(), any()); + verify(mRankingHelper, never()).updateNotificationChannel( + anyString(), anyInt(), any(), anyBoolean()); verify(mListeners, never()).notifyNotificationChannelChanged(eq(PKG), eq(Process.myUserHandle()), eq(mTestNotificationChannel), @@ -1359,7 +1439,8 @@ public class NotificationManagerServiceTest extends NotificationTestCase { @Test public void testOnlyAutogroupIfGroupChanged_groupChanged_autogroups() throws Exception { - NotificationRecord r = generateNotificationRecord(mTestNotificationChannel, 0, "group", false); + NotificationRecord r = + generateNotificationRecord(mTestNotificationChannel, 0, "group", false); mNotificationManagerService.addNotification(r); r = generateNotificationRecord(mTestNotificationChannel, 0, null, false); @@ -1439,12 +1520,16 @@ public class NotificationManagerServiceTest extends NotificationTestCase { // Same notifications are enqueued as posted, everything counts b/c id and tag don't match int userId = new UserHandle(mUid).getIdentifier(); - assertEquals(40, mNotificationManagerService.getNotificationCountLocked(PKG, userId, 0, null)); - assertEquals(40, mNotificationManagerService.getNotificationCountLocked(PKG, userId, 0, "tag2")); - assertEquals(2, mNotificationManagerService.getNotificationCountLocked("a", userId, 0, "banana")); + assertEquals(40, + mNotificationManagerService.getNotificationCountLocked(PKG, userId, 0, null)); + assertEquals(40, + mNotificationManagerService.getNotificationCountLocked(PKG, userId, 0, "tag2")); + assertEquals(2, + mNotificationManagerService.getNotificationCountLocked("a", userId, 0, "banana")); // exclude a known notification - it's excluded from only the posted list, not enqueued - assertEquals(39, mNotificationManagerService.getNotificationCountLocked(PKG, userId, 0, "tag")); + assertEquals(39, + mNotificationManagerService.getNotificationCountLocked(PKG, userId, 0, "tag")); } @Test @@ -1574,4 +1659,51 @@ public class NotificationManagerServiceTest extends NotificationTestCase { verify(mZenModeHelper, times(1)).updateDefaultZenRules(); } + + @Test + public void testBumpFGImportance_noChannelChangePreOApp() throws Exception { + String preOPkg = "preO"; + int preOUid = 145; + final ApplicationInfo legacy = new ApplicationInfo(); + legacy.targetSdkVersion = Build.VERSION_CODES.N_MR1; + when(mPackageManagerClient.getApplicationInfoAsUser(eq(preOPkg), anyInt(), anyInt())) + .thenReturn(legacy); + when(mPackageManagerClient.getPackageUidAsUser(eq(preOPkg), anyInt())).thenReturn(preOUid); + getContext().setMockPackageManager(mPackageManagerClient); + + Notification.Builder nb = new Notification.Builder(mContext, + NotificationChannel.DEFAULT_CHANNEL_ID) + .setContentTitle("foo") + .setSmallIcon(android.R.drawable.sym_def_app_icon) + .setFlag(Notification.FLAG_FOREGROUND_SERVICE, true) + .setPriority(Notification.PRIORITY_MIN); + + StatusBarNotification sbn = new StatusBarNotification(preOPkg, preOPkg, 9, "tag", preOUid, + 0, nb.build(), new UserHandle(preOUid), null, 0); + + mBinderService.enqueueNotificationWithTag(preOPkg, preOPkg, "tag", + sbn.getId(), sbn.getNotification(), sbn.getUserId()); + waitForIdle(); + assertEquals(IMPORTANCE_LOW, + mNotificationManagerService.getNotificationRecord(sbn.getKey()).getImportance()); + + nb = new Notification.Builder(mContext) + .setContentTitle("foo") + .setSmallIcon(android.R.drawable.sym_def_app_icon) + .setFlag(Notification.FLAG_FOREGROUND_SERVICE, true) + .setPriority(Notification.PRIORITY_MIN); + + sbn = new StatusBarNotification(preOPkg, preOPkg, 9, "tag", preOUid, + 0, nb.build(), new UserHandle(preOUid), null, 0); + + mBinderService.enqueueNotificationWithTag(preOPkg, preOPkg, "tag", + sbn.getId(), sbn.getNotification(), sbn.getUserId()); + waitForIdle(); + assertEquals(IMPORTANCE_LOW, + mNotificationManagerService.getNotificationRecord(sbn.getKey()).getImportance()); + + NotificationChannel defaultChannel = mBinderService.getNotificationChannel( + preOPkg, NotificationChannel.DEFAULT_CHANNEL_ID); + assertEquals(IMPORTANCE_UNSPECIFIED, defaultChannel.getImportance()); + } } diff --git a/services/tests/notification/src/com/android/server/notification/RankingHelperTest.java b/services/tests/notification/src/com/android/server/notification/RankingHelperTest.java index 306dd98acaad..2249ff0ce448 100644 --- a/services/tests/notification/src/com/android/server/notification/RankingHelperTest.java +++ b/services/tests/notification/src/com/android/server/notification/RankingHelperTest.java @@ -497,7 +497,7 @@ public class RankingHelperTest extends NotificationTestCase { final NotificationChannel defaultChannel = mHelper.getNotificationChannel(PKG, UID, NotificationChannel.DEFAULT_CHANNEL_ID, false); defaultChannel.setImportance(NotificationManager.IMPORTANCE_LOW); - mHelper.updateNotificationChannel(PKG, UID, defaultChannel); + mHelper.updateNotificationChannel(PKG, UID, defaultChannel, true); ByteArrayOutputStream baos = writeXmlAndPurge(PKG, UID, false, NotificationChannel.DEFAULT_CHANNEL_ID); @@ -646,7 +646,7 @@ public class RankingHelperTest extends NotificationTestCase { channel2.setBypassDnd(false); channel2.setLockscreenVisibility(Notification.VISIBILITY_PUBLIC); - mHelper.updateNotificationChannel(PKG, UID, channel2); + mHelper.updateNotificationChannel(PKG, UID, channel2, true); // all fields should be changed assertEquals(channel2, mHelper.getNotificationChannel(PKG, UID, channel.getId(), false)); @@ -670,7 +670,7 @@ public class RankingHelperTest extends NotificationTestCase { defaultChannel.setBypassDnd(true); defaultChannel.setLockscreenVisibility(Notification.VISIBILITY_SECRET); - mHelper.updateNotificationChannel(PKG, UID, defaultChannel); + mHelper.updateNotificationChannel(PKG, UID, defaultChannel, true); // ensure app level fields are changed assertFalse(mHelper.canShowBadge(PKG, UID)); @@ -694,7 +694,7 @@ public class RankingHelperTest extends NotificationTestCase { channel.setBypassDnd(true); channel.setLockscreenVisibility(Notification.VISIBILITY_SECRET); - mHelper.updateNotificationChannel(PKG, UID, channel); + mHelper.updateNotificationChannel(PKG, UID, channel, true); // ensure app level fields are not changed assertTrue(mHelper.canShowBadge(PKG, UID)); @@ -785,14 +785,14 @@ public class RankingHelperTest extends NotificationTestCase { update1.setSound(new Uri.Builder().scheme("test").build(), new AudioAttributes.Builder().build()); update1.lockFields(NotificationChannel.USER_LOCKED_PRIORITY); // should be ignored - mHelper.updateNotificationChannel(PKG, UID, update1); + mHelper.updateNotificationChannel(PKG, UID, update1, true); assertEquals(NotificationChannel.USER_LOCKED_SOUND, mHelper.getNotificationChannel(PKG, UID, update1.getId(), false) .getUserLockedFields()); NotificationChannel update2 = getChannel(); update2.enableVibration(true); - mHelper.updateNotificationChannel(PKG, UID, update2); + mHelper.updateNotificationChannel(PKG, UID, update2, true); assertEquals(NotificationChannel.USER_LOCKED_SOUND | NotificationChannel.USER_LOCKED_VIBRATION, mHelper.getNotificationChannel(PKG, UID, update2.getId(), false) @@ -805,14 +805,14 @@ public class RankingHelperTest extends NotificationTestCase { final NotificationChannel update1 = getChannel(); update1.setVibrationPattern(new long[]{7945, 46 ,246}); - mHelper.updateNotificationChannel(PKG, UID, update1); + mHelper.updateNotificationChannel(PKG, UID, update1, true); assertEquals(NotificationChannel.USER_LOCKED_VIBRATION, mHelper.getNotificationChannel(PKG, UID, update1.getId(), false) .getUserLockedFields()); final NotificationChannel update2 = getChannel(); update2.enableLights(true); - mHelper.updateNotificationChannel(PKG, UID, update2); + mHelper.updateNotificationChannel(PKG, UID, update2, true); assertEquals(NotificationChannel.USER_LOCKED_VIBRATION | NotificationChannel.USER_LOCKED_LIGHTS, mHelper.getNotificationChannel(PKG, UID, update2.getId(), false) @@ -825,14 +825,14 @@ public class RankingHelperTest extends NotificationTestCase { final NotificationChannel update1 = getChannel(); update1.setLightColor(Color.GREEN); - mHelper.updateNotificationChannel(PKG, UID, update1); + mHelper.updateNotificationChannel(PKG, UID, update1, true); assertEquals(NotificationChannel.USER_LOCKED_LIGHTS, mHelper.getNotificationChannel(PKG, UID, update1.getId(), false) .getUserLockedFields()); final NotificationChannel update2 = getChannel(); update2.setImportance(IMPORTANCE_DEFAULT); - mHelper.updateNotificationChannel(PKG, UID, update2); + mHelper.updateNotificationChannel(PKG, UID, update2, true); assertEquals(NotificationChannel.USER_LOCKED_LIGHTS | NotificationChannel.USER_LOCKED_IMPORTANCE, mHelper.getNotificationChannel(PKG, UID, update2.getId(), false) @@ -848,14 +848,14 @@ public class RankingHelperTest extends NotificationTestCase { final NotificationChannel update1 = getChannel(); update1.setBypassDnd(true); - mHelper.updateNotificationChannel(PKG, UID, update1); + mHelper.updateNotificationChannel(PKG, UID, update1, true); assertEquals(NotificationChannel.USER_LOCKED_PRIORITY, mHelper.getNotificationChannel(PKG, UID, update1.getId(), false) .getUserLockedFields()); final NotificationChannel update2 = getChannel(); update2.setLockscreenVisibility(Notification.VISIBILITY_SECRET); - mHelper.updateNotificationChannel(PKG, UID, update2); + mHelper.updateNotificationChannel(PKG, UID, update2, true); assertEquals(NotificationChannel.USER_LOCKED_PRIORITY | NotificationChannel.USER_LOCKED_VISIBILITY, mHelper.getNotificationChannel(PKG, UID, update2.getId(), false) @@ -863,7 +863,7 @@ public class RankingHelperTest extends NotificationTestCase { final NotificationChannel update3 = getChannel(); update3.setShowBadge(false); - mHelper.updateNotificationChannel(PKG, UID, update3); + mHelper.updateNotificationChannel(PKG, UID, update3, true); assertEquals(NotificationChannel.USER_LOCKED_PRIORITY | NotificationChannel.USER_LOCKED_VISIBILITY | NotificationChannel.USER_LOCKED_SHOW_BADGE, @@ -1276,7 +1276,7 @@ public class RankingHelperTest extends NotificationTestCase { mHelper.getNotificationChannelGroups(PKG, UID, true).getList(); channel1.setImportance(IMPORTANCE_LOW); - mHelper.updateNotificationChannel(PKG, UID, channel1); + mHelper.updateNotificationChannel(PKG, UID, channel1, true); List<NotificationChannelGroup> actual = mHelper.getNotificationChannelGroups(PKG, UID, true).getList(); diff --git a/services/tests/servicestests/src/com/android/server/am/ActivityTestsBase.java b/services/tests/servicestests/src/com/android/server/am/ActivityTestsBase.java index 0cf1df84c073..6caa60b5a010 100644 --- a/services/tests/servicestests/src/com/android/server/am/ActivityTestsBase.java +++ b/services/tests/servicestests/src/com/android/server/am/ActivityTestsBase.java @@ -17,6 +17,7 @@ package com.android.server.am; import static android.app.ActivityManager.StackId.PINNED_STACK_ID; +import static android.view.Display.DEFAULT_DISPLAY; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.any; @@ -24,7 +25,6 @@ import static org.mockito.Mockito.doAnswer; import org.mockito.invocation.InvocationOnMock; -import android.app.ActivityManager; import android.content.ComponentName; import android.content.Context; import android.content.Intent; @@ -32,6 +32,7 @@ import android.content.pm.ActivityInfo; import android.content.pm.ApplicationInfo; import android.content.res.Configuration; import android.graphics.Rect; +import android.hardware.display.DisplayManager; import android.os.HandlerThread; import android.os.Looper; import android.support.test.InstrumentationRegistry; @@ -167,8 +168,11 @@ public class ActivityTestsBase { public TestActivityStackSupervisor(ActivityManagerService service, Looper looper) { super(service, looper); + mDisplayManager = + (DisplayManager) mService.mContext.getSystemService(Context.DISPLAY_SERVICE); mWindowManager = prepareMockWindowManager(); - mDisplay = new ActivityDisplay(); + mDisplay = new ActivityDisplay(this, DEFAULT_DISPLAY); + attachDisplay(mDisplay); } // TODO: Use Mockito spy instead. Currently not possible due to TestActivityStackSupervisor @@ -220,17 +224,15 @@ public class ActivityTestsBase { @Override ActivityStack createStack(int stackId, ActivityDisplay display, boolean onTop) { - final RecentTasks recents = - new RecentTasks(mService, mService.mStackSupervisor); if (stackId == PINNED_STACK_ID) { - return new PinnedActivityStack(display, stackId, this, recents, onTop) { + return new PinnedActivityStack(display, stackId, this, onTop) { @Override Rect getDefaultPictureInPictureBounds(float aspectRatio) { return new Rect(50, 50, 100, 100); } }; } else { - return new TestActivityStack(display, stackId, this, recents, onTop); + return new TestActivityStack(display, stackId, this, onTop); } } @@ -280,9 +282,9 @@ public class ActivityTestsBase { extends ActivityStack<T> implements ActivityStackReporter { private int mOnActivityRemovedFromStackCount = 0; private T mContainerController; - TestActivityStack(ActivityStackSupervisor.ActivityDisplay display, int stackId, - ActivityStackSupervisor supervisor, RecentTasks recentTasks, boolean onTop) { - super(display, stackId, supervisor, recentTasks, onTop); + TestActivityStack(ActivityDisplay display, int stackId, ActivityStackSupervisor supervisor, + boolean onTop) { + super(display, stackId, supervisor, onTop); } @Override 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/utils/PriorityDumpTest.java b/services/tests/servicestests/src/com/android/server/utils/PriorityDumpTest.java index d378b7c56acb..8a312f64a846 100644 --- a/services/tests/servicestests/src/com/android/server/utils/PriorityDumpTest.java +++ b/services/tests/servicestests/src/com/android/server/utils/PriorityDumpTest.java @@ -80,7 +80,7 @@ public class PriorityDumpTest { @Test public void testMissingPriority() { final String[] args = { - "--dump_priority" + "--dump-priority" }; dump(mDumper, mFd, mPw, args); verify(mDumper).dump(same(mFd), same(mPw), same(args)); @@ -89,7 +89,7 @@ public class PriorityDumpTest { @Test public void testInvalidPriorityNoExtraArgs() { final String[] args = { - "--dump_priority", "SUPER_HIGH" + "--dump-priority", "SUPER_HIGH" }; dump(mDumper, mFd, mPw, args); verify(mDumper).dump(same(mFd), same(mPw), same(args)); @@ -98,7 +98,7 @@ public class PriorityDumpTest { @Test public void testInvalidPriorityExtraArgs() { final String[] args = { - "--dump_priority", "SUPER_HIGH", "--high", "--five" + "--dump-priority", "SUPER_HIGH", "--high", "--five" }; dump(mDumper, mFd, mPw, args); verify(mDumper).dump(same(mFd), same(mPw), same(args)); @@ -129,7 +129,7 @@ public class PriorityDumpTest { @Test public void testCriticalNoExtraArgs() { dump(mDumper, mFd, mPw, new String[] { - "--dump_priority", "CRITICAL" + "--dump-priority", "CRITICAL" }); verify(mDumper).dumpCritical(same(mFd), same(mPw), eq(EMPTY_ARGS)); } @@ -137,7 +137,7 @@ public class PriorityDumpTest { @Test public void testCriticalExtraArgs() { dump(mDumper, mFd, mPw, new String[] { - "--dump_priority", "CRITICAL", "--high", "--five" + "--dump-priority", "CRITICAL", "--high", "--five" }); verify(mDumper).dumpCritical(same(mFd), same(mPw), eq(new String[] { "--high", "--five" @@ -147,7 +147,7 @@ public class PriorityDumpTest { @Test public void testHighNoExtraArgs() { dump(mDumper, mFd, mPw, new String[] { - "--dump_priority", "HIGH" + "--dump-priority", "HIGH" }); verify(mDumper).dumpHigh(same(mFd), same(mPw), eq(EMPTY_ARGS)); } @@ -155,7 +155,7 @@ public class PriorityDumpTest { @Test public void testHighExtraArgs() { dump(mDumper, mFd, mPw, new String[] { - "--dump_priority", "HIGH", "--high", "--five" + "--dump-priority", "HIGH", "--high", "--five" }); verify(mDumper).dumpHigh(same(mFd), same(mPw), eq(new String[] { "--high", "--five" @@ -165,7 +165,7 @@ public class PriorityDumpTest { @Test public void testNormalNoExtraArgs() { dump(mDumper, mFd, mPw, new String[] { - "--dump_priority", "NORMAL" + "--dump-priority", "NORMAL" }); verify(mDumper).dumpNormal(same(mFd), same(mPw), eq(EMPTY_ARGS)); } @@ -173,7 +173,7 @@ public class PriorityDumpTest { @Test public void testNormalExtraArgs() { dump(mDumper, mFd, mPw, new String[] { - "--dump_priority", "NORMAL", "--high", "--five" + "--dump-priority", "NORMAL", "--high", "--five" }); verify(mDumper).dumpNormal(same(mFd), same(mPw), eq(new String[] { "--high", "--five" 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 e3f46a40e2b1..dfe31bde4ecf 100644 --- a/tests/net/java/com/android/server/connectivity/Nat464XlatTest.java +++ b/tests/net/java/com/android/server/connectivity/Nat464XlatTest.java @@ -85,6 +85,32 @@ public class Nat464XlatTest { } @Test + public void testRequiresClat() throws Exception { + final int[] supportedTypes = { + ConnectivityManager.TYPE_MOBILE, + ConnectivityManager.TYPE_WIFI, + ConnectivityManager.TYPE_ETHERNET, + }; + + // NetworkInfo doesn't allow setting the State directly, but rather + // requires setting DetailedState in order set State as a side-effect. + final NetworkInfo.DetailedState[] supportedDetailedStates = { + NetworkInfo.DetailedState.CONNECTED, + NetworkInfo.DetailedState.SUSPENDED, + }; + + for (int type : supportedTypes) { + mNai.networkInfo.setType(type); + for (NetworkInfo.DetailedState state : supportedDetailedStates) { + mNai.networkInfo.setDetailedState(state, "reason", "extraInfo"); + assertTrue( + String.format("requiresClat expected for type=%d state=%s", type, state), + Nat464Xlat.requiresClat(mNai)); + } + } + } + + @Test public void testNormalStartAndStop() throws Exception { Nat464Xlat nat = makeNat464Xlat(); ArgumentCaptor<LinkProperties> c = ArgumentCaptor.forClass(LinkProperties.class); @@ -100,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)); @@ -110,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); @@ -141,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)); @@ -153,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/tests/net/java/com/android/server/connectivity/tethering/OffloadControllerTest.java b/tests/net/java/com/android/server/connectivity/tethering/OffloadControllerTest.java index 7a2ff8995458..b98f63b6a5a5 100644 --- a/tests/net/java/com/android/server/connectivity/tethering/OffloadControllerTest.java +++ b/tests/net/java/com/android/server/connectivity/tethering/OffloadControllerTest.java @@ -671,6 +671,35 @@ public class OffloadControllerTest { offload.setUpstreamLinkProperties(upstreamLp); } + // Pretend that some local prefixes and downstreams have been added + // (and removed, for good measure). + final Set<IpPrefix> minimumLocalPrefixes = new HashSet<>(); + for (String s : new String[]{ + "127.0.0.0/8", "192.0.2.0/24", "fe80::/64", "2001:db8::/64"}) { + minimumLocalPrefixes.add(new IpPrefix(s)); + } + offload.setLocalPrefixes(minimumLocalPrefixes); + + final LinkProperties usbLinkProperties = new LinkProperties(); + usbLinkProperties.setInterfaceName(RNDIS0); + usbLinkProperties.addLinkAddress(new LinkAddress("192.168.42.1/24")); + usbLinkProperties.addRoute(new RouteInfo(new IpPrefix(USB_PREFIX))); + offload.notifyDownstreamLinkProperties(usbLinkProperties); + + final LinkProperties wifiLinkProperties = new LinkProperties(); + wifiLinkProperties.setInterfaceName(WLAN0); + wifiLinkProperties.addLinkAddress(new LinkAddress("192.168.43.1/24")); + wifiLinkProperties.addRoute(new RouteInfo(new IpPrefix(WIFI_PREFIX))); + wifiLinkProperties.addRoute(new RouteInfo(new IpPrefix(IPV6_LINKLOCAL))); + // Use a benchmark prefix (RFC 5180 + erratum), since the documentation + // prefix is included in the excluded prefix list. + wifiLinkProperties.addLinkAddress(new LinkAddress("2001:2::1/64")); + wifiLinkProperties.addLinkAddress(new LinkAddress("2001:2::2/64")); + wifiLinkProperties.addRoute(new RouteInfo(new IpPrefix("2001:2::/64"))); + offload.notifyDownstreamLinkProperties(wifiLinkProperties); + + offload.removeDownstreamInterface(RNDIS0); + // Clear invocation history, especially the getForwardedStats() calls // that happen with setUpstreamParameters(). clearInvocations(mHardware); @@ -685,6 +714,17 @@ public class OffloadControllerTest { verifyNoMoreInteractions(mNMService); // TODO: verify local prefixes and downstreams are also pushed to the HAL. + verify(mHardware, times(1)).setLocalPrefixes(mStringArrayCaptor.capture()); + ArrayList<String> localPrefixes = mStringArrayCaptor.getValue(); + assertEquals(4, localPrefixes.size()); + assertArrayListContains(localPrefixes, + // TODO: The logic to find and exclude downstream IP prefixes + // is currently in Tethering's OffloadWrapper but must be moved + // into OffloadController proper. After this, also check for: + // "192.168.43.1/32", "2001:2::1/128", "2001:2::2/128" + "127.0.0.0/8", "192.0.2.0/24", "fe80::/64", "2001:db8::/64"); + verify(mHardware, times(1)).addDownstreamPrefix(WLAN0, "192.168.43.0/24"); + verify(mHardware, times(1)).addDownstreamPrefix(WLAN0, "2001:2::/64"); verify(mHardware, times(1)).setUpstreamParameters(eq(RMNET0), any(), any(), any()); verify(mHardware, times(1)).setDataLimit(eq(RMNET0), anyLong()); verifyNoMoreInteractions(mHardware); @@ -692,7 +732,7 @@ public class OffloadControllerTest { private static void assertArrayListContains(ArrayList<String> list, String... elems) { for (String element : elems) { - assertTrue(list.contains(element)); + assertTrue(element + " not in list", list.contains(element)); } } } diff --git a/tools/aapt2/Resources.proto b/tools/aapt2/Resources.proto index 71f33b0853ad..c1af88a1a74e 100644 --- a/tools/aapt2/Resources.proto +++ b/tools/aapt2/Resources.proto @@ -14,77 +14,86 @@ * limitations under the License. */ -// Keep proto2 syntax because we require the distinction between fields that -// are set and unset. -syntax = "proto2"; +syntax = "proto3"; + +package aapt.pb; option java_package = "com.android.aapt"; option optimize_for = LITE_RUNTIME; -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; + bytes data = 1; + string product = 2; } // 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 +121,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 +146,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 +163,54 @@ message Entry { // A Configuration/Value pair. message ConfigValue { - optional ConfigDescription config = 1; - optional Value value = 2; + ConfigDescription 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 +223,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 +242,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 +276,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 +291,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 +324,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 +344,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 +372,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 +390,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 +418,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 +437,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 +452,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 +466,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..17604e4c6fe8 100644 --- a/tools/aapt2/ResourcesInternal.proto +++ b/tools/aapt2/ResourcesInternal.proto @@ -14,39 +14,39 @@ * 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/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.ConfigDescription 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..59ca8e484fbe 100644 --- a/tools/aapt2/proto/ProtoHelpers.cpp +++ b/tools/aapt2/proto/ProtoHelpers.cpp @@ -42,13 +42,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) { @@ -84,7 +79,8 @@ void SerializeConfig(const ConfigDescription& config, pb::ConfigDescription* out bool DeserializeConfigDescriptionFromPb(const pb::ConfigDescription& pb_config, ConfigDescription* out_config) { - if (!pb_config.has_data()) { + // a ConfigDescription must be at least 4 bytes to store the size. + if (pb_config.data().size() < 4) { return false; } diff --git a/tools/aapt2/proto/TableProtoDeserializer.cpp b/tools/aapt2/proto/TableProtoDeserializer.cpp index b9d5878f2f71..f4a2b1e19331 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,7 +116,8 @@ 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); } @@ -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: diff --git a/tools/aapt2/proto/TableProtoSerializer.cpp b/tools/aapt2/proto/TableProtoSerializer.cpp index a08df71eae1e..981b72ab7221 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); diff --git a/wifi/java/android/net/wifi/WifiManager.java b/wifi/java/android/net/wifi/WifiManager.java index 9c8ea88c8c86..b08b4b7c71b6 100644 --- a/wifi/java/android/net/wifi/WifiManager.java +++ b/wifi/java/android/net/wifi/WifiManager.java @@ -967,8 +967,7 @@ public class WifiManager { * <li>allowedGroupCiphers</li> * </ul> * @return a list of network configurations in the form of a list - * of {@link WifiConfiguration} objects. Upon failure to fetch or - * when Wi-Fi is turned off, it can be null. + * of {@link WifiConfiguration} objects. */ public List<WifiConfiguration> getConfiguredNetworks() { try { |