diff options
656 files changed, 25291 insertions, 5842 deletions
diff --git a/Android.bp b/Android.bp index b4d5e58b570b..f032e6287d89 100644 --- a/Android.bp +++ b/Android.bp @@ -191,10 +191,6 @@ java_defaults { "core/java/android/hardware/input/IInputDevicesChangedListener.aidl", "core/java/android/hardware/input/ITabletModeChangedListener.aidl", "core/java/android/hardware/iris/IIrisService.aidl", - "core/java/android/hardware/location/IActivityRecognitionHardware.aidl", - "core/java/android/hardware/location/IActivityRecognitionHardwareClient.aidl", - "core/java/android/hardware/location/IActivityRecognitionHardwareSink.aidl", - "core/java/android/hardware/location/IActivityRecognitionHardwareWatcher.aidl", "core/java/android/hardware/location/IGeofenceHardware.aidl", "core/java/android/hardware/location/IGeofenceHardwareCallback.aidl", "core/java/android/hardware/location/IGeofenceHardwareMonitorCallback.aidl", @@ -358,6 +354,8 @@ java_defaults { "core/java/android/service/textclassifier/ITextLanguageCallback.aidl", "core/java/android/service/textclassifier/ITextLinksCallback.aidl", "core/java/android/service/textclassifier/ITextSelectionCallback.aidl", + "core/java/android/service/attention/IAttentionService.aidl", + "core/java/android/service/attention/IAttentionCallback.aidl", "core/java/android/view/accessibility/IAccessibilityInteractionConnection.aidl", "core/java/android/view/accessibility/IAccessibilityInteractionConnectionCallback.aidl", "core/java/android/view/accessibility/IAccessibilityManager.aidl", @@ -477,6 +475,7 @@ java_defaults { "media/java/android/media/IMediaRouterClient.aidl", "media/java/android/media/IMediaRouterService.aidl", "media/java/android/media/IMediaSession2.aidl", + "media/java/android/media/IMediaSession2Service.aidl", "media/java/android/media/IMediaScannerListener.aidl", "media/java/android/media/IMediaScannerService.aidl", "media/java/android/media/IPlaybackConfigDispatcher.aidl", @@ -888,7 +887,12 @@ aidl_interface { "core/java/android/net/IIpMemoryStore.aidl", "core/java/android/net/INetworkStackConnector.aidl", "core/java/android/net/INetworkStackStatusCallback.aidl", + "core/java/android/net/IpPrefixParcelable.aidl", + "core/java/android/net/LinkAddressParcelable.aidl", + "core/java/android/net/LinkPropertiesParcelable.aidl", "core/java/android/net/PrivateDnsConfigParcel.aidl", + "core/java/android/net/ProxyInfoParcelable.aidl", + "core/java/android/net/RouteInfoParcelable.aidl", "core/java/android/net/dhcp/DhcpServingParamsParcel.aidl", "core/java/android/net/dhcp/IDhcpServer.aidl", "core/java/android/net/dhcp/IDhcpServerCallbacks.aidl", diff --git a/Android.mk b/Android.mk index e3cc2754fed3..9f7bf9905c09 100644 --- a/Android.mk +++ b/Android.mk @@ -80,6 +80,8 @@ update-api: doc-comment-check-docs # ==== hiddenapi lists ======================================= .KATI_RESTAT: $(INTERNAL_PLATFORM_HIDDENAPI_FLAGS) $(INTERNAL_PLATFORM_HIDDENAPI_FLAGS): \ + PRIVATE_FLAGS_INPUTS := $(PRIVATE_FLAGS_INPUTS) $(SOONG_HIDDENAPI_FLAGS) +$(INTERNAL_PLATFORM_HIDDENAPI_FLAGS): \ frameworks/base/tools/hiddenapi/generate_hiddenapi_lists.py \ frameworks/base/config/hiddenapi-greylist.txt \ frameworks/base/config/hiddenapi-greylist-max-p.txt \ @@ -87,7 +89,8 @@ $(INTERNAL_PLATFORM_HIDDENAPI_FLAGS): \ frameworks/base/config/hiddenapi-force-blacklist.txt \ $(INTERNAL_PLATFORM_HIDDENAPI_PUBLIC_LIST) \ $(INTERNAL_PLATFORM_HIDDENAPI_PRIVATE_LIST) \ - $(INTERNAL_PLATFORM_REMOVED_DEX_API_FILE) + $(INTERNAL_PLATFORM_REMOVED_DEX_API_FILE) \ + $(SOONG_HIDDENAPI_FLAGS) frameworks/base/tools/hiddenapi/generate_hiddenapi_lists.py \ --public $(INTERNAL_PLATFORM_HIDDENAPI_PUBLIC_LIST) \ --private $(INTERNAL_PLATFORM_HIDDENAPI_PRIVATE_LIST) \ diff --git a/api/current.txt b/api/current.txt index 7074d4854620..07614caa4699 100644 --- a/api/current.txt +++ b/api/current.txt @@ -6784,9 +6784,11 @@ package android.app.admin { method public void wipeData(int); method public void wipeData(int, java.lang.CharSequence); field public static final java.lang.String ACTION_ADD_DEVICE_ADMIN = "android.app.action.ADD_DEVICE_ADMIN"; + field public static final java.lang.String ACTION_ADMIN_POLICY_COMPLIANCE = "android.app.action.ADMIN_POLICY_COMPLIANCE"; field public static final java.lang.String ACTION_APPLICATION_DELEGATION_SCOPES_CHANGED = "android.app.action.APPLICATION_DELEGATION_SCOPES_CHANGED"; field public static final java.lang.String ACTION_DEVICE_ADMIN_SERVICE = "android.app.action.DEVICE_ADMIN_SERVICE"; field public static final java.lang.String ACTION_DEVICE_OWNER_CHANGED = "android.app.action.DEVICE_OWNER_CHANGED"; + field public static final java.lang.String ACTION_GET_PROVISIONING_MODE = "android.app.action.GET_PROVISIONING_MODE"; field public static final java.lang.String ACTION_MANAGED_PROFILE_PROVISIONED = "android.app.action.MANAGED_PROFILE_PROVISIONED"; field public static final java.lang.String ACTION_PROFILE_OWNER_CHANGED = "android.app.action.PROFILE_OWNER_CHANGED"; field public static final java.lang.String ACTION_PROVISIONING_SUCCESSFUL = "android.app.action.PROVISIONING_SUCCESSFUL"; @@ -6829,12 +6831,15 @@ package android.app.admin { field public static final java.lang.String EXTRA_PROVISIONING_DISCLAIMER_CONTENT = "android.app.extra.PROVISIONING_DISCLAIMER_CONTENT"; field public static final java.lang.String EXTRA_PROVISIONING_DISCLAIMER_HEADER = "android.app.extra.PROVISIONING_DISCLAIMER_HEADER"; field public static final deprecated java.lang.String EXTRA_PROVISIONING_EMAIL_ADDRESS = "android.app.extra.PROVISIONING_EMAIL_ADDRESS"; + field public static final java.lang.String EXTRA_PROVISIONING_IMEI = "android.app.extra.PROVISIONING_IMEI"; field public static final java.lang.String EXTRA_PROVISIONING_KEEP_ACCOUNT_ON_MIGRATION = "android.app.extra.PROVISIONING_KEEP_ACCOUNT_ON_MIGRATION"; field public static final java.lang.String EXTRA_PROVISIONING_LEAVE_ALL_SYSTEM_APPS_ENABLED = "android.app.extra.PROVISIONING_LEAVE_ALL_SYSTEM_APPS_ENABLED"; field public static final java.lang.String EXTRA_PROVISIONING_LOCALE = "android.app.extra.PROVISIONING_LOCALE"; field public static final java.lang.String EXTRA_PROVISIONING_LOCAL_TIME = "android.app.extra.PROVISIONING_LOCAL_TIME"; field public static final java.lang.String EXTRA_PROVISIONING_LOGO_URI = "android.app.extra.PROVISIONING_LOGO_URI"; field public static final java.lang.String EXTRA_PROVISIONING_MAIN_COLOR = "android.app.extra.PROVISIONING_MAIN_COLOR"; + field public static final java.lang.String EXTRA_PROVISIONING_MODE = "android.app.extra.PROVISIONING_MODE"; + field public static final java.lang.String EXTRA_PROVISIONING_SERIAL_NUMBER = "android.app.extra.PROVISIONING_SERIAL_NUMBER"; field public static final java.lang.String EXTRA_PROVISIONING_SKIP_ENCRYPTION = "android.app.extra.PROVISIONING_SKIP_ENCRYPTION"; field public static final java.lang.String EXTRA_PROVISIONING_SKIP_USER_CONSENT = "android.app.extra.PROVISIONING_SKIP_USER_CONSENT"; field public static final java.lang.String EXTRA_PROVISIONING_TIME_ZONE = "android.app.extra.PROVISIONING_TIME_ZONE"; @@ -6911,6 +6916,9 @@ package android.app.admin { field public static final int PRIVATE_DNS_SET_ERROR_FAILURE_SETTING = 2; // 0x2 field public static final int PRIVATE_DNS_SET_ERROR_HOST_NOT_SERVING = 1; // 0x1 field public static final int PRIVATE_DNS_SET_SUCCESS = 0; // 0x0 + field public static final int PROVISIONING_MODE_FULLY_MANAGED_DEVICE = 1; // 0x1 + field public static final int PROVISIONING_MODE_MANAGED_PROFILE = 2; // 0x2 + field public static final int PROVISIONING_MODE_MANAGED_PROFILE_ON_FULLY_MANAGED_DEVICE = 3; // 0x3 field public static final int RESET_PASSWORD_DO_NOT_ASK_CREDENTIALS_ON_BOOT = 2; // 0x2 field public static final int RESET_PASSWORD_REQUIRE_ENTRY = 1; // 0x1 field public static final int SKIP_SETUP_WIZARD = 1; // 0x1 @@ -7682,6 +7690,7 @@ package android.app.usage { field public static final int ACTIVITY_RESUMED = 1; // 0x1 field public static final int ACTIVITY_STOPPED = 23; // 0x17 field public static final int CONFIGURATION_CHANGE = 5; // 0x5 + field public static final int DEVICE_SHUTDOWN = 26; // 0x1a field public static final int FOREGROUND_SERVICE_START = 19; // 0x13 field public static final int FOREGROUND_SERVICE_STOP = 20; // 0x14 field public static final int KEYGUARD_HIDDEN = 18; // 0x12 @@ -10366,6 +10375,7 @@ package android.content { field public static final java.lang.String EXTRA_RETURN_RESULT = "android.intent.extra.RETURN_RESULT"; field public static final deprecated java.lang.String EXTRA_SHORTCUT_ICON = "android.intent.extra.shortcut.ICON"; field public static final deprecated java.lang.String EXTRA_SHORTCUT_ICON_RESOURCE = "android.intent.extra.shortcut.ICON_RESOURCE"; + field public static final java.lang.String EXTRA_SHORTCUT_ID = "android.intent.extra.shortcut.ID"; field public static final deprecated java.lang.String EXTRA_SHORTCUT_INTENT = "android.intent.extra.shortcut.INTENT"; field public static final deprecated java.lang.String EXTRA_SHORTCUT_NAME = "android.intent.extra.shortcut.NAME"; field public static final java.lang.String EXTRA_SHUTDOWN_USERSPACE_ONLY = "android.intent.extra.SHUTDOWN_USERSPACE_ONLY"; @@ -11941,6 +11951,9 @@ package android.content.pm { method public android.content.pm.ShortcutInfo.Builder setIntent(android.content.Intent); method public android.content.pm.ShortcutInfo.Builder setIntents(android.content.Intent[]); method public android.content.pm.ShortcutInfo.Builder setLongLabel(java.lang.CharSequence); + method public android.content.pm.ShortcutInfo.Builder setLongLived(); + method public android.content.pm.ShortcutInfo.Builder setPerson(android.app.Person); + method public android.content.pm.ShortcutInfo.Builder setPersons(android.app.Person[]); method public android.content.pm.ShortcutInfo.Builder setRank(int); method public android.content.pm.ShortcutInfo.Builder setShortLabel(java.lang.CharSequence); } @@ -12281,6 +12294,7 @@ package android.content.res { method public void parseBundleExtra(java.lang.String, android.util.AttributeSet, android.os.Bundle) throws org.xmlpull.v1.XmlPullParserException; method public void parseBundleExtras(android.content.res.XmlResourceParser, android.os.Bundle) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException; method public deprecated void updateConfiguration(android.content.res.Configuration, android.util.DisplayMetrics); + field public static final int ID_NULL = 0; // 0x0 } public static class Resources.NotFoundException extends java.lang.RuntimeException { @@ -24013,6 +24027,7 @@ package android.media { method public android.view.Surface getSurface(); method public int getWidth(); method public static android.media.ImageReader newInstance(int, int, int, int); + method public static android.media.ImageReader newInstance(int, int, int, int, long); method public void setOnImageAvailableListener(android.media.ImageReader.OnImageAvailableListener, android.os.Handler); } @@ -24026,6 +24041,7 @@ package android.media { method public int getFormat(); method public int getMaxImages(); method public static android.media.ImageWriter newInstance(android.view.Surface, int); + method public static android.media.ImageWriter newInstance(android.view.Surface, int, int); method public void queueInputImage(android.media.Image); method public void setOnImageReleasedListener(android.media.ImageWriter.OnImageReleasedListener, android.os.Handler); } @@ -24137,6 +24153,7 @@ package android.media { method public int dequeueOutputBuffer(android.media.MediaCodec.BufferInfo, long); method protected void finalize(); method public void flush(); + method public java.lang.String getCanonicalName(); method public android.media.MediaCodecInfo getCodecInfo(); method public java.nio.ByteBuffer getInputBuffer(int); method public deprecated java.nio.ByteBuffer[] getInputBuffers(); @@ -24263,10 +24280,15 @@ package android.media { } public final class MediaCodecInfo { + method public java.lang.String getCanonicalName(); method public android.media.MediaCodecInfo.CodecCapabilities getCapabilitiesForType(java.lang.String); method public java.lang.String getName(); method public java.lang.String[] getSupportedTypes(); + method public boolean isAlias(); method public boolean isEncoder(); + method public boolean isHardwareAccelerated(); + method public boolean isSoftwareOnly(); + method public boolean isVendor(); } public static final class MediaCodecInfo.AudioCapabilities { @@ -24342,7 +24364,10 @@ package android.media { field public static final deprecated int COLOR_QCOM_FormatYUV420SemiPlanar = 2141391872; // 0x7fa30c00 field public static final deprecated int COLOR_TI_FormatYUV420PackedSemiPlanar = 2130706688; // 0x7f000100 field public static final java.lang.String FEATURE_AdaptivePlayback = "adaptive-playback"; + field public static final java.lang.String FEATURE_DynamicTimestamp = "dynamic-timestamp"; + field public static final java.lang.String FEATURE_FrameParsing = "frame-parsing"; field public static final java.lang.String FEATURE_IntraRefresh = "intra-refresh"; + field public static final java.lang.String FEATURE_MultipleFrames = "multiple-frames"; field public static final java.lang.String FEATURE_PartialFrame = "partial-frame"; field public static final java.lang.String FEATURE_SecurePlayback = "secure-playback"; field public static final java.lang.String FEATURE_TunneledPlayback = "tunneled-playback"; @@ -24364,6 +24389,33 @@ package android.media { field public static final int AACObjectSSR = 3; // 0x3 field public static final int AACObjectScalable = 6; // 0x6 field public static final int AACObjectXHE = 42; // 0x2a + field public static final int AV1Level2 = 1; // 0x1 + field public static final int AV1Level21 = 2; // 0x2 + field public static final int AV1Level22 = 4; // 0x4 + field public static final int AV1Level23 = 8; // 0x8 + field public static final int AV1Level3 = 16; // 0x10 + field public static final int AV1Level31 = 32; // 0x20 + field public static final int AV1Level32 = 64; // 0x40 + field public static final int AV1Level33 = 128; // 0x80 + field public static final int AV1Level4 = 256; // 0x100 + field public static final int AV1Level41 = 512; // 0x200 + field public static final int AV1Level42 = 1024; // 0x400 + field public static final int AV1Level43 = 2048; // 0x800 + field public static final int AV1Level5 = 4096; // 0x1000 + field public static final int AV1Level51 = 8192; // 0x2000 + field public static final int AV1Level52 = 16384; // 0x4000 + field public static final int AV1Level53 = 32768; // 0x8000 + field public static final int AV1Level6 = 65536; // 0x10000 + field public static final int AV1Level61 = 131072; // 0x20000 + field public static final int AV1Level62 = 262144; // 0x40000 + field public static final int AV1Level63 = 524288; // 0x80000 + field public static final int AV1Level7 = 1048576; // 0x100000 + field public static final int AV1Level71 = 2097152; // 0x200000 + field public static final int AV1Level72 = 4194304; // 0x400000 + field public static final int AV1Level73 = 8388608; // 0x800000 + field public static final int AV1Profile0 = 1; // 0x1 + field public static final int AV1Profile1 = 2; // 0x2 + field public static final int AV1Profile2 = 4; // 0x4 field public static final int AVCLevel1 = 1; // 0x1 field public static final int AVCLevel11 = 4; // 0x4 field public static final int AVCLevel12 = 8; // 0x8 @@ -24381,6 +24433,9 @@ package android.media { field public static final int AVCLevel5 = 16384; // 0x4000 field public static final int AVCLevel51 = 32768; // 0x8000 field public static final int AVCLevel52 = 65536; // 0x10000 + field public static final int AVCLevel6 = 131072; // 0x20000 + field public static final int AVCLevel61 = 262144; // 0x40000 + field public static final int AVCLevel62 = 524288; // 0x80000 field public static final int AVCProfileBaseline = 1; // 0x1 field public static final int AVCProfileConstrainedBaseline = 65536; // 0x10000 field public static final int AVCProfileConstrainedHigh = 524288; // 0x80000 @@ -24543,12 +24598,53 @@ package android.media { method public android.util.Range<java.lang.Double> getSupportedFrameRatesFor(int, int); method public android.util.Range<java.lang.Integer> getSupportedHeights(); method public android.util.Range<java.lang.Integer> getSupportedHeightsFor(int); + method public java.util.List<android.media.MediaCodecInfo.VideoCapabilities.PerformancePoint> getSupportedPerformancePoints(); method public android.util.Range<java.lang.Integer> getSupportedWidths(); method public android.util.Range<java.lang.Integer> getSupportedWidthsFor(int); method public int getWidthAlignment(); method public boolean isSizeSupported(int, int); } + public static final class MediaCodecInfo.VideoCapabilities.PerformancePoint { + method public boolean covers(android.media.MediaFormat); + field public static final android.media.MediaCodecInfo.VideoCapabilities.PerformancePoint FHD_100; + field public static final android.media.MediaCodecInfo.VideoCapabilities.PerformancePoint FHD_120; + field public static final android.media.MediaCodecInfo.VideoCapabilities.PerformancePoint FHD_200; + field public static final android.media.MediaCodecInfo.VideoCapabilities.PerformancePoint FHD_24; + field public static final android.media.MediaCodecInfo.VideoCapabilities.PerformancePoint FHD_240; + field public static final android.media.MediaCodecInfo.VideoCapabilities.PerformancePoint FHD_25; + field public static final android.media.MediaCodecInfo.VideoCapabilities.PerformancePoint FHD_30; + field public static final android.media.MediaCodecInfo.VideoCapabilities.PerformancePoint FHD_50; + field public static final android.media.MediaCodecInfo.VideoCapabilities.PerformancePoint FHD_60; + field public static final android.media.MediaCodecInfo.VideoCapabilities.PerformancePoint HD_100; + field public static final android.media.MediaCodecInfo.VideoCapabilities.PerformancePoint HD_120; + field public static final android.media.MediaCodecInfo.VideoCapabilities.PerformancePoint HD_200; + field public static final android.media.MediaCodecInfo.VideoCapabilities.PerformancePoint HD_24; + field public static final android.media.MediaCodecInfo.VideoCapabilities.PerformancePoint HD_240; + field public static final android.media.MediaCodecInfo.VideoCapabilities.PerformancePoint HD_25; + field public static final android.media.MediaCodecInfo.VideoCapabilities.PerformancePoint HD_30; + field public static final android.media.MediaCodecInfo.VideoCapabilities.PerformancePoint HD_50; + field public static final android.media.MediaCodecInfo.VideoCapabilities.PerformancePoint HD_60; + field public static final android.media.MediaCodecInfo.VideoCapabilities.PerformancePoint SD_24; + field public static final android.media.MediaCodecInfo.VideoCapabilities.PerformancePoint SD_25; + field public static final android.media.MediaCodecInfo.VideoCapabilities.PerformancePoint SD_30; + field public static final android.media.MediaCodecInfo.VideoCapabilities.PerformancePoint SD_48; + field public static final android.media.MediaCodecInfo.VideoCapabilities.PerformancePoint SD_50; + field public static final android.media.MediaCodecInfo.VideoCapabilities.PerformancePoint SD_60; + field public static final android.media.MediaCodecInfo.VideoCapabilities.PerformancePoint UHD_100; + field public static final android.media.MediaCodecInfo.VideoCapabilities.PerformancePoint UHD_120; + field public static final android.media.MediaCodecInfo.VideoCapabilities.PerformancePoint UHD_200; + field public static final android.media.MediaCodecInfo.VideoCapabilities.PerformancePoint UHD_24; + field public static final android.media.MediaCodecInfo.VideoCapabilities.PerformancePoint UHD_240; + field public static final android.media.MediaCodecInfo.VideoCapabilities.PerformancePoint UHD_25; + field public static final android.media.MediaCodecInfo.VideoCapabilities.PerformancePoint UHD_30; + field public static final android.media.MediaCodecInfo.VideoCapabilities.PerformancePoint UHD_50; + field public static final android.media.MediaCodecInfo.VideoCapabilities.PerformancePoint UHD_60; + field public final int frameRate; + field public final int height; + field public final int width; + } + public final class MediaCodecList { ctor public MediaCodecList(int); method public java.lang.String findDecoderForFormat(android.media.MediaFormat); @@ -24565,6 +24661,7 @@ package android.media { ctor public MediaController2(android.content.Context, android.media.Session2Token, java.util.concurrent.Executor, android.media.MediaController2.ControllerCallback); method public void cancelSessionCommand(java.lang.Object); method public void close(); + method public boolean isPlaybackActive(); method public java.lang.Object sendSessionCommand(android.media.Session2Command, android.os.Bundle); } @@ -24573,6 +24670,7 @@ package android.media { method public void onCommandResult(android.media.MediaController2, java.lang.Object, android.media.Session2Command, android.media.Session2Command.Result); method public void onConnected(android.media.MediaController2, android.media.Session2CommandGroup); method public void onDisconnected(android.media.MediaController2); + method public void onPlaybackActiveChanged(android.media.MediaController2, boolean); method public android.media.Session2Command.Result onSessionCommand(android.media.MediaController2, android.media.Session2Command, android.os.Bundle); } @@ -24698,6 +24796,7 @@ package android.media { field public static final int HDCP_V2 = 3; // 0x3 field public static final int HDCP_V2_1 = 4; // 0x4 field public static final int HDCP_V2_2 = 5; // 0x5 + field public static final int HDCP_V2_3 = 6; // 0x6 field public static final int KEY_TYPE_OFFLINE = 2; // 0x2 field public static final int KEY_TYPE_RELEASE = 3; // 0x3 field public static final int KEY_TYPE_STREAMING = 1; // 0x1 @@ -25001,6 +25100,7 @@ package android.media { field public static final java.lang.String MIMETYPE_TEXT_CEA_708 = "text/cea-708"; field public static final java.lang.String MIMETYPE_TEXT_SUBRIP = "application/x-subrip"; field public static final java.lang.String MIMETYPE_TEXT_VTT = "text/vtt"; + field public static final java.lang.String MIMETYPE_VIDEO_AV1 = "video/av01"; field public static final java.lang.String MIMETYPE_VIDEO_AVC = "video/avc"; field public static final java.lang.String MIMETYPE_VIDEO_DOLBY_VISION = "video/dolby-vision"; field public static final java.lang.String MIMETYPE_VIDEO_H263 = "video/3gpp"; @@ -25706,6 +25806,7 @@ package android.media { field public static final int VOICE_CALL = 4; // 0x4 field public static final int VOICE_COMMUNICATION = 7; // 0x7 field public static final int VOICE_DOWNLINK = 3; // 0x3 + field public static final int VOICE_PERFORMANCE = 10; // 0xa field public static final int VOICE_RECOGNITION = 6; // 0x6 field public static final int VOICE_UPLINK = 2; // 0x2 } @@ -25913,7 +26014,9 @@ package android.media { method public void close(); method public java.lang.String getSessionId(); method public android.media.Session2Token getSessionToken(); + method public boolean isPlaybackActive(); method public java.lang.Object sendSessionCommand(android.media.MediaSession2.ControllerInfo, android.media.Session2Command, android.os.Bundle); + method public void setPlaybackActive(boolean); } public static final class MediaSession2.Builder { @@ -29822,12 +29925,12 @@ package android.net.wifi { method public android.net.wifi.WifiInfo getConnectionInfo(); method public android.net.DhcpInfo getDhcpInfo(); method public int getMaxNumberOfNetworkSuggestionsPerApp(); - method public java.util.List<android.net.wifi.hotspot2.PasspointConfiguration> getPasspointConfigurations(); + method public deprecated java.util.List<android.net.wifi.hotspot2.PasspointConfiguration> getPasspointConfigurations(); method public java.util.List<android.net.wifi.ScanResult> getScanResults(); method public int getWifiState(); method public boolean is5GHzBandSupported(); method public boolean isDeviceToApRttSupported(); - method public boolean isDppSupported(); + method public boolean isEasyConnectSupported(); method public boolean isEnhancedPowerReportingSupported(); method public boolean isOweSupported(); method public boolean isP2pSupported(); @@ -29842,7 +29945,7 @@ package android.net.wifi { method public deprecated boolean reconnect(); method public deprecated boolean removeNetwork(int); method public int removeNetworkSuggestions(java.util.List<android.net.wifi.WifiNetworkSuggestion>); - method public void removePasspointConfiguration(java.lang.String); + method public deprecated void removePasspointConfiguration(java.lang.String); method public deprecated boolean saveConfiguration(); method public void setTdlsEnabled(java.net.InetAddress, boolean); method public void setTdlsEnabledWithMacAddress(java.lang.String, boolean); @@ -41738,6 +41841,7 @@ package android.service.voice { field public static final int SHOW_SOURCE_ACTIVITY = 16; // 0x10 field public static final int SHOW_SOURCE_APPLICATION = 8; // 0x8 field public static final int SHOW_SOURCE_ASSIST_GESTURE = 4; // 0x4 + field public static final int SHOW_SOURCE_AUTOMOTIVE_SYSTEM_UI = 128; // 0x80 field public static final int SHOW_SOURCE_NOTIFICATION = 64; // 0x40 field public static final int SHOW_SOURCE_PUSH_TO_TALK = 32; // 0x20 field public static final int SHOW_WITH_ASSIST = 1; // 0x1 @@ -48441,6 +48545,7 @@ package android.view { field public static final android.os.Parcelable.Creator<android.view.Display.HdrCapabilities> CREATOR; field public static final int HDR_TYPE_DOLBY_VISION = 1; // 0x1 field public static final int HDR_TYPE_HDR10 = 2; // 0x2 + field public static final int HDR_TYPE_HDR10_PLUS = 4; // 0x4 field public static final int HDR_TYPE_HLG = 3; // 0x3 field public static final float INVALID_LUMINANCE = -1.0f; } @@ -52579,7 +52684,7 @@ package android.view.contentcapture { method public final void notifyViewAppeared(android.view.ViewStructure); method public final void notifyViewDisappeared(android.view.autofill.AutofillId); method public final void notifyViewTextChanged(android.view.autofill.AutofillId, java.lang.CharSequence, int); - field public static final int FLAG_USER_INPUT = 1; // 0x1 + method public final void notifyViewsDisappeared(android.view.autofill.AutofillId, int[]); } public final class ContentCaptureSessionId implements android.os.Parcelable { @@ -54243,6 +54348,8 @@ package android.webkit { method public static java.lang.ClassLoader getWebViewClassLoader(); method public android.webkit.WebViewClient getWebViewClient(); method public android.os.Looper getWebViewLooper(); + method public android.webkit.WebViewRenderer getWebViewRenderer(); + method public android.webkit.WebViewRendererClient getWebViewRendererClient(); method public void goBack(); method public void goBackOrForward(int); method public void goForward(); @@ -54292,6 +54399,8 @@ package android.webkit { method public void setWebChromeClient(android.webkit.WebChromeClient); method public static void setWebContentsDebuggingEnabled(boolean); method public void setWebViewClient(android.webkit.WebViewClient); + method public void setWebViewRendererClient(java.util.concurrent.Executor, android.webkit.WebViewRendererClient); + method public void setWebViewRendererClient(android.webkit.WebViewRendererClient); method public deprecated boolean shouldDelayChildPressedState(); method public deprecated boolean showFindDialog(java.lang.String, boolean); method public static void startSafeBrowsing(android.content.Context, android.webkit.ValueCallback<java.lang.Boolean>); @@ -54407,6 +54516,16 @@ package android.webkit { method public android.webkit.WebView getWebView(); } + public abstract class WebViewRenderer { + method public abstract boolean terminate(); + } + + public abstract class WebViewRendererClient { + ctor public WebViewRendererClient(); + method public abstract void onRendererResponsive(android.webkit.WebView, android.webkit.WebViewRenderer); + method public abstract void onRendererUnresponsive(android.webkit.WebView, android.webkit.WebViewRenderer); + } + } package android.widget { diff --git a/api/system-current.txt b/api/system-current.txt index 83d1da7619fc..eba32cd4f390 100644 --- a/api/system-current.txt +++ b/api/system-current.txt @@ -18,6 +18,7 @@ package android { field public static final java.lang.String ALLOW_ANY_CODEC_FOR_PLAYBACK = "android.permission.ALLOW_ANY_CODEC_FOR_PLAYBACK"; field public static final java.lang.String AMBIENT_WALLPAPER = "android.permission.AMBIENT_WALLPAPER"; field public static final java.lang.String BACKUP = "android.permission.BACKUP"; + field public static final java.lang.String BIND_ATTENTION_SERVICE = "android.permission.BIND_ATTENTION_SERVICE"; field public static final java.lang.String BIND_AUGMENTED_AUTOFILL_SERVICE = "android.permission.BIND_AUGMENTED_AUTOFILL_SERVICE"; field public static final deprecated java.lang.String BIND_CONNECTION_SERVICE = "android.permission.BIND_CONNECTION_SERVICE"; field public static final java.lang.String BIND_CONTENT_CAPTURE_SERVICE = "android.permission.BIND_CONTENT_CAPTURE_SERVICE"; @@ -128,6 +129,7 @@ package android { field public static final java.lang.String QUERY_TIME_ZONE_RULES = "android.permission.QUERY_TIME_ZONE_RULES"; field public static final java.lang.String READ_CELL_BROADCASTS = "android.permission.READ_CELL_BROADCASTS"; field public static final java.lang.String READ_CONTENT_RATING_SYSTEMS = "android.permission.READ_CONTENT_RATING_SYSTEMS"; + field public static final java.lang.String READ_DEVICE_CONFIG = "android.permission.READ_DEVICE_CONFIG"; field public static final java.lang.String READ_DREAM_STATE = "android.permission.READ_DREAM_STATE"; field public static final java.lang.String READ_INSTALL_SESSIONS = "android.permission.READ_INSTALL_SESSIONS"; field public static final java.lang.String READ_NETWORK_USAGE_HISTORY = "android.permission.READ_NETWORK_USAGE_HISTORY"; @@ -184,6 +186,7 @@ package android { field public static final java.lang.String UPDATE_TIME_ZONE_RULES = "android.permission.UPDATE_TIME_ZONE_RULES"; field public static final java.lang.String USER_ACTIVITY = "android.permission.USER_ACTIVITY"; field public static final java.lang.String USE_RESERVED_DISK = "android.permission.USE_RESERVED_DISK"; + field public static final java.lang.String WRITE_DEVICE_CONFIG = "android.permission.WRITE_DEVICE_CONFIG"; field public static final java.lang.String WRITE_DREAM_STATE = "android.permission.WRITE_DREAM_STATE"; field public static final java.lang.String WRITE_EMBEDDED_SUBSCRIPTIONS = "android.permission.WRITE_EMBEDDED_SUBSCRIPTIONS"; field public static final java.lang.String WRITE_MEDIA_STORAGE = "android.permission.WRITE_MEDIA_STORAGE"; @@ -195,6 +198,7 @@ package android { } public static final class R.array { + field public static final int config_defaultRoleHolders = 17235974; // 0x1070006 field public static final int config_keySystemUuidMapping = 17235973; // 0x1070005 } @@ -1332,7 +1336,7 @@ package android.content.pm { } public class CrossProfileApps { - method public void startAnyActivity(android.content.ComponentName, android.os.UserHandle); + method public void startActivity(android.content.ComponentName, android.os.UserHandle); } public final class InstantAppInfo implements android.os.Parcelable { @@ -1559,6 +1563,7 @@ package android.content.pm { public class PermissionInfo extends android.content.pm.PackageItemInfo implements android.os.Parcelable { field public static final int FLAG_REMOVED = 2; // 0x2 + field public static final int PROTECTION_FLAG_CONFIGURATOR = 524288; // 0x80000 field public static final int PROTECTION_FLAG_DOCUMENTER = 262144; // 0x40000 field public static final int PROTECTION_FLAG_OEM = 16384; // 0x4000 field public static final int PROTECTION_FLAG_SYSTEM_TEXT_CLASSIFIER = 65536; // 0x10000 @@ -1567,6 +1572,22 @@ package android.content.pm { field public int requestRes; } + public class ResolveInfo implements android.os.Parcelable { + field public boolean handleAllWebDataURI; + } + + public class ShortcutManager { + method public java.util.List<android.content.pm.ShortcutManager.ShareShortcutInfo> getShareTargets(android.content.IntentFilter); + } + + public static final class ShortcutManager.ShareShortcutInfo implements android.os.Parcelable { + method public int describeContents(); + method public android.content.pm.ShortcutInfo getShortcutInfo(); + method public android.content.ComponentName getTargetComponent(); + method public void writeToParcel(android.os.Parcel, int); + field public static final android.os.Parcelable.Creator<android.content.pm.ShortcutManager.ShareShortcutInfo> CREATOR; + } + public final class SuspendDialogInfo implements android.os.Parcelable { method public int describeContents(); method public void writeToParcel(android.os.Parcel, int); @@ -1754,6 +1775,7 @@ package android.hardware.display { } public final class ColorDisplayManager { + method public boolean setAppSaturationLevel(java.lang.String, int); method public boolean setSaturationLevel(int); } @@ -2883,6 +2905,7 @@ package android.location { method public int getConstellationType(); method public float getExcessPathLengthMeters(); method public float getExcessPathLengthUncertaintyMeters(); + method public float getProbSatIsLos(); method public android.location.GnssReflectingPlane getReflectingPlane(); method public int getSatId(); method public int getSingleSatCorrectionFlags(); @@ -2890,13 +2913,12 @@ package android.location { method public boolean hasExcessPathLengthUncertainty(); method public boolean hasReflectingPlane(); method public boolean hasSatelliteLineOfSight(); - method public boolean isSatelliteLineOfSight(); method public void writeToParcel(android.os.Parcel, int); field public static final android.os.Parcelable.Creator<android.location.GnssSingleSatCorrection> CREATOR; field public static final int HAS_EXCESS_PATH_LENGTH_MASK = 2; // 0x2 field public static final int HAS_EXCESS_PATH_LENGTH_UNC_MASK = 4; // 0x4 + field public static final int HAS_PROB_SAT_IS_LOS_MASK = 1; // 0x1 field public static final int HAS_REFLECTING_PLANE_MASK = 8; // 0x8 - field public static final int HAS_SAT_IS_LOS_MASK = 1; // 0x1 } public static class GnssSingleSatCorrection.Builder { @@ -2906,9 +2928,9 @@ package android.location { method public android.location.GnssSingleSatCorrection.Builder setConstellationType(int); method public android.location.GnssSingleSatCorrection.Builder setExcessPathLengthMeters(float); method public android.location.GnssSingleSatCorrection.Builder setExcessPathLengthUncertaintyMeters(float); + method public android.location.GnssSingleSatCorrection.Builder setProbSatIsLos(float); method public android.location.GnssSingleSatCorrection.Builder setReflectingPlane(android.location.GnssReflectingPlane); method public android.location.GnssSingleSatCorrection.Builder setSatId(int); - method public android.location.GnssSingleSatCorrection.Builder setSatIsLos(boolean); method public android.location.GnssSingleSatCorrection.Builder setSingleSatCorrectionFlags(int); } @@ -3301,6 +3323,7 @@ package android.media { } public final class MediaRecorder.AudioSource { + field public static final int ECHO_REFERENCE = 1997; // 0x7cd field public static final int HOTWORD = 1999; // 0x7cf field public static final int RADIO_TUNER = 1998; // 0x7ce } @@ -3914,10 +3937,10 @@ package android.net.wifi { method public abstract void onEnrolleeSuccess(int); method public abstract void onFailure(int); method public abstract void onProgress(int); - field public static final int EASY_CONNECT_EVENT_FAILURE = -7; // 0xfffffff9 field public static final int EASY_CONNECT_EVENT_FAILURE_AUTHENTICATION = -2; // 0xfffffffe field public static final int EASY_CONNECT_EVENT_FAILURE_BUSY = -5; // 0xfffffffb field public static final int EASY_CONNECT_EVENT_FAILURE_CONFIGURATION = -4; // 0xfffffffc + field public static final int EASY_CONNECT_EVENT_FAILURE_GENERIC = -7; // 0xfffffff9 field public static final int EASY_CONNECT_EVENT_FAILURE_INVALID_NETWORK = -9; // 0xfffffff7 field public static final int EASY_CONNECT_EVENT_FAILURE_INVALID_URI = -1; // 0xffffffff field public static final int EASY_CONNECT_EVENT_FAILURE_NOT_COMPATIBLE = -3; // 0xfffffffd @@ -4139,12 +4162,19 @@ package android.net.wifi { field public static final int WPA2_PSK = 4; // 0x4 } + public class WifiInfo implements android.os.Parcelable { + method public boolean isOsuAp(); + } + public class WifiManager { method public void connect(android.net.wifi.WifiConfiguration, android.net.wifi.WifiManager.ActionListener); method public void connect(int, android.net.wifi.WifiManager.ActionListener); method public void disable(int, android.net.wifi.WifiManager.ActionListener); method public void disableEphemeralNetwork(java.lang.String); method public void forget(int, android.net.wifi.WifiManager.ActionListener); + method public java.util.List<android.util.Pair<android.net.wifi.WifiConfiguration, java.util.Map<java.lang.Integer, java.util.List<android.net.wifi.ScanResult>>>> getAllMatchingWifiConfigs(java.util.List<android.net.wifi.ScanResult>); + method public java.util.Map<android.net.wifi.hotspot2.OsuProvider, java.util.List<android.net.wifi.ScanResult>> getMatchingOsuProviders(java.util.List<android.net.wifi.ScanResult>); + method public java.util.Map<android.net.wifi.hotspot2.OsuProvider, android.net.wifi.hotspot2.PasspointConfiguration> getMatchingPasspointConfigsForOsuProviders(java.util.Set<android.net.wifi.hotspot2.OsuProvider>); method public java.util.List<android.net.wifi.WifiConfiguration> getPrivilegedConfiguredNetworks(); method public android.net.wifi.WifiConfiguration getWifiApConfiguration(); method public int getWifiApState(); @@ -4156,9 +4186,10 @@ package android.net.wifi { method public void save(android.net.wifi.WifiConfiguration, android.net.wifi.WifiManager.ActionListener); method public void setDeviceMobilityState(int); method public boolean setWifiApConfiguration(android.net.wifi.WifiConfiguration); - method public void startEasyConnectAsConfiguratorInitiator(java.lang.String, int, int, android.os.Handler, android.net.wifi.EasyConnectStatusCallback); - method public void startEasyConnectAsEnrolleeInitiator(java.lang.String, android.os.Handler, android.net.wifi.EasyConnectStatusCallback); + method public void startEasyConnectAsConfiguratorInitiator(java.lang.String, int, int, java.util.concurrent.Executor, android.net.wifi.EasyConnectStatusCallback); + method public void startEasyConnectAsEnrolleeInitiator(java.lang.String, java.util.concurrent.Executor, android.net.wifi.EasyConnectStatusCallback); method public boolean startScan(android.os.WorkSource); + method public void startSubscriptionProvisioning(android.net.wifi.hotspot2.OsuProvider, android.net.wifi.hotspot2.ProvisioningCallback, android.os.Handler); method public void stopEasyConnectSession(); method public void unregisterNetworkRequestMatchCallback(android.net.wifi.WifiManager.NetworkRequestMatchCallback); field public static final int CHANGE_REASON_ADDED = 0; // 0x0 @@ -4178,6 +4209,8 @@ package android.net.wifi { field public static final java.lang.String EXTRA_WIFI_CONFIGURATION = "wifiConfiguration"; field public static final java.lang.String EXTRA_WIFI_CREDENTIAL_EVENT_TYPE = "et"; field public static final java.lang.String EXTRA_WIFI_CREDENTIAL_SSID = "ssid"; + field public static final int PASSPOINT_HOME_NETWORK = 0; // 0x0 + field public static final int PASSPOINT_ROAMING_NETWORK = 1; // 0x1 field public static final java.lang.String WIFI_AP_STATE_CHANGED_ACTION = "android.net.wifi.WIFI_AP_STATE_CHANGED"; field public static final int WIFI_AP_STATE_DISABLED = 11; // 0xb field public static final int WIFI_AP_STATE_DISABLING = 10; // 0xa @@ -4354,6 +4387,59 @@ package android.net.wifi.aware { } +package android.net.wifi.hotspot2 { + + public final class OsuProvider implements android.os.Parcelable { + method public int describeContents(); + method public java.lang.String getFriendlyName(); + method public android.net.Uri getServerUri(); + method public void writeToParcel(android.os.Parcel, int); + field public static final android.os.Parcelable.Creator<android.net.wifi.hotspot2.OsuProvider> CREATOR; + } + + public abstract class ProvisioningCallback { + ctor public ProvisioningCallback(); + method public abstract void onProvisioningComplete(); + method public abstract void onProvisioningFailure(int); + method public abstract void onProvisioningStatus(int); + field public static final int OSU_FAILURE_ADD_PASSPOINT_CONFIGURATION = 22; // 0x16 + field public static final int OSU_FAILURE_AP_CONNECTION = 1; // 0x1 + field public static final int OSU_FAILURE_INVALID_SERVER_URL = 8; // 0x8 + field public static final int OSU_FAILURE_NO_AAA_SERVER_TRUST_ROOT_NODE = 17; // 0x11 + field public static final int OSU_FAILURE_NO_AAA_TRUST_ROOT_CERTIFICATE = 21; // 0x15 + field public static final int OSU_FAILURE_NO_OSU_ACTIVITY_FOUND = 14; // 0xe + field public static final int OSU_FAILURE_NO_POLICY_SERVER_TRUST_ROOT_NODE = 19; // 0x13 + field public static final int OSU_FAILURE_NO_PPS_MO = 16; // 0x10 + field public static final int OSU_FAILURE_NO_REMEDIATION_SERVER_TRUST_ROOT_NODE = 18; // 0x12 + field public static final int OSU_FAILURE_OSU_PROVIDER_NOT_FOUND = 23; // 0x17 + field public static final int OSU_FAILURE_PROVISIONING_ABORTED = 6; // 0x6 + field public static final int OSU_FAILURE_PROVISIONING_NOT_AVAILABLE = 7; // 0x7 + field public static final int OSU_FAILURE_RETRIEVE_TRUST_ROOT_CERTIFICATES = 20; // 0x14 + field public static final int OSU_FAILURE_SERVER_CONNECTION = 3; // 0x3 + field public static final int OSU_FAILURE_SERVER_URL_INVALID = 2; // 0x2 + field public static final int OSU_FAILURE_SERVER_VALIDATION = 4; // 0x4 + field public static final int OSU_FAILURE_SERVICE_PROVIDER_VERIFICATION = 5; // 0x5 + field public static final int OSU_FAILURE_SOAP_MESSAGE_EXCHANGE = 11; // 0xb + field public static final int OSU_FAILURE_START_REDIRECT_LISTENER = 12; // 0xc + field public static final int OSU_FAILURE_TIMED_OUT_REDIRECT_LISTENER = 13; // 0xd + field public static final int OSU_FAILURE_UNEXPECTED_COMMAND_TYPE = 9; // 0x9 + field public static final int OSU_FAILURE_UNEXPECTED_SOAP_MESSAGE_STATUS = 15; // 0xf + field public static final int OSU_FAILURE_UNEXPECTED_SOAP_MESSAGE_TYPE = 10; // 0xa + field public static final int OSU_STATUS_AP_CONNECTED = 2; // 0x2 + field public static final int OSU_STATUS_AP_CONNECTING = 1; // 0x1 + field public static final int OSU_STATUS_INIT_SOAP_EXCHANGE = 6; // 0x6 + field public static final int OSU_STATUS_REDIRECT_RESPONSE_RECEIVED = 8; // 0x8 + field public static final int OSU_STATUS_RETRIEVING_TRUST_ROOT_CERTS = 11; // 0xb + field public static final int OSU_STATUS_SECOND_SOAP_EXCHANGE = 9; // 0x9 + field public static final int OSU_STATUS_SERVER_CONNECTED = 5; // 0x5 + field public static final int OSU_STATUS_SERVER_CONNECTING = 3; // 0x3 + field public static final int OSU_STATUS_SERVER_VALIDATED = 4; // 0x4 + field public static final int OSU_STATUS_THIRD_SOAP_EXCHANGE = 10; // 0xa + field public static final int OSU_STATUS_WAITING_FOR_REDIRECT_RESPONSE = 7; // 0x7 + } + +} + package android.net.wifi.rtt { public static final class RangingRequest.Builder { @@ -5024,6 +5110,9 @@ package android.provider { method public static void removeOnPropertyChangedListener(android.provider.DeviceConfig.OnPropertyChangedListener); method public static void resetToDefaults(int, java.lang.String); method public static boolean setProperty(java.lang.String, java.lang.String, java.lang.String, boolean); + field public static final java.lang.String NAMESPACE_AUTOFILL = "autofill"; + field public static final java.lang.String NAMESPACE_CONTENT_CAPTURE = "content_capture"; + field public static final java.lang.String NAMESPACE_GAME_DRIVER = "game_driver"; field public static final java.lang.String NAMESPACE_INPUT_NATIVE_BOOT = "input_native_boot"; } @@ -5339,7 +5428,8 @@ package android.security.keystore.recovery { public class RecoveryController { method public android.security.keystore.recovery.RecoverySession createRecoverySession(); - method public java.security.Key generateKey(java.lang.String) throws android.security.keystore.recovery.InternalRecoveryServiceException, android.security.keystore.recovery.LockScreenRequiredException; + method public deprecated java.security.Key generateKey(java.lang.String) throws android.security.keystore.recovery.InternalRecoveryServiceException, android.security.keystore.recovery.LockScreenRequiredException; + method public java.security.Key generateKey(java.lang.String, byte[]) throws android.security.keystore.recovery.InternalRecoveryServiceException, android.security.keystore.recovery.LockScreenRequiredException; method public java.util.List<java.lang.String> getAliases() throws android.security.keystore.recovery.InternalRecoveryServiceException; method public static android.security.keystore.recovery.RecoveryController getInstance(android.content.Context); method public java.security.Key getKey(java.lang.String) throws android.security.keystore.recovery.InternalRecoveryServiceException, java.security.UnrecoverableKeyException; @@ -5347,7 +5437,8 @@ package android.security.keystore.recovery { method public int[] getRecoverySecretTypes() throws android.security.keystore.recovery.InternalRecoveryServiceException; method public int getRecoveryStatus(java.lang.String) throws android.security.keystore.recovery.InternalRecoveryServiceException; method public java.util.Map<java.lang.String, java.security.cert.X509Certificate> getRootCertificates(); - method public java.security.Key importKey(java.lang.String, byte[]) throws android.security.keystore.recovery.InternalRecoveryServiceException, android.security.keystore.recovery.LockScreenRequiredException; + method public deprecated java.security.Key importKey(java.lang.String, byte[]) throws android.security.keystore.recovery.InternalRecoveryServiceException, android.security.keystore.recovery.LockScreenRequiredException; + method public java.security.Key importKey(java.lang.String, byte[], byte[]) throws android.security.keystore.recovery.InternalRecoveryServiceException, android.security.keystore.recovery.LockScreenRequiredException; method public void initRecoveryService(java.lang.String, byte[], byte[]) throws java.security.cert.CertificateException, android.security.keystore.recovery.InternalRecoveryServiceException; method public static boolean isRecoverableKeyStoreEnabled(android.content.Context); method public void removeKey(java.lang.String) throws android.security.keystore.recovery.InternalRecoveryServiceException; @@ -5374,6 +5465,7 @@ package android.security.keystore.recovery { method public int describeContents(); method public java.lang.String getAlias(); method public byte[] getEncryptedKeyMaterial(); + method public byte[] getMetadata(); method public void writeToParcel(android.os.Parcel, int); field public static final android.os.Parcelable.Creator<android.security.keystore.recovery.WrappedApplicationKey> CREATOR; } @@ -5383,6 +5475,7 @@ package android.security.keystore.recovery { method public android.security.keystore.recovery.WrappedApplicationKey build(); method public android.security.keystore.recovery.WrappedApplicationKey.Builder setAlias(java.lang.String); method public android.security.keystore.recovery.WrappedApplicationKey.Builder setEncryptedKeyMaterial(byte[]); + method public android.security.keystore.recovery.WrappedApplicationKey.Builder setMetadata(byte[]); } } @@ -5405,6 +5498,28 @@ package android.service.appprediction { } +package android.service.attention { + + public abstract class AttentionService extends android.app.Service { + ctor public AttentionService(); + method public final android.os.IBinder onBind(android.content.Intent); + method public abstract void onCancelAttentionCheck(int); + method public abstract void onCheckAttention(int, android.service.attention.AttentionService.AttentionCallback); + field public static final int ATTENTION_FAILURE_PREEMPTED = 2; // 0x2 + field public static final int ATTENTION_FAILURE_TIMED_OUT = 3; // 0x3 + field public static final int ATTENTION_FAILURE_UNKNOWN = 4; // 0x4 + field public static final int ATTENTION_SUCCESS_ABSENT = 0; // 0x0 + field public static final int ATTENTION_SUCCESS_PRESENT = 1; // 0x1 + field public static final java.lang.String SERVICE_INTERFACE = "android.service.attention.AttentionService"; + } + + public static final class AttentionService.AttentionCallback { + method public void onFailure(int, int); + method public void onSuccess(int, int, long); + } + +} + package android.service.autofill { public abstract class AutofillFieldClassificationService extends android.app.Service { @@ -5635,6 +5750,7 @@ package android.service.euicc { field public static final java.lang.String EUICC_SERVICE_INTERFACE = "android.service.euicc.EuiccService"; field public static final java.lang.String EXTRA_RESOLUTION_ALLOW_POLICY_RULES = "android.service.euicc.extra.RESOLUTION_ALLOW_POLICY_RULES"; field public static final java.lang.String EXTRA_RESOLUTION_CALLING_PACKAGE = "android.service.euicc.extra.RESOLUTION_CALLING_PACKAGE"; + field public static final java.lang.String EXTRA_RESOLUTION_CARD_ID = "android.service.euicc.extra.RESOLUTION_CARD_ID"; field public static final java.lang.String EXTRA_RESOLUTION_CONFIRMATION_CODE = "android.service.euicc.extra.RESOLUTION_CONFIRMATION_CODE"; field public static final java.lang.String EXTRA_RESOLUTION_CONFIRMATION_CODE_RETRIED = "android.service.euicc.extra.RESOLUTION_CONFIRMATION_CODE_RETRIED"; field public static final java.lang.String EXTRA_RESOLUTION_CONSENT = "android.service.euicc.extra.RESOLUTION_CONSENT"; @@ -6266,6 +6382,30 @@ package android.telephony { field public static final java.lang.String KEY_CARRIER_SETUP_APP_STRING = "carrier_setup_app_string"; } + public final class CarrierRestrictionRules implements android.os.Parcelable { + method public int describeContents(); + method public java.util.List<android.service.carrier.CarrierIdentifier> getAllowedCarriers(); + method public int getDefaultCarrierRestriction(); + method public java.util.List<android.service.carrier.CarrierIdentifier> getExcludedCarriers(); + method public int getMultiSimPolicy(); + method public boolean isAllCarriersAllowed(); + method public void writeToParcel(android.os.Parcel, int); + field public static final int CARRIER_RESTRICTION_DEFAULT_ALLOWED = 1; // 0x1 + field public static final int CARRIER_RESTRICTION_DEFAULT_NOT_ALLOWED = 0; // 0x0 + field public static final android.os.Parcelable.Creator<android.telephony.CarrierRestrictionRules> CREATOR; + field public static final int MULTISIM_POLICY_NONE = 0; // 0x0 + field public static final int MULTISIM_POLICY_ONE_VALID_SIM_MUST_BE_PRESENT = 1; // 0x1 + } + + public static class CarrierRestrictionRules.Builder { + method public android.telephony.CarrierRestrictionRules build(); + method public android.telephony.CarrierRestrictionRules.Builder setAllCarriersAllowed(); + method public android.telephony.CarrierRestrictionRules.Builder setAllowedCarriers(java.util.List<android.service.carrier.CarrierIdentifier>); + method public android.telephony.CarrierRestrictionRules.Builder setDefaultCarrierRestriction(int); + method public android.telephony.CarrierRestrictionRules.Builder setExcludedCarriers(java.util.List<android.service.carrier.CarrierIdentifier>); + method public android.telephony.CarrierRestrictionRules.Builder setMultiSimPolicy(int); + } + public final class DataFailCause { field public static final int ACTIVATION_REJECT_GGSN = 30; // 0x1e field public static final int ACTIVATION_REJECT_UNSPECIFIED = 31; // 0x1f @@ -6759,12 +6899,14 @@ package android.telephony { method public void dial(java.lang.String); method public boolean disableDataConnectivity(); method public boolean enableDataConnectivity(); + method public boolean enableModemForSlot(int, boolean); method public void enableVideoCalling(boolean); method public java.lang.String getAidForAppType(int); - method public java.util.List<android.service.carrier.CarrierIdentifier> getAllowedCarriers(int); + method public deprecated java.util.List<android.service.carrier.CarrierIdentifier> getAllowedCarriers(int); method public int getCardIdForDefaultEuicc(); method public java.util.List<java.lang.String> getCarrierPackageNamesForIntent(android.content.Intent); method public java.util.List<java.lang.String> getCarrierPackageNamesForIntentAndPhone(android.content.Intent, int); + method public android.telephony.CarrierRestrictionRules getCarrierRestrictionRules(); method public java.lang.String getCdmaMdn(); method public java.lang.String getCdmaMdn(int); method public java.lang.String getCdmaMin(); @@ -6803,8 +6945,9 @@ package android.telephony { method public void requestCellInfoUpdate(android.os.WorkSource, java.util.concurrent.Executor, android.telephony.TelephonyManager.CellInfoCallback); method public void requestNumberVerification(android.telephony.PhoneNumberRange, long, java.util.concurrent.Executor, android.telephony.NumberVerificationCallback); method public boolean resetRadioConfig(); - method public int setAllowedCarriers(int, java.util.List<android.service.carrier.CarrierIdentifier>); + method public deprecated int setAllowedCarriers(int, java.util.List<android.service.carrier.CarrierIdentifier>); method public void setCarrierDataEnabled(boolean); + method public int setCarrierRestrictionRules(android.telephony.CarrierRestrictionRules); method public void setDataActivationState(int); method public deprecated void setDataEnabled(int, boolean); method public void setDataRoamingEnabled(boolean); @@ -6856,6 +6999,9 @@ package android.telephony { field public static final int RADIO_POWER_OFF = 0; // 0x0 field public static final int RADIO_POWER_ON = 1; // 0x1 field public static final int RADIO_POWER_UNAVAILABLE = 2; // 0x2 + field public static final int SET_CARRIER_RESTRICTION_ERROR = 2; // 0x2 + field public static final int SET_CARRIER_RESTRICTION_NOT_SUPPORTED = 1; // 0x1 + field public static final int SET_CARRIER_RESTRICTION_SUCCESS = 0; // 0x0 field public static final int SIM_ACTIVATION_STATE_ACTIVATED = 2; // 0x2 field public static final int SIM_ACTIVATION_STATE_ACTIVATING = 1; // 0x1 field public static final int SIM_ACTIVATION_STATE_DEACTIVATED = 3; // 0x3 @@ -7186,6 +7332,7 @@ package android.telephony.ims { method public int getServiceType(); method public static int getVideoStateFromCallType(int); method public static int getVideoStateFromImsCallProfile(android.telephony.ims.ImsCallProfile); + method public boolean isEmergencyCallTesting(); method public boolean isVideoCall(); method public boolean isVideoPaused(); method public static int presentationToOir(int); @@ -7194,6 +7341,7 @@ package android.telephony.ims { method public void setCallExtraInt(java.lang.String, int); method public void setCallRestrictCause(int); method public void setEmergencyCallRouting(int); + method public void setEmergencyCallTesting(boolean); method public void setEmergencyServiceCategories(int); method public void setEmergencyUrns(java.util.List<java.lang.String>); method public void updateCallExtras(android.telephony.ims.ImsCallProfile); @@ -7244,6 +7392,7 @@ package android.telephony.ims { } public class ImsCallSessionListener { + method public void callQualityChanged(android.telephony.CallQuality); method public void callSessionConferenceExtendFailed(android.telephony.ims.ImsReasonInfo); method public void callSessionConferenceExtendReceived(android.telephony.ims.stub.ImsCallSessionImplBase, android.telephony.ims.ImsCallProfile); method public void callSessionConferenceExtended(android.telephony.ims.stub.ImsCallSessionImplBase, android.telephony.ims.ImsCallProfile); @@ -8194,8 +8343,8 @@ package android.view.contentcapture { public final class ContentCaptureEvent implements android.os.Parcelable { method public int describeContents(); method public long getEventTime(); - method public int getFlags(); method public android.view.autofill.AutofillId getId(); + method public java.util.List<android.view.autofill.AutofillId> getIds(); method public java.lang.CharSequence getText(); method public int getType(); method public android.view.contentcapture.ViewNode getViewNode(); @@ -8499,6 +8648,8 @@ package android.webkit { method public abstract int getVisibleTitleHeight(); method public abstract android.webkit.WebChromeClient getWebChromeClient(); method public abstract android.webkit.WebViewClient getWebViewClient(); + method public abstract android.webkit.WebViewRenderer getWebViewRenderer(); + method public abstract android.webkit.WebViewRendererClient getWebViewRendererClient(); method public abstract android.view.View getZoomControls(); method public abstract void goBack(); method public abstract void goBackOrForward(int); @@ -8548,6 +8699,7 @@ package android.webkit { method public abstract void setVerticalScrollbarOverlay(boolean); method public abstract void setWebChromeClient(android.webkit.WebChromeClient); method public abstract void setWebViewClient(android.webkit.WebViewClient); + method public abstract void setWebViewRendererClient(java.util.concurrent.Executor, android.webkit.WebViewRendererClient); method public abstract boolean showFindDialog(java.lang.String, boolean); method public abstract void stopLoading(); method public abstract boolean zoomBy(float); diff --git a/api/test-current.txt b/api/test-current.txt index 6ddb341191cb..08531829cba1 100644 --- a/api/test-current.txt +++ b/api/test-current.txt @@ -420,6 +420,7 @@ package android.content.pm { } public class PermissionInfo extends android.content.pm.PackageItemInfo implements android.os.Parcelable { + field public static final int PROTECTION_FLAG_CONFIGURATOR = 524288; // 0x80000 field public static final int PROTECTION_FLAG_DOCUMENTER = 262144; // 0x40000 field public static final int PROTECTION_FLAG_OEM = 16384; // 0x4000 field public static final int PROTECTION_FLAG_SYSTEM_TEXT_CLASSIFIER = 65536; // 0x10000 @@ -510,6 +511,8 @@ package android.graphics { } public class Paint { + method public long getColorLong(); + method public long getShadowLayerColorLong(); method public void setColor(long); method public void setShadowLayer(float, float, float, long); } @@ -579,6 +582,8 @@ package android.hardware.display { public final class BrightnessConfiguration implements android.os.Parcelable { method public int describeContents(); + method public android.hardware.display.BrightnessCorrection getCorrectionByCategory(int); + method public android.hardware.display.BrightnessCorrection getCorrectionByPackageName(java.lang.String); method public android.util.Pair<float[], float[]> getCurve(); method public void writeToParcel(android.os.Parcel, int); field public static final android.os.Parcelable.Creator<android.hardware.display.BrightnessConfiguration> CREATOR; @@ -586,10 +591,22 @@ package android.hardware.display { public static class BrightnessConfiguration.Builder { ctor public BrightnessConfiguration.Builder(float[], float[]); + method public android.hardware.display.BrightnessConfiguration.Builder addCorrectionByCategory(int, android.hardware.display.BrightnessCorrection); + method public android.hardware.display.BrightnessConfiguration.Builder addCorrectionByPackageName(java.lang.String, android.hardware.display.BrightnessCorrection); method public android.hardware.display.BrightnessConfiguration build(); + method public int getMaxCorrectionsByCategory(); + method public int getMaxCorrectionsByPackageName(); method public android.hardware.display.BrightnessConfiguration.Builder setDescription(java.lang.String); } + public final class BrightnessCorrection implements android.os.Parcelable { + method public float apply(float); + method public static android.hardware.display.BrightnessCorrection createScaleAndTranslateLog(float, float); + method public int describeContents(); + method public void writeToParcel(android.os.Parcel, int); + field public static final android.os.Parcelable.Creator<android.hardware.display.BrightnessCorrection> CREATOR; + } + public final class DisplayManager { method public java.util.List<android.hardware.display.AmbientBrightnessDayStats> getAmbientBrightnessStats(); method public android.hardware.display.BrightnessConfiguration getBrightnessConfiguration(); @@ -1103,6 +1120,24 @@ package android.os { field public static final android.os.Parcelable.Creator<android.os.VibrationEffect.Waveform> CREATOR; } + public class VintfObject { + method public static java.lang.String[] getHalNamesAndVersions(); + method public static java.lang.String getSepolicyVersion(); + method public static java.lang.Long getTargetFrameworkCompatibilityMatrixVersion(); + method public static java.util.Map<java.lang.String, java.lang.String[]> getVndkSnapshots(); + method public static java.lang.String[] report(); + } + + public class VintfRuntimeInfo { + method public static java.lang.String getCpuInfo(); + method public static java.lang.String getHardwareId(); + method public static java.lang.String getKernelVersion(); + method public static java.lang.String getNodeName(); + method public static java.lang.String getOsName(); + method public static java.lang.String getOsRelease(); + method public static java.lang.String getOsVersion(); + } + public class WorkSource implements android.os.Parcelable { ctor public WorkSource(int); method public boolean add(int); @@ -2089,6 +2124,33 @@ package android.view.inputmethod { } +package android.view.inspector { + + public abstract class InspectableNodeName implements java.lang.annotation.Annotation { + } + + public abstract class InspectableProperty implements java.lang.annotation.Annotation { + } + + public static abstract class InspectableProperty.EnumMap implements java.lang.annotation.Annotation { + } + + public static abstract class InspectableProperty.FlagMap implements java.lang.annotation.Annotation { + } + + public static final class InspectableProperty.ValueType extends java.lang.Enum { + method public static android.view.inspector.InspectableProperty.ValueType valueOf(java.lang.String); + method public static final android.view.inspector.InspectableProperty.ValueType[] values(); + enum_constant public static final android.view.inspector.InspectableProperty.ValueType COLOR; + enum_constant public static final android.view.inspector.InspectableProperty.ValueType GRAVITY; + enum_constant public static final android.view.inspector.InspectableProperty.ValueType INFERRED; + enum_constant public static final android.view.inspector.InspectableProperty.ValueType INT_ENUM; + enum_constant public static final android.view.inspector.InspectableProperty.ValueType INT_FLAG; + enum_constant public static final android.view.inspector.InspectableProperty.ValueType NONE; + } + +} + package android.widget { public abstract class AbsListView extends android.widget.AdapterView implements android.widget.Filter.FilterListener android.text.TextWatcher android.view.ViewTreeObserver.OnGlobalLayoutListener android.view.ViewTreeObserver.OnTouchModeChangeListener { diff --git a/cmds/idmap2/Android.bp b/cmds/idmap2/Android.bp index abe18ba8a415..803f83c0bc6f 100644 --- a/cmds/idmap2/Android.bp +++ b/cmds/idmap2/Android.bp @@ -20,6 +20,7 @@ cc_defaults { "misc-*", "modernize-*", "readability-*", + "-modernize-avoid-c-arrays", ], tidy_flags: [ "-system-headers", @@ -38,6 +39,7 @@ cc_library { "libidmap2/CommandLineOptions.cpp", "libidmap2/FileUtils.cpp", "libidmap2/Idmap.cpp", + "libidmap2/Policies.cpp", "libidmap2/PrettyPrintVisitor.cpp", "libidmap2/RawPrintVisitor.cpp", "libidmap2/ResourceUtils.cpp", @@ -87,6 +89,7 @@ cc_test { "tests/Idmap2BinaryTests.cpp", "tests/IdmapTests.cpp", "tests/Main.cpp", + "tests/PoliciesTests.cpp", "tests/PrettyPrintVisitorTests.cpp", "tests/RawPrintVisitorTests.cpp", "tests/ResourceUtilsTests.cpp", diff --git a/cmds/idmap2/idmap2/Create.cpp b/cmds/idmap2/idmap2/Create.cpp index b07567331e85..c455ac0f83af 100644 --- a/cmds/idmap2/idmap2/Create.cpp +++ b/cmds/idmap2/idmap2/Create.cpp @@ -27,17 +27,25 @@ #include "idmap2/CommandLineOptions.h" #include "idmap2/FileUtils.h" #include "idmap2/Idmap.h" +#include "idmap2/Policies.h" +#include "idmap2/Result.h" using android::ApkAssets; using android::idmap2::BinaryStreamVisitor; using android::idmap2::CommandLineOptions; using android::idmap2::Idmap; +using android::idmap2::PoliciesToBitmask; +using android::idmap2::PolicyBitmask; +using android::idmap2::PolicyFlags; +using android::idmap2::Result; using android::idmap2::utils::kIdmapFilePermissionMask; bool Create(const std::vector<std::string>& args, std::ostream& out_error) { std::string target_apk_path; std::string overlay_apk_path; std::string idmap_path; + std::vector<std::string> policies; + bool ignore_overlayable; const CommandLineOptions opts = CommandLineOptions("idmap2 create") @@ -47,12 +55,28 @@ bool Create(const std::vector<std::string>& args, std::ostream& out_error) { .MandatoryOption("--overlay-apk-path", "input: path to apk which contains the new resource values", &overlay_apk_path) - .MandatoryOption("--idmap-path", "output: path to where to write idmap file", - &idmap_path); + .MandatoryOption("--idmap-path", "output: path to where to write idmap file", &idmap_path) + .OptionalOption("--policy", + "input: an overlayable policy this overlay fulfills " + "(if none or supplied, the overlay policy will default to \"public\")", + &policies) + .OptionalFlag("--ignore-overlayable", "disables overlayable and policy checks", + &ignore_overlayable); if (!opts.Parse(args, out_error)) { return false; } + PolicyBitmask fulfilled_policies = 0; + if (auto result = PoliciesToBitmask(policies, out_error)) { + fulfilled_policies |= *result; + } else { + return false; + } + + if (fulfilled_policies == 0) { + fulfilled_policies |= PolicyFlags::POLICY_PUBLIC; + } + const std::unique_ptr<const ApkAssets> target_apk = ApkAssets::Load(target_apk_path); if (!target_apk) { out_error << "error: failed to load apk " << target_apk_path << std::endl; @@ -66,7 +90,8 @@ bool Create(const std::vector<std::string>& args, std::ostream& out_error) { } const std::unique_ptr<const Idmap> idmap = - Idmap::FromApkAssets(target_apk_path, *target_apk, overlay_apk_path, *overlay_apk, out_error); + Idmap::FromApkAssets(target_apk_path, *target_apk, overlay_apk_path, *overlay_apk, + fulfilled_policies, !ignore_overlayable, out_error); if (!idmap) { return false; } diff --git a/cmds/idmap2/idmap2/Scan.cpp b/cmds/idmap2/idmap2/Scan.cpp index 4f88127f8af1..b1ed42a3e624 100644 --- a/cmds/idmap2/idmap2/Scan.cpp +++ b/cmds/idmap2/idmap2/Scan.cpp @@ -21,11 +21,15 @@ #include <set> #include <sstream> #include <string> +#include <utility> #include <vector> +#include "android-base/properties.h" + #include "idmap2/CommandLineOptions.h" #include "idmap2/FileUtils.h" #include "idmap2/Idmap.h" +#include "idmap2/ResourceUtils.h" #include "idmap2/Xml.h" #include "idmap2/ZipFile.h" @@ -33,10 +37,13 @@ using android::idmap2::CommandLineOptions; using android::idmap2::Idmap; -using android::idmap2::MemoryChunk; -using android::idmap2::Xml; -using android::idmap2::ZipFile; +using android::idmap2::PoliciesToBitmask; +using android::idmap2::PolicyBitmask; +using android::idmap2::PolicyFlags; +using android::idmap2::Result; +using android::idmap2::utils::ExtractOverlayManifestInfo; using android::idmap2::utils::FindFiles; +using android::idmap2::utils::OverlayManifestInfo; namespace { @@ -45,11 +52,19 @@ struct InputOverlay { return priority < rhs.priority || (priority == rhs.priority && apk_path < rhs.apk_path); } - std::string apk_path; // NOLINT(misc-non-private-member-variables-in-classes) - std::string idmap_path; // NOLINT(misc-non-private-member-variables-in-classes) - int priority; // NOLINT(misc-non-private-member-variables-in-classes) + std::string apk_path; // NOLINT(misc-non-private-member-variables-in-classes) + std::string idmap_path; // NOLINT(misc-non-private-member-variables-in-classes) + int priority; // NOLINT(misc-non-private-member-variables-in-classes) + std::vector<std::string> policies; // NOLINT(misc-non-private-member-variables-in-classes) + bool ignore_overlayable; // NOLINT(misc-non-private-member-variables-in-classes) }; +bool VendorIsQOrLater() { + // STOPSHIP(b/119390857): Check api version once Q sdk version is finalized + std::string version = android::base::GetProperty("ro.vndk.version", "Q"); + return version == "Q" || version == "q"; +} + std::unique_ptr<std::vector<std::string>> FindApkFiles(const std::vector<std::string>& dirs, bool recursive, std::ostream& out_error) { const auto predicate = [](unsigned char type, const std::string& path) -> bool { @@ -70,6 +85,22 @@ std::unique_ptr<std::vector<std::string>> FindApkFiles(const std::vector<std::st return std::make_unique<std::vector<std::string>>(paths.cbegin(), paths.cend()); } +PolicyBitmask PolicyForPath(const std::string& apk_path) { + static const std::vector<std::pair<std::string, PolicyBitmask>> values = { + {"/product/", PolicyFlags::POLICY_PRODUCT_PARTITION}, + {"/system/", PolicyFlags::POLICY_SYSTEM_PARTITION}, + {"/vendor/", PolicyFlags::POLICY_VENDOR_PARTITION}, + }; + + for (auto const& pair : values) { + if (apk_path.compare(0, pair.first.size(), pair.first) == 0) { + return pair.second | PolicyFlags::POLICY_PUBLIC; + } + } + + return PolicyFlags::POLICY_PUBLIC; +} + } // namespace bool Scan(const std::vector<std::string>& args, std::ostream& out_error) { @@ -77,6 +108,7 @@ bool Scan(const std::vector<std::string>& args, std::ostream& out_error) { std::string target_package_name; std::string target_apk_path; std::string output_directory; + std::vector<std::string> override_policies; bool recursive = false; const CommandLineOptions opts = @@ -89,7 +121,12 @@ bool Scan(const std::vector<std::string>& args, std::ostream& out_error) { .MandatoryOption("--target-apk-path", "path to target apk", &target_apk_path) .MandatoryOption("--output-directory", "directory in which to write artifacts (idmap files and overlays.list)", - &output_directory); + &output_directory) + .OptionalOption( + "--override-policy", + "input: an overlayable policy this overlay fulfills " + "(if none or supplied, the overlays will not have their policies overriden", + &override_policies); if (!opts.Parse(args, out_error)) { return false; } @@ -101,72 +138,84 @@ bool Scan(const std::vector<std::string>& args, std::ostream& out_error) { std::vector<InputOverlay> interesting_apks; for (const std::string& path : *apk_paths) { - std::unique_ptr<const ZipFile> zip = ZipFile::Open(path); - if (!zip) { - out_error << "error: failed to open " << path << " as a zip file" << std::endl; - return false; - } - - std::unique_ptr<const MemoryChunk> entry = zip->Uncompress("AndroidManifest.xml"); - if (!entry) { - out_error << "error: failed to uncompress AndroidManifest.xml from " << path << std::endl; + Result<OverlayManifestInfo> overlay_info = + ExtractOverlayManifestInfo(path, out_error, + /* assert_overlay */ false); + if (!overlay_info) { return false; } - std::unique_ptr<const Xml> xml = Xml::Create(entry->buf, entry->size); - if (!xml) { - out_error << "error: failed to parse AndroidManifest.xml from " << path << std::endl; + if (!overlay_info->is_static) { continue; } - const auto tag = xml->FindTag("overlay"); - if (!tag) { + if (overlay_info->target_package.empty() || + overlay_info->target_package != target_package_name) { continue; } - auto iter = tag->find("isStatic"); - if (iter == tag->end() || std::stoul(iter->second) == 0U) { + if (overlay_info->priority < 0) { continue; } - iter = tag->find("targetPackage"); - if (iter == tag->end() || iter->second != target_package_name) { - continue; + PolicyBitmask fulfilled_policies; + if (!override_policies.empty()) { + if (Result<PolicyBitmask> result = PoliciesToBitmask(override_policies, out_error)) { + fulfilled_policies = *result; + } else { + return false; + } + } else { + fulfilled_policies = PolicyForPath(path); } - iter = tag->find("priority"); - if (iter == tag->end()) { - continue; + bool ignore_overlayable = false; + if ((fulfilled_policies & PolicyFlags::POLICY_VENDOR_PARTITION) != 0 && !VendorIsQOrLater()) { + // If the overlay is on a pre-Q vendor partition, do not enforce overlayable + // restrictions on this overlay because the pre-Q platform has no understanding of + // overlayable. + ignore_overlayable = true; } - const int priority = std::stoi(iter->second); - if (priority < 0) { - continue; - } + std::string idmap_path = Idmap::CanonicalIdmapPathFor(output_directory, path); // Sort the static overlays in ascending priority order - std::string idmap_path = Idmap::CanonicalIdmapPathFor(output_directory, path); - InputOverlay input{path, idmap_path, priority}; + InputOverlay input{path, idmap_path, overlay_info->priority, override_policies, + ignore_overlayable}; interesting_apks.insert( std::lower_bound(interesting_apks.begin(), interesting_apks.end(), input), input); } std::stringstream stream; for (const auto& overlay : interesting_apks) { + // Create the idmap for the overlay if it currently does not exist or if it is not up to date. std::stringstream dev_null; - if (!Verify(std::vector<std::string>({"--idmap-path", overlay.idmap_path}), dev_null) && - !Create(std::vector<std::string>({ - "--target-apk-path", - target_apk_path, - "--overlay-apk-path", - overlay.apk_path, - "--idmap-path", - overlay.idmap_path, - }), - out_error)) { - return false; + + std::vector<std::string> verify_args = {"--idmap-path", overlay.idmap_path}; + for (const std::string& policy : overlay.policies) { + verify_args.emplace_back("--policy"); + verify_args.emplace_back(policy); } - stream << overlay.idmap_path << std::endl; + + if (!Verify(std::vector<std::string>(verify_args), dev_null)) { + std::vector<std::string> create_args = {"--target-apk-path", target_apk_path, + "--overlay-apk-path", overlay.apk_path, + "--idmap-path", overlay.idmap_path}; + if (overlay.ignore_overlayable) { + create_args.emplace_back("--ignore-overlayable"); + } + + for (const std::string& policy : overlay.policies) { + verify_args.emplace_back("--policy"); + verify_args.emplace_back(policy); + } + + if (!Create(create_args, out_error)) { + return false; + } + } + + stream << overlay.idmap_path << std::endl; } std::cout << stream.str(); diff --git a/cmds/idmap2/idmap2d/Idmap2Service.cpp b/cmds/idmap2/idmap2d/Idmap2Service.cpp index d2e46e15fc59..a3c752718ee2 100644 --- a/cmds/idmap2/idmap2d/Idmap2Service.cpp +++ b/cmds/idmap2/idmap2d/Idmap2Service.cpp @@ -26,12 +26,15 @@ #include <string> #include "android-base/macros.h" +#include "android-base/stringprintf.h" #include "utils/String8.h" #include "utils/Trace.h" #include "idmap2/BinaryStreamVisitor.h" #include "idmap2/FileUtils.h" #include "idmap2/Idmap.h" +#include "idmap2/Policies.h" +#include "idmap2/Result.h" #include "idmap2d/Idmap2Service.h" @@ -39,6 +42,8 @@ using android::binder::Status; using android::idmap2::BinaryStreamVisitor; using android::idmap2::Idmap; using android::idmap2::IdmapHeader; +using android::idmap2::PolicyBitmask; +using android::idmap2::Result; using android::idmap2::utils::kIdmapFilePermissionMask; namespace { @@ -54,6 +59,10 @@ Status error(const std::string& msg) { return Status::fromExceptionCode(Status::EX_NONE, msg.c_str()); } +PolicyBitmask ConvertAidlArgToPolicyBitmask(int32_t arg) { + return static_cast<PolicyBitmask>(arg); +} + } // namespace namespace android::os { @@ -78,6 +87,8 @@ Status Idmap2Service::removeIdmap(const std::string& overlay_apk_path, } Status Idmap2Service::verifyIdmap(const std::string& overlay_apk_path, + int32_t fulfilled_policies ATTRIBUTE_UNUSED, + bool enforce_overlayable ATTRIBUTE_UNUSED, int32_t user_id ATTRIBUTE_UNUSED, bool* _aidl_return) { assert(_aidl_return); const std::string idmap_path = Idmap::CanonicalIdmapPathFor(kIdmapCacheDir, overlay_apk_path); @@ -86,11 +97,15 @@ Status Idmap2Service::verifyIdmap(const std::string& overlay_apk_path, fin.close(); std::stringstream dev_null; *_aidl_return = header && header->IsUpToDate(dev_null); + + // TODO(b/119328308): Check that the set of fulfilled policies of the overlay has not changed + return ok(); } Status Idmap2Service::createIdmap(const std::string& target_apk_path, - const std::string& overlay_apk_path, int32_t user_id, + const std::string& overlay_apk_path, int32_t fulfilled_policies, + bool enforce_overlayable, int32_t user_id, std::unique_ptr<std::string>* _aidl_return) { assert(_aidl_return); std::stringstream trace; @@ -101,6 +116,8 @@ Status Idmap2Service::createIdmap(const std::string& target_apk_path, _aidl_return->reset(nullptr); + const PolicyBitmask policy_bitmask = ConvertAidlArgToPolicyBitmask(fulfilled_policies); + const std::unique_ptr<const ApkAssets> target_apk = ApkAssets::Load(target_apk_path); if (!target_apk) { return error("failed to load apk " + target_apk_path); @@ -113,7 +130,8 @@ Status Idmap2Service::createIdmap(const std::string& target_apk_path, std::stringstream err; const std::unique_ptr<const Idmap> idmap = - Idmap::FromApkAssets(target_apk_path, *target_apk, overlay_apk_path, *overlay_apk, err); + Idmap::FromApkAssets(target_apk_path, *target_apk, overlay_apk_path, *overlay_apk, + policy_bitmask, enforce_overlayable, err); if (!idmap) { return error(err.str()); } diff --git a/cmds/idmap2/idmap2d/Idmap2Service.h b/cmds/idmap2/idmap2d/Idmap2Service.h index e0bc22e9e9e6..1aab0598449b 100644 --- a/cmds/idmap2/idmap2d/Idmap2Service.h +++ b/cmds/idmap2/idmap2d/Idmap2Service.h @@ -39,11 +39,12 @@ class Idmap2Service : public BinderService<Idmap2Service>, public BnIdmap2 { binder::Status removeIdmap(const std::string& overlay_apk_path, int32_t user_id, bool* _aidl_return); - binder::Status verifyIdmap(const std::string& overlay_apk_path, int32_t user_id, - bool* _aidl_return); + binder::Status verifyIdmap(const std::string& overlay_apk_path, int32_t fulfilled_policies, + bool enforce_overlayable, int32_t user_id, bool* _aidl_return); binder::Status createIdmap(const std::string& target_apk_path, - const std::string& overlay_apk_path, int32_t user_id, + const std::string& overlay_apk_path, int32_t fulfilled_policies, + bool enforce_overlayable, int32_t user_id, std::unique_ptr<std::string>* _aidl_return); }; diff --git a/cmds/idmap2/idmap2d/aidl/android/os/IIdmap2.aidl b/cmds/idmap2/idmap2d/aidl/android/os/IIdmap2.aidl index d475417a0935..ea7274f3ea58 100644 --- a/cmds/idmap2/idmap2d/aidl/android/os/IIdmap2.aidl +++ b/cmds/idmap2/idmap2d/aidl/android/os/IIdmap2.aidl @@ -20,9 +20,18 @@ package android.os; * @hide */ interface IIdmap2 { + const int POLICY_PUBLIC = 0x00000001; + const int POLICY_SYSTEM_PARTITION = 0x00000002; + const int POLICY_VENDOR_PARTITION = 0x00000004; + const int POLICY_PRODUCT_PARTITION = 0x00000008; + @utf8InCpp String getIdmapPath(@utf8InCpp String overlayApkPath, int userId); boolean removeIdmap(@utf8InCpp String overlayApkPath, int userId); - boolean verifyIdmap(@utf8InCpp String overlayApkPath, int userId); + boolean verifyIdmap(@utf8InCpp String overlayApkPath, int fulfilledPolicies, + boolean enforceOverlayable, int userId); @nullable @utf8InCpp String createIdmap(@utf8InCpp String targetApkPath, - @utf8InCpp String overlayApkPath, int userId); + @utf8InCpp String overlayApkPath, + int fulfilledPolicies, + boolean enforceOverlayable, + int userId); } diff --git a/cmds/idmap2/include/idmap2/CommandLineOptions.h b/cmds/idmap2/include/idmap2/CommandLineOptions.h index b93e71631d08..6db6bf9ea8ad 100644 --- a/cmds/idmap2/include/idmap2/CommandLineOptions.h +++ b/cmds/idmap2/include/idmap2/CommandLineOptions.h @@ -44,6 +44,8 @@ class CommandLineOptions { std::vector<std::string>* value); CommandLineOptions& OptionalOption(const std::string& name, const std::string& description, std::string* value); + CommandLineOptions& OptionalOption(const std::string& name, const std::string& description, + std::vector<std::string>* value); bool Parse(const std::vector<std::string>& argv, std::ostream& outError) const; void Usage(std::ostream& out) const; @@ -56,6 +58,7 @@ class CommandLineOptions { COUNT_OPTIONAL, COUNT_EXACTLY_ONCE, COUNT_ONCE_OR_MORE, + COUNT_OPTIONAL_ONCE_OR_MORE, } count; bool argument; }; diff --git a/cmds/idmap2/include/idmap2/Idmap.h b/cmds/idmap2/include/idmap2/Idmap.h index b989e4c3f9d1..1666dc8a3bbd 100644 --- a/cmds/idmap2/include/idmap2/Idmap.h +++ b/cmds/idmap2/include/idmap2/Idmap.h @@ -57,6 +57,8 @@ #include "androidfw/ResourceTypes.h" #include "androidfw/StringPiece.h" +#include "idmap2/Policies.h" + namespace android::idmap2 { class Idmap; @@ -233,11 +235,10 @@ class Idmap { // file is used; change this in the next version of idmap to use a named // package instead; also update FromApkAssets to take additional parameters: // the target and overlay package names - static std::unique_ptr<const Idmap> FromApkAssets(const std::string& target_apk_path, - const ApkAssets& target_apk_assets, - const std::string& overlay_apk_path, - const ApkAssets& overlay_apk_assets, - std::ostream& out_error); + static std::unique_ptr<const Idmap> FromApkAssets( + const std::string& target_apk_path, const ApkAssets& target_apk_assets, + const std::string& overlay_apk_path, const ApkAssets& overlay_apk_assets, + const PolicyBitmask& fulfilled_policies, bool enforce_overlayable, std::ostream& out_error); inline const std::unique_ptr<const IdmapHeader>& GetHeader() const { return header_; diff --git a/cmds/idmap2/include/idmap2/Policies.h b/cmds/idmap2/include/idmap2/Policies.h new file mode 100644 index 000000000000..eecee25445e2 --- /dev/null +++ b/cmds/idmap2/include/idmap2/Policies.h @@ -0,0 +1,41 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <ostream> +#include <string> +#include <vector> + +#include "androidfw/ResourceTypes.h" +#include "androidfw/StringPiece.h" + +#include "Result.h" + +#ifndef IDMAP2_INCLUDE_IDMAP2_POLICIES_H_ +#define IDMAP2_INCLUDE_IDMAP2_POLICIES_H_ + +namespace android::idmap2 { + +using PolicyFlags = ResTable_overlayable_policy_header::PolicyFlags; +using PolicyBitmask = uint32_t; + +// Parses a the string representation of a set of policies into a bitmask. The format of the string +// is the same as for the <policy> element. +Result<PolicyBitmask> PoliciesToBitmask(const std::vector<std::string>& policies, + std::ostream& err); + +} // namespace android::idmap2 + +#endif // IDMAP2_INCLUDE_IDMAP2_POLICIES_H_ diff --git a/cmds/idmap2/include/idmap2/ResourceUtils.h b/cmds/idmap2/include/idmap2/ResourceUtils.h index 323796b05986..22827ac45f9b 100644 --- a/cmds/idmap2/include/idmap2/ResourceUtils.h +++ b/cmds/idmap2/include/idmap2/ResourceUtils.h @@ -17,6 +17,8 @@ #ifndef IDMAP2_INCLUDE_IDMAP2_RESOURCEUTILS_H_ #define IDMAP2_INCLUDE_IDMAP2_RESOURCEUTILS_H_ +#include <optional> +#include <ostream> #include <string> #include "android-base/macros.h" @@ -24,9 +26,21 @@ #include "idmap2/Idmap.h" #include "idmap2/Result.h" +#include "idmap2/ZipFile.h" namespace android::idmap2::utils { +struct OverlayManifestInfo { + std::string target_package; // NOLINT(misc-non-private-member-variables-in-classes) + std::string target_name; // NOLINT(misc-non-private-member-variables-in-classes) + bool is_static; // NOLINT(misc-non-private-member-variables-in-classes) + int priority = -1; // NOLINT(misc-non-private-member-variables-in-classes) +}; + +Result<OverlayManifestInfo> ExtractOverlayManifestInfo(const std::string& path, + std::ostream& out_error, + bool assert_overlay = true); + Result<std::string> WARN_UNUSED ResToTypeEntryName(const AssetManager2& am, ResourceId resid); } // namespace android::idmap2::utils diff --git a/cmds/idmap2/libidmap2/CommandLineOptions.cpp b/cmds/idmap2/libidmap2/CommandLineOptions.cpp index cabc8f398c46..a49a607091a4 100644 --- a/cmds/idmap2/libidmap2/CommandLineOptions.cpp +++ b/cmds/idmap2/libidmap2/CommandLineOptions.cpp @@ -68,9 +68,18 @@ CommandLineOptions& CommandLineOptions::OptionalOption(const std::string& name, return *this; } +CommandLineOptions& CommandLineOptions::OptionalOption(const std::string& name, + const std::string& description, + std::vector<std::string>* value) { + assert(value != nullptr); + auto func = [value](const std::string& arg) -> void { value->push_back(arg); }; + options_.push_back(Option{name, description, func, Option::COUNT_OPTIONAL_ONCE_OR_MORE, true}); + return *this; +} + bool CommandLineOptions::Parse(const std::vector<std::string>& argv, std::ostream& outError) const { const auto pivot = std::partition(options_.begin(), options_.end(), [](const Option& opt) { - return opt.count != Option::COUNT_OPTIONAL; + return opt.count != Option::COUNT_OPTIONAL && opt.count != Option::COUNT_OPTIONAL_ONCE_OR_MORE; }); std::set<std::string> mandatory_opts; std::transform(options_.begin(), pivot, std::inserter(mandatory_opts, mandatory_opts.end()), @@ -122,7 +131,8 @@ void CommandLineOptions::Usage(std::ostream& out) const { size_t maxLength = 0; out << "usage: " << name_; for (const Option& opt : options_) { - const bool mandatory = opt.count != Option::COUNT_OPTIONAL; + const bool mandatory = + opt.count != Option::COUNT_OPTIONAL && opt.count != Option::COUNT_OPTIONAL_ONCE_OR_MORE; out << " "; if (!mandatory) { out << "["; @@ -134,9 +144,15 @@ void CommandLineOptions::Usage(std::ostream& out) const { out << opt.name; maxLength = std::max(maxLength, opt.name.size()); } + + if (opt.count == Option::COUNT_OPTIONAL_ONCE_OR_MORE) { + out << " [..]"; + } + if (!mandatory) { out << "]"; } + if (opt.count == Option::COUNT_ONCE_OR_MORE) { out << " [" << opt.name << " arg [..]]"; } @@ -150,7 +166,8 @@ void CommandLineOptions::Usage(std::ostream& out) const { out << opt.name; } out << " " << opt.description; - if (opt.count == Option::COUNT_ONCE_OR_MORE) { + if (opt.count == Option::COUNT_ONCE_OR_MORE || + opt.count == Option::COUNT_OPTIONAL_ONCE_OR_MORE) { out << " (can be provided multiple times)"; } out << std::endl; diff --git a/cmds/idmap2/libidmap2/Idmap.cpp b/cmds/idmap2/libidmap2/Idmap.cpp index 37d6af8fa477..5d449e96663e 100644 --- a/cmds/idmap2/libidmap2/Idmap.cpp +++ b/cmds/idmap2/libidmap2/Idmap.cpp @@ -274,11 +274,30 @@ std::unique_ptr<const Idmap> Idmap::FromBinaryStream(std::istream& stream, return std::move(idmap); } -std::unique_ptr<const Idmap> Idmap::FromApkAssets(const std::string& target_apk_path, - const ApkAssets& target_apk_assets, - const std::string& overlay_apk_path, - const ApkAssets& overlay_apk_assets, - std::ostream& out_error) { +bool CheckOverlayable(const LoadedPackage& target_package, + const utils::OverlayManifestInfo& overlay_info, + const PolicyBitmask& fulfilled_polices, const ResourceId& resid) { + const OverlayableInfo* overlayable_info = target_package.GetOverlayableInfo(resid); + if (overlayable_info == nullptr) { + // If the resource does not have an overlayable definition, allow the resource to be overlaid. + // Once overlayable enforcement is turned on, this check will return false. + return true; + } + + if (!overlay_info.target_name.empty() && overlay_info.target_name != overlayable_info->name) { + // If the overlay supplies a target overlayable name, the resource must belong to the + // overlayable defined with the specified name to be overlaid. + return false; + } + + // Enforce policy restrictions if the resource is declared as overlayable. + return (overlayable_info->policy_flags & fulfilled_polices) != 0; +} + +std::unique_ptr<const Idmap> Idmap::FromApkAssets( + const std::string& target_apk_path, const ApkAssets& target_apk_assets, + const std::string& overlay_apk_path, const ApkAssets& overlay_apk_assets, + const PolicyBitmask& fulfilled_policies, bool enforce_overlayable, std::ostream& out_error) { AssetManager2 target_asset_manager; if (!target_asset_manager.SetApkAssets({&target_apk_assets}, true, false)) { out_error << "error: failed to create target asset manager" << std::endl; @@ -327,6 +346,12 @@ std::unique_ptr<const Idmap> Idmap::FromApkAssets(const std::string& target_apk_ return nullptr; } + Result<utils::OverlayManifestInfo> overlay_info = + utils::ExtractOverlayManifestInfo(overlay_apk_path, out_error); + if (!overlay_info) { + return nullptr; + } + std::unique_ptr<IdmapHeader> header(new IdmapHeader()); header->magic_ = kIdmapMagic; header->version_ = kIdmapCurrentVersion; @@ -380,6 +405,14 @@ std::unique_ptr<const Idmap> Idmap::FromApkAssets(const std::string& target_apk_ if (target_resid == 0) { continue; } + + if (enforce_overlayable && + !CheckOverlayable(*target_pkg, *overlay_info, fulfilled_policies, target_resid)) { + LOG(WARNING) << "overlay \"" << overlay_apk_path << "\" is not allowed to overlay resource \"" + << full_name << "\"" << std::endl; + continue; + } + matching_resources.Add(target_resid, overlay_resid); } diff --git a/cmds/idmap2/libidmap2/Policies.cpp b/cmds/idmap2/libidmap2/Policies.cpp new file mode 100644 index 000000000000..0f87ef0c4ea9 --- /dev/null +++ b/cmds/idmap2/libidmap2/Policies.cpp @@ -0,0 +1,57 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <iterator> +#include <map> +#include <sstream> +#include <string> +#include <vector> + +#include "androidfw/ResourceTypes.h" + +#include "idmap2/Idmap.h" +#include "idmap2/Policies.h" +#include "idmap2/Result.h" + +namespace android::idmap2 { + +namespace { + +const std::map<android::StringPiece, PolicyFlags> kStringToFlag = { + {"public", PolicyFlags::POLICY_PUBLIC}, + {"product", PolicyFlags::POLICY_PRODUCT_PARTITION}, + {"system", PolicyFlags::POLICY_SYSTEM_PARTITION}, + {"vendor", PolicyFlags::POLICY_VENDOR_PARTITION}, +}; +} // namespace + +Result<PolicyBitmask> PoliciesToBitmask(const std::vector<std::string>& policies, + std::ostream& err) { + PolicyBitmask bitmask = 0; + for (const std::string& policy : policies) { + const auto iter = kStringToFlag.find(policy); + if (iter != kStringToFlag.end()) { + bitmask |= iter->second; + } else { + err << "error: unknown policy \"" << policy << "\""; + return kResultError; + } + } + + return Result<PolicyBitmask>(bitmask); +} + +} // namespace android::idmap2 diff --git a/cmds/idmap2/libidmap2/ResourceUtils.cpp b/cmds/idmap2/libidmap2/ResourceUtils.cpp index 04e0ec756045..7a984f3f98ad 100644 --- a/cmds/idmap2/libidmap2/ResourceUtils.cpp +++ b/cmds/idmap2/libidmap2/ResourceUtils.cpp @@ -14,6 +14,7 @@ * limitations under the License. */ +#include <memory> #include <string> #include "androidfw/StringPiece.h" @@ -21,8 +22,13 @@ #include "idmap2/ResourceUtils.h" #include "idmap2/Result.h" +#include "idmap2/Xml.h" +#include "idmap2/ZipFile.h" using android::StringPiece16; +using android::idmap2::Result; +using android::idmap2::Xml; +using android::idmap2::ZipFile; using android::util::Utf16ToUtf8; namespace android::idmap2::utils { @@ -47,4 +53,63 @@ Result<std::string> WARN_UNUSED ResToTypeEntryName(const AssetManager2& am, Reso return {out}; } +Result<OverlayManifestInfo> ExtractOverlayManifestInfo(const std::string& path, + std::ostream& out_error, + bool assert_overlay) { + std::unique_ptr<const ZipFile> zip = ZipFile::Open(path); + if (!zip) { + out_error << "error: failed to open " << path << " as a zip file" << std::endl; + return kResultError; + } + + std::unique_ptr<const MemoryChunk> entry = zip->Uncompress("AndroidManifest.xml"); + if (!entry) { + out_error << "error: failed to uncompress AndroidManifest.xml from " << path << std::endl; + return kResultError; + } + + std::unique_ptr<const Xml> xml = Xml::Create(entry->buf, entry->size); + if (!xml) { + out_error << "error: failed to parse AndroidManifest.xml from " << path << std::endl; + return kResultError; + } + + OverlayManifestInfo info{}; + const auto tag = xml->FindTag("overlay"); + if (!tag) { + if (assert_overlay) { + out_error << "error: <overlay> missing from AndroidManifest.xml of " << path << std::endl; + return kResultError; + } + return info; + } + + auto iter = tag->find("targetPackage"); + if (iter == tag->end()) { + if (assert_overlay) { + out_error << "error: android:targetPackage missing from <overlay> of " << path << std::endl; + return kResultError; + } + } else { + info.target_package = iter->second; + } + + iter = tag->find("targetName"); + if (iter != tag->end()) { + info.target_name = iter->second; + } + + iter = tag->find("isStatic"); + if (iter != tag->end()) { + info.is_static = std::stoul(iter->second) != 0U; + } + + iter = tag->find("priority"); + if (iter != tag->end()) { + info.priority = std::stoi(iter->second); + } + + return info; +} + } // namespace android::idmap2::utils diff --git a/cmds/idmap2/tests/BinaryStreamVisitorTests.cpp b/cmds/idmap2/tests/BinaryStreamVisitorTests.cpp index 2698ac0a734d..0e0e25f4f0f3 100644 --- a/cmds/idmap2/tests/BinaryStreamVisitorTests.cpp +++ b/cmds/idmap2/tests/BinaryStreamVisitorTests.cpp @@ -78,7 +78,8 @@ TEST(BinaryStreamVisitorTests, CreateIdmapFromApkAssetsInteropWithLoadedIdmap) { std::stringstream error; std::unique_ptr<const Idmap> idmap = - Idmap::FromApkAssets(target_apk_path, *target_apk, overlay_apk_path, *overlay_apk, error); + Idmap::FromApkAssets(target_apk_path, *target_apk, overlay_apk_path, *overlay_apk, + PolicyFlags::POLICY_PUBLIC, /* enforce_overlayable */ true, error); ASSERT_THAT(idmap, NotNull()); std::stringstream stream; @@ -101,25 +102,55 @@ TEST(BinaryStreamVisitorTests, CreateIdmapFromApkAssetsInteropWithLoadedIdmap) { header = loaded_idmap->GetEntryMapForType(0x02); ASSERT_THAT(header, NotNull()); - success = LoadedIdmap::Lookup(header, 0x0002, &entry); + success = LoadedIdmap::Lookup(header, 0x0000, &entry); // string/a ASSERT_FALSE(success); - success = LoadedIdmap::Lookup(header, 0x0003, &entry); + success = LoadedIdmap::Lookup(header, 0x0001, &entry); // string/b + ASSERT_FALSE(success); + + success = LoadedIdmap::Lookup(header, 0x0002, &entry); // string/c + ASSERT_FALSE(success); + + success = LoadedIdmap::Lookup(header, 0x0003, &entry); // string/other + ASSERT_FALSE(success); + + success = LoadedIdmap::Lookup(header, 0x0004, &entry); // string/not_overlayable + ASSERT_FALSE(success); + + success = LoadedIdmap::Lookup(header, 0x0005, &entry); // string/policy_product + ASSERT_FALSE(success); + + success = LoadedIdmap::Lookup(header, 0x0006, &entry); // string/policy_public + ASSERT_FALSE(success); + + success = LoadedIdmap::Lookup(header, 0x0007, &entry); // string/policy_system + ASSERT_FALSE(success); + + success = LoadedIdmap::Lookup(header, 0x0008, &entry); // string/policy_system_vendor + ASSERT_FALSE(success); + + success = LoadedIdmap::Lookup(header, 0x0009, &entry); // string/str1 ASSERT_TRUE(success); ASSERT_EQ(entry, 0x0000); - success = LoadedIdmap::Lookup(header, 0x0004, &entry); + success = LoadedIdmap::Lookup(header, 0x000a, &entry); // string/str2 ASSERT_FALSE(success); - success = LoadedIdmap::Lookup(header, 0x0005, &entry); + success = LoadedIdmap::Lookup(header, 0x000b, &entry); // string/str3 ASSERT_TRUE(success); ASSERT_EQ(entry, 0x0001); - success = LoadedIdmap::Lookup(header, 0x0006, &entry); + success = LoadedIdmap::Lookup(header, 0x000c, &entry); // string/str4 ASSERT_TRUE(success); ASSERT_EQ(entry, 0x0002); - success = LoadedIdmap::Lookup(header, 0x0007, &entry); + success = LoadedIdmap::Lookup(header, 0x000d, &entry); // string/x + ASSERT_FALSE(success); + + success = LoadedIdmap::Lookup(header, 0x000e, &entry); // string/y + ASSERT_FALSE(success); + + success = LoadedIdmap::Lookup(header, 0x000f, &entry); // string/z ASSERT_FALSE(success); } diff --git a/cmds/idmap2/tests/CommandLineOptionsTests.cpp b/cmds/idmap2/tests/CommandLineOptionsTests.cpp index c27d27a16b94..39f18d3336af 100644 --- a/cmds/idmap2/tests/CommandLineOptionsTests.cpp +++ b/cmds/idmap2/tests/CommandLineOptionsTests.cpp @@ -121,6 +121,56 @@ TEST(CommandLineOptionsTests, OptionalOption) { ASSERT_FALSE(success); } +TEST(CommandLineOptionsTests, OptionalOptionList) { + std::vector<std::string> foo; + std::vector<std::string> bar; + CommandLineOptions opts = CommandLineOptions("test") + .OptionalOption("--foo", "", &foo) + .OptionalOption("--bar", "", &bar); + std::ostream fakeStdErr(nullptr); + bool success = opts.Parse({"--foo", "FOO", "--bar", "BAR"}, fakeStdErr); + ASSERT_TRUE(success); + ASSERT_EQ(foo.size(), 1U); + ASSERT_EQ(foo[0], "FOO"); + ASSERT_EQ(bar.size(), 1U); + ASSERT_EQ(bar[0], "BAR"); + + foo.clear(); + bar.clear(); + success = opts.Parse({"--foo", "BAZ"}, fakeStdErr); + ASSERT_TRUE(success); + ASSERT_EQ(foo.size(), 1U); + ASSERT_EQ(foo[0], "BAZ"); + ASSERT_EQ(bar.size(), 0U); + + foo.clear(); + bar.clear(); + success = + opts.Parse({"--foo", "BAZ", "--foo", "BIZ", "--bar", "FIZ", "--bar", "FUZZ"}, fakeStdErr); + ASSERT_TRUE(success); + ASSERT_EQ(foo.size(), 2U); + ASSERT_EQ(foo[0], "BAZ"); + ASSERT_EQ(foo[1], "BIZ"); + ASSERT_EQ(bar.size(), 2U); + ASSERT_EQ(bar[0], "FIZ"); + ASSERT_EQ(bar[1], "FUZZ"); + + foo.clear(); + bar.clear(); + success = opts.Parse({"--foo"}, fakeStdErr); + ASSERT_FALSE(success); + + foo.clear(); + bar.clear(); + success = opts.Parse({"--foo", "--bar", "BAR"}, fakeStdErr); + ASSERT_FALSE(success); + + foo.clear(); + bar.clear(); + success = opts.Parse({"--foo", "FOO", "--bar"}, fakeStdErr); + ASSERT_FALSE(success); +} + TEST(CommandLineOptionsTests, CornerCases) { std::string foo; std::string bar; @@ -172,6 +222,7 @@ TEST(CommandLineOptionsTests, Usage) { bool arg5 = false; bool arg6 = false; std::vector<std::string> arg7; + std::vector<std::string> arg8; CommandLineOptions opts = CommandLineOptions("test") .MandatoryOption("--aa", "description-aa", &arg1) .OptionalFlag("--bb", "description-bb", &arg5) @@ -179,12 +230,13 @@ TEST(CommandLineOptionsTests, Usage) { .OptionalOption("--dd", "description-dd", &arg3) .MandatoryOption("--ee", "description-ee", &arg4) .OptionalFlag("--ff", "description-ff", &arg6) - .MandatoryOption("--gg", "description-gg", &arg7); + .MandatoryOption("--gg", "description-gg", &arg7) + .OptionalOption("--hh", "description-hh", &arg8); std::stringstream stream; opts.Usage(stream); const std::string s = stream.str(); ASSERT_NE(s.find("usage: test --aa arg [--bb] [--cc arg] [--dd arg] --ee arg [--ff] --gg arg " - "[--gg arg [..]]"), + "[--gg arg [..]] [--hh arg [..]]"), std::string::npos); ASSERT_NE(s.find("--aa arg description-aa"), std::string::npos); ASSERT_NE(s.find("--ff description-ff"), std::string::npos); diff --git a/cmds/idmap2/tests/FileUtilsTests.cpp b/cmds/idmap2/tests/FileUtilsTests.cpp index 4bf832a34691..d9d9a7f829cf 100644 --- a/cmds/idmap2/tests/FileUtilsTests.cpp +++ b/cmds/idmap2/tests/FileUtilsTests.cpp @@ -37,10 +37,10 @@ TEST(FileUtilsTests, FindFilesFindEverythingNonRecursive) { [](unsigned char type ATTRIBUTE_UNUSED, const std::string& path ATTRIBUTE_UNUSED) -> bool { return true; }); ASSERT_THAT(v, NotNull()); - ASSERT_EQ(v->size(), 4U); - ASSERT_EQ( - std::set<std::string>(v->begin(), v->end()), - std::set<std::string>({root + "/.", root + "/..", root + "/overlay", root + "/target"})); + ASSERT_EQ(v->size(), 6U); + ASSERT_EQ(std::set<std::string>(v->begin(), v->end()), + std::set<std::string>({root + "/.", root + "/..", root + "/overlay", root + "/target", + root + "/system-overlay", root + "/system-overlay-invalid"})); } TEST(FileUtilsTests, FindFilesFindApkFilesRecursive) { @@ -49,11 +49,13 @@ TEST(FileUtilsTests, FindFilesFindApkFilesRecursive) { return type == DT_REG && path.size() > 4 && path.compare(path.size() - 4, 4, ".apk") == 0; }); ASSERT_THAT(v, NotNull()); - ASSERT_EQ(v->size(), 4U); + ASSERT_EQ(v->size(), 6U); ASSERT_EQ(std::set<std::string>(v->begin(), v->end()), std::set<std::string>({root + "/target/target.apk", root + "/overlay/overlay.apk", root + "/overlay/overlay-static-1.apk", - root + "/overlay/overlay-static-2.apk"})); + root + "/overlay/overlay-static-2.apk", + root + "/system-overlay/system-overlay.apk", + root + "/system-overlay-invalid/system-overlay-invalid.apk"})); } TEST(FileUtilsTests, ReadFile) { diff --git a/cmds/idmap2/tests/Idmap2BinaryTests.cpp b/cmds/idmap2/tests/Idmap2BinaryTests.cpp index 22f48e9a396f..4334fa60767b 100644 --- a/cmds/idmap2/tests/Idmap2BinaryTests.cpp +++ b/cmds/idmap2/tests/Idmap2BinaryTests.cpp @@ -38,6 +38,7 @@ #include "gtest/gtest.h" #include "androidfw/PosixUtils.h" + #include "idmap2/FileUtils.h" #include "idmap2/Idmap.h" @@ -114,8 +115,9 @@ TEST_F(Idmap2BinaryTests, Dump) { ASSERT_THAT(result, NotNull()); ASSERT_EQ(result->status, EXIT_SUCCESS) << result->stderr; ASSERT_NE(result->stdout.find("0x7f010000 -> 0x7f010000 integer/int1"), std::string::npos); - ASSERT_NE(result->stdout.find("0x7f020003 -> 0x7f020000 string/str1"), std::string::npos); - ASSERT_NE(result->stdout.find("0x7f020005 -> 0x7f020001 string/str3"), std::string::npos); + ASSERT_NE(result->stdout.find("0x7f020009 -> 0x7f020000 string/str1"), std::string::npos); + ASSERT_NE(result->stdout.find("0x7f02000b -> 0x7f020001 string/str3"), std::string::npos); + ASSERT_NE(result->stdout.find("0x7f02000c -> 0x7f020002 string/str4"), std::string::npos); ASSERT_EQ(result->stdout.find("00000210: 007f target package id"), std::string::npos); // clang-format off @@ -157,7 +159,8 @@ TEST_F(Idmap2BinaryTests, Scan) { "--recursive", "--target-package-name", "test.target", "--target-apk-path", GetTargetApkPath(), - "--output-directory", GetTempDirPath()}); + "--output-directory", GetTempDirPath(), + "--override-policy", "public"}); // clang-format on ASSERT_THAT(result, NotNull()); ASSERT_EQ(result->status, EXIT_SUCCESS) << result->stderr; @@ -190,7 +193,8 @@ TEST_F(Idmap2BinaryTests, Scan) { "--input-directory", GetTestDataPath() + "/overlay", "--target-package-name", "test.target", "--target-apk-path", GetTargetApkPath(), - "--output-directory", GetTempDirPath()}); + "--output-directory", GetTempDirPath(), + "--override-policy", "public"}); // clang-format on ASSERT_THAT(result, NotNull()); ASSERT_EQ(result->status, EXIT_SUCCESS) << result->stderr; @@ -207,7 +211,8 @@ TEST_F(Idmap2BinaryTests, Scan) { "--recursive", "--target-package-name", "test.target", "--target-apk-path", GetTargetApkPath(), - "--output-directory", GetTempDirPath()}); + "--output-directory", GetTempDirPath(), + "--override-policy", "public"}); // clang-format on ASSERT_THAT(result, NotNull()); ASSERT_EQ(result->status, EXIT_SUCCESS) << result->stderr; @@ -222,7 +227,8 @@ TEST_F(Idmap2BinaryTests, Scan) { "--input-directory", GetTempDirPath(), "--target-package-name", "test.target", "--target-apk-path", GetTargetApkPath(), - "--output-directory", GetTempDirPath()}); + "--output-directory", GetTempDirPath(), + "--override-policy", "public"}); // clang-format on ASSERT_THAT(result, NotNull()); ASSERT_EQ(result->status, EXIT_SUCCESS) << result->stderr; @@ -245,7 +251,7 @@ TEST_F(Idmap2BinaryTests, Lookup) { "lookup", "--idmap-path", GetIdmapPath(), "--config", "", - "--resid", "0x7f020003"}); // string/str1 + "--resid", "0x7f020009"}); // string/str1 // clang-format on ASSERT_THAT(result, NotNull()); ASSERT_EQ(result->status, EXIT_SUCCESS) << result->stderr; @@ -310,6 +316,18 @@ TEST_F(Idmap2BinaryTests, InvalidCommandLineOptions) { // clang-format on ASSERT_THAT(result, NotNull()); ASSERT_NE(result->status, EXIT_SUCCESS); + + // unknown policy + // clang-format off + result = ExecuteBinary({"idmap2", + "create", + "--target-apk-path", GetTargetApkPath(), + "--overlay-apk-path", GetOverlayApkPath(), + "--idmap-path", GetIdmapPath(), + "--policy", "this-does-not-exist"}); + // clang-format on + ASSERT_THAT(result, NotNull()); + ASSERT_NE(result->status, EXIT_SUCCESS); } } // namespace android::idmap2 diff --git a/cmds/idmap2/tests/IdmapTests.cpp b/cmds/idmap2/tests/IdmapTests.cpp index 963f22ec8d72..df28918ac9b4 100644 --- a/cmds/idmap2/tests/IdmapTests.cpp +++ b/cmds/idmap2/tests/IdmapTests.cpp @@ -184,13 +184,14 @@ TEST(IdmapTests, CreateIdmapFromApkAssets) { std::stringstream error; std::unique_ptr<const Idmap> idmap = - Idmap::FromApkAssets(target_apk_path, *target_apk, overlay_apk_path, *overlay_apk, error); + Idmap::FromApkAssets(target_apk_path, *target_apk, overlay_apk_path, *overlay_apk, + PolicyFlags::POLICY_PUBLIC, /* enforce_overlayable */ true, error); ASSERT_THAT(idmap, NotNull()); ASSERT_THAT(idmap->GetHeader(), NotNull()); ASSERT_EQ(idmap->GetHeader()->GetMagic(), 0x504d4449U); ASSERT_EQ(idmap->GetHeader()->GetVersion(), 0x01U); - ASSERT_EQ(idmap->GetHeader()->GetTargetCrc(), 0xf5ad1d1d); + ASSERT_EQ(idmap->GetHeader()->GetTargetCrc(), 0xab7cf70d); ASSERT_EQ(idmap->GetHeader()->GetOverlayCrc(), 0xd470336b); ASSERT_EQ(idmap->GetHeader()->GetTargetPath().to_string(), target_apk_path); ASSERT_EQ(idmap->GetHeader()->GetOverlayPath(), overlay_apk_path); @@ -216,13 +217,129 @@ TEST(IdmapTests, CreateIdmapFromApkAssets) { ASSERT_EQ(types[1]->GetTargetTypeId(), 0x02U); ASSERT_EQ(types[1]->GetOverlayTypeId(), 0x02U); ASSERT_EQ(types[1]->GetEntryCount(), 4U); - ASSERT_EQ(types[1]->GetEntryOffset(), 3U); + ASSERT_EQ(types[1]->GetEntryOffset(), 9U); ASSERT_EQ(types[1]->GetEntry(0), 0x0000U); ASSERT_EQ(types[1]->GetEntry(1), kNoEntry); ASSERT_EQ(types[1]->GetEntry(2), 0x0001U); ASSERT_EQ(types[1]->GetEntry(3), 0x0002U); } +TEST(IdmapTests, CreateIdmapFromApkAssetsPolicySystemPublic) { + const std::string target_apk_path(GetTestDataPath() + "/target/target.apk"); + std::unique_ptr<const ApkAssets> target_apk = ApkAssets::Load(target_apk_path); + ASSERT_THAT(target_apk, NotNull()); + + const std::string overlay_apk_path(GetTestDataPath() + "/system-overlay/system-overlay.apk"); + std::unique_ptr<const ApkAssets> overlay_apk = ApkAssets::Load(overlay_apk_path); + ASSERT_THAT(overlay_apk, NotNull()); + + std::stringstream error; + std::unique_ptr<const Idmap> idmap = + Idmap::FromApkAssets(target_apk_path, *target_apk, overlay_apk_path, *overlay_apk, + PolicyFlags::POLICY_SYSTEM_PARTITION | PolicyFlags::POLICY_PUBLIC, + /* enforce_overlayable */ true, error); + ASSERT_THAT(idmap, NotNull()); + + const std::vector<std::unique_ptr<const IdmapData>>& dataBlocks = idmap->GetData(); + ASSERT_EQ(dataBlocks.size(), 1U); + + const std::unique_ptr<const IdmapData>& data = dataBlocks[0]; + + ASSERT_EQ(data->GetHeader()->GetTargetPackageId(), 0x7fU); + ASSERT_EQ(data->GetHeader()->GetTypeCount(), 1U); + + const std::vector<std::unique_ptr<const IdmapData::TypeEntry>>& types = data->GetTypeEntries(); + ASSERT_EQ(types.size(), 1U); + + ASSERT_EQ(types[0]->GetTargetTypeId(), 0x02U); + ASSERT_EQ(types[0]->GetOverlayTypeId(), 0x01U); + ASSERT_EQ(types[0]->GetEntryCount(), 3U); + ASSERT_EQ(types[0]->GetEntryOffset(), 6U); + ASSERT_EQ(types[0]->GetEntry(0), 0x0000U); // string/policy_public + ASSERT_EQ(types[0]->GetEntry(1), 0x0001U); // string/policy_system + ASSERT_EQ(types[0]->GetEntry(2), 0x0002U); // string/policy_system_vendor +} + +TEST(IdmapTests, CreateIdmapFromApkAssetsPolicySystemPublicInvalid) { + const std::string target_apk_path(GetTestDataPath() + "/target/target.apk"); + std::unique_ptr<const ApkAssets> target_apk = ApkAssets::Load(target_apk_path); + ASSERT_THAT(target_apk, NotNull()); + + const std::string overlay_apk_path(GetTestDataPath() + + "/system-overlay-invalid/system-overlay-invalid.apk"); + std::unique_ptr<const ApkAssets> overlay_apk = ApkAssets::Load(overlay_apk_path); + ASSERT_THAT(overlay_apk, NotNull()); + + std::stringstream error; + std::unique_ptr<const Idmap> idmap = + Idmap::FromApkAssets(target_apk_path, *target_apk, overlay_apk_path, *overlay_apk, + PolicyFlags::POLICY_SYSTEM_PARTITION | PolicyFlags::POLICY_PUBLIC, + /* enforce_overlayable */ true, error); + ASSERT_THAT(idmap, NotNull()); + + const std::vector<std::unique_ptr<const IdmapData>>& dataBlocks = idmap->GetData(); + ASSERT_EQ(dataBlocks.size(), 1U); + + const std::unique_ptr<const IdmapData>& data = dataBlocks[0]; + + ASSERT_EQ(data->GetHeader()->GetTargetPackageId(), 0x7fU); + ASSERT_EQ(data->GetHeader()->GetTypeCount(), 1U); + + const std::vector<std::unique_ptr<const IdmapData::TypeEntry>>& types = data->GetTypeEntries(); + ASSERT_EQ(types.size(), 1U); + + ASSERT_EQ(types[0]->GetTargetTypeId(), 0x02U); + ASSERT_EQ(types[0]->GetOverlayTypeId(), 0x01U); + ASSERT_EQ(types[0]->GetEntryCount(), 6U); + ASSERT_EQ(types[0]->GetEntryOffset(), 3U); + ASSERT_EQ(types[0]->GetEntry(0), 0x0000U); // string/not_overlayable + ASSERT_EQ(types[0]->GetEntry(1), kNoEntry); // string/other + ASSERT_EQ(types[0]->GetEntry(2), kNoEntry); // string/policy_product + ASSERT_EQ(types[0]->GetEntry(3), 0x0003U); // string/policy_public + ASSERT_EQ(types[0]->GetEntry(4), 0x0004U); // string/policy_system + ASSERT_EQ(types[0]->GetEntry(5), 0x0005U); // string/policy_system_vendor +} + +TEST(IdmapTests, CreateIdmapFromApkAssetsPolicySystemPublicInvalidIgnoreOverlayable) { + const std::string target_apk_path(GetTestDataPath() + "/target/target.apk"); + std::unique_ptr<const ApkAssets> target_apk = ApkAssets::Load(target_apk_path); + ASSERT_THAT(target_apk, NotNull()); + + const std::string overlay_apk_path(GetTestDataPath() + + "/system-overlay-invalid/system-overlay-invalid.apk"); + std::unique_ptr<const ApkAssets> overlay_apk = ApkAssets::Load(overlay_apk_path); + ASSERT_THAT(overlay_apk, NotNull()); + + std::stringstream error; + std::unique_ptr<const Idmap> idmap = + Idmap::FromApkAssets(target_apk_path, *target_apk, overlay_apk_path, *overlay_apk, + PolicyFlags::POLICY_SYSTEM_PARTITION | PolicyFlags::POLICY_PUBLIC, + /* enforce_overlayable */ false, error); + ASSERT_THAT(idmap, NotNull()); + + const std::vector<std::unique_ptr<const IdmapData>>& dataBlocks = idmap->GetData(); + ASSERT_EQ(dataBlocks.size(), 1U); + + const std::unique_ptr<const IdmapData>& data = dataBlocks[0]; + + ASSERT_EQ(data->GetHeader()->GetTargetPackageId(), 0x7fU); + ASSERT_EQ(data->GetHeader()->GetTypeCount(), 1U); + + const std::vector<std::unique_ptr<const IdmapData::TypeEntry>>& types = data->GetTypeEntries(); + ASSERT_EQ(types.size(), 1U); + + ASSERT_EQ(types[0]->GetTargetTypeId(), 0x02U); + ASSERT_EQ(types[0]->GetOverlayTypeId(), 0x01U); + ASSERT_EQ(types[0]->GetEntryCount(), 6U); + ASSERT_EQ(types[0]->GetEntryOffset(), 3U); + ASSERT_EQ(types[0]->GetEntry(0), 0x0000U); // string/not_overlayable + ASSERT_EQ(types[0]->GetEntry(1), 0x0001U); // string/other + ASSERT_EQ(types[0]->GetEntry(2), 0x0002U); // string/policy_product + ASSERT_EQ(types[0]->GetEntry(3), 0x0003U); // string/policy_public + ASSERT_EQ(types[0]->GetEntry(4), 0x0004U); // string/policy_system + ASSERT_EQ(types[0]->GetEntry(5), 0x0005U); // string/policy_system_vendor +} + TEST(IdmapTests, FailToCreateIdmapFromApkAssetsIfPathTooLong) { std::string target_apk_path(GetTestDataPath()); for (int i = 0; i < 32; i++) { @@ -239,7 +356,8 @@ TEST(IdmapTests, FailToCreateIdmapFromApkAssetsIfPathTooLong) { std::stringstream error; std::unique_ptr<const Idmap> idmap = - Idmap::FromApkAssets(target_apk_path, *target_apk, overlay_apk_path, *overlay_apk, error); + Idmap::FromApkAssets(target_apk_path, *target_apk, overlay_apk_path, *overlay_apk, + PolicyFlags::POLICY_PUBLIC, /* enforce_overlayable */ true, error); ASSERT_THAT(idmap, IsNull()); } @@ -255,8 +373,9 @@ TEST(IdmapTests, IdmapHeaderIsUpToDate) { ASSERT_THAT(overlay_apk, NotNull()); std::stringstream error; - std::unique_ptr<const Idmap> idmap = - Idmap::FromApkAssets(target_apk_path, *target_apk, overlay_apk_path, *overlay_apk, error); + std::unique_ptr<const Idmap> idmap = Idmap::FromApkAssets( + target_apk_path, *target_apk, overlay_apk_path, *overlay_apk, PolicyFlags::POLICY_PUBLIC, + /* enforce_overlayable */ true, error); ASSERT_THAT(idmap, NotNull()); std::stringstream stream; diff --git a/cmds/idmap2/tests/PoliciesTests.cpp b/cmds/idmap2/tests/PoliciesTests.cpp new file mode 100644 index 000000000000..ab567adc6f19 --- /dev/null +++ b/cmds/idmap2/tests/PoliciesTests.cpp @@ -0,0 +1,70 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <string> + +#include "gtest/gtest.h" + +#include "TestHelpers.h" +#include "idmap2/Policies.h" + +using android::idmap2::PolicyBitmask; +using android::idmap2::PolicyFlags; + +namespace android::idmap2 { + +TEST(PoliciesTests, PoliciesToBitmasks) { + const Result<PolicyBitmask> bitmask1 = PoliciesToBitmask({"system"}, std::cerr); + ASSERT_NE(bitmask1, kResultError); + ASSERT_EQ(bitmask1, PolicyFlags::POLICY_SYSTEM_PARTITION); + + const Result<PolicyBitmask> bitmask2 = PoliciesToBitmask({"system", "vendor"}, std::cerr); + ASSERT_NE(bitmask2, kResultError); + ASSERT_EQ(bitmask2, PolicyFlags::POLICY_SYSTEM_PARTITION | PolicyFlags::POLICY_VENDOR_PARTITION); + + const Result<PolicyBitmask> bitmask3 = PoliciesToBitmask({"vendor", "system"}, std::cerr); + ASSERT_NE(bitmask3, kResultError); + ASSERT_EQ(bitmask3, PolicyFlags::POLICY_SYSTEM_PARTITION | PolicyFlags::POLICY_VENDOR_PARTITION); + + const Result<PolicyBitmask> bitmask4 = + PoliciesToBitmask({"public", "product", "system", "vendor"}, std::cerr); + ASSERT_NE(bitmask4, kResultError); + ASSERT_EQ(bitmask4, PolicyFlags::POLICY_PUBLIC | PolicyFlags::POLICY_PRODUCT_PARTITION | + PolicyFlags::POLICY_SYSTEM_PARTITION | + PolicyFlags::POLICY_VENDOR_PARTITION); + + const Result<PolicyBitmask> bitmask5 = + PoliciesToBitmask({"system", "system", "system"}, std::cerr); + ASSERT_NE(bitmask5, kResultError); + ASSERT_EQ(bitmask5, PolicyFlags::POLICY_SYSTEM_PARTITION); + + const Result<PolicyBitmask> bitmask6 = PoliciesToBitmask({""}, std::cerr); + ASSERT_EQ(bitmask6, kResultError); + + const Result<PolicyBitmask> bitmask7 = PoliciesToBitmask({"foo"}, std::cerr); + ASSERT_EQ(bitmask7, kResultError); + + const Result<PolicyBitmask> bitmask8 = PoliciesToBitmask({"system", "foo"}, std::cerr); + ASSERT_EQ(bitmask8, kResultError); + + const Result<PolicyBitmask> bitmask9 = PoliciesToBitmask({"system", ""}, std::cerr); + ASSERT_EQ(bitmask9, kResultError); + + const Result<PolicyBitmask> bitmask10 = PoliciesToBitmask({"system "}, std::cerr); + ASSERT_EQ(bitmask10, kResultError); +} + +} // namespace android::idmap2 diff --git a/cmds/idmap2/tests/PrettyPrintVisitorTests.cpp b/cmds/idmap2/tests/PrettyPrintVisitorTests.cpp index 7736bc063131..eaa47cd79533 100644 --- a/cmds/idmap2/tests/PrettyPrintVisitorTests.cpp +++ b/cmds/idmap2/tests/PrettyPrintVisitorTests.cpp @@ -25,6 +25,7 @@ #include "androidfw/Idmap.h" #include "idmap2/Idmap.h" +#include "idmap2/Policies.h" #include "idmap2/PrettyPrintVisitor.h" #include "TestHelpers.h" @@ -32,6 +33,7 @@ using ::testing::NotNull; using android::ApkAssets; +using android::idmap2::PolicyBitmask; namespace android::idmap2 { @@ -46,7 +48,8 @@ TEST(PrettyPrintVisitorTests, CreatePrettyPrintVisitor) { std::stringstream error; std::unique_ptr<const Idmap> idmap = - Idmap::FromApkAssets(target_apk_path, *target_apk, overlay_apk_path, *overlay_apk, error); + Idmap::FromApkAssets(target_apk_path, *target_apk, overlay_apk_path, *overlay_apk, + PolicyFlags::POLICY_PUBLIC, /* enforce_overlayable */ true, error); ASSERT_THAT(idmap, NotNull()); std::stringstream stream; diff --git a/cmds/idmap2/tests/RawPrintVisitorTests.cpp b/cmds/idmap2/tests/RawPrintVisitorTests.cpp index 0318cd20a9bb..b1ca12557dcb 100644 --- a/cmds/idmap2/tests/RawPrintVisitorTests.cpp +++ b/cmds/idmap2/tests/RawPrintVisitorTests.cpp @@ -42,7 +42,8 @@ TEST(RawPrintVisitorTests, CreateRawPrintVisitor) { std::stringstream error; std::unique_ptr<const Idmap> idmap = - Idmap::FromApkAssets(target_apk_path, *target_apk, overlay_apk_path, *overlay_apk, error); + Idmap::FromApkAssets(target_apk_path, *target_apk, overlay_apk_path, *overlay_apk, + PolicyFlags::POLICY_PUBLIC, /* enforce_overlayable */ true, error); ASSERT_THAT(idmap, NotNull()); std::stringstream stream; @@ -51,7 +52,7 @@ TEST(RawPrintVisitorTests, CreateRawPrintVisitor) { ASSERT_NE(stream.str().find("00000000: 504d4449 magic\n"), std::string::npos); ASSERT_NE(stream.str().find("00000004: 00000001 version\n"), std::string::npos); - ASSERT_NE(stream.str().find("00000008: f5ad1d1d target crc\n"), std::string::npos); + ASSERT_NE(stream.str().find("00000008: ab7cf70d target crc\n"), std::string::npos); ASSERT_NE(stream.str().find("0000000c: d470336b overlay crc\n"), std::string::npos); ASSERT_NE(stream.str().find("0000021c: 00000000 0x7f010000 -> 0x7f010000 integer/int1\n"), std::string::npos); diff --git a/cmds/idmap2/tests/data/system-overlay-invalid/AndroidManifest.xml b/cmds/idmap2/tests/data/system-overlay-invalid/AndroidManifest.xml new file mode 100644 index 000000000000..ae687d375e7f --- /dev/null +++ b/cmds/idmap2/tests/data/system-overlay-invalid/AndroidManifest.xml @@ -0,0 +1,22 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 2019 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> +<manifest + xmlns:android="http://schemas.android.com/apk/res/android" + package="test.overlay.system.invalid"> + <overlay + android:targetPackage="test.target" + android:targetName="TestResources"/> +</manifest> diff --git a/cmds/idmap2/tests/data/system-overlay-invalid/build b/cmds/idmap2/tests/data/system-overlay-invalid/build new file mode 100644 index 000000000000..920e1f8ad6f3 --- /dev/null +++ b/cmds/idmap2/tests/data/system-overlay-invalid/build @@ -0,0 +1,26 @@ +# Copyright (C) 2019 The Android Open Source Project +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +FRAMEWORK_RES_APK=${ANDROID_BUILD_TOP}/prebuilts/sdk/current/public/android.jar + +aapt2 compile --dir res -o compiled.flata + +aapt2 link \ + --no-resource-removal \ + -I "$FRAMEWORK_RES_APK" \ + --manifest AndroidManifest.xml \ + -o system-overlay-invalid.apk \ + compiled.flata + +rm compiled.flata diff --git a/cmds/idmap2/tests/data/system-overlay-invalid/res/values/values.xml b/cmds/idmap2/tests/data/system-overlay-invalid/res/values/values.xml new file mode 100644 index 000000000000..af1bea16daee --- /dev/null +++ b/cmds/idmap2/tests/data/system-overlay-invalid/res/values/values.xml @@ -0,0 +1,32 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 2019 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> +<resources> + <!-- This overlay will fulfill the policies "public|system". This allows it overlay the + following resources. --> + <string name="policy_system">policy_system</string> + <string name="policy_system_vendor">policy_system_vendor</string> + <string name="policy_public">policy_public</string> + + <!-- Requests to overlay a resource that belongs to a policy the overlay does not fulfill. --> + <string name="policy_product">policy_product</string> + + <!-- Requests to overlay a resource that is not declared as overlayable. --> + <string name="not_overlayable">not_overlayable</string> + + <!-- Requests to overlay a resource that is defined in an overlayable with a name other than + the targetName in the manifest. --> + <string name="other">other</string> +</resources> diff --git a/cmds/idmap2/tests/data/system-overlay-invalid/system-overlay-invalid.apk b/cmds/idmap2/tests/data/system-overlay-invalid/system-overlay-invalid.apk Binary files differnew file mode 100644 index 000000000000..710ed9067f69 --- /dev/null +++ b/cmds/idmap2/tests/data/system-overlay-invalid/system-overlay-invalid.apk diff --git a/cmds/idmap2/tests/data/system-overlay/AndroidManifest.xml b/cmds/idmap2/tests/data/system-overlay/AndroidManifest.xml new file mode 100644 index 000000000000..8af9064ba64f --- /dev/null +++ b/cmds/idmap2/tests/data/system-overlay/AndroidManifest.xml @@ -0,0 +1,21 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 2019 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> +<manifest + xmlns:android="http://schemas.android.com/apk/res/android" + package="test.overlay.system"> + <overlay + android:targetPackage="test.target" /> +</manifest> diff --git a/cmds/idmap2/tests/data/system-overlay/build b/cmds/idmap2/tests/data/system-overlay/build new file mode 100644 index 000000000000..be0d2390f535 --- /dev/null +++ b/cmds/idmap2/tests/data/system-overlay/build @@ -0,0 +1,26 @@ +# Copyright (C) 2019 The Android Open Source Project +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +FRAMEWORK_RES_APK=${ANDROID_BUILD_TOP}/prebuilts/sdk/current/public/android.jar + +aapt2 compile --dir res -o compiled.flata + +aapt2 link \ + --no-resource-removal \ + -I "$FRAMEWORK_RES_APK" \ + --manifest AndroidManifest.xml \ + -o system-overlay.apk \ + compiled.flata + +rm compiled.flata diff --git a/cmds/idmap2/tests/data/system-overlay/res/values/values.xml b/cmds/idmap2/tests/data/system-overlay/res/values/values.xml new file mode 100644 index 000000000000..6aaa0b02639e --- /dev/null +++ b/cmds/idmap2/tests/data/system-overlay/res/values/values.xml @@ -0,0 +1,22 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 2019 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> +<resources> + <!-- This overlay will fulfill the policies "public|system". This allows it overlay the + following resources. --> + <string name="policy_system">policy_system</string> + <string name="policy_system_vendor">policy_system_vendor</string> + <string name="policy_public">policy_public</string> +</resources> diff --git a/cmds/idmap2/tests/data/system-overlay/system-overlay.apk b/cmds/idmap2/tests/data/system-overlay/system-overlay.apk Binary files differnew file mode 100644 index 000000000000..90f30eb68c15 --- /dev/null +++ b/cmds/idmap2/tests/data/system-overlay/system-overlay.apk diff --git a/cmds/idmap2/tests/data/target/res/values/overlayable.xml b/cmds/idmap2/tests/data/target/res/values/overlayable.xml new file mode 100644 index 000000000000..02d25630546f --- /dev/null +++ b/cmds/idmap2/tests/data/target/res/values/overlayable.xml @@ -0,0 +1,52 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 2019 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> +<resources> +<overlayable name="TestResources"> + <!-- Publicly overlayable resources --> + <item type="string" name="a" /> + <item type="string" name="b" /> + <item type="string" name="c" /> + <item type="string" name="str1" /> + <item type="string" name="str2" /> + <item type="string" name="str3" /> + <item type="string" name="str4" /> + <item type="string" name="x" /> + <item type="string" name="y" /> + <item type="string" name="z" /> + <item type="integer" name="int1" /> + + <!-- Resources with partition restrictins --> + <policy type="system"> + <item type="string" name="policy_system" /> + </policy> + + <policy type="system|vendor"> + <item type="string" name="policy_system_vendor" /> + </policy> + + <policy type="product"> + <item type="string" name="policy_product" /> + </policy> + + <policy type="public"> + <item type="string" name="policy_public" /> + </policy> +</overlayable> + +<overlayable name="OtherResources"> + <item type="string" name="other" /> +</overlayable> +</resources>
\ No newline at end of file diff --git a/cmds/idmap2/tests/data/target/res/values/values.xml b/cmds/idmap2/tests/data/target/res/values/values.xml index 56bf0d60021a..0d337f3890a8 100644 --- a/cmds/idmap2/tests/data/target/res/values/values.xml +++ b/cmds/idmap2/tests/data/target/res/values/values.xml @@ -25,4 +25,14 @@ <string name="y">y</string> <string name="z">z</string> <integer name="int1">1</integer> + + <!-- This resources is not marked as overlayable --> + <string name="not_overlayable">not_overlayable</string> + + <string name="policy_system">policy_system</string> + <string name="policy_system_vendor">policy_system_vendor</string> + <string name="policy_product">policy_product</string> + <string name="policy_public">policy_public</string> + + <item type="string" name="other" /> </resources> diff --git a/cmds/idmap2/tests/data/target/target.apk b/cmds/idmap2/tests/data/target/target.apk Binary files differindex 18ecc276caae..ecbe87578684 100644 --- a/cmds/idmap2/tests/data/target/target.apk +++ b/cmds/idmap2/tests/data/target/target.apk diff --git a/cmds/statsd/src/atoms.proto b/cmds/statsd/src/atoms.proto index 453a0c033a18..ef3eac017192 100644 --- a/cmds/statsd/src/atoms.proto +++ b/cmds/statsd/src/atoms.proto @@ -26,6 +26,7 @@ import "frameworks/base/core/proto/android/app/settings_enums.proto"; import "frameworks/base/core/proto/android/app/job/enums.proto"; import "frameworks/base/core/proto/android/bluetooth/enums.proto"; import "frameworks/base/core/proto/android/bluetooth/hci/enums.proto"; +import "frameworks/base/core/proto/android/bluetooth/hfp/enums.proto"; import "frameworks/base/core/proto/android/net/networkcapabilities.proto"; import "frameworks/base/core/proto/android/os/enums.proto"; import "frameworks/base/core/proto/android/server/connectivity/data_stall_event.proto"; @@ -185,6 +186,13 @@ message Atom { SignedConfigReported signed_config_reported = 123; GnssNiEventReported gnss_ni_event_reported = 124; BluetoothLinkLayerConnectionEvent bluetooth_link_layer_connection_event = 125; + BluetoothAclConnectionStateChanged bluetooth_acl_connection_state_changed = 126; + BluetoothScoConnectionStateChanged bluetooth_sco_connection_state_changed = 127; + AppDowngraded app_downgraded = 128; + AppOptimizedAfterDowngraded app_optimized_after_downgraded = 129; + LowStorageStateChanged low_storage_state_changed = 130; + GnssNfwNotificationReported gnss_nfw_notification_reported = 131; + GnssConfigurationReported gnss_configuration_reported = 132; } // Pulled events will start at field 10000. @@ -1300,10 +1308,12 @@ message BluetoothEnabledStateChanged { } /** - * Logs when a Bluetooth device connects and disconnects. + * Logs when profiles on a Bluetooth device connects and disconnects. * * Logged from: - * packages/apps/Bluetooth/src/com/android/bluetooth/btservice/AdapterProperties.java + * packages/apps/Bluetooth/src/com/android/bluetooth/btservice/RemoteDevices.java + * + * Next Tag: 5 */ message BluetoothConnectionStateChanged { // The state of the connection. @@ -1312,10 +1322,65 @@ message BluetoothConnectionStateChanged { // An identifier that can be used to match connect and disconnect events. // Currently is last two bytes of a hash of a device level ID and // the mac address of the bluetooth device that is connected. - optional int32 obfuscated_id = 2; + // Deprecated: use obfuscated_id instead, this one is always 0 for Q+ + optional int32 OBSOLETE_obfuscated_id = 2 [deprecated = true]; // The profile that is connected. Eg. GATT, A2DP, HEADSET. // From android.bluetooth.BluetoothAdapter.java + // Default: 0 when not used optional int32 bt_profile = 3; + // An identifier that can be used to match events for this device. + // Currently, this is a salted hash of the MAC address of this Bluetooth device. + // Salt: Randomly generated 256 bit value + // Hash algorithm: HMAC-SHA256 + // Size: 32 byte + // Default: null or empty if the device identifier is not known + optional bytes obfuscated_id = 4 [(android.os.statsd.log_mode) = MODE_BYTES]; +} + +/** + * Logs when a Bluetooth device connects and disconnects over ACL + * + * Logged from: + * packages/apps/Bluetooth/src/com/android/bluetooth/btservice/AdapterProperties.java + * + * Next Tag: 3 + */ +message BluetoothAclConnectionStateChanged { + // An identifier that can be used to match events for this device. + // Currently, this is a salted hash of the MAC address of this Bluetooth device. + // Salt: Randomly generated 256 bit value + // Hash algorithm: HMAC-SHA256 + // Size: 32 byte + // Default: null or empty if the device identifier is not known + optional bytes obfuscated_id = 1 [(android.os.statsd.log_mode) = MODE_BYTES]; + // The state of the connection. + // Eg: CONNECTING, CONNECTED, DISCONNECTING, DISCONNECTED. + optional android.bluetooth.ConnectionStateEnum state = 2; +} + +/** + * Logs when a Bluetooth device connects and disconnects over SCO + * + * Logged from: + * packages/apps/Bluetooth/src/com/android/bluetooth/hfp/HeadsetStateMachine.java + * packages/apps/Bluetooth/src/com/android/bluetooth/hfp/HeadsetClientStateMachine.java + * + * Next Tag: 4 + */ +message BluetoothScoConnectionStateChanged { + // An identifier that can be used to match events for this device. + // Currently, this is a salted hash of the MAC address of this Bluetooth device. + // Salt: Randomly generated 256 bit value + // Hash algorithm: HMAC-SHA256 + // Size: 32 byte + // Default: null or empty if the device identifier is not known + optional bytes obfuscated_id = 1 [(android.os.statsd.log_mode) = MODE_BYTES]; + // The state of the connection. + // Eg: CONNECTING, CONNECTED, DISCONNECTING, DISCONNECTED. + optional android.bluetooth.ConnectionStateEnum state = 2; + // Codec used for this SCO connection + // Default: UNKNOWN + optional android.bluetooth.hfp.ScoCodec codec = 3; } // Logs when there is an event affecting Bluetooth device's link layer connection. @@ -1727,6 +1792,47 @@ message ActivityForegroundStateChanged { } /** + * Logs when a volume entered low Storage state. + * Logged from: + * frameworks/base/services/core/java/com/android/server/storage/DeviceStorageMonitorService.java + */ +message LowStorageStateChanged { + // Volume that ran out of storage. + optional string volume_description = 1; + + enum State { + UNKNOWN = 0; + OFF = 1; + ON = 2; + } + optional State state = 2; +} + +/** + * Logs when an app is downgraded. + * Logged from: + * frameworks/base/services/core/java/com/android/server/pm/BackgroundDexOptService.java + */ +message AppDowngraded { + optional string package_name = 1; + // Size of the package (all data) before being downgraded. + optional int64 size_in_bytes_before = 2; + // Size of the package (all data) after being downgraded. + optional int64 size_in_bytes_after = 3; + + optional bool aggressive = 4; +} + +/** + * Logs when an app is optimized after being downgraded. + * Logged from: + * frameworks/base/services/core/java/com/android/server/pm/BackgroundDexOptService.java + */ +message AppOptimizedAfterDowngraded { + optional string package_name = 1; +} + +/** * Logs when an app crashes. * Logged from: * frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java @@ -3271,7 +3377,8 @@ message PackageAssociationSourceProcessStatsProto { optional int32 process_uid = 1; // Process name. optional string process_name = 2; - + // Package name. + optional string package_name = 7; // Total count of the times this association appeared. optional int32 total_count = 3; @@ -3350,6 +3457,9 @@ message ProcessStatsSectionProto { } repeated Status status = 7; + // Number of pages available of various types and sizes, representation fragmentation. + repeated ProcessStatsAvailablePagesProto available_pages = 10; + // Stats for each process. repeated ProcessStatsProto process_stats = 8; @@ -3357,6 +3467,21 @@ message ProcessStatsSectionProto { repeated ProcessStatsPackageProto package_stats = 9; } +message ProcessStatsAvailablePagesProto { + // Node these pages are in (as per /proc/pagetypeinfo) + optional int32 node = 1; + + // Zone these pages are in (as per /proc/pagetypeinfo) + optional string zone = 2; + + // Label for the type of these pages (as per /proc/pagetypeinfo) + optional string label = 3; + + // Distribution of number of pages available by order size. First entry in array is + // order 0, second is order 1, etc. Each order increase is a doubling of page size. + repeated int32 pages_per_order = 4; +} + /** * Pulled from ProcessStatsService.java */ @@ -4009,7 +4134,7 @@ message GnssNiEventReported { optional int32 notification_id = 2; // A type which distinguishes different categories of NI request, such as VOICE, UMTS_SUPL etc. - optional int32 ni_type = 3; + optional android.server.location.GnssNiType ni_type = 3; // NI requires notification. optional bool need_notify = 4; @@ -4025,7 +4150,7 @@ message GnssNiEventReported { optional int32 timeout = 7; // Default response when timeout. - optional int32 default_response = 8; + optional android.server.location.GnssUserResponseType default_response = 8; // String representing the requester of the network inititated location request. optional string requestor_id = 9; @@ -4035,10 +4160,10 @@ message GnssNiEventReported { optional string text = 10; // requestorId decoding scheme. - optional int32 requestor_id_encoding = 11; + optional android.server.location.GnssNiEncodingType requestor_id_encoding = 11; // Notification message text decoding scheme. - optional int32 text_encoding = 12; + optional android.server.location.GnssNiEncodingType text_encoding = 12; // True if SUPL ES is enabled. optional bool is_supl_es_enabled = 13; @@ -4047,5 +4172,94 @@ message GnssNiEventReported { optional bool is_location_enabled = 14; // GNSS NI responses which define the response in NI structures. - optional int32 user_response = 15; + optional android.server.location.GnssUserResponseType user_response = 15; +} + +/** + * Logs GNSS non-framework (NFW) location notification. + * + * Logged from: + * frameworks/base/services/core/java/com/android/server/location/GnssLocationProvider.java + */ +message GnssNfwNotificationReported { + // Package name of the Android proxy application representing the non-framework entity that + // requested location. Set to empty string if unknown. + optional string proxy_app_package_name = 1; + + // Protocol stack that initiated the non-framework location request. + optional android.server.location.NfwProtocolStack protocol_stack = 2; + + // Name of the protocol stack if protocol_stack field is set to OTHER_PROTOCOL_STACK. Otherwise, + // set to empty string. This field is opaque to the framework and used for logging purposes. + optional string other_protocol_stack_name = 3; + + // Source initiating/receiving the location information. + optional android.server.location.NfwRequestor requestor = 4; + + // Identity of the endpoint receiving the location information. For example, carrier name, OEM + // name, SUPL SLP/E-SLP FQDN, chipset vendor name, etc. This field is opaque to the framework + // and used for logging purposes. + optional string requestor_id = 5; + + // Indicates whether location information was provided for this request. + optional android.server.location.NfwResponseType response_type = 6; + + // True if the device is in user initiated emergency session. + optional bool in_emergency_mode = 7; + + // True if cached location is provided. + optional bool is_cached_location = 8; + + // True if proxy app permission mismatch between framework and GNSS HAL. + optional bool is_permission_mismatched = 9; +} + +/** + * Logs GNSS configuration as defined in IGnssConfiguration.hal. + * + * Logged from: + * frameworks/base/services/core/java/com/android/server/location/GnssConfiguration.java + */ +message GnssConfigurationReported { + // SUPL host name. + optional string supl_host = 1; + + // SUPL port number. + optional int32 supl_port = 2; + + // C2K host name. + optional string c2k_host = 3; + + // C2K port number. + optional int32 c2k_port = 4; + + // The SUPL version requested by Carrier. + optional int32 supl_ver = 5; + + // The SUPL mode. + optional android.server.location.SuplMode supl_mode = 6; + + // True if NI emergency SUPL restrictions is enabled. + optional bool supl_es = 7; + + // LTE Positioning Profile settings + optional android.server.location.LppProfile lpp_profile = 8; + + // Positioning protocol on A-Glonass system. + optional android.server.location.GlonassPosProtocol a_glonass_pos_protocol_select = 9; + + // True if emergency PDN is used. Otherwise, regular PDN is used. + optional bool use_emergency_pdn_for_emergency_supl= 10; + + // Configurations of how GPS functionalities should be locked when user turns off GPS On setting. + optional android.server.location.GpsLock gps_lock = 11; + + // Number of seconds to extend the emergency session duration post emergency call. + optional int32 es_extension_sec = 12; + + // The full list of package names of proxy Android applications representing the non-framework + // location access entities (on/off the device) for which the framework user has granted + // non-framework location access permission. The package names are concatenated in one string + // with spaces as separators. + optional string enabled_proxy_app_package_name_list = 13; } diff --git a/cmds/statsd/src/metrics/GaugeMetricProducer.cpp b/cmds/statsd/src/metrics/GaugeMetricProducer.cpp index 67a1a4720576..c2878f02a691 100644 --- a/cmds/statsd/src/metrics/GaugeMetricProducer.cpp +++ b/cmds/statsd/src/metrics/GaugeMetricProducer.cpp @@ -93,7 +93,8 @@ GaugeMetricProducer::GaugeMetricProducer( StatsdStats::kAtomDimensionKeySizeLimitMap.end() ? StatsdStats::kAtomDimensionKeySizeLimitMap.at(pullTagId).second : StatsdStats::kDimensionKeySizeHardLimit), - mGaugeAtomsPerDimensionLimit(metric.max_num_gauge_atoms_per_bucket()) { + mGaugeAtomsPerDimensionLimit(metric.max_num_gauge_atoms_per_bucket()), + mSplitBucketForAppUpgrade(metric.split_bucket_for_app_upgrade()) { mCurrentSlicedBucket = std::make_shared<DimToGaugeAtomsMap>(); mCurrentSlicedBucketForAnomaly = std::make_shared<DimToValMap>(); int64_t bucketSizeMills = 0; diff --git a/cmds/statsd/src/metrics/GaugeMetricProducer.h b/cmds/statsd/src/metrics/GaugeMetricProducer.h index a1a506144d43..df0877954d70 100644 --- a/cmds/statsd/src/metrics/GaugeMetricProducer.h +++ b/cmds/statsd/src/metrics/GaugeMetricProducer.h @@ -74,6 +74,9 @@ public: const int64_t version) override { std::lock_guard<std::mutex> lock(mMutex); + if (!mSplitBucketForAppUpgrade) { + return; + } if (eventTimeNs > getCurrentBucketEndTimeNs()) { // Flush full buckets on the normal path up to the latest bucket boundary. flushIfNeededLocked(eventTimeNs); @@ -176,11 +179,14 @@ private: const size_t mGaugeAtomsPerDimensionLimit; + const bool mSplitBucketForAppUpgrade; + FRIEND_TEST(GaugeMetricProducerTest, TestPulledEventsWithCondition); FRIEND_TEST(GaugeMetricProducerTest, TestPulledEventsWithSlicedCondition); FRIEND_TEST(GaugeMetricProducerTest, TestPulledEventsNoCondition); FRIEND_TEST(GaugeMetricProducerTest, TestPushedEventsWithUpgrade); FRIEND_TEST(GaugeMetricProducerTest, TestPulledWithUpgrade); + FRIEND_TEST(GaugeMetricProducerTest, TestPulledWithAppUpgradeDisabled); FRIEND_TEST(GaugeMetricProducerTest, TestPulledEventsAnomalyDetection); FRIEND_TEST(GaugeMetricProducerTest, TestFirstBucket); FRIEND_TEST(GaugeMetricProducerTest, TestPullOnTrigger); diff --git a/cmds/statsd/src/metrics/ValueMetricProducer.cpp b/cmds/statsd/src/metrics/ValueMetricProducer.cpp index 9a8e3bd7b3eb..4122d8440959 100644 --- a/cmds/statsd/src/metrics/ValueMetricProducer.cpp +++ b/cmds/statsd/src/metrics/ValueMetricProducer.cpp @@ -105,7 +105,8 @@ ValueMetricProducer::ValueMetricProducer( mUseZeroDefaultBase(metric.use_zero_default_base()), mHasGlobalBase(false), mMaxPullDelayNs(metric.max_pull_delay_sec() > 0 ? metric.max_pull_delay_sec() * NS_PER_SEC - : StatsdStats::kPullMaxDelayNs) { + : StatsdStats::kPullMaxDelayNs), + mSplitBucketForAppUpgrade(metric.split_bucket_for_app_upgrade()) { int64_t bucketSizeMills = 0; if (metric.has_bucket()) { bucketSizeMills = TimeUnitToBucketSizeInMillisGuardrailed(key.GetUid(), metric.bucket()); diff --git a/cmds/statsd/src/metrics/ValueMetricProducer.h b/cmds/statsd/src/metrics/ValueMetricProducer.h index 4865aee57187..69eb0afaf7c4 100644 --- a/cmds/statsd/src/metrics/ValueMetricProducer.h +++ b/cmds/statsd/src/metrics/ValueMetricProducer.h @@ -57,6 +57,9 @@ public: void notifyAppUpgrade(const int64_t& eventTimeNs, const string& apk, const int uid, const int64_t version) override { std::lock_guard<std::mutex> lock(mMutex); + if (!mSplitBucketForAppUpgrade) { + return; + } if (mIsPulled && mCondition) { pullAndMatchEventsLocked(eventTimeNs - 1); } @@ -185,6 +188,8 @@ private: const int64_t mMaxPullDelayNs; + const bool mSplitBucketForAppUpgrade; + FRIEND_TEST(ValueMetricProducerTest, TestPulledEventsNoCondition); FRIEND_TEST(ValueMetricProducerTest, TestPulledEventsWithFiltering); FRIEND_TEST(ValueMetricProducerTest, TestPulledEventsTakeAbsoluteValueOnReset); @@ -193,6 +198,7 @@ private: FRIEND_TEST(ValueMetricProducerTest, TestPushedEventsWithUpgrade); FRIEND_TEST(ValueMetricProducerTest, TestPulledValueWithUpgrade); FRIEND_TEST(ValueMetricProducerTest, TestPulledValueWithUpgradeWhileConditionFalse); + FRIEND_TEST(ValueMetricProducerTest, TestPulledWithAppUpgradeDisabled); FRIEND_TEST(ValueMetricProducerTest, TestPushedEventsWithoutCondition); FRIEND_TEST(ValueMetricProducerTest, TestPushedEventsWithCondition); FRIEND_TEST(ValueMetricProducerTest, TestAnomalyDetection); diff --git a/cmds/statsd/src/statsd_config.proto b/cmds/statsd/src/statsd_config.proto index 381ac321a77a..9d3a66902804 100644 --- a/cmds/statsd/src/statsd_config.proto +++ b/cmds/statsd/src/statsd_config.proto @@ -244,6 +244,8 @@ message GaugeMetric { optional int64 max_num_gauge_atoms_per_bucket = 11 [default = 10]; optional int32 max_pull_delay_sec = 13 [default = 10]; + + optional bool split_bucket_for_app_upgrade = 14 [default = true]; } message ValueMetric { @@ -290,6 +292,8 @@ message ValueMetric { optional bool skip_zero_diff_output = 14 [default = true]; optional int32 max_pull_delay_sec = 16 [default = 10]; + + optional bool split_bucket_for_app_upgrade = 17 [default = true]; } message Alert { diff --git a/cmds/statsd/tests/metrics/GaugeMetricProducer_test.cpp b/cmds/statsd/tests/metrics/GaugeMetricProducer_test.cpp index 2799107c53d2..0ffbb54c8d48 100644 --- a/cmds/statsd/tests/metrics/GaugeMetricProducer_test.cpp +++ b/cmds/statsd/tests/metrics/GaugeMetricProducer_test.cpp @@ -276,8 +276,9 @@ TEST(GaugeMetricProducerTest, TestPulledWithUpgrade) { UidMap uidMap; SimpleAtomMatcher atomMatcher; atomMatcher.set_atom_id(tagId); - sp<EventMatcherWizard> eventMatcherWizard = new EventMatcherWizard({ - new SimpleLogMatchingTracker(atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)}); + sp<EventMatcherWizard> eventMatcherWizard = + new EventMatcherWizard({new SimpleLogMatchingTracker( + atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)}); sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>(); EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _, _)).WillOnce(Return()); @@ -295,9 +296,8 @@ TEST(GaugeMetricProducerTest, TestPulledWithUpgrade) { })); GaugeMetricProducer gaugeProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard, - logEventMatcherIndex, eventMatcherWizard, - tagId, -1, tagId, bucketStartTimeNs, bucketStartTimeNs, - pullerManager); + logEventMatcherIndex, eventMatcherWizard, tagId, -1, tagId, + bucketStartTimeNs, bucketStartTimeNs, pullerManager); vector<shared_ptr<LogEvent>> allData; shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 1); @@ -337,6 +337,58 @@ TEST(GaugeMetricProducerTest, TestPulledWithUpgrade) { ->mValue.int_value); } +TEST(GaugeMetricProducerTest, TestPulledWithAppUpgradeDisabled) { + GaugeMetric metric; + metric.set_id(metricId); + metric.set_bucket(ONE_MINUTE); + metric.set_max_pull_delay_sec(INT_MAX); + metric.set_split_bucket_for_app_upgrade(false); + auto gaugeFieldMatcher = metric.mutable_gauge_fields_filter()->mutable_fields(); + gaugeFieldMatcher->set_field(tagId); + gaugeFieldMatcher->add_child()->set_field(2); + + sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>(); + + UidMap uidMap; + SimpleAtomMatcher atomMatcher; + atomMatcher.set_atom_id(tagId); + sp<EventMatcherWizard> eventMatcherWizard = new EventMatcherWizard({ + new SimpleLogMatchingTracker(atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)}); + + sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>(); + EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _, _)).WillOnce(Return()); + EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillOnce(Return()); + EXPECT_CALL(*pullerManager, Pull(tagId, _)).WillOnce(Return(false)); + + GaugeMetricProducer gaugeProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard, + logEventMatcherIndex, eventMatcherWizard, + tagId, -1, tagId, bucketStartTimeNs, bucketStartTimeNs, + pullerManager); + + vector<shared_ptr<LogEvent>> allData; + shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 1); + event->write("some value"); + event->write(1); + event->init(); + allData.push_back(event); + gaugeProducer.onDataPulled(allData); + EXPECT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->size()); + EXPECT_EQ(1, gaugeProducer.mCurrentSlicedBucket->begin() + ->second.front() + .mFields->begin() + ->mValue.int_value); + + gaugeProducer.notifyAppUpgrade(eventUpgradeTimeNs, "ANY.APP", 1, 1); + EXPECT_EQ(0UL, gaugeProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size()); + EXPECT_EQ(0L, gaugeProducer.mCurrentBucketNum); + EXPECT_EQ(bucketStartTimeNs, gaugeProducer.mCurrentBucketStartTimeNs); + EXPECT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->size()); + EXPECT_EQ(1, gaugeProducer.mCurrentSlicedBucket->begin() + ->second.front() + .mFields->begin() + ->mValue.int_value); +} + TEST(GaugeMetricProducerTest, TestPulledEventsWithCondition) { GaugeMetric metric; metric.set_id(metricId); diff --git a/cmds/statsd/tests/metrics/ValueMetricProducer_test.cpp b/cmds/statsd/tests/metrics/ValueMetricProducer_test.cpp index 67570fc2ab51..9cfe3436ada7 100644 --- a/cmds/statsd/tests/metrics/ValueMetricProducer_test.cpp +++ b/cmds/statsd/tests/metrics/ValueMetricProducer_test.cpp @@ -641,7 +641,8 @@ TEST(ValueMetricProducerTest, TestPulledValueWithUpgrade) { valueProducer.notifyAppUpgrade(bucket2StartTimeNs + 150, "ANY.APP", 1, 1); EXPECT_EQ(1UL, valueProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size()); EXPECT_EQ(bucket2StartTimeNs + 150, valueProducer.mCurrentBucketStartTimeNs); - EXPECT_EQ(20L, valueProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY][0].values[0].long_value); + EXPECT_EQ(20L, + valueProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY][0].values[0].long_value); allData.clear(); event = make_shared<LogEvent>(tagId, bucket3StartTimeNs + 1); @@ -652,7 +653,48 @@ TEST(ValueMetricProducerTest, TestPulledValueWithUpgrade) { valueProducer.onDataPulled(allData); EXPECT_EQ(1UL, valueProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size()); EXPECT_EQ(bucket2StartTimeNs + 150, valueProducer.mCurrentBucketStartTimeNs); - EXPECT_EQ(20L, valueProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY][0].values[0].long_value); + EXPECT_EQ(20L, + valueProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY][0].values[0].long_value); +} + +TEST(ValueMetricProducerTest, TestPulledWithAppUpgradeDisabled) { + ValueMetric metric; + metric.set_id(metricId); + metric.set_bucket(ONE_MINUTE); + metric.mutable_value_field()->set_field(tagId); + metric.mutable_value_field()->add_child()->set_field(2); + metric.set_max_pull_delay_sec(INT_MAX); + metric.set_split_bucket_for_app_upgrade(false); + + UidMap uidMap; + SimpleAtomMatcher atomMatcher; + atomMatcher.set_atom_id(tagId); + sp<EventMatcherWizard> eventMatcherWizard = + new EventMatcherWizard({new SimpleLogMatchingTracker( + atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)}); + sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>(); + sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>(); + EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _, _)).WillOnce(Return()); + EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillOnce(Return()); + EXPECT_CALL(*pullerManager, Pull(tagId, _)).WillOnce(Return(true)); + ValueMetricProducer valueProducer(kConfigKey, metric, -1, wizard, logEventMatcherIndex, + eventMatcherWizard, tagId, bucketStartTimeNs, + bucketStartTimeNs, pullerManager); + + vector<shared_ptr<LogEvent>> allData; + allData.clear(); + shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 1); + event->write(tagId); + event->write(100); + event->init(); + allData.push_back(event); + + valueProducer.onDataPulled(allData); + EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size()); + + valueProducer.notifyAppUpgrade(bucket2StartTimeNs + 150, "ANY.APP", 1, 1); + EXPECT_EQ(0UL, valueProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size()); + EXPECT_EQ(bucketStartTimeNs, valueProducer.mCurrentBucketStartTimeNs); } TEST(ValueMetricProducerTest, TestPulledValueWithUpgradeWhileConditionFalse) { diff --git a/config/boot-image-profile.txt b/config/boot-image-profile.txt index c2e441b35f48..3ec0db4d99ce 100644 --- a/config/boot-image-profile.txt +++ b/config/boot-image-profile.txt @@ -2768,11 +2768,6 @@ HPLandroid/hardware/location/GeofenceHardwareService$1;->getStatusOfMonitoringTy HPLandroid/hardware/location/GeofenceHardwareService$1;->registerForMonitorStateChangeCallback(ILandroid/hardware/location/IGeofenceHardwareMonitorCallback;)Z HPLandroid/hardware/location/GeofenceHardwareService$1;->removeGeofence(II)Z HPLandroid/hardware/location/GeofenceHardwareService;->checkPermission(III)V -HPLandroid/hardware/location/IActivityRecognitionHardwareClient$Stub$Proxy;->onAvailabilityChanged(ZLandroid/hardware/location/IActivityRecognitionHardware;)V -HPLandroid/hardware/location/IActivityRecognitionHardwareClient$Stub;-><init>()V -HPLandroid/hardware/location/IActivityRecognitionHardwareClient$Stub;->asInterface(Landroid/os/IBinder;)Landroid/hardware/location/IActivityRecognitionHardwareClient; -HPLandroid/hardware/location/IActivityRecognitionHardwareClient$Stub;->onTransact(ILandroid/os/Parcel;Landroid/os/Parcel;I)Z -HPLandroid/hardware/location/IActivityRecognitionHardwareClient;->onAvailabilityChanged(ZLandroid/hardware/location/IActivityRecognitionHardware;)V HPLandroid/hardware/location/IContextHubCallback$Stub;->asBinder()Landroid/os/IBinder; HPLandroid/hardware/location/IContextHubCallback$Stub;->onTransact(ILandroid/os/Parcel;Landroid/os/Parcel;I)Z HPLandroid/hardware/location/IContextHubService$Stub$Proxy;->findNanoAppOnHub(ILandroid/hardware/location/NanoAppFilter;)[I @@ -21782,7 +21777,6 @@ HSPLandroid/hardware/input/KeyboardLayout$1;-><init>()V HSPLandroid/hardware/input/TouchCalibration$1;-><init>()V HSPLandroid/hardware/input/TouchCalibration;-><init>()V HSPLandroid/hardware/input/TouchCalibration;->getAffineTransform()[F -HSPLandroid/hardware/location/ActivityRecognitionHardware;->isSupported()Z HSPLandroid/hardware/location/ContextHubInfo$1;-><init>()V HSPLandroid/hardware/location/ContextHubInfo;-><init>(Landroid/hardware/contexthub/V1_0/ContextHub;)V HSPLandroid/hardware/location/ContextHubMessage$1;-><init>()V @@ -21802,13 +21796,6 @@ HSPLandroid/hardware/location/GeofenceHardwareService$1;->setGpsGeofenceHardware HSPLandroid/hardware/location/GeofenceHardwareService;-><init>()V HSPLandroid/hardware/location/GeofenceHardwareService;->onBind(Landroid/content/Intent;)Landroid/os/IBinder; HSPLandroid/hardware/location/GeofenceHardwareService;->onCreate()V -HSPLandroid/hardware/location/IActivityRecognitionHardware;->disableActivityEvent(Ljava/lang/String;I)Z -HSPLandroid/hardware/location/IActivityRecognitionHardware;->enableActivityEvent(Ljava/lang/String;IJ)Z -HSPLandroid/hardware/location/IActivityRecognitionHardware;->flush()Z -HSPLandroid/hardware/location/IActivityRecognitionHardware;->getSupportedActivities()[Ljava/lang/String; -HSPLandroid/hardware/location/IActivityRecognitionHardware;->isActivitySupported(Ljava/lang/String;)Z -HSPLandroid/hardware/location/IActivityRecognitionHardware;->registerSink(Landroid/hardware/location/IActivityRecognitionHardwareSink;)Z -HSPLandroid/hardware/location/IActivityRecognitionHardware;->unregisterSink(Landroid/hardware/location/IActivityRecognitionHardwareSink;)Z HSPLandroid/hardware/location/IContextHubCallback$Stub$Proxy;->asBinder()Landroid/os/IBinder; HSPLandroid/hardware/location/IContextHubCallback$Stub$Proxy;->onMessageReceipt(IILandroid/hardware/location/ContextHubMessage;)V HSPLandroid/hardware/location/IContextHubCallback;->onMessageReceipt(IILandroid/hardware/location/ContextHubMessage;)V @@ -55650,7 +55637,6 @@ Landroid/hardware/input/InputManagerInternal; Landroid/hardware/input/KeyboardLayout$1; Landroid/hardware/input/TouchCalibration$1; Landroid/hardware/input/TouchCalibration; -Landroid/hardware/location/ActivityRecognitionHardware; Landroid/hardware/location/ContextHubInfo$1; Landroid/hardware/location/ContextHubInfo; Landroid/hardware/location/ContextHubManager; @@ -55666,11 +55652,6 @@ Landroid/hardware/location/GeofenceHardwareMonitorEvent; Landroid/hardware/location/GeofenceHardwareRequestParcelable$1; Landroid/hardware/location/GeofenceHardwareService$1; Landroid/hardware/location/GeofenceHardwareService; -Landroid/hardware/location/IActivityRecognitionHardware$Stub; -Landroid/hardware/location/IActivityRecognitionHardware; -Landroid/hardware/location/IActivityRecognitionHardwareClient$Stub$Proxy; -Landroid/hardware/location/IActivityRecognitionHardwareClient$Stub; -Landroid/hardware/location/IActivityRecognitionHardwareClient; Landroid/hardware/location/IContextHubCallback$Stub$Proxy; Landroid/hardware/location/IContextHubCallback; Landroid/hardware/location/IContextHubClient$Stub; diff --git a/config/hiddenapi-greylist.txt b/config/hiddenapi-greylist.txt index 5392a3c428c1..13f8dd924d4a 100644 --- a/config/hiddenapi-greylist.txt +++ b/config/hiddenapi-greylist.txt @@ -462,8 +462,6 @@ Landroid/hardware/input/IInputManager$Stub$Proxy;-><init>(Landroid/os/IBinder;)V Landroid/hardware/input/IInputManager$Stub;->asInterface(Landroid/os/IBinder;)Landroid/hardware/input/IInputManager; Landroid/hardware/input/IInputManager$Stub;->TRANSACTION_injectInputEvent:I Landroid/hardware/input/IInputManager;->injectInputEvent(Landroid/view/InputEvent;I)Z -Landroid/hardware/location/IActivityRecognitionHardwareClient$Stub;-><init>()V -Landroid/hardware/location/IActivityRecognitionHardwareClient;->onAvailabilityChanged(ZLandroid/hardware/location/IActivityRecognitionHardware;)V Landroid/hardware/location/IContextHubService$Stub;->asInterface(Landroid/os/IBinder;)Landroid/hardware/location/IContextHubService; Landroid/hardware/usb/IUsbManager$Stub$Proxy;-><init>(Landroid/os/IBinder;)V Landroid/hardware/usb/IUsbManager$Stub;->asInterface(Landroid/os/IBinder;)Landroid/hardware/usb/IUsbManager; @@ -1108,18 +1106,6 @@ Landroid/os/UserManager;->isUserUnlocked(I)Z Landroid/os/UserManager;->mService:Landroid/os/IUserManager; Landroid/os/UserManager;->removeUser(I)Z Landroid/os/Vibrator;-><init>()V -Landroid/os/VintfObject;->getHalNamesAndVersions()[Ljava/lang/String; -Landroid/os/VintfObject;->getSepolicyVersion()Ljava/lang/String; -Landroid/os/VintfObject;->getTargetFrameworkCompatibilityMatrixVersion()Ljava/lang/Long; -Landroid/os/VintfObject;->getVndkSnapshots()Ljava/util/Map; -Landroid/os/VintfObject;->report()[Ljava/lang/String; -Landroid/os/VintfRuntimeInfo;->getCpuInfo()Ljava/lang/String; -Landroid/os/VintfRuntimeInfo;->getHardwareId()Ljava/lang/String; -Landroid/os/VintfRuntimeInfo;->getKernelVersion()Ljava/lang/String; -Landroid/os/VintfRuntimeInfo;->getNodeName()Ljava/lang/String; -Landroid/os/VintfRuntimeInfo;->getOsName()Ljava/lang/String; -Landroid/os/VintfRuntimeInfo;->getOsRelease()Ljava/lang/String; -Landroid/os/VintfRuntimeInfo;->getOsVersion()Ljava/lang/String; Landroid/os/WorkSource;-><init>(Landroid/os/Parcel;)V Landroid/os/WorkSource;->mNames:[Ljava/lang/String; Landroid/os/WorkSource;->mNum:I @@ -1824,22 +1810,10 @@ Lcom/android/internal/os/RuntimeInit;->getApplicationObject()Landroid/os/IBinder Lcom/android/internal/os/RuntimeInit;->initialized:Z Lcom/android/internal/os/RuntimeInit;->main([Ljava/lang/String;)V Lcom/android/internal/os/RuntimeInit;->mApplicationObject:Landroid/os/IBinder; -Lcom/android/internal/os/ZygoteConnection$Arguments;-><init>([Ljava/lang/String;)V -Lcom/android/internal/os/ZygoteConnection$Arguments;->effectiveCapabilities:J -Lcom/android/internal/os/ZygoteConnection$Arguments;->gid:I -Lcom/android/internal/os/ZygoteConnection$Arguments;->gids:[I -Lcom/android/internal/os/ZygoteConnection$Arguments;->permittedCapabilities:J -Lcom/android/internal/os/ZygoteConnection$Arguments;->remainingArgs:[Ljava/lang/String; -Lcom/android/internal/os/ZygoteConnection$Arguments;->rlimits:Ljava/util/ArrayList; -Lcom/android/internal/os/ZygoteConnection$Arguments;->uid:I -Lcom/android/internal/os/ZygoteConnection;->applyUidSecurityPolicy(Lcom/android/internal/os/ZygoteConnection$Arguments;Landroid/net/Credentials;)V Lcom/android/internal/os/ZygoteConnection;->closeSocket()V -Lcom/android/internal/os/ZygoteConnection;->getFileDesciptor()Ljava/io/FileDescriptor; -Lcom/android/internal/os/ZygoteConnection;->intArray2d:[[I Lcom/android/internal/os/ZygoteConnection;->mSocket:Landroid/net/LocalSocket; Lcom/android/internal/os/ZygoteConnection;->mSocketOutStream:Ljava/io/DataOutputStream; Lcom/android/internal/os/ZygoteConnection;->peer:Landroid/net/Credentials; -Lcom/android/internal/os/ZygoteConnection;->readArgumentList()[Ljava/lang/String; Lcom/android/internal/os/ZygoteInit;->main([Ljava/lang/String;)V Lcom/android/internal/os/ZygoteInit;->mResources:Landroid/content/res/Resources; Lcom/android/internal/os/ZygoteSecurityException;-><init>(Ljava/lang/String;)V diff --git a/config/preloaded-classes b/config/preloaded-classes index c8a2a9c19b28..cd798adf5d44 100644 --- a/config/preloaded-classes +++ b/config/preloaded-classes @@ -1405,10 +1405,7 @@ android.hardware.input.InputManager android.hardware.input.InputManager$InputDeviceListener android.hardware.input.InputManager$InputDeviceListenerDelegate android.hardware.input.InputManager$InputDevicesChangedListener -android.hardware.location.ActivityRecognitionHardware android.hardware.location.ContextHubManager -android.hardware.location.IActivityRecognitionHardware -android.hardware.location.IActivityRecognitionHardware$Stub android.hardware.radio.RadioManager android.hardware.soundtrigger.SoundTrigger android.hardware.soundtrigger.SoundTrigger$ConfidenceLevel diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java index d374f1c0acdf..836627efb379 100644 --- a/core/java/android/app/Activity.java +++ b/core/java/android/app/Activity.java @@ -124,6 +124,7 @@ import android.view.autofill.AutofillPopupWindow; import android.view.autofill.IAutofillWindowPresenter; import android.view.contentcapture.ContentCaptureContext; import android.view.contentcapture.ContentCaptureManager; +import android.view.contentcapture.ContentCaptureSession; import android.widget.AdapterView; import android.widget.Toast; import android.widget.Toolbar; @@ -1034,13 +1035,15 @@ public class Activity extends ContextThemeWrapper } /** @hide */ private static final int CONTENT_CAPTURE_START = 1; - /** @hide */ private static final int CONTENT_CAPTURE_FLUSH = 2; - /** @hide */ private static final int CONTENT_CAPTURE_STOP = 3; + /** @hide */ private static final int CONTENT_CAPTURE_PAUSE = 2; + /** @hide */ private static final int CONTENT_CAPTURE_RESUME = 3; + /** @hide */ private static final int CONTENT_CAPTURE_STOP = 4; /** @hide */ @IntDef(prefix = { "CONTENT_CAPTURE_" }, value = { CONTENT_CAPTURE_START, - CONTENT_CAPTURE_FLUSH, + CONTENT_CAPTURE_PAUSE, + CONTENT_CAPTURE_RESUME, CONTENT_CAPTURE_STOP }) @Retention(RetentionPolicy.SOURCE) @@ -1062,8 +1065,11 @@ public class Activity extends ContextThemeWrapper } cm.onActivityStarted(mToken, getComponentName(), flags); break; - case CONTENT_CAPTURE_FLUSH: - cm.flush(); + case CONTENT_CAPTURE_PAUSE: + cm.flush(ContentCaptureSession.FLUSH_REASON_ACTIVITY_PAUSED); + break; + case CONTENT_CAPTURE_RESUME: + cm.flush(ContentCaptureSession.FLUSH_REASON_ACTIVITY_RESUMED); break; case CONTENT_CAPTURE_STOP: cm.onActivityStopped(); @@ -1755,7 +1761,7 @@ public class Activity extends ContextThemeWrapper } } mCalled = true; - notifyContentCaptureManagerIfNeeded(CONTENT_CAPTURE_FLUSH); + notifyContentCaptureManagerIfNeeded(CONTENT_CAPTURE_RESUME); } /** @@ -2149,7 +2155,7 @@ public class Activity extends ContextThemeWrapper } } mCalled = true; - notifyContentCaptureManagerIfNeeded(CONTENT_CAPTURE_FLUSH); + notifyContentCaptureManagerIfNeeded(CONTENT_CAPTURE_PAUSE); } /** diff --git a/core/java/android/app/ActivityManagerInternal.java b/core/java/android/app/ActivityManagerInternal.java index 1f01e2698fb5..5cac0489e8df 100644 --- a/core/java/android/app/ActivityManagerInternal.java +++ b/core/java/android/app/ActivityManagerInternal.java @@ -320,4 +320,10 @@ public abstract class ActivityManagerInternal { /** Remove pending backup for the given userId. */ public abstract void clearPendingBackup(int userId); + + /** + * When power button is very long pressed, call this interface to do some pre-shutdown work + * like persisting database etc. + */ + public abstract void prepareForPossibleShutdown(); } diff --git a/core/java/android/app/AlertDialog.java b/core/java/android/app/AlertDialog.java index cf40e067e5b1..bfc216a24c1b 100644 --- a/core/java/android/app/AlertDialog.java +++ b/core/java/android/app/AlertDialog.java @@ -25,6 +25,7 @@ import android.annotation.UnsupportedAppUsage; import android.content.Context; import android.content.DialogInterface; import android.content.res.ResourceId; +import android.content.res.Resources; import android.database.Cursor; import android.graphics.drawable.Drawable; import android.os.Bundle; @@ -465,7 +466,7 @@ public class AlertDialog extends Dialog implements DialogInterface { * @param context the parent context */ public Builder(Context context) { - this(context, resolveDialogTheme(context, ResourceId.ID_NULL)); + this(context, resolveDialogTheme(context, Resources.ID_NULL)); } /** diff --git a/core/java/android/app/Dialog.java b/core/java/android/app/Dialog.java index 4bd935c0e924..088c245c9c2c 100644 --- a/core/java/android/app/Dialog.java +++ b/core/java/android/app/Dialog.java @@ -31,7 +31,7 @@ import android.content.ContextWrapper; import android.content.DialogInterface; import android.content.pm.ApplicationInfo; import android.content.res.Configuration; -import android.content.res.ResourceId; +import android.content.res.Resources; import android.graphics.drawable.Drawable; import android.net.Uri; import android.os.Build; @@ -183,7 +183,7 @@ public class Dialog implements DialogInterface, Window.Callback, Dialog(@NonNull Context context, @StyleRes int themeResId, boolean createContextThemeWrapper) { if (createContextThemeWrapper) { - if (themeResId == ResourceId.ID_NULL) { + if (themeResId == Resources.ID_NULL) { final TypedValue outValue = new TypedValue(); context.getTheme().resolveAttribute(R.attr.dialogTheme, outValue, true); themeResId = outValue.resourceId; diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java index 72819cb1493b..b8d748dce9e6 100644 --- a/core/java/android/app/Notification.java +++ b/core/java/android/app/Notification.java @@ -384,9 +384,7 @@ public class Notification implements Parcelable STANDARD_LAYOUTS.add(R.layout.notification_template_material_messaging); STANDARD_LAYOUTS.add(R.layout.notification_template_material_media); STANDARD_LAYOUTS.add(R.layout.notification_template_material_big_media); - STANDARD_LAYOUTS.add(R.layout.notification_template_ambient_header); STANDARD_LAYOUTS.add(R.layout.notification_template_header); - STANDARD_LAYOUTS.add(R.layout.notification_template_material_ambient); } /** @@ -4570,9 +4568,7 @@ public class Notification implements Parcelable if (p.title != null) { contentView.setViewVisibility(R.id.title, View.VISIBLE); contentView.setTextViewText(R.id.title, processTextSpans(p.title)); - if (!p.ambient) { - setTextViewColorPrimary(contentView, R.id.title, p); - } + setTextViewColorPrimary(contentView, R.id.title, p); contentView.setViewLayoutWidth(R.id.title, showProgress ? ViewGroup.LayoutParams.WRAP_CONTENT : ViewGroup.LayoutParams.MATCH_PARENT); @@ -4581,9 +4577,7 @@ 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)); - if (!p.ambient) { - setTextViewColorSecondary(contentView, textId, p); - } + setTextViewColorSecondary(contentView, textId, p); contentView.setViewVisibility(textId, View.VISIBLE); } @@ -4842,7 +4836,7 @@ public class Notification implements Parcelable if (mN.mLargeIcon == null && mN.largeIcon != null) { mN.mLargeIcon = Icon.createWithBitmap(mN.largeIcon); } - boolean showLargeIcon = mN.mLargeIcon != null && !p.hideLargeIcon && !p.ambient; + boolean showLargeIcon = mN.mLargeIcon != null && !p.hideLargeIcon; if (showLargeIcon) { contentView.setViewVisibility(R.id.right_icon, View.VISIBLE); contentView.setImageViewIcon(R.id.right_icon, mN.mLargeIcon); @@ -4856,7 +4850,7 @@ public class Notification implements Parcelable * @return if the reply icon is visible */ private boolean bindReplyIcon(RemoteViews contentView, StandardTemplateParams p) { - boolean actionVisible = !p.hideReplyIcon && !p.ambient; + boolean actionVisible = !p.hideReplyIcon; Action action = null; if (actionVisible) { action = findReplyAction(); @@ -4896,21 +4890,18 @@ public class Notification implements Parcelable private void bindNotificationHeader(RemoteViews contentView, StandardTemplateParams p) { bindSmallIcon(contentView, p); bindHeaderAppName(contentView, p); - if (!p.ambient) { - // Ambient view does not have these - bindHeaderText(contentView, p); - bindHeaderTextSecondary(contentView, p); - bindHeaderChronometerAndTime(contentView, p); - bindProfileBadge(contentView, p); - bindAlertedIcon(contentView, p); - } + bindHeaderText(contentView, p); + bindHeaderTextSecondary(contentView, p); + bindHeaderChronometerAndTime(contentView, p); + bindProfileBadge(contentView, p); + bindAlertedIcon(contentView, p); bindActivePermissions(contentView, p); bindExpandButton(contentView, p); mN.mUsesStandardHeader = true; } private void bindActivePermissions(RemoteViews contentView, StandardTemplateParams p) { - int color = p.ambient ? resolveAmbientColor(p) : getNeutralColor(p); + int color = getNeutralColor(p); contentView.setDrawableTint(R.id.camera, false, color, PorterDuff.Mode.SRC_ATOP); contentView.setDrawableTint(R.id.mic, false, color, PorterDuff.Mode.SRC_ATOP); contentView.setDrawableTint(R.id.overlay, false, color, PorterDuff.Mode.SRC_ATOP); @@ -5021,13 +5012,12 @@ public class Notification implements Parcelable if (isColorized(p)) { setTextViewColorPrimary(contentView, R.id.app_name_text, p); } else { - contentView.setTextColor(R.id.app_name_text, - p.ambient ? resolveAmbientColor(p) : getSecondaryTextColor(p)); + contentView.setTextColor(R.id.app_name_text, getSecondaryTextColor(p)); } } private boolean isColorized(StandardTemplateParams p) { - return p.allowColorization && !p.ambient && mN.isColorized(); + return p.allowColorization && mN.isColorized(); } private void bindSmallIcon(RemoteViews contentView, StandardTemplateParams p) { @@ -5097,7 +5087,7 @@ public class Notification implements Parcelable List<Notification.Action> nonContextualActions = filterOutContextualActions(mActions); int N = nonContextualActions.size(); - boolean emphazisedMode = mN.fullScreenIntent != null && !p.ambient; + boolean emphazisedMode = mN.fullScreenIntent != null; big.setBoolean(R.id.actions, "setEmphasizedMode", emphazisedMode); if (N > 0) { big.setViewVisibility(R.id.actions_container, View.VISIBLE); @@ -5122,7 +5112,7 @@ public class Notification implements Parcelable } CharSequence[] replyText = mN.extras.getCharSequenceArray(EXTRA_REMOTE_INPUT_HISTORY); - if (!p.ambient && validRemoteInput && replyText != null + if (validRemoteInput && replyText != null && replyText.length > 0 && !TextUtils.isEmpty(replyText[0]) && p.maxRemoteInputHistory > 0) { boolean showSpinner = mN.extras.getBoolean(EXTRA_SHOW_REMOTE_INPUT_SPINNER); @@ -5239,11 +5229,10 @@ public class Notification implements Parcelable * Construct a RemoteViews for the final notification header only. This will not be * colorized. * - * @param ambient if true, generate the header for the ambient display layout. * @hide */ - public RemoteViews makeNotificationHeader(boolean ambient) { - return makeNotificationHeader(mParams.reset().ambient(ambient).fillTextsFrom(this)); + public RemoteViews makeNotificationHeader() { + return makeNotificationHeader(mParams.reset().fillTextsFrom(this)); } /** @@ -5256,8 +5245,7 @@ public class Notification implements Parcelable // Headers on their own are never colorized p.disallowColorization(); RemoteViews header = new BuilderRemoteViews(mContext.getApplicationInfo(), - p.ambient ? R.layout.notification_template_ambient_header - : R.layout.notification_template_header); + R.layout.notification_template_header); resetNotificationHeader(header); bindNotificationHeader(header, p); return header; @@ -5269,11 +5257,7 @@ public class Notification implements Parcelable * @hide */ public RemoteViews makeAmbientNotification() { - RemoteViews ambient = applyStandardTemplateWithActions( - R.layout.notification_template_material_ambient, - mParams.reset().ambient(true).fillTextsFrom(this).hasProgress(false), - null /* result */); - return ambient; + return createHeadsUpContentView(false /* increasedHeight */); } private void hideLine1Text(RemoteViews result) { @@ -5377,14 +5361,8 @@ public class Notification implements Parcelable } mN.extras = publicExtras; RemoteViews view; - if (ambient) { - publicExtras.putCharSequence(EXTRA_TITLE, - mContext.getString(com.android.internal.R.string.notification_hidden_text)); - view = makeAmbientNotification(); - } else{ - view = makeNotificationHeader(false /* ambient */); - view.setBoolean(R.id.notification_header, "setExpandOnlyOnButton", true); - } + view = makeNotificationHeader(); + view.setBoolean(R.id.notification_header, "setExpandOnlyOnButton", true); mN.extras = savedBundle; mN.mLargeIcon = largeIcon; mN.largeIcon = largeIconLegacy; @@ -5404,7 +5382,6 @@ public class Notification implements Parcelable public RemoteViews makeLowPriorityContentView(boolean useRegularSubtext) { StandardTemplateParams p = mParams.reset() .forceDefaultColor() - .ambient(false) .fillTextsFrom(this); if (!useRegularSubtext || TextUtils.isEmpty(mParams.summaryText)) { p.summaryText(createSummaryText()); @@ -5495,8 +5472,7 @@ public class Notification implements Parcelable if (isColorized(p)) { setTextViewColorPrimary(button, R.id.action0, p); } else if (getRawColor(p) != COLOR_DEFAULT && mTintActionButtons) { - button.setTextColor(R.id.action0, - p.ambient ? resolveAmbientColor(p) : resolveContrastColor(p)); + button.setTextColor(R.id.action0, resolveContrastColor(p)); } } button.setIntTag(R.id.action0, R.id.notification_action_index_tag, @@ -5589,13 +5565,8 @@ public class Notification implements Parcelable } private CharSequence processLegacyText(CharSequence charSequence) { - return processLegacyText(charSequence, false /* ambient */); - } - - private CharSequence processLegacyText(CharSequence charSequence, boolean ambient) { boolean isAlreadyLightText = isLegacy() || textColorsNeedInversion(); - boolean wantLightText = ambient; - if (isAlreadyLightText != wantLightText) { + if (isAlreadyLightText) { return getColorUtil().invertCharSequenceColors(charSequence); } else { return charSequence; @@ -5609,9 +5580,7 @@ public class Notification implements Parcelable StandardTemplateParams p) { boolean colorable = !isLegacy() || getColorUtil().isGrayscaleIcon(mContext, smallIcon); int color; - if (p.ambient) { - color = resolveAmbientColor(p); - } else if (isColorized(p)) { + if (isColorized(p)) { color = getPrimaryTextColor(p); } else { color = resolveContrastColor(p); @@ -5698,17 +5667,6 @@ public class Notification implements Parcelable return mNeutralColor; } - int resolveAmbientColor(StandardTemplateParams p) { - int rawColor = getRawColor(p); - if (mCachedAmbientColorIsFor == rawColor && mCachedAmbientColorIsFor != COLOR_INVALID) { - return mCachedAmbientColor; - } - final int contrasted = ContrastColorUtil.resolveAmbientColor(mContext, rawColor); - - mCachedAmbientColorIsFor = rawColor; - return mCachedAmbientColor = contrasted; - } - /** * Apply the unstyled operations and return a new {@link Notification} object. * @hide @@ -10144,7 +10102,6 @@ public class Notification implements Parcelable private static class StandardTemplateParams { boolean hasProgress = true; - boolean ambient = false; CharSequence title; CharSequence text; CharSequence headerTextSecondary; @@ -10157,7 +10114,6 @@ public class Notification implements Parcelable final StandardTemplateParams reset() { hasProgress = true; - ambient = false; title = null; text = null; summaryText = null; @@ -10213,22 +10169,15 @@ public class Notification implements Parcelable return this; } - final StandardTemplateParams ambient(boolean ambient) { - Preconditions.checkState(title == null && text == null, "must set ambient before text"); - this.ambient = ambient; - return this; - } - final StandardTemplateParams fillTextsFrom(Builder b) { Bundle extras = b.mN.extras; - this.title = b.processLegacyText(extras.getCharSequence(EXTRA_TITLE), ambient); + this.title = b.processLegacyText(extras.getCharSequence(EXTRA_TITLE)); - // Big text notifications should contain their content when viewed in ambient mode. CharSequence text = extras.getCharSequence(EXTRA_BIG_TEXT); - if (!ambient || TextUtils.isEmpty(text)) { + if (TextUtils.isEmpty(text)) { text = extras.getCharSequence(EXTRA_TEXT); } - this.text = b.processLegacyText(text, ambient); + this.text = b.processLegacyText(text); this.summaryText = extras.getCharSequence(EXTRA_SUB_TEXT); return this; } diff --git a/core/java/android/app/SystemServiceRegistry.java b/core/java/android/app/SystemServiceRegistry.java index 3adafd725a10..2dc225af6482 100644 --- a/core/java/android/app/SystemServiceRegistry.java +++ b/core/java/android/app/SystemServiceRegistry.java @@ -439,10 +439,11 @@ final class SystemServiceRegistry { }}); registerService(Context.TEXT_SERVICES_MANAGER_SERVICE, TextServicesManager.class, - new StaticServiceFetcher<TextServicesManager>() { + new CachedServiceFetcher<TextServicesManager>() { @Override - public TextServicesManager createService() { - return TextServicesManager.getInstance(); + public TextServicesManager createService(ContextImpl ctx) + throws ServiceNotFoundException { + return TextServicesManager.createInstance(ctx); }}); registerService(Context.KEYGUARD_SERVICE, KeyguardManager.class, diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java index 9247486dff40..6d7c547f7cf1 100644 --- a/core/java/android/app/admin/DevicePolicyManager.java +++ b/core/java/android/app/admin/DevicePolicyManager.java @@ -2168,6 +2168,74 @@ public class DevicePolicyManager { public @interface SetPrivateDnsModeResultConstants {} /** + * Activity action: Starts the administrator to get the mode for the provisioning. + * This intent may contain the following extras: + * <ul> + * <li>{@link #EXTRA_PROVISIONING_ADMIN_EXTRAS_BUNDLE}</li> + * <li>{@link #EXTRA_PROVISIONING_IMEI}</li> + * <li>{@link #EXTRA_PROVISIONING_SERIAL_NUMBER}</li> + * </ul> + * + * <p>The target activity should return one of the following values in + * {@link #EXTRA_PROVISIONING_MODE} as result: + * <ul> + * <li>{@link #PROVISIONING_MODE_FULLY_MANAGED_DEVICE}</li> + * <li>{@link #PROVISIONING_MODE_MANAGED_PROFILE}</li> + * <li>{@link #PROVISIONING_MODE_MANAGED_PROFILE_ON_FULLY_MANAGED_DEVICE}</li> + * </ul> + * + * <p>The target activity may also return the account that needs to be migrated from primary + * user to managed profile in case of a profile owner provisioning in + * {@link #EXTRA_PROVISIONING_ACCOUNT_TO_MIGRATE} as result. + */ + public static final String ACTION_GET_PROVISIONING_MODE = + "android.app.action.GET_PROVISIONING_MODE"; + + /** + * A string extra holding the IMEI (International Mobile Equipment Identity) of the device. + */ + public static final String EXTRA_PROVISIONING_IMEI = "android.app.extra.PROVISIONING_IMEI"; + + /** + * A string extra holding the serial number of the device. + */ + public static final String EXTRA_PROVISIONING_SERIAL_NUMBER = + "android.app.extra.PROVISIONING_SERIAL_NUMBER"; + + /** + * An intent extra holding the provisioning mode returned by the administrator. + * The value for this extra should be one of the following: + * <ul> + * <li>{@link #PROVISIONING_MODE_FULLY_MANAGED_DEVICE}</li> + * <li>{@link #PROVISIONING_MODE_MANAGED_PROFILE}</li> + * <li>{@link #PROVISIONING_MODE_MANAGED_PROFILE_ON_FULLY_MANAGED_DEVICE}</li> + * </ul> + */ + public static final String EXTRA_PROVISIONING_MODE = + "android.app.extra.PROVISIONING_MODE"; + + /** + * The provisioning mode for fully managed device. + */ + public static final int PROVISIONING_MODE_FULLY_MANAGED_DEVICE = 1; + + /** + * The provisioning mode for managed profile. + */ + public static final int PROVISIONING_MODE_MANAGED_PROFILE = 2; + + /** + * The provisioning mode for managed profile on a fully managed device. + */ + public static final int PROVISIONING_MODE_MANAGED_PROFILE_ON_FULLY_MANAGED_DEVICE = 3; + + /** + * Activity action: Starts the administrator to show policy compliance for the provisioning. + */ + public static final String ACTION_ADMIN_POLICY_COMPLIANCE = + "android.app.action.ADMIN_POLICY_COMPLIANCE"; + + /** * Return true if the given administrator component is currently active (enabled) in the system. * * @param admin The administrator component to check for. diff --git a/core/java/android/app/usage/EventList.java b/core/java/android/app/usage/EventList.java index a79ad2fc8607..aaae57e526a0 100644 --- a/core/java/android/app/usage/EventList.java +++ b/core/java/android/app/usage/EventList.java @@ -103,21 +103,4 @@ public class EventList { } return result; } - - /** - * Remove events of certain type on or after a timestamp. - * @param type The type of event to remove. - * @param timeStamp the timeStamp on or after which to remove the event. - */ - public void removeOnOrAfter(int type, long timeStamp) { - for (int i = mEvents.size() - 1; i >= 0; i--) { - UsageEvents.Event event = mEvents.get(i); - if (event.mTimeStamp < timeStamp) { - break; - } - if (event.mEventType == type) { - mEvents.remove(i); - } - } - } } diff --git a/core/java/android/app/usage/UsageEvents.java b/core/java/android/app/usage/UsageEvents.java index d7a53281bc56..2c5fe046faad 100644 --- a/core/java/android/app/usage/UsageEvents.java +++ b/core/java/android/app/usage/UsageEvents.java @@ -245,10 +245,18 @@ public final class UsageEvents implements Parcelable { public static final int FLUSH_TO_DISK = 25; /** + * An event type denoting that the device underwent a shutdown process. + * A DEVICE_SHUTDOWN event should be treated as if all started activities and foreground + * services are now stopped and no explicit {@link #ACTIVITY_STOPPED} and + * {@link #FOREGROUND_SERVICE_STOP} events will be generated for them. + */ + public static final int DEVICE_SHUTDOWN = 26; + + /** * Keep in sync with the greatest event type value. * @hide */ - public static final int MAX_EVENT_TYPE = 25; + public static final int MAX_EVENT_TYPE = 26; /** @hide */ public static final int FLAG_IS_PACKAGE_INSTANT_APP = 1 << 0; diff --git a/core/java/android/app/usage/UsageStats.java b/core/java/android/app/usage/UsageStats.java index 308180badbb8..94a2a3eaae7f 100644 --- a/core/java/android/app/usage/UsageStats.java +++ b/core/java/android/app/usage/UsageStats.java @@ -21,6 +21,7 @@ import static android.app.usage.UsageEvents.Event.ACTIVITY_PAUSED; import static android.app.usage.UsageEvents.Event.ACTIVITY_RESUMED; import static android.app.usage.UsageEvents.Event.ACTIVITY_STOPPED; import static android.app.usage.UsageEvents.Event.CONTINUING_FOREGROUND_SERVICE; +import static android.app.usage.UsageEvents.Event.DEVICE_SHUTDOWN; import static android.app.usage.UsageEvents.Event.END_OF_DAY; import static android.app.usage.UsageEvents.Event.FLUSH_TO_DISK; import static android.app.usage.UsageEvents.Event.FOREGROUND_SERVICE_START; @@ -119,12 +120,9 @@ public final class UsageStats implements Parcelable { public int mLastEvent; /** - * If an activity is visible(onStart(), onPause() states) or in foreground (onResume() state), - * it has one entry in this map. When an activity becomes invisible (onStop() or onDestroy()), - * it is removed from this map. * Key is instanceId of the activity (ActivityRecode appToken hashCode).. - * Value is this activity's last event, one of ACTIVITY_RESUMED or - * ACTIVITY_PAUSED. + * Value is this activity's last event, one of ACTIVITY_RESUMED, ACTIVITY_PAUSED or + * ACTIVITY_STOPPED. * {@hide} */ public SparseIntArray mActivities = new SparseIntArray(); @@ -560,6 +558,7 @@ public final class UsageStats implements Parcelable { mLastTimeForegroundServiceUsed = timeStamp; mForegroundServices.put(className, eventType); break; + case DEVICE_SHUTDOWN: case FLUSH_TO_DISK: // update usage of all active activities/services. if (hasForegroundActivity()) { diff --git a/core/java/android/app/usage/UsageStatsManagerInternal.java b/core/java/android/app/usage/UsageStatsManagerInternal.java index 2edad350e18e..cc3ab0025864 100644 --- a/core/java/android/app/usage/UsageStatsManagerInternal.java +++ b/core/java/android/app/usage/UsageStatsManagerInternal.java @@ -98,6 +98,12 @@ public abstract class UsageStatsManagerInternal { public abstract void prepareShutdown(); /** + * When the device power button is long pressed for 3.5 seconds, prepareForPossibleShutdown() + * is called. + */ + public abstract void prepareForPossibleShutdown(); + + /** * Returns true if the app has not been used for a certain amount of time. How much time? * Could be hours, could be days, who knows? * diff --git a/core/java/android/attention/AttentionManagerInternal.java b/core/java/android/attention/AttentionManagerInternal.java new file mode 100644 index 000000000000..6b7f10e8d426 --- /dev/null +++ b/core/java/android/attention/AttentionManagerInternal.java @@ -0,0 +1,73 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.attention; + +/** + * Attention manager local system server interface. + * + * @hide Only for use within the system server. + */ +public abstract class AttentionManagerInternal { + /** + * Returns {@code true} if attention service is supported on this device. + */ + public abstract boolean isAttentionServiceSupported(); + + /** + * Checks whether user attention is at the screen and calls in the provided callback. + * + * @param requestCode a code associated with the attention check request; this code would be + * used to call back in {@link AttentionCallbackInternal#onSuccess} and + * {@link AttentionCallbackInternal#onFailure} + * @param timeoutMillis a budget for the attention check; if it takes longer - {@link + * AttentionCallbackInternal#onFailure} would be called with the {@link + * android.service.attention.AttentionService#ATTENTION_FAILURE_TIMED_OUT} + * code + * @param callback a callback for when the attention check has completed + * @return {@code true} if the attention check should succeed; {@false} otherwise. + */ + public abstract boolean checkAttention(int requestCode, + long timeoutMillis, AttentionCallbackInternal callback); + + /** + * Cancels the specified attention check in case it's no longer needed. + * + * @param requestCode a code provided during {@link #checkAttention} + */ + public abstract void cancelAttentionCheck(int requestCode); + + /** Internal interface for attention callback. */ + public abstract static class AttentionCallbackInternal { + /** + * Provides the result of the attention check, if the check was successful. + * + * @param requestCode a code provided in {@link #checkAttention} + * @param result an int with the result of the check + * @param timestamp a {@code SystemClock.uptimeMillis()} timestamp associated with the + * attention check + */ + public abstract void onSuccess(int requestCode, int result, long timestamp); + + /** + * Provides the explanation for why the attention check had failed. + * + * @param requestCode a code provided in {@link #checkAttention} + * @param error an int with the reason for failure + */ + public abstract void onFailure(int requestCode, int error); + } +} diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java index d27cce535c3b..8497656df2be 100644 --- a/core/java/android/content/Intent.java +++ b/core/java/android/content/Intent.java @@ -33,6 +33,7 @@ import android.content.pm.ApplicationInfo; import android.content.pm.ComponentInfo; import android.content.pm.PackageManager; import android.content.pm.ResolveInfo; +import android.content.pm.ShortcutInfo; import android.content.res.Resources; import android.content.res.TypedArray; import android.graphics.Rect; @@ -1954,6 +1955,17 @@ public class Intent implements Parcelable, Cloneable { public static final String EXTRA_LAUNCHER_EXTRAS = "android.intent.extra.LAUNCHER_EXTRAS"; /** + * Intent extra: ID of the shortcut used to send the share intent. + * + * @see ShortcutInfo#getId() + * + * <p> + * Type: String + * </p> + */ + public static final String EXTRA_SHORTCUT_ID = "android.intent.extra.shortcut.ID"; + + /** * Activity action: Launch UI to manage which apps have a given permission. * <p> * Input: {@link #EXTRA_PERMISSION_NAME} specifies the permission group diff --git a/core/java/android/content/pm/CrossProfileApps.java b/core/java/android/content/pm/CrossProfileApps.java index 740fd7f963f9..b7366f1bbafc 100644 --- a/core/java/android/content/pm/CrossProfileApps.java +++ b/core/java/android/content/pm/CrossProfileApps.java @@ -18,6 +18,7 @@ package android.content.pm; import android.annotation.NonNull; import android.annotation.RequiresPermission; import android.annotation.SystemApi; +import android.annotation.UnsupportedAppUsage; import android.content.ComponentName; import android.content.Context; import android.content.res.Resources; @@ -76,9 +77,23 @@ public class CrossProfileApps { } /** - * Starts the specified activity of the caller package in the specified profile if the caller - * has {@link android.Manifest.permission#INTERACT_ACROSS_PROFILES} permission and - * both the caller and target user profiles are in the same user group. + * @deprecated use {@link #startActivity(ComponentName, UserHandle)} instead. + * + * @removed + * @hide + */ + @Deprecated + @UnsupportedAppUsage + public void startAnyActivity(@NonNull ComponentName component, @NonNull UserHandle targetUser) { + startActivity(component, targetUser); + } + + /** + * Starts the specified activity of the caller package in the specified profile. Unlike + * {@link #startMainActivity}, this can start any activity of the caller package, not just + * the main activity. + * The caller must have the {@link android.Manifest.permission#INTERACT_ACROSS_PROFILES} + * permission and both the caller and target user profiles must be in the same profile group. * * @param component The ComponentName of the activity to launch. It must be exported. * @param targetUser The UserHandle of the profile, must be one of the users returned by @@ -88,7 +103,7 @@ public class CrossProfileApps { */ @SystemApi @RequiresPermission(android.Manifest.permission.INTERACT_ACROSS_PROFILES) - public void startAnyActivity(@NonNull ComponentName component, @NonNull UserHandle targetUser) { + public void startActivity(@NonNull ComponentName component, @NonNull UserHandle targetUser) { try { mService.startActivityAsUser(mContext.getIApplicationThread(), mContext.getPackageName(), component, targetUser.getIdentifier(), false); diff --git a/core/java/android/content/pm/IPackageManager.aidl b/core/java/android/content/pm/IPackageManager.aidl index d5c3b26b094d..4b130b2371bf 100644 --- a/core/java/android/content/pm/IPackageManager.aidl +++ b/core/java/android/content/pm/IPackageManager.aidl @@ -540,6 +540,11 @@ interface IPackageManager { String targetCompilerFilter, boolean force); /** + * Ask the package manager to compile layouts in the given package. + */ + boolean compileLayouts(String packageName); + + /** * Ask the package manager to dump profiles associated with a package. */ void dumpProfiles(String packageName); diff --git a/core/java/android/content/pm/IShortcutService.aidl b/core/java/android/content/pm/IShortcutService.aidl index 03124be7ab7d..c702b16c97f6 100644 --- a/core/java/android/content/pm/IShortcutService.aidl +++ b/core/java/android/content/pm/IShortcutService.aidl @@ -16,6 +16,7 @@ package android.content.pm; import android.content.Intent; +import android.content.IntentFilter; import android.content.IntentSender; import android.content.pm.ParceledListSlice; import android.content.pm.ShortcutInfo; @@ -72,4 +73,7 @@ interface IShortcutService { void applyRestore(in byte[] payload, int user); boolean isRequestPinItemSupported(int user, int requestType); + + // System API used by framework's ShareSheet (ChooserActivity) + ParceledListSlice getShareTargets(String packageName, in IntentFilter filter, int userId); }
\ No newline at end of file diff --git a/core/java/android/content/pm/PackageInfo.java b/core/java/android/content/pm/PackageInfo.java index b8d7889c86ff..3a77a6a269dc 100644 --- a/core/java/android/content/pm/PackageInfo.java +++ b/core/java/android/content/pm/PackageInfo.java @@ -23,9 +23,6 @@ import android.os.Build; import android.os.Parcel; import android.os.Parcelable; -import java.util.ArrayList; -import java.util.List; - /** * Overall information about the contents of a package. This corresponds * to all of the information collected from AndroidManifest.xml. @@ -374,6 +371,14 @@ public class PackageInfo implements Parcelable { public String overlayTarget; /** + * What overlayable set of elements package, if any, this package will overlay. + * + * Overlayable name defined within the target package, or null. + * @hide + */ + public String overlayTargetName; + + /** * The overlay category, if any, of this package * * @hide diff --git a/core/java/android/content/pm/PackageManagerInternal.java b/core/java/android/content/pm/PackageManagerInternal.java index 45b5dcac6cc0..c7320b0d6ccf 100644 --- a/core/java/android/content/pm/PackageManagerInternal.java +++ b/core/java/android/content/pm/PackageManagerInternal.java @@ -55,6 +55,7 @@ public abstract class PackageManagerInternal { public static final int PACKAGE_PERMISSION_CONTROLLER = 6; public static final int PACKAGE_WELLBEING = 7; public static final int PACKAGE_DOCUMENTER = 8; + public static final int PACKAGE_CONFIGURATOR = 9; @IntDef(value = { PACKAGE_SYSTEM, PACKAGE_SETUP_WIZARD, @@ -65,6 +66,7 @@ public abstract class PackageManagerInternal { PACKAGE_PERMISSION_CONTROLLER, PACKAGE_WELLBEING, PACKAGE_DOCUMENTER, + PACKAGE_CONFIGURATOR, }) @Retention(RetentionPolicy.SOURCE) public @interface KnownPackage {} @@ -820,4 +822,9 @@ public abstract class PackageManagerInternal { * PACKAGE_ROLLBACK_AGENT permission. */ public abstract void setEnableRollbackCode(int token, int enableRollbackCode); + + /** + * Ask the package manager to compile layouts in the given package. + */ + public abstract boolean compileLayouts(String packageName); } diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java index 1ac0ab6c9e59..5e15b009c39f 100644 --- a/core/java/android/content/pm/PackageParser.java +++ b/core/java/android/content/pm/PackageParser.java @@ -689,6 +689,7 @@ public class PackageParser { pi.restrictedAccountType = p.mRestrictedAccountType; pi.requiredAccountType = p.mRequiredAccountType; pi.overlayTarget = p.mOverlayTarget; + pi.overlayTargetName = p.mOverlayTargetName; pi.overlayCategory = p.mOverlayCategory; pi.overlayPriority = p.mOverlayPriority; pi.mOverlayIsStatic = p.mOverlayIsStatic; @@ -2122,6 +2123,8 @@ public class PackageParser { com.android.internal.R.styleable.AndroidManifestResourceOverlay); pkg.mOverlayTarget = sa.getString( com.android.internal.R.styleable.AndroidManifestResourceOverlay_targetPackage); + pkg.mOverlayTargetName = sa.getString( + com.android.internal.R.styleable.AndroidManifestResourceOverlay_targetName); pkg.mOverlayCategory = sa.getString( com.android.internal.R.styleable.AndroidManifestResourceOverlay_category); pkg.mOverlayPriority = sa.getInt( @@ -3777,9 +3780,11 @@ public class PackageParser { ai.flags |= ApplicationInfo.FLAG_MULTIARCH; } + final boolean extractNativeLibsDefault = + owner.applicationInfo.targetSdkVersion < Build.VERSION_CODES.Q; if (sa.getBoolean( com.android.internal.R.styleable.AndroidManifestApplication_extractNativeLibs, - true)) { + extractNativeLibsDefault)) { ai.flags |= ApplicationInfo.FLAG_EXTRACT_NATIVE_LIBS; } @@ -6728,6 +6733,7 @@ public class PackageParser { public String mRequiredAccountType; public String mOverlayTarget; + public String mOverlayTargetName; public String mOverlayCategory; public int mOverlayPriority; public boolean mOverlayIsStatic; @@ -7251,6 +7257,7 @@ public class PackageParser { mRestrictedAccountType = dest.readString(); mRequiredAccountType = dest.readString(); mOverlayTarget = dest.readString(); + mOverlayTargetName = dest.readString(); mOverlayCategory = dest.readString(); mOverlayPriority = dest.readInt(); mOverlayIsStatic = (dest.readInt() == 1); @@ -7378,6 +7385,7 @@ public class PackageParser { dest.writeString(mRestrictedAccountType); dest.writeString(mRequiredAccountType); dest.writeString(mOverlayTarget); + dest.writeString(mOverlayTargetName); dest.writeString(mOverlayCategory); dest.writeInt(mOverlayPriority); dest.writeInt(mOverlayIsStatic ? 1 : 0); diff --git a/core/java/android/content/pm/PermissionGroupInfo.java b/core/java/android/content/pm/PermissionGroupInfo.java index 8cf66d81972f..f21612a58a53 100644 --- a/core/java/android/content/pm/PermissionGroupInfo.java +++ b/core/java/android/content/pm/PermissionGroupInfo.java @@ -49,7 +49,7 @@ public class PermissionGroupInfo extends PackageItemInfo implements Parcelable { * only access while in the foreground. * * From the "requestDetail" attribute or, if not set, {@link - * android.content.res.ResourceId#ID_NULL}. + * android.content.res.Resources#ID_NULL}. * * @hide */ @@ -61,7 +61,7 @@ public class PermissionGroupInfo extends PackageItemInfo implements Parcelable { * access. Also used when requesting both foreground and background access. * * From the "backgroundRequest" attribute or, if not set, {@link - * android.content.res.ResourceId#ID_NULL}. + * android.content.res.Resources#ID_NULL}. * * @hide */ @@ -73,7 +73,7 @@ public class PermissionGroupInfo extends PackageItemInfo implements Parcelable { * background access. * * From the "backgroundRequestDetail" attribute or, if not set, {@link - * android.content.res.ResourceId#ID_NULL}. + * android.content.res.Resources#ID_NULL}. * * @hide */ diff --git a/core/java/android/content/pm/PermissionInfo.java b/core/java/android/content/pm/PermissionInfo.java index a3395ac9fd13..5d2cf0a7d101 100644 --- a/core/java/android/content/pm/PermissionInfo.java +++ b/core/java/android/content/pm/PermissionInfo.java @@ -203,6 +203,16 @@ public class PermissionInfo extends PackageItemInfo implements Parcelable { @TestApi public static final int PROTECTION_FLAG_DOCUMENTER = 0x40000; + /** + * Additional flag for {@link #protectionLevel}, corresponding to the + * {@code configurator} value of {@link android.R.attr#protectionLevel}. + * + * @hide + */ + @SystemApi + @TestApi + public static final int PROTECTION_FLAG_CONFIGURATOR = 0x80000; + /** @hide */ @IntDef(flag = true, prefix = { "PROTECTION_FLAG_" }, value = { @@ -222,6 +232,7 @@ public class PermissionInfo extends PackageItemInfo implements Parcelable { PROTECTION_FLAG_SYSTEM_TEXT_CLASSIFIER, PROTECTION_FLAG_WELLBEING, PROTECTION_FLAG_DOCUMENTER, + PROTECTION_FLAG_CONFIGURATOR, }) @Retention(RetentionPolicy.SOURCE) public @interface ProtectionFlags {} @@ -417,6 +428,9 @@ public class PermissionInfo extends PackageItemInfo implements Parcelable { if ((level & PermissionInfo.PROTECTION_FLAG_DOCUMENTER) != 0) { protLevel += "|documenter"; } + if ((level & PROTECTION_FLAG_CONFIGURATOR) != 0) { + protLevel += "|configurator"; + } return protLevel; } diff --git a/core/java/android/content/pm/ResolveInfo.java b/core/java/android/content/pm/ResolveInfo.java index 701c5dbc8398..894de94a47a0 100644 --- a/core/java/android/content/pm/ResolveInfo.java +++ b/core/java/android/content/pm/ResolveInfo.java @@ -16,6 +16,7 @@ package android.content.pm; +import android.annotation.SystemApi; import android.annotation.UnsupportedAppUsage; import android.content.ComponentName; import android.content.IntentFilter; @@ -175,9 +176,12 @@ public class ResolveInfo implements Parcelable { public boolean system; /** - * @hide Does the associated IntentFilter comes from a Browser ? + * Will be set to {@code true} if the {@link IntentFilter} responsible for intent + * resolution is classified as a "browser". + * + * @hide */ - @UnsupportedAppUsage + @SystemApi public boolean handleAllWebDataURI; /** {@hide} */ diff --git a/core/java/android/content/pm/ShortcutInfo.java b/core/java/android/content/pm/ShortcutInfo.java index ec2e2fd474a2..fe68b8a048c2 100644 --- a/core/java/android/content/pm/ShortcutInfo.java +++ b/core/java/android/content/pm/ShortcutInfo.java @@ -21,6 +21,7 @@ import android.annotation.Nullable; import android.annotation.TestApi; import android.annotation.UnsupportedAppUsage; import android.annotation.UserIdInt; +import android.app.Person; import android.app.TaskStackBuilder; import android.content.ComponentName; import android.content.Context; @@ -111,6 +112,9 @@ public final class ShortcutInfo implements Parcelable { public static final int FLAG_SHADOW = 1 << 12; /** @hide */ + public static final int FLAG_LONG_LIVED = 1 << 13; + + /** @hide */ @IntDef(flag = true, prefix = { "FLAG_" }, value = { FLAG_DYNAMIC, FLAG_PINNED, @@ -124,6 +128,8 @@ public final class ShortcutInfo implements Parcelable { FLAG_ADAPTIVE_BITMAP, FLAG_RETURNED_BY_SERVICE, FLAG_ICON_FILE_PENDING_SAVE, + FLAG_SHADOW, + FLAG_LONG_LIVED, }) @Retention(RetentionPolicy.SOURCE) public @interface ShortcutFlags {} @@ -344,6 +350,9 @@ public final class ShortcutInfo implements Parcelable { @Nullable private PersistableBundle[] mIntentPersistableExtrases; + @Nullable + private Person[] mPersons; + private int mRank; /** @@ -399,6 +408,10 @@ public final class ShortcutInfo implements Parcelable { mCategories = cloneCategories(b.mCategories); mIntents = cloneIntents(b.mIntents); fixUpIntentExtras(); + mPersons = clonePersons(b.mPersons); + if (b.mIsLongLived) { + setLongLived(); + } mRank = b.mRank; mExtras = b.mExtras; updateTimestamp(); @@ -465,6 +478,20 @@ public final class ShortcutInfo implements Parcelable { return ret; } + private static Person[] clonePersons(Person[] persons) { + if (persons == null) { + return null; + } + final Person[] ret = new Person[persons.length]; + for (int i = 0; i < ret.length; i++) { + if (persons[i] != null) { + // Don't need to keep the icon, remove it to save space + ret[i] = persons[i].toBuilder().setIcon(null).build(); + } + } + return ret; + } + /** * Throws if any of the mandatory fields is not set. * @@ -511,6 +538,7 @@ public final class ShortcutInfo implements Parcelable { mDisabledMessage = source.mDisabledMessage; mDisabledMessageResId = source.mDisabledMessageResId; mCategories = cloneCategories(source.mCategories); + mPersons = clonePersons(source.mPersons); if ((cloneFlags & CLONE_REMOVE_INTENT) == 0) { mIntents = cloneIntents(source.mIntents); mIntentPersistableExtrases = @@ -833,6 +861,9 @@ public final class ShortcutInfo implements Parcelable { if (source.mCategories != null) { mCategories = cloneCategories(source.mCategories); } + if (source.mPersons != null) { + mPersons = clonePersons(source.mPersons); + } if (source.mIntents != null) { mIntents = cloneIntents(source.mIntents); mIntentPersistableExtrases = @@ -901,6 +932,10 @@ public final class ShortcutInfo implements Parcelable { private Intent[] mIntents; + private Person[] mPersons; + + private boolean mIsLongLived; + private int mRank = RANK_NOT_SET; private PersistableBundle mExtras; @@ -1165,6 +1200,53 @@ public final class ShortcutInfo implements Parcelable { } /** + * Add a person that is relevant to this shortcut. Alternatively, + * {@link #setPersons(Person[])} can be used to add multiple persons to a shortcut. + * + * <p> This is an optional field, but the addition of person may cause this shortcut to + * appear more prominently in the user interface (e.g. ShareSheet). + * + * <p> A person should usually contain a uri in order to benefit from the ranking boost. + * However, even if no uri is provided, it's beneficial to provide people in the shortcut, + * such that listeners and voice only devices can announce and handle them properly. + * + * @see Person + * @see #setPersons(Person[]) + */ + @NonNull + public Builder setPerson(@NonNull Person person) { + return setPersons(new Person[]{person}); + } + + /** + * Sets multiple persons instead of a single person. + * + * @see Person + * @see #setPerson(Person) + */ + @NonNull + public Builder setPersons(@NonNull Person[] persons) { + Preconditions.checkNotNull(persons, "persons cannot be null"); + Preconditions.checkNotNull(persons.length, "persons cannot be empty"); + for (Person person : persons) { + Preconditions.checkNotNull(person, "persons cannot contain null"); + } + mPersons = clonePersons(persons); + return this; + } + + /** + * Sets if a shortcut would be valid even if it has been unpublished/invisible by the app + * (as a dynamic or pinned shortcut). If it is long lived, it can be cached by various + * system services even after it has been unpublished as a dynamic shortcut. + */ + @NonNull + public Builder setLongLived() { + mIsLongLived = true; + return this; + } + + /** * "Rank" of a shortcut, which is a non-negative value that's used by the launcher app * to sort shortcuts. * @@ -1395,6 +1477,16 @@ public final class ShortcutInfo implements Parcelable { } /** + * Return the Persons set with {@link Builder#setPersons(Person[])}. + * + * @hide + */ + @Nullable + public Person[] getPersons() { + return clonePersons(mPersons); + } + + /** * The extras in the intents. We convert extras into {@link PersistableBundle} so we can * persist them. * @hide @@ -1525,6 +1617,16 @@ public final class ShortcutInfo implements Parcelable { addFlags(FLAG_RETURNED_BY_SERVICE); } + /** @hide */ + public boolean isLongLived() { + return hasFlags(FLAG_LONG_LIVED); + } + + /** @hide */ + public void setLongLived() { + addFlags(FLAG_LONG_LIVED); + } + /** Return whether a shortcut is dynamic. */ public boolean isDynamic() { return hasFlags(FLAG_DYNAMIC); @@ -1893,6 +1995,8 @@ public final class ShortcutInfo implements Parcelable { mCategories.add(source.readString().intern()); } } + + mPersons = source.readParcelableArray(cl, Person.class); } @Override @@ -1940,6 +2044,8 @@ public final class ShortcutInfo implements Parcelable { } else { dest.writeInt(0); } + + dest.writeParcelableArray(mPersons, flags); } public static final Creator<ShortcutInfo> CREATOR = @@ -2040,6 +2146,9 @@ public final class ShortcutInfo implements Parcelable { if (isReturnedByServer()) { sb.append("Rets"); } + if (isLongLived()) { + sb.append("Liv"); + } sb.append("]"); addIndentOrComma(sb, indent); @@ -2094,6 +2203,11 @@ public final class ShortcutInfo implements Parcelable { addIndentOrComma(sb, indent); + sb.append("persons="); + sb.append(mPersons); + + addIndentOrComma(sb, indent); + sb.append("icon="); sb.append(mIcon); diff --git a/core/java/android/content/pm/ShortcutManager.java b/core/java/android/content/pm/ShortcutManager.java index 2d590033259f..4f7acd96aa6b 100644 --- a/core/java/android/content/pm/ShortcutManager.java +++ b/core/java/android/content/pm/ShortcutManager.java @@ -17,17 +17,22 @@ package android.content.pm; import android.annotation.NonNull; import android.annotation.Nullable; +import android.annotation.SystemApi; import android.annotation.SystemService; import android.annotation.TestApi; import android.annotation.UnsupportedAppUsage; import android.annotation.UserIdInt; import android.app.usage.UsageStatsManager; +import android.content.ComponentName; import android.content.Context; import android.content.Intent; +import android.content.IntentFilter; import android.content.IntentSender; import android.graphics.drawable.AdaptiveIconDrawable; import android.os.Build; import android.os.Build.VERSION_CODES; +import android.os.Parcel; +import android.os.Parcelable; import android.os.RemoteException; import android.os.ServiceManager; @@ -549,4 +554,85 @@ public class ShortcutManager { protected int injectMyUserId() { return mContext.getUserId(); } + + /** + * Used by framework's ShareSheet (ChooserActivity.java) to retrieve all of the direct share + * targets that match the given IntentFilter. + * + * @param filter IntentFilter that will be used to retrieve the matching {@link ShortcutInfo}s. + * @return List of {@link ShareShortcutInfo}s that match the given IntentFilter. + * @hide + */ + @NonNull + @SystemApi + public List<ShareShortcutInfo> getShareTargets(@NonNull IntentFilter filter) { + try { + return mService.getShareTargets(mContext.getPackageName(), filter, + injectMyUserId()).getList(); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + /** + * Represents the result of a query return by {@link #getShareTargets(IntentFilter)}. + * + * @hide + */ + @SystemApi + public static final class ShareShortcutInfo implements Parcelable { + private final ShortcutInfo mShortcutInfo; + private final ComponentName mTargetComponent; + + /** + * @hide + */ + public ShareShortcutInfo(@NonNull ShortcutInfo shortcutInfo, + @NonNull ComponentName targetComponent) { + if (shortcutInfo == null) { + throw new NullPointerException("shortcut info is null"); + } + if (targetComponent == null) { + throw new NullPointerException("target component is null"); + } + + mShortcutInfo = shortcutInfo; + mTargetComponent = targetComponent; + } + + private ShareShortcutInfo(Parcel in) { + mShortcutInfo = in.readParcelable(ShortcutInfo.class.getClassLoader()); + mTargetComponent = in.readParcelable(ComponentName.class.getClassLoader()); + } + + public ShortcutInfo getShortcutInfo() { + return mShortcutInfo; + } + + public ComponentName getTargetComponent() { + return mTargetComponent; + } + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(Parcel dest, int flags) { + dest.writeParcelable(mShortcutInfo, flags); + dest.writeParcelable(mTargetComponent, flags); + } + + public static final Parcelable.Creator<ShareShortcutInfo> CREATOR = + new Parcelable.Creator<ShareShortcutInfo>() { + public ShareShortcutInfo createFromParcel(Parcel in) { + return new ShareShortcutInfo(in); + } + + public ShareShortcutInfo[] newArray(int size) { + return new ShareShortcutInfo[size]; + } + }; + } } diff --git a/core/java/android/content/pm/SuspendDialogInfo.java b/core/java/android/content/pm/SuspendDialogInfo.java index c798c99fed90..53b52f535fa0 100644 --- a/core/java/android/content/pm/SuspendDialogInfo.java +++ b/core/java/android/content/pm/SuspendDialogInfo.java @@ -16,7 +16,7 @@ package android.content.pm; -import static android.content.res.ResourceId.ID_NULL; +import static android.content.res.Resources.ID_NULL; import android.annotation.DrawableRes; import android.annotation.NonNull; diff --git a/core/java/android/content/res/ResourceId.java b/core/java/android/content/res/ResourceId.java index adb9cf1c8015..3c7b5fc11164 100644 --- a/core/java/android/content/res/ResourceId.java +++ b/core/java/android/content/res/ResourceId.java @@ -22,12 +22,6 @@ import android.annotation.AnyRes; * @hide */ public final class ResourceId { - - /** - * The {@code null} resource ID. - */ - public static final @AnyRes int ID_NULL = 0; - /** * Checks whether the integer {@code id} is a valid resource ID, as generated by AAPT. * <p>Note that a negative integer is not necessarily an invalid resource ID, and custom diff --git a/core/java/android/content/res/Resources.java b/core/java/android/content/res/Resources.java index c4b315ec90c8..baf64ad72a51 100644 --- a/core/java/android/content/res/Resources.java +++ b/core/java/android/content/res/Resources.java @@ -98,6 +98,12 @@ import java.util.ArrayList; * href="{@docRoot}guide/topics/resources/index.html">Application Resources</a>.</p> */ public class Resources { + /** + * The {@code null} resource ID. This denotes an invalid resource ID that is returned by the + * system when a resource is not found or the value is set to {@code @null} in XML. + */ + public static final @AnyRes int ID_NULL = 0; + static final String TAG = "Resources"; private static final Object sSync = new Object(); @@ -168,7 +174,7 @@ public class Resources { /** @hide */ public static int selectSystemTheme(int curTheme, int targetSdkVersion, int orig, int holo, int dark, int deviceDefault) { - if (curTheme != ResourceId.ID_NULL) { + if (curTheme != ID_NULL) { return curTheme; } if (targetSdkVersion < Build.VERSION_CODES.HONEYCOMB) { diff --git a/core/java/android/content/res/ResourcesImpl.java b/core/java/android/content/res/ResourcesImpl.java index 77796d9ebdf5..d8564d570a4d 100644 --- a/core/java/android/content/res/ResourcesImpl.java +++ b/core/java/android/content/res/ResourcesImpl.java @@ -855,13 +855,9 @@ public class ResourcesImpl { try { if (file.endsWith(".xml")) { if (file.startsWith("res/color/")) { - ColorStateList csl = loadColorStateList(wrapper, value, id, null); - dr = (csl != null ? new ColorStateListDrawable(csl) : null); + dr = loadColorOrXmlDrawable(wrapper, value, id, density, file); } else { - final XmlResourceParser rp = loadXmlResourceParser( - file, id, value.assetCookie, "drawable"); - dr = Drawable.createFromXmlForDensity(wrapper, rp, density, null); - rp.close(); + dr = loadXmlDrawable(wrapper, value, id, density, file); } } else { final InputStream is = mAssets.openNonAsset( @@ -915,6 +911,33 @@ public class ResourcesImpl { return dr; } + private Drawable loadColorOrXmlDrawable(@NonNull Resources wrapper, @NonNull TypedValue value, + int id, int density, String file) { + try { + ColorStateList csl = loadColorStateList(wrapper, value, id, null); + return new ColorStateListDrawable(csl); + } catch (NotFoundException originalException) { + // If we fail to load as color, try as normal XML drawable + try { + return loadXmlDrawable(wrapper, value, id, density, file); + } catch (Exception ignored) { + // If fallback also fails, throw the original exception + throw originalException; + } + } + } + + private Drawable loadXmlDrawable(@NonNull Resources wrapper, @NonNull TypedValue value, + int id, int density, String file) + throws IOException, XmlPullParserException { + try ( + XmlResourceParser rp = + loadXmlResourceParser(file, id, value.assetCookie, "drawable") + ) { + return Drawable.createFromXmlForDensity(wrapper, rp, density, null); + } + } + /** * Loads a font from XML or resources stream. */ diff --git a/core/java/android/hardware/display/BrightnessConfiguration.java b/core/java/android/hardware/display/BrightnessConfiguration.java index be054297c769..8c74ddc7698c 100644 --- a/core/java/android/hardware/display/BrightnessConfiguration.java +++ b/core/java/android/hardware/display/BrightnessConfiguration.java @@ -91,9 +91,7 @@ public final class BrightnessConfiguration implements Parcelable { * * @return The matching brightness correction, or null. * - * @hide */ - @SystemApi @Nullable public BrightnessCorrection getCorrectionByPackageName(String packageName) { return mCorrectionsByPackageName.get(packageName); @@ -106,10 +104,7 @@ public final class BrightnessConfiguration implements Parcelable { * The app category. * * @return The matching brightness correction, or null. - * - * @hide */ - @SystemApi @Nullable public BrightnessCorrection getCorrectionByCategory(int category) { return mCorrectionsByCategory.get(category); @@ -416,9 +411,7 @@ public final class BrightnessConfiguration implements Parcelable { * * @return The maximum number of corrections by package name allowed. * - * @hide */ - @SystemApi public int getMaxCorrectionsByPackageName() { return MAX_CORRECTIONS_BY_PACKAGE_NAME; } @@ -428,9 +421,7 @@ public final class BrightnessConfiguration implements Parcelable { * * @return The maximum number of corrections by category allowed. * - * @hide */ - @SystemApi public int getMaxCorrectionsByCategory() { return MAX_CORRECTIONS_BY_CATEGORY; } @@ -451,9 +442,7 @@ public final class BrightnessConfiguration implements Parcelable { * Maximum number of corrections by package name exceeded (see * {@link #getMaxCorrectionsByPackageName}). * - * @hide */ - @SystemApi public Builder addCorrectionByPackageName(String packageName, BrightnessCorrection correction) { if (mCorrectionsByPackageName.size() >= getMaxCorrectionsByPackageName()) { @@ -479,9 +468,7 @@ public final class BrightnessConfiguration implements Parcelable { * Maximum number of corrections by category exceeded (see * {@link #getMaxCorrectionsByCategory}). * - * @hide */ - @SystemApi public Builder addCorrectionByCategory(@ApplicationInfo.Category int category, BrightnessCorrection correction) { if (mCorrectionsByCategory.size() >= getMaxCorrectionsByCategory()) { @@ -504,8 +491,6 @@ public final class BrightnessConfiguration implements Parcelable { /** * Builds the {@link BrightnessConfiguration}. - * - * A brightness curve <b>must</b> be set before calling this. */ public BrightnessConfiguration build() { if (mCurveLux == null || mCurveNits == null) { diff --git a/core/java/android/hardware/display/BrightnessCorrection.java b/core/java/android/hardware/display/BrightnessCorrection.java index c4e0e3b723cd..6a073ffaaa5b 100644 --- a/core/java/android/hardware/display/BrightnessCorrection.java +++ b/core/java/android/hardware/display/BrightnessCorrection.java @@ -18,6 +18,7 @@ package android.hardware.display; import android.annotation.NonNull; import android.annotation.SystemApi; +import android.annotation.TestApi; import android.os.Parcel; import android.os.Parcelable; import android.util.MathUtils; @@ -41,6 +42,7 @@ import java.io.IOException; * @hide */ @SystemApi +@TestApi public final class BrightnessCorrection implements Parcelable { private static final int SCALE_AND_TRANSLATE_LOG = 1; @@ -98,6 +100,24 @@ public final class BrightnessCorrection implements Parcelable { return mImplementation.toString(); } + + @Override + public boolean equals(Object o) { + if (o == this) { + return true; + } + if (!(o instanceof BrightnessCorrection)) { + return false; + } + BrightnessCorrection other = (BrightnessCorrection) o; + return other.mImplementation.equals(mImplementation); + } + + @Override + public int hashCode() { + return mImplementation.hashCode(); + } + public static final Creator<BrightnessCorrection> CREATOR = new Creator<BrightnessCorrection>() { public BrightnessCorrection createFromParcel(Parcel in) { @@ -215,6 +235,26 @@ public final class BrightnessCorrection implements Parcelable { } @Override + public boolean equals(Object o) { + if (o == this) { + return true; + } + if (!(o instanceof ScaleAndTranslateLog)) { + return false; + } + ScaleAndTranslateLog other = (ScaleAndTranslateLog) o; + return other.mScale == mScale && other.mTranslate == mTranslate; + } + + @Override + public int hashCode() { + int result = 1; + result = result * 31 + Float.hashCode(mScale); + result = result * 31 + Float.hashCode(mTranslate); + return result; + } + + @Override public void writeToParcel(Parcel dest) { dest.writeInt(SCALE_AND_TRANSLATE_LOG); dest.writeFloat(mScale); diff --git a/core/java/android/hardware/display/ColorDisplayManager.java b/core/java/android/hardware/display/ColorDisplayManager.java index 0cf2d18e5c04..70a9f08ea58a 100644 --- a/core/java/android/hardware/display/ColorDisplayManager.java +++ b/core/java/android/hardware/display/ColorDisplayManager.java @@ -17,6 +17,8 @@ package android.hardware.display; import android.Manifest; +import android.annotation.IntRange; +import android.annotation.NonNull; import android.annotation.RequiresPermission; import android.annotation.SystemApi; import android.annotation.SystemService; @@ -61,16 +63,30 @@ public final class ColorDisplayManager { * * @param saturationLevel 0-100 (inclusive), where 100 is full saturation * @return whether the saturation level change was applied successfully - * * @hide */ @SystemApi @RequiresPermission(Manifest.permission.CONTROL_DISPLAY_COLOR_TRANSFORMS) - public boolean setSaturationLevel(int saturationLevel) { + public boolean setSaturationLevel(@IntRange(from = 0, to = 100) int saturationLevel) { return mManager.setSaturationLevel(saturationLevel); } /** + * Set the level of color saturation to apply to a specific app. + * + * @param packageName the package name of the app whose windows should be desaturated + * @param saturationLevel 0-100 (inclusive), where 100 is full saturation + * @return whether the saturation level change was applied successfully + * @hide + */ + @SystemApi + @RequiresPermission(Manifest.permission.CONTROL_DISPLAY_COLOR_TRANSFORMS) + public boolean setAppSaturationLevel(@NonNull String packageName, + @IntRange(from = 0, to = 100) int saturationLevel) { + return mManager.setAppSaturationLevel(packageName, saturationLevel); + } + + /** * Returns {@code true} if Night Display is supported by the device. * * @hide @@ -88,6 +104,16 @@ public final class ColorDisplayManager { return context.getResources().getBoolean(R.bool.config_displayWhiteBalanceAvailable); } + /** + * Check if the color transforms are color accelerated. Some transforms are experimental only + * on non-accelerated platforms due to the performance implications. + * + * @hide + */ + public static boolean isColorTransformAccelerated(Context context) { + return context.getResources().getBoolean(R.bool.config_setColorTransformAccelerated); + } + private static class ColorDisplayManagerInternal { private static ColorDisplayManagerInternal sInstance; @@ -128,5 +154,13 @@ public final class ColorDisplayManager { throw e.rethrowFromSystemServer(); } } + + boolean setAppSaturationLevel(String packageName, int saturationLevel) { + try { + return mCdm.setAppSaturationLevel(packageName, saturationLevel); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } } } diff --git a/core/java/android/hardware/display/IColorDisplayManager.aidl b/core/java/android/hardware/display/IColorDisplayManager.aidl index 81b82c64461f..644f510d45f9 100644 --- a/core/java/android/hardware/display/IColorDisplayManager.aidl +++ b/core/java/android/hardware/display/IColorDisplayManager.aidl @@ -21,4 +21,5 @@ interface IColorDisplayManager { boolean isDeviceColorManaged(); boolean setSaturationLevel(int saturationLevel); + boolean setAppSaturationLevel(String packageName, int saturationLevel); }
\ No newline at end of file diff --git a/core/java/android/hardware/hdmi/HdmiControlManager.java b/core/java/android/hardware/hdmi/HdmiControlManager.java index a7734f544607..a98b31ad6a5e 100644 --- a/core/java/android/hardware/hdmi/HdmiControlManager.java +++ b/core/java/android/hardware/hdmi/HdmiControlManager.java @@ -55,6 +55,10 @@ public final class HdmiControlManager { @Nullable private final IHdmiControlService mService; + private static final int INVALID_PHYSICAL_ADDRESS = 0xFFFF; + + private int mPhysicalAddress = INVALID_PHYSICAL_ADDRESS; + /** * Broadcast Action: Display OSD message. * <p>Send when the service has a message to display on screen for events @@ -505,14 +509,41 @@ public final class HdmiControlManager { * @hide */ public int getPhysicalAddress() { + if (mPhysicalAddress != INVALID_PHYSICAL_ADDRESS) { + return mPhysicalAddress; + } try { - return mService.getPhysicalAddress(); + mPhysicalAddress = mService.getPhysicalAddress(); + return mPhysicalAddress; } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } /** + * Check if the target device is connected to the current device. The + * API also returns true if the current device is the target. + * + * @param targetDevice {@link HdmiDeviceInfo} of the target device. + * @return true if {@code device} is directly or indirectly connected to the + * + * TODO(b/110094868): unhide for Q + * @hide + */ + public boolean isTargetDeviceConnected(HdmiDeviceInfo targetDevice) { + mPhysicalAddress = getPhysicalAddress(); + if (mPhysicalAddress == INVALID_PHYSICAL_ADDRESS) { + return false; + } + int targetPhysicalAddress = targetDevice.getPhysicalAddress(); + if (targetPhysicalAddress == INVALID_PHYSICAL_ADDRESS) { + return false; + } + return HdmiUtils.getLocalPortFromPhysicalAddress(targetPhysicalAddress, mPhysicalAddress) + != HdmiUtils.TARGET_NOT_UNDER_LOCAL_DEVICE; + } + + /** * Listener used to get hotplug event from HDMI port. */ public interface HotplugEventListener { diff --git a/core/java/android/hardware/hdmi/HdmiUtils.java b/core/java/android/hardware/hdmi/HdmiUtils.java new file mode 100644 index 000000000000..308173816f13 --- /dev/null +++ b/core/java/android/hardware/hdmi/HdmiUtils.java @@ -0,0 +1,81 @@ +/* + * Copyright (C) 2014 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.hardware.hdmi; + +/** + * Various utilities to handle HDMI CEC messages. + * + * TODO(b/110094868): unhide for Q + * @hide + */ +public class HdmiUtils { + + /** + * Return value of {@link #getLocalPortFromPhysicalAddress(int, int)} + */ + static final int TARGET_NOT_UNDER_LOCAL_DEVICE = -1; + static final int TARGET_SAME_PHYSICAL_ADDRESS = 0; + + private HdmiUtils() { /* cannot be instantiated */ } + + /** + * Method to parse target physical address to the port number on the current device. + * + * <p>This check assumes target address is valid. + * + * @param targetPhysicalAddress is the physical address of the target device + * @param myPhysicalAddress is the physical address of the current device + * @return + * If the target device is under the current device, return the port number of current device + * that the target device is connected to. This also applies to the devices that are indirectly + * connected to the current device. + * + * <p>If the target device has the same physical address as the current device, return + * {@link #TARGET_SAME_PHYSICAL_ADDRESS}. + * + * <p>If the target device is not under the current device, return + * {@link #TARGET_NOT_UNDER_LOCAL_DEVICE}. + */ + public static int getLocalPortFromPhysicalAddress( + int targetPhysicalAddress, int myPhysicalAddress) { + if (myPhysicalAddress == targetPhysicalAddress) { + return TARGET_SAME_PHYSICAL_ADDRESS; + } + + int mask = 0xF000; + int finalMask = 0xF000; + int maskedAddress = myPhysicalAddress; + + while (maskedAddress != 0) { + maskedAddress = myPhysicalAddress & mask; + finalMask |= mask; + mask >>= 4; + } + + int portAddress = targetPhysicalAddress & finalMask; + if ((portAddress & (finalMask << 4)) != myPhysicalAddress) { + return TARGET_NOT_UNDER_LOCAL_DEVICE; + } + + mask <<= 4; + int port = portAddress & mask; + while ((port >> 4) != 0) { + port >>= 4; + } + return port; + } +} diff --git a/core/java/android/hardware/location/ActivityChangedEvent.java b/core/java/android/hardware/location/ActivityChangedEvent.java deleted file mode 100644 index 16cfe6e23e88..000000000000 --- a/core/java/android/hardware/location/ActivityChangedEvent.java +++ /dev/null @@ -1,92 +0,0 @@ -/* - * Copyright (C) 2014 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License - */ - -package android.hardware.location; - -import android.annotation.NonNull; -import android.os.Parcel; -import android.os.Parcelable; - -import java.security.InvalidParameterException; -import java.util.Arrays; -import java.util.List; - -/** - * A class representing an event for Activity changes. - * - * @hide - */ -public class ActivityChangedEvent implements Parcelable { - private final List<ActivityRecognitionEvent> mActivityRecognitionEvents; - - public ActivityChangedEvent(ActivityRecognitionEvent[] activityRecognitionEvents) { - if (activityRecognitionEvents == null) { - throw new InvalidParameterException( - "Parameter 'activityRecognitionEvents' must not be null."); - } - - mActivityRecognitionEvents = Arrays.asList(activityRecognitionEvents); - } - - @NonNull - public Iterable<ActivityRecognitionEvent> getActivityRecognitionEvents() { - return mActivityRecognitionEvents; - } - - public static final Creator<ActivityChangedEvent> CREATOR = - new Creator<ActivityChangedEvent>() { - @Override - public ActivityChangedEvent createFromParcel(Parcel source) { - int activityRecognitionEventsLength = source.readInt(); - ActivityRecognitionEvent[] activityRecognitionEvents = - new ActivityRecognitionEvent[activityRecognitionEventsLength]; - source.readTypedArray(activityRecognitionEvents, ActivityRecognitionEvent.CREATOR); - - return new ActivityChangedEvent(activityRecognitionEvents); - } - - @Override - public ActivityChangedEvent[] newArray(int size) { - return new ActivityChangedEvent[size]; - } - }; - - @Override - public int describeContents() { - return 0; - } - - @Override - public void writeToParcel(Parcel parcel, int flags) { - ActivityRecognitionEvent[] activityRecognitionEventArray = - mActivityRecognitionEvents.toArray(new ActivityRecognitionEvent[0]); - parcel.writeInt(activityRecognitionEventArray.length); - parcel.writeTypedArray(activityRecognitionEventArray, flags); - } - - @Override - public String toString() { - StringBuilder builder = new StringBuilder("[ ActivityChangedEvent:"); - - for (ActivityRecognitionEvent event : mActivityRecognitionEvents) { - builder.append("\n "); - builder.append(event.toString()); - } - builder.append("\n]"); - - return builder.toString(); - } -} diff --git a/core/java/android/hardware/location/ActivityRecognitionEvent.java b/core/java/android/hardware/location/ActivityRecognitionEvent.java deleted file mode 100644 index 190030a82d6b..000000000000 --- a/core/java/android/hardware/location/ActivityRecognitionEvent.java +++ /dev/null @@ -1,87 +0,0 @@ -/* - * Copyright (C) 2014 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.hardware.location; - -import android.os.Parcel; -import android.os.Parcelable; - -/** - * A class that represents an Activity Recognition Event. - * - * @hide - */ -public class ActivityRecognitionEvent implements Parcelable { - private final String mActivity; - private final int mEventType; - private final long mTimestampNs; - - public ActivityRecognitionEvent(String activity, int eventType, long timestampNs) { - mActivity = activity; - mEventType = eventType; - mTimestampNs = timestampNs; - } - - public String getActivity() { - return mActivity; - } - - public int getEventType() { - return mEventType; - } - - public long getTimestampNs() { - return mTimestampNs; - } - - public static final Creator<ActivityRecognitionEvent> CREATOR = - new Creator<ActivityRecognitionEvent>() { - @Override - public ActivityRecognitionEvent createFromParcel(Parcel source) { - String activity = source.readString(); - int eventType = source.readInt(); - long timestampNs = source.readLong(); - - return new ActivityRecognitionEvent(activity, eventType, timestampNs); - } - - @Override - public ActivityRecognitionEvent[] newArray(int size) { - return new ActivityRecognitionEvent[size]; - } - }; - - @Override - public int describeContents() { - return 0; - } - - @Override - public void writeToParcel(Parcel parcel, int flags) { - parcel.writeString(mActivity); - parcel.writeInt(mEventType); - parcel.writeLong(mTimestampNs); - } - - @Override - public String toString() { - return String.format( - "Activity='%s', EventType=%s, TimestampNs=%s", - mActivity, - mEventType, - mTimestampNs); - } -} diff --git a/core/java/android/hardware/location/ActivityRecognitionHardware.java b/core/java/android/hardware/location/ActivityRecognitionHardware.java deleted file mode 100644 index 8acd1ff27917..000000000000 --- a/core/java/android/hardware/location/ActivityRecognitionHardware.java +++ /dev/null @@ -1,279 +0,0 @@ -/* - * Copyright (C) 2014 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License - */ - -package android.hardware.location; - -import android.Manifest; -import android.content.Context; -import android.os.RemoteCallbackList; -import android.os.RemoteException; -import android.text.TextUtils; -import android.util.Log; - -/** - * A class that implements an {@link IActivityRecognitionHardware} backed up by the Activity - * Recognition HAL. - * - * @hide - */ -public class ActivityRecognitionHardware extends IActivityRecognitionHardware.Stub { - private static final String TAG = "ActivityRecognitionHW"; - private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG); - - private static final String HARDWARE_PERMISSION = Manifest.permission.LOCATION_HARDWARE; - private static final String ENFORCE_HW_PERMISSION_MESSAGE = "Permission '" - + HARDWARE_PERMISSION + "' not granted to access ActivityRecognitionHardware"; - - private static final int INVALID_ACTIVITY_TYPE = -1; - private static final int NATIVE_SUCCESS_RESULT = 0; - private static final int EVENT_TYPE_DISABLED = 0; - private static final int EVENT_TYPE_ENABLED = 1; - - /** - * Contains the number of supported Event Types. - * - * NOTE: increment this counter every time a new EVENT_TYPE_ is added to - * com.android.location.provider.ActivityRecognitionProvider - */ - private static final int EVENT_TYPE_COUNT = 3; - - private static ActivityRecognitionHardware sSingletonInstance; - private static final Object sSingletonInstanceLock = new Object(); - - private final Context mContext; - private final int mSupportedActivitiesCount; - private final String[] mSupportedActivities; - private final int[][] mSupportedActivitiesEnabledEvents; - private final SinkList mSinks = new SinkList(); - - private static class Event { - public int activity; - public int type; - public long timestamp; - } - - private ActivityRecognitionHardware(Context context) { - nativeInitialize(); - - mContext = context; - mSupportedActivities = fetchSupportedActivities(); - mSupportedActivitiesCount = mSupportedActivities.length; - mSupportedActivitiesEnabledEvents = new int[mSupportedActivitiesCount][EVENT_TYPE_COUNT]; - } - - public static ActivityRecognitionHardware getInstance(Context context) { - synchronized (sSingletonInstanceLock) { - if (sSingletonInstance == null) { - sSingletonInstance = new ActivityRecognitionHardware(context); - } - - return sSingletonInstance; - } - } - - public static boolean isSupported() { - return nativeIsSupported(); - } - - @Override - public String[] getSupportedActivities() { - checkPermissions(); - return mSupportedActivities; - } - - @Override - public boolean isActivitySupported(String activity) { - checkPermissions(); - int activityType = getActivityType(activity); - return activityType != INVALID_ACTIVITY_TYPE; - } - - @Override - public boolean registerSink(IActivityRecognitionHardwareSink sink) { - checkPermissions(); - return mSinks.register(sink); - } - - @Override - public boolean unregisterSink(IActivityRecognitionHardwareSink sink) { - checkPermissions(); - return mSinks.unregister(sink); - } - - @Override - public boolean enableActivityEvent(String activity, int eventType, long reportLatencyNs) { - checkPermissions(); - - int activityType = getActivityType(activity); - if (activityType == INVALID_ACTIVITY_TYPE) { - return false; - } - - int result = nativeEnableActivityEvent(activityType, eventType, reportLatencyNs); - if (result == NATIVE_SUCCESS_RESULT) { - mSupportedActivitiesEnabledEvents[activityType][eventType] = EVENT_TYPE_ENABLED; - return true; - } - return false; - } - - @Override - public boolean disableActivityEvent(String activity, int eventType) { - checkPermissions(); - - int activityType = getActivityType(activity); - if (activityType == INVALID_ACTIVITY_TYPE) { - return false; - } - - int result = nativeDisableActivityEvent(activityType, eventType); - if (result == NATIVE_SUCCESS_RESULT) { - mSupportedActivitiesEnabledEvents[activityType][eventType] = EVENT_TYPE_DISABLED; - return true; - } - return false; - } - - @Override - public boolean flush() { - checkPermissions(); - int result = nativeFlush(); - return result == NATIVE_SUCCESS_RESULT; - } - - /** - * Called by the Activity-Recognition HAL. - */ - private void onActivityChanged(Event[] events) { - if (events == null || events.length == 0) { - if (DEBUG) Log.d(TAG, "No events to broadcast for onActivityChanged."); - return; - } - - int eventsLength = events.length; - ActivityRecognitionEvent activityRecognitionEventArray[] = - new ActivityRecognitionEvent[eventsLength]; - for (int i = 0; i < eventsLength; ++i) { - Event event = events[i]; - String activityName = getActivityName(event.activity); - activityRecognitionEventArray[i] = - new ActivityRecognitionEvent(activityName, event.type, event.timestamp); - } - ActivityChangedEvent activityChangedEvent = - new ActivityChangedEvent(activityRecognitionEventArray); - - int size = mSinks.beginBroadcast(); - for (int i = 0; i < size; ++i) { - IActivityRecognitionHardwareSink sink = mSinks.getBroadcastItem(i); - try { - sink.onActivityChanged(activityChangedEvent); - } catch (RemoteException e) { - Log.e(TAG, "Error delivering activity changed event.", e); - } - } - mSinks.finishBroadcast(); - } - - private String getActivityName(int activityType) { - if (activityType < 0 || activityType >= mSupportedActivities.length) { - String message = String.format( - "Invalid ActivityType: %d, SupportedActivities: %d", - activityType, - mSupportedActivities.length); - Log.e(TAG, message); - return null; - } - - return mSupportedActivities[activityType]; - } - - private int getActivityType(String activity) { - if (TextUtils.isEmpty(activity)) { - return INVALID_ACTIVITY_TYPE; - } - - int supportedActivitiesLength = mSupportedActivities.length; - for (int i = 0; i < supportedActivitiesLength; ++i) { - if (activity.equals(mSupportedActivities[i])) { - return i; - } - } - - return INVALID_ACTIVITY_TYPE; - } - - private void checkPermissions() { - mContext.enforceCallingPermission(HARDWARE_PERMISSION, ENFORCE_HW_PERMISSION_MESSAGE); - } - - private String[] fetchSupportedActivities() { - String[] supportedActivities = nativeGetSupportedActivities(); - if (supportedActivities != null) { - return supportedActivities; - } - - return new String[0]; - } - - private class SinkList extends RemoteCallbackList<IActivityRecognitionHardwareSink> { - @Override - public void onCallbackDied(IActivityRecognitionHardwareSink callback) { - int callbackCount = mSinks.getRegisteredCallbackCount(); - if (DEBUG) Log.d(TAG, "RegisteredCallbackCount: " + callbackCount); - if (callbackCount != 0) { - return; - } - // currently there is only one client for this, so if all its sinks have died, we clean - // up after them, this ensures that the AR HAL is not out of sink - for (int activity = 0; activity < mSupportedActivitiesCount; ++activity) { - for (int event = 0; event < EVENT_TYPE_COUNT; ++event) { - disableActivityEventIfEnabled(activity, event); - } - } - } - - private void disableActivityEventIfEnabled(int activityType, int eventType) { - if (mSupportedActivitiesEnabledEvents[activityType][eventType] != EVENT_TYPE_ENABLED) { - return; - } - - int result = nativeDisableActivityEvent(activityType, eventType); - mSupportedActivitiesEnabledEvents[activityType][eventType] = EVENT_TYPE_DISABLED; - String message = String.format( - "DisableActivityEvent: activityType=%d, eventType=%d, result=%d", - activityType, - eventType, - result); - Log.e(TAG, message); - } - } - - // native bindings - static { nativeClassInit(); } - - private static native void nativeClassInit(); - private static native boolean nativeIsSupported(); - - private native void nativeInitialize(); - private native void nativeRelease(); - private native String[] nativeGetSupportedActivities(); - private native int nativeEnableActivityEvent( - int activityType, - int eventType, - long reportLatenceNs); - private native int nativeDisableActivityEvent(int activityType, int eventType); - private native int nativeFlush(); -} diff --git a/core/java/android/hardware/location/IActivityRecognitionHardware.aidl b/core/java/android/hardware/location/IActivityRecognitionHardware.aidl deleted file mode 100644 index bc6b1830cd4f..000000000000 --- a/core/java/android/hardware/location/IActivityRecognitionHardware.aidl +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright (C) 2014, The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/license/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.hardware.location; - -import android.hardware.location.IActivityRecognitionHardwareSink; - -/** - * Activity Recognition Hardware provider interface. - * This interface can be used to implement hardware based activity recognition. - * - * @hide - */ -interface IActivityRecognitionHardware { - /** - * Gets an array of supported activities by hardware. - */ - String[] getSupportedActivities(); - - /** - * Returns true if the given activity is supported, false otherwise. - */ - boolean isActivitySupported(in String activityType); - - /** - * Registers a sink with Hardware Activity-Recognition. - */ - boolean registerSink(in IActivityRecognitionHardwareSink sink); - - /** - * Unregisters a sink with Hardware Activity-Recognition. - */ - boolean unregisterSink(in IActivityRecognitionHardwareSink sink); - - /** - * Enables tracking of a given activity/event type, if the activity is supported. - */ - boolean enableActivityEvent(in String activityType, int eventType, long reportLatencyNs); - - /** - * Disables tracking of a given activity/eventy type. - */ - boolean disableActivityEvent(in String activityType, int eventType); - - /** - * Requests hardware for all the activity events detected up to the given point in time. - */ - boolean flush(); -}
\ No newline at end of file diff --git a/core/java/android/hardware/location/IActivityRecognitionHardwareClient.aidl b/core/java/android/hardware/location/IActivityRecognitionHardwareClient.aidl deleted file mode 100644 index 3fe645c59a30..000000000000 --- a/core/java/android/hardware/location/IActivityRecognitionHardwareClient.aidl +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright (C) 2015, The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/license/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.hardware.location; - -import android.hardware.location.IActivityRecognitionHardware; - -/** - * Activity Recognition Hardware client interface. - * This interface can be used to receive interfaces to implementations of - * {@link IActivityRecognitionHardware}. - * - * @hide - */ -oneway interface IActivityRecognitionHardwareClient { - /** - * Hardware Activity-Recognition availability event. - * - * @param isSupported whether the platform has hardware support for the feature - * @param instance the available instance to provide access to the feature - */ - void onAvailabilityChanged(in boolean isSupported, in IActivityRecognitionHardware instance); -} diff --git a/core/java/android/hardware/location/IActivityRecognitionHardwareWatcher.aidl b/core/java/android/hardware/location/IActivityRecognitionHardwareWatcher.aidl deleted file mode 100644 index 12e3117259e1..000000000000 --- a/core/java/android/hardware/location/IActivityRecognitionHardwareWatcher.aidl +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright (C) 2014, The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/license/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.hardware.location; - -import android.hardware.location.IActivityRecognitionHardware; - -/** - * Activity Recognition Hardware watcher. This interface can be used to receive interfaces to - * implementations of {@link IActivityRecognitionHardware}. - * - * @deprecated use {@link IActivityRecognitionHardwareClient} instead. - - * @hide - */ -interface IActivityRecognitionHardwareWatcher { - /** - * Hardware Activity-Recognition availability event. - */ - void onInstanceChanged(in IActivityRecognitionHardware instance); -} diff --git a/core/java/android/net/IpPrefixParcelable.aidl b/core/java/android/net/IpPrefixParcelable.aidl new file mode 100644 index 000000000000..93a8d41936cc --- /dev/null +++ b/core/java/android/net/IpPrefixParcelable.aidl @@ -0,0 +1,22 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. +*/ + +package android.net; + +parcelable IpPrefixParcelable { + String address; + int prefixLength; +}
\ No newline at end of file diff --git a/core/java/android/net/LinkAddressParcelable.aidl b/core/java/android/net/LinkAddressParcelable.aidl new file mode 100644 index 000000000000..af8e79b21f69 --- /dev/null +++ b/core/java/android/net/LinkAddressParcelable.aidl @@ -0,0 +1,24 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. +*/ + +package android.net; + +parcelable LinkAddressParcelable { + String address; + int prefixLength; + int flags; + int scope; +}
\ No newline at end of file diff --git a/core/java/android/net/LinkPropertiesParcelable.aidl b/core/java/android/net/LinkPropertiesParcelable.aidl new file mode 100644 index 000000000000..b153dc70e1b8 --- /dev/null +++ b/core/java/android/net/LinkPropertiesParcelable.aidl @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. +*/ + +package android.net; + +import android.net.IpPrefixParcelable; +import android.net.LinkAddressParcelable; +import android.net.ProxyInfoParcelable; +import android.net.RouteInfoParcelable; + +parcelable LinkPropertiesParcelable { + String ifaceName; + LinkAddressParcelable[] linkAddresses; + String[] dnses; + String[] pcscfs; + String[] validatedPrivateDnses; + boolean usePrivateDns; + String privateDnsServerName; + String domains; + RouteInfoParcelable[] routes; + ProxyInfoParcelable httpProxy; + int mtu; + String tcpBufferSizes; + IpPrefixParcelable nat64Prefix; + LinkPropertiesParcelable[] stackedLinks; +}
\ No newline at end of file diff --git a/core/java/android/net/NetworkSpecifier.java b/core/java/android/net/NetworkSpecifier.java index be2f9551daff..fcfb72035c19 100644 --- a/core/java/android/net/NetworkSpecifier.java +++ b/core/java/android/net/NetworkSpecifier.java @@ -17,7 +17,7 @@ package android.net; /** - * Describes specific properties of a network for use in a {@link NetworkRequest}. + * Describes specific properties of a requested network for use in a {@link NetworkRequest}. * * Applications cannot instantiate this class by themselves, but can obtain instances of * subclasses of this class via other APIs. @@ -49,4 +49,29 @@ public abstract class NetworkSpecifier { public void assertValidFromUid(int requestorUid) { // empty } + + /** + * Optional method which can be overridden by concrete implementations of NetworkSpecifier to + * perform any redaction of information from the NetworkSpecifier, e.g. if it contains + * sensitive information. The default implementation simply returns the object itself - i.e. + * no information is redacted. A concrete implementation may return a modified (copy) of the + * NetworkSpecifier, or even return a null to fully remove all information. + * <p> + * This method is relevant to NetworkSpecifier objects used by agents - those are shared with + * apps by default. Some agents may store sensitive matching information in the specifier, + * e.g. a Wi-Fi SSID (which should not be shared since it may leak location). Those classes + * can redact to a null. Other agents use the Network Specifier to share public information + * with apps - those should not be redacted. + * <p> + * The default implementation redacts no information. + * + * @return A NetworkSpecifier object to be passed along to the requesting app. + * + * @hide + */ + public NetworkSpecifier redact() { + // TODO (b/122160111): convert default to null once all platform NetworkSpecifiers + // implement this method. + return this; + } } diff --git a/core/java/android/net/ProxyInfoParcelable.aidl b/core/java/android/net/ProxyInfoParcelable.aidl new file mode 100644 index 000000000000..59fd8467b820 --- /dev/null +++ b/core/java/android/net/ProxyInfoParcelable.aidl @@ -0,0 +1,24 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. +*/ + +package android.net; + +parcelable ProxyInfoParcelable { + String host; + int port; + String[] exclusionList; + String pacFileUrl; +} diff --git a/core/java/android/net/RouteInfoParcelable.aidl b/core/java/android/net/RouteInfoParcelable.aidl new file mode 100644 index 000000000000..15bcdcfc2000 --- /dev/null +++ b/core/java/android/net/RouteInfoParcelable.aidl @@ -0,0 +1,26 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. +*/ + +package android.net; + +import android.net.IpPrefixParcelable; + +parcelable RouteInfoParcelable { + IpPrefixParcelable destination; + String gatewayAddr; + String ifaceName; + int type; +} diff --git a/core/java/android/os/AppZygote.java b/core/java/android/os/AppZygote.java index 40cbaf75c02d..950f38167754 100644 --- a/core/java/android/os/AppZygote.java +++ b/core/java/android/os/AppZygote.java @@ -34,8 +34,15 @@ import com.android.internal.annotations.GuardedBy; public class AppZygote { private static final String LOG_TAG = "AppZygote"; + // UID of the Zygote itself private final int mZygoteUid; + // First UID/GID of the range the AppZygote can setuid()/setgid() to + private final int mZygoteUidGidMin; + + // Last UID/GID of the range the AppZygote can setuid()/setgid() to + private final int mZygoteUidGidMax; + private final Object mLock = new Object(); /** @@ -47,9 +54,11 @@ public class AppZygote { private final ApplicationInfo mAppInfo; - public AppZygote(ApplicationInfo appInfo, int zygoteUid) { + public AppZygote(ApplicationInfo appInfo, int zygoteUid, int uidGidMin, int uidGidMax) { mAppInfo = appInfo; mZygoteUid = zygoteUid; + mZygoteUidGidMin = uidGidMin; + mZygoteUidGidMax = uidGidMax; } /** @@ -104,7 +113,9 @@ public class AppZygote { "app_zygote", // seInfo abi, // abi abi, // acceptedAbiList - null); // instructionSet + null, // instructionSet + mZygoteUidGidMin, + mZygoteUidGidMax); ZygoteProcess.waitForConnectionToZygote(mZygote.getPrimarySocketAddress()); // preload application code in the zygote diff --git a/core/java/android/os/BugreportManager.java b/core/java/android/os/BugreportManager.java index cbb3909a5536..c5a51f133047 100644 --- a/core/java/android/os/BugreportManager.java +++ b/core/java/android/os/BugreportManager.java @@ -66,10 +66,14 @@ public class BugreportManager { @interface BugreportErrorCode {} /** The input options were invalid */ - int BUGREPORT_ERROR_INVALID_INPUT = 1; + int BUGREPORT_ERROR_INVALID_INPUT = IDumpstateListener.BUGREPORT_ERROR_INVALID_INPUT; /** A runtime error occured */ - int BUGREPORT_ERROR_RUNTIME = 2; + int BUGREPORT_ERROR_RUNTIME = IDumpstateListener.BUGREPORT_ERROR_RUNTIME_ERROR; + + /** User denied consent to share the bugreport */ + int BUGREPORT_ERROR_USER_DENIED_CONSENT = + IDumpstateListener.BUGREPORT_ERROR_USER_DENIED_CONSENT; /** * Called when taking bugreport resulted in an error. @@ -108,7 +112,10 @@ public class BugreportManager { DumpstateListener dsListener = new DumpstateListener(listener); try { - mBinder.startBugreport(bugreportFd, screenshotFd, params.getMode(), dsListener); + // Note: mBinder can get callingUid from the binder transaction. + mBinder.startBugreport(-1 /* callingUid */, + mContext.getOpPackageName(), bugreportFd, screenshotFd, + params.getMode(), dsListener); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } diff --git a/core/java/android/os/FileUtils.java b/core/java/android/os/FileUtils.java index e84a518c4986..ca3905148ede 100644 --- a/core/java/android/os/FileUtils.java +++ b/core/java/android/os/FileUtils.java @@ -846,7 +846,16 @@ public class FileUtils { return contains(dir.getAbsolutePath(), file.getAbsolutePath()); } - /** {@hide} */ + /** + * Test if a file lives under the given directory, either as a direct child + * or a distant grandchild. + * <p> + * Both files <em>must</em> have been resolved using + * {@link File#getCanonicalFile()} to avoid symlink or path traversal + * attacks. + * + * @hide + */ public static boolean contains(String dirPath, String filePath) { if (dirPath.equals(filePath)) { return true; diff --git a/core/java/android/os/GraphicsEnvironment.java b/core/java/android/os/GraphicsEnvironment.java index b0b8f493e98a..f51ba9a41a2b 100644 --- a/core/java/android/os/GraphicsEnvironment.java +++ b/core/java/android/os/GraphicsEnvironment.java @@ -306,9 +306,18 @@ public class GraphicsEnvironment { String packageName, String paths, String devOptIn) { - // Check for temporary rules if debuggable or root - if (!isDebuggable(context) && !(getCanLoadSystemLibraries() == 1)) { - Log.v(TAG, "Skipping loading temporary rules file"); + /** + * We only want to load a temp rules file for: + * - apps that are marked 'debuggable' in their manifest + * - devices that are running a userdebug build (ro.debuggable) or can inject libraries for + * debugging (PR_SET_DUMPABLE). + */ + boolean appIsDebuggable = isDebuggable(context); + boolean deviceIsDebuggable = getCanLoadSystemLibraries() == 1; + if (!(appIsDebuggable || deviceIsDebuggable)) { + Log.v(TAG, "Skipping loading temporary rules file: " + + "appIsDebuggable = " + appIsDebuggable + ", " + + "adbRootEnabled = " + deviceIsDebuggable); return false; } @@ -480,21 +489,36 @@ public class GraphicsEnvironment { return; } - if (getGlobalSettingsString(coreSettings, Settings.Global.GUP_DEV_OPT_OUT_APPS) - .contains(ai.packageName)) { + // GUP_DEV_ALL_APPS + // 0: Default (Invalid values fallback to default as well) + // 1: All apps use Game Update Package + // 2: All apps use system graphics driver + int gupDevAllApps = coreSettings.getInt(Settings.Global.GUP_DEV_ALL_APPS, 0); + if (gupDevAllApps == 2) { if (DEBUG) { - Log.w(TAG, ai.packageName + " opts out from GUP."); + Log.w(TAG, "GUP is turned off on this device"); } return; } - if (!getGlobalSettingsString(coreSettings, Settings.Global.GUP_DEV_OPT_IN_APPS) - .contains(ai.packageName) - && !onWhitelist(context, driverPackageName, ai.packageName)) { - if (DEBUG) { - Log.w(TAG, ai.packageName + " is not on the whitelist."); + if (gupDevAllApps != 1) { + // GUP_DEV_OPT_OUT_APPS has higher priority than GUP_DEV_OPT_IN_APPS + if (getGlobalSettingsString(coreSettings, Settings.Global.GUP_DEV_OPT_OUT_APPS) + .contains(ai.packageName)) { + if (DEBUG) { + Log.w(TAG, ai.packageName + " opts out from GUP."); + } + return; + } + + if (!getGlobalSettingsString(coreSettings, Settings.Global.GUP_DEV_OPT_IN_APPS) + .contains(ai.packageName) + && !onWhitelist(context, driverPackageName, ai.packageName)) { + if (DEBUG) { + Log.w(TAG, ai.packageName + " is not on the whitelist."); + } + return; } - return; } ApplicationInfo driverInfo; diff --git a/core/java/android/os/VintfObject.java b/core/java/android/os/VintfObject.java index fb22194098b6..23c54f450a67 100644 --- a/core/java/android/os/VintfObject.java +++ b/core/java/android/os/VintfObject.java @@ -16,23 +16,27 @@ package android.os; -import java.util.Map; +import android.annotation.TestApi; +import java.util.Map; /** * Java API for libvintf. + * * @hide */ +@TestApi public class VintfObject { - /// ---------- OTA - /** * Slurps all device information (both manifests and both matrices) * and report them. * If any error in getting one of the manifests, it is not included in * the list. + * + * @hide */ + @TestApi public static native String[] report(); /** @@ -44,6 +48,8 @@ public class VintfObject { * @return = 0 if success (compatible) * > 0 if incompatible * < 0 if any error (mount partition fails, illformed XML, etc.) + * + * @hide */ public static native int verify(String[] packageInfo); @@ -55,22 +61,28 @@ public class VintfObject { * @return = 0 if success (compatible) * > 0 if incompatible * < 0 if any error (mount partition fails, illformed XML, etc.) + * + * @hide */ public static native int verifyWithoutAvb(); - /// ---------- CTS Device Info - /** * @return a list of HAL names and versions that is supported by this * device as stated in device and framework manifests. For example, * ["android.hidl.manager@1.0", "android.hardware.camera.device@1.0", * "android.hardware.camera.device@3.2"]. There are no duplicates. + * + * @hide */ + @TestApi public static native String[] getHalNamesAndVersions(); /** * @return the BOARD_SEPOLICY_VERS build flag available in device manifest. + * + * @hide */ + @TestApi public static native String getSepolicyVersion(); /** @@ -78,13 +90,22 @@ public class VintfObject { * specified in framework manifest. For example, * [("27", ["libjpeg.so", "libbase.so"]), * ("28", ["libjpeg.so", "libbase.so"])] + * + * @hide */ + @TestApi public static native Map<String, String[]> getVndkSnapshots(); /** - * @return target FCM version, a number specified in the device manifest - * indicating the FCM version that the device manifest implements. Null if - * device manifest doesn't specify this number (for legacy devices). + * @return Target Framework Compatibility Matrix (FCM) version, a number + * specified in the device manifest indicating the FCM version that the + * device manifest implements. Null if device manifest doesn't specify this + * number (for legacy devices). + * + * @hide */ + @TestApi public static native Long getTargetFrameworkCompatibilityMatrixVersion(); + + private VintfObject() {} } diff --git a/core/java/android/os/VintfRuntimeInfo.java b/core/java/android/os/VintfRuntimeInfo.java index 29698b9fa684..f17039ba9bf4 100644 --- a/core/java/android/os/VintfRuntimeInfo.java +++ b/core/java/android/os/VintfRuntimeInfo.java @@ -16,55 +16,84 @@ package android.os; +import android.annotation.TestApi; + /** * Java API for ::android::vintf::RuntimeInfo. Methods return null / 0 on any error. * * @hide */ +@TestApi public class VintfRuntimeInfo { private VintfRuntimeInfo() {} /** * @return /sys/fs/selinux/policyvers, via security_policyvers() native call + * + * @hide */ public static native long getKernelSepolicyVersion(); /** * @return content of /proc/cpuinfo + * + * @hide */ + @TestApi public static native String getCpuInfo(); /** * @return os name extracted from uname() native call + * + * @hide */ + @TestApi public static native String getOsName(); /** * @return node name extracted from uname() native call + * + * @hide */ + @TestApi public static native String getNodeName(); /** * @return os release extracted from uname() native call + * + * @hide */ + @TestApi public static native String getOsRelease(); /** * @return os version extracted from uname() native call + * + * @hide */ + @TestApi public static native String getOsVersion(); /** * @return hardware id extracted from uname() native call + * + * @hide */ + @TestApi public static native String getHardwareId(); /** * @return kernel version extracted from uname() native call. Format is * {@code x.y.z}. + * + * @hide */ + @TestApi public static native String getKernelVersion(); /** * @return libavb version in OS. Format is {@code x.y}. + * + * @hide */ public static native String getBootAvbVersion(); /** * @return libavb version in bootloader. Format is {@code x.y}. + * + * @hide */ public static native String getBootVbmetaAvbVersion(); - } diff --git a/core/java/android/os/ZygoteProcess.java b/core/java/android/os/ZygoteProcess.java index 251c5eebadc4..99a85eaefe53 100644 --- a/core/java/android/os/ZygoteProcess.java +++ b/core/java/android/os/ZygoteProcess.java @@ -809,6 +809,8 @@ public class ZygoteProcess { * may be different from <code>abi</code> in case the children * spawned from this Zygote only communicate using ABI-safe methods. * @param instructionSet null-ok the instruction set to use. + * @param uidRangeStart The first UID in the range the child zygote may setuid()/setgid() to + * @param uidRangeEnd The last UID in the range the child zygote may setuid()/setgid() to */ public ChildZygoteProcess startChildZygote(final String processClass, final String niceName, @@ -817,13 +819,17 @@ public class ZygoteProcess { String seInfo, String abi, String acceptedAbiList, - String instructionSet) { + String instructionSet, + int uidRangeStart, + int uidRangeEnd) { // Create an unguessable address in the global abstract namespace. final LocalSocketAddress serverAddress = new LocalSocketAddress( processClass + "/" + UUID.randomUUID().toString()); final String[] extraArgs = {Zygote.CHILD_ZYGOTE_SOCKET_NAME_ARG + serverAddress.getName(), - Zygote.CHILD_ZYGOTE_ABI_LIST_ARG + acceptedAbiList}; + Zygote.CHILD_ZYGOTE_ABI_LIST_ARG + acceptedAbiList, + Zygote.CHILD_ZYGOTE_UID_RANGE_START + uidRangeStart, + Zygote.CHILD_ZYGOTE_UID_RANGE_END + uidRangeEnd}; Process.ProcessStartResult result; try { diff --git a/core/java/android/provider/DeviceConfig.java b/core/java/android/provider/DeviceConfig.java index c79589577366..901570389957 100644 --- a/core/java/android/provider/DeviceConfig.java +++ b/core/java/android/provider/DeviceConfig.java @@ -16,9 +16,13 @@ package android.provider; +import static android.Manifest.permission.READ_DEVICE_CONFIG; +import static android.Manifest.permission.WRITE_DEVICE_CONFIG; + import android.annotation.CallbackExecutor; import android.annotation.NonNull; import android.annotation.Nullable; +import android.annotation.RequiresPermission; import android.annotation.SystemApi; import android.app.ActivityThread; import android.content.ContentResolver; @@ -49,6 +53,31 @@ public final class DeviceConfig { public static final Uri CONTENT_URI = Uri.parse("content://" + Settings.AUTHORITY + "/config"); /** + * Namespace for all Game Driver features. + * @hide + */ + @SystemApi + public static final String NAMESPACE_GAME_DRIVER = "game_driver"; + + /** + * Namespace for autofill feature that provides suggestions across all apps when + * the user interacts with input fields. + * + * @hide + */ + @SystemApi + public static final String NAMESPACE_AUTOFILL = "autofill"; + + /** + * Namespace for content capture feature used by on-device machine intelligence + * to provide suggestions in a privacy-safe manner. + * + * @hide + */ + @SystemApi + public static final String NAMESPACE_CONTENT_CAPTURE = "content_capture"; + + /** * Namespace for all input-related features that are used at the native level. * These features are applied at reboot. * @@ -78,6 +107,7 @@ public final class DeviceConfig { * @hide */ @SystemApi + @RequiresPermission(READ_DEVICE_CONFIG) public static String getProperty(String namespace, String name) { ContentResolver contentResolver = ActivityThread.currentApplication().getContentResolver(); String compositeName = createCompositeName(namespace, name); @@ -105,6 +135,7 @@ public final class DeviceConfig { * @hide */ @SystemApi + @RequiresPermission(WRITE_DEVICE_CONFIG) public static boolean setProperty( String namespace, String name, String value, boolean makeDefault) { ContentResolver contentResolver = ActivityThread.currentApplication().getContentResolver(); @@ -125,6 +156,7 @@ public final class DeviceConfig { * @hide */ @SystemApi + @RequiresPermission(WRITE_DEVICE_CONFIG) public static void resetToDefaults(@ResetMode int resetMode, @Nullable String namespace) { ContentResolver contentResolver = ActivityThread.currentApplication().getContentResolver(); Settings.Config.resetToDefaults(contentResolver, resetMode, namespace); @@ -146,10 +178,12 @@ public final class DeviceConfig { * @hide */ @SystemApi + @RequiresPermission(READ_DEVICE_CONFIG) public static void addOnPropertyChangedListener( @NonNull String namespace, @NonNull @CallbackExecutor Executor executor, @NonNull OnPropertyChangedListener onPropertyChangedListener) { + // TODO enforce READ_DEVICE_CONFIG permission synchronized (sLock) { Pair<String, Executor> oldNamespace = sListeners.get(onPropertyChangedListener); if (oldNamespace == null) { diff --git a/core/java/android/provider/FontsContract.java b/core/java/android/provider/FontsContract.java index 8e37559001db..e931826d2455 100644 --- a/core/java/android/provider/FontsContract.java +++ b/core/java/android/provider/FontsContract.java @@ -34,6 +34,7 @@ import android.graphics.fonts.FontFamily; import android.graphics.fonts.FontStyle; import android.graphics.fonts.FontVariationAxis; import android.net.Uri; +import android.os.Build.VERSION_CODES; import android.os.CancellationSignal; import android.os.Handler; import android.os.HandlerThread; @@ -651,7 +652,16 @@ public class FontsContract { if (familyBuilder == null) { familyBuilder = new FontFamily.Builder(font); } else { - familyBuilder.addFont(font); + try { + familyBuilder.addFont(font); + } catch (IllegalArgumentException e) { + if (context.getApplicationInfo().targetSdkVersion <= VERSION_CODES.P) { + // Surpress the IllegalArgumentException for keeping the backward + // compatibility. + continue; + } + throw e; + } } } catch (IOException e) { continue; diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java index 39c4266e4cf8..d5de13c40194 100644 --- a/core/java/android/provider/Settings.java +++ b/core/java/android/provider/Settings.java @@ -6026,6 +6026,12 @@ public final class Settings { ANY_STRING_VALIDATOR; /** + * Indicates which clock face to show on lock screen and AOD while docked. + * @hide + */ + private static final String DOCKED_CLOCK_FACE = "docked_clock_face"; + + /** * Set by the system to track if the user needs to see the call to action for * the lockscreen notification policy. * @hide @@ -7391,6 +7397,14 @@ public final class Settings { private static final Validator DOZE_DOUBLE_TAP_GESTURE_VALIDATOR = BOOLEAN_VALIDATOR; /** + * Whether the device should respond to the SLPI tap gesture. + * @hide + */ + public static final String DOZE_TAP_SCREEN_GESTURE = "doze_tap_gesture"; + + private static final Validator DOZE_TAP_SCREEN_GESTURE_VALIDATOR = BOOLEAN_VALIDATOR; + + /** * Gesture that wakes up the lock screen. * @hide */ @@ -7724,6 +7738,23 @@ public final class Settings { public static final String TV_INPUT_CUSTOM_LABELS = "tv_input_custom_labels"; /** + * Whether TV app uses non-system inputs. + * + * <p> + * The value is boolean (1 or 0), where 1 means non-system TV inputs are allowed, + * and 0 means non-system TV inputs are not allowed. + * + * <p> + * Devices such as sound bars may have changed the system property allow_third_party_inputs + * to false so the TV Application only uses HDMI and other built in inputs. This setting + * allows user to override the default and have the TV Application use third party TV inputs + * available on play store. + * + * @hide + */ + public static final String TV_APP_USES_NON_SYSTEM_INPUTS = "tv_app_uses_non_system_inputs"; + + /** * Whether automatic routing of system audio to USB audio peripheral is disabled. * The value is boolean (1 or 0), where 1 means automatic routing is disabled, * and 0 means automatic routing is enabled. @@ -8461,6 +8492,7 @@ public final class Settings { DOZE_ALWAYS_ON, DOZE_PICK_UP_GESTURE, DOZE_DOUBLE_TAP_GESTURE, + DOZE_TAP_SCREEN_GESTURE, DOZE_WAKE_LOCK_SCREEN_GESTURE, DOZE_WAKE_SCREEN_GESTURE, NFC_PAYMENT_DEFAULT_COMPONENT, @@ -8617,6 +8649,7 @@ public final class Settings { VALIDATORS.put(DOZE_ALWAYS_ON, DOZE_ALWAYS_ON_VALIDATOR); VALIDATORS.put(DOZE_PICK_UP_GESTURE, DOZE_PICK_UP_GESTURE_VALIDATOR); VALIDATORS.put(DOZE_DOUBLE_TAP_GESTURE, DOZE_DOUBLE_TAP_GESTURE_VALIDATOR); + VALIDATORS.put(DOZE_TAP_SCREEN_GESTURE, DOZE_TAP_SCREEN_GESTURE_VALIDATOR); VALIDATORS.put(DOZE_WAKE_LOCK_SCREEN_GESTURE, DOZE_WAKE_LOCK_SCREEN_GESTURE_VALIDATOR); VALIDATORS.put(DOZE_WAKE_SCREEN_GESTURE, DOZE_WAKE_SCREEN_GESTURE_VALIDATOR); VALIDATORS.put(NFC_PAYMENT_DEFAULT_COMPONENT, NFC_PAYMENT_DEFAULT_COMPONENT_VALIDATOR); @@ -10925,6 +10958,21 @@ public final class Settings { public static final String DATA_STALL_EVALUATION_TYPE = "data_stall_evaluation_type"; /** + * Whether to try cellular data recovery when a bad network is reported. + * + * @hide + */ + public static final String DATA_STALL_RECOVERY_ON_BAD_NETWORK = + "data_stall_recovery_on_bad_network"; + + /** + * Minumim duration in millisecodns between cellular data recovery attempts + * + * @hide + */ + public static final String MIN_DURATION_BETWEEN_RECOVERY_STEPS_IN_MS = + "min_duration_between_recovery_steps"; + /** * Whether network service discovery is enabled. * * @hide @@ -11606,6 +11654,7 @@ public final class Settings { * battery_level_collection_delay_ms (long) * max_history_files (int) * max_history_buffer_kb (int) + * battery_charged_delay_ms (int) * </pre> * * <p> @@ -11991,22 +12040,33 @@ public final class Settings { "angle_gl_driver_selection_values"; /** - * List of Apps selected to use Game Update Packages. + * Game Update Package global preference for all Apps. + * 0 = Default + * 1 = All Apps use Game Update Package + * 2 = All Apps use system graphics driver + * @hide + */ + public static final String GUP_DEV_ALL_APPS = "gup_dev_all_apps"; + + /** + * List of Apps selected to use Game Update Package. + * i.e. <pkg1>,<pkg2>,...,<pkgN> * @hide */ public static final String GUP_DEV_OPT_IN_APPS = "gup_dev_opt_in_apps"; /** - * List of Apps selected not to use Game Update Packages. + * List of Apps selected not to use Game Update Package. + * i.e. <pkg1>,<pkg2>,...,<pkgN> * @hide */ public static final String GUP_DEV_OPT_OUT_APPS = "gup_dev_opt_out_apps"; /** - * Apps on the black list that are forbidden to useGame Update Package. + * Apps on the blacklist that are forbidden to use Game Update Package. * @hide */ - public static final String GUP_BLACK_LIST = "gup_black_list"; + public static final String GUP_BLACKLIST = "gup_blacklist"; /** * Ordered GPU debug layer list for Vulkan @@ -14087,7 +14147,7 @@ public final class Settings { * * @hide */ - // TODO(b/117663715): require a new read permission + @RequiresPermission(Manifest.permission.READ_DEVICE_CONFIG) static String getString(ContentResolver resolver, String name) { return sNameValueCache.getStringForUser(resolver, name, resolver.getUserId()); } @@ -14110,8 +14170,7 @@ public final class Settings { * * @hide */ - // TODO(b/117663715): require a new write permission restricted to a single source - @RequiresPermission(Manifest.permission.WRITE_SECURE_SETTINGS) + @RequiresPermission(Manifest.permission.WRITE_DEVICE_CONFIG) static boolean putString(@NonNull ContentResolver resolver, @NonNull String name, @Nullable String value, boolean makeDefault) { return sNameValueCache.putStringForUser(resolver, name, value, null, makeDefault, @@ -14133,7 +14192,7 @@ public final class Settings { * @hide */ // TODO(b/117663715): require a new write permission restricted to a single source - @RequiresPermission(Manifest.permission.WRITE_SECURE_SETTINGS) + @RequiresPermission(Manifest.permission.WRITE_DEVICE_CONFIG) static void resetToDefaults(@NonNull ContentResolver resolver, @ResetMode int resetMode, @Nullable String prefix) { try { diff --git a/core/java/android/security/keystore/recovery/RecoveryController.java b/core/java/android/security/keystore/recovery/RecoveryController.java index 31a5962c7e9a..c43a6668b9c3 100644 --- a/core/java/android/security/keystore/recovery/RecoveryController.java +++ b/core/java/android/security/keystore/recovery/RecoveryController.java @@ -533,7 +533,10 @@ public class RecoveryController { * service. * @throws LockScreenRequiredException if the user does not have a lock screen set. A lock * screen is required to generate recoverable keys. + * + * @deprecated Use the method {@link #generateKey(String, byte[])} instead. */ + @Deprecated @RequiresPermission(android.Manifest.permission.RECOVER_KEYSTORE) public @NonNull Key generateKey(@NonNull String alias) throws InternalRecoveryServiceException, LockScreenRequiredException { @@ -556,6 +559,47 @@ public class RecoveryController { } /** + * Generates a recoverable key with the given {@code alias} and {@code metadata}. + * + * <p>The metadata should contain any data that needs to be cryptographically bound to the + * generated key, but does not need to be encrypted by the key. For example, the metadata can + * be a byte string describing the algorithms and non-secret parameters to be used with the + * key. The supplied metadata can later be obtained via + * {@link WrappedApplicationKey#getMetadata()}. + * + * <p>During the key recovery process, the same metadata has to be supplied via + * {@link WrappedApplicationKey.Builder#setMetadata(byte[])}; otherwise, the recovery process + * will fail due to the checking of the cryptographic binding. This can help prevent + * potential attacks that try to swap key materials on the backup server and trick the + * application to use keys with different algorithms or parameters. + * + * @throws InternalRecoveryServiceException if an unexpected error occurred in the recovery + * service. + * @throws LockScreenRequiredException if the user does not have a lock screen set. A lock + * screen is required to generate recoverable keys. + */ + @RequiresPermission(android.Manifest.permission.RECOVER_KEYSTORE) + public @NonNull Key generateKey(@NonNull String alias, @Nullable byte[] metadata) + throws InternalRecoveryServiceException, LockScreenRequiredException { + try { + String grantAlias = mBinder.generateKeyWithMetadata(alias, metadata); + if (grantAlias == null) { + throw new InternalRecoveryServiceException("null grant alias"); + } + return getKeyFromGrant(grantAlias); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } catch (UnrecoverableKeyException e) { + throw new InternalRecoveryServiceException("Failed to get key from keystore", e); + } catch (ServiceSpecificException e) { + if (e.errorCode == ERROR_INSECURE_USER) { + throw new LockScreenRequiredException(e.getMessage()); + } + throw wrapUnexpectedServiceSpecificException(e); + } + } + + /** * Imports a 256-bit recoverable AES key with the given {@code alias} and the raw bytes {@code * keyBytes}. * @@ -564,7 +608,9 @@ public class RecoveryController { * @throws LockScreenRequiredException if the user does not have a lock screen set. A lock * screen is required to generate recoverable keys. * + * @deprecated Use the method {@link #importKey(String, byte[], byte[])} instead. */ + @Deprecated @RequiresPermission(android.Manifest.permission.RECOVER_KEYSTORE) public @NonNull Key importKey(@NonNull String alias, @NonNull byte[] keyBytes) throws InternalRecoveryServiceException, LockScreenRequiredException { @@ -587,6 +633,49 @@ public class RecoveryController { } /** + * Imports a recoverable 256-bit AES key with the given {@code alias}, the raw bytes {@code + * keyBytes}, and the {@code metadata}. + * + * <p>The metadata should contain any data that needs to be cryptographically bound to the + * imported key, but does not need to be encrypted by the key. For example, the metadata can + * be a byte string describing the algorithms and non-secret parameters to be used with the + * key. The supplied metadata can later be obtained via + * {@link WrappedApplicationKey#getMetadata()}. + * + * <p>During the key recovery process, the same metadata has to be supplied via + * {@link WrappedApplicationKey.Builder#setMetadata(byte[])}; otherwise, the recovery process + * will fail due to the checking of the cryptographic binding. This can help prevent + * potential attacks that try to swap key materials on the backup server and trick the + * application to use keys with different algorithms or parameters. + * + * @throws InternalRecoveryServiceException if an unexpected error occurred in the recovery + * service. + * @throws LockScreenRequiredException if the user does not have a lock screen set. A lock + * screen is required to generate recoverable keys. + */ + @RequiresPermission(android.Manifest.permission.RECOVER_KEYSTORE) + public @NonNull Key importKey(@NonNull String alias, @NonNull byte[] keyBytes, + @Nullable byte[] metadata) + throws InternalRecoveryServiceException, LockScreenRequiredException { + try { + String grantAlias = mBinder.importKeyWithMetadata(alias, keyBytes, metadata); + if (grantAlias == null) { + throw new InternalRecoveryServiceException("Null grant alias"); + } + return getKeyFromGrant(grantAlias); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } catch (UnrecoverableKeyException e) { + throw new InternalRecoveryServiceException("Failed to get key from keystore", e); + } catch (ServiceSpecificException e) { + if (e.errorCode == ERROR_INSECURE_USER) { + throw new LockScreenRequiredException(e.getMessage()); + } + throw wrapUnexpectedServiceSpecificException(e); + } + } + + /** * Gets a key called {@code alias} from the recoverable key store. * * @param alias The key alias. diff --git a/core/java/android/security/keystore/recovery/WrappedApplicationKey.java b/core/java/android/security/keystore/recovery/WrappedApplicationKey.java index ae4448f9c908..dbfd655953d6 100644 --- a/core/java/android/security/keystore/recovery/WrappedApplicationKey.java +++ b/core/java/android/security/keystore/recovery/WrappedApplicationKey.java @@ -17,6 +17,7 @@ package android.security.keystore.recovery; import android.annotation.NonNull; +import android.annotation.Nullable; import android.annotation.SystemApi; import android.os.Parcel; import android.os.Parcelable; @@ -41,6 +42,8 @@ public final class WrappedApplicationKey implements Parcelable { private String mAlias; // The only supported format is AES-256 symmetric key. private byte[] mEncryptedKeyMaterial; + // The optional metadata that's authenticated (but unencrypted) with the key material. + private byte[] mMetadata; // IMPORTANT! PLEASE READ! // ----------------------- @@ -80,13 +83,23 @@ public final class WrappedApplicationKey implements Parcelable { * @param encryptedKeyMaterial The key material * @return This builder */ - public Builder setEncryptedKeyMaterial(@NonNull byte[] encryptedKeyMaterial) { mInstance.mEncryptedKeyMaterial = encryptedKeyMaterial; return this; } /** + * Sets the metadata that is authenticated (but unecrypted) with the key material. + * + * @param metadata The metadata + * @return This builder + */ + public Builder setMetadata(@Nullable byte[] metadata) { + mInstance.mMetadata = metadata; + return this; + } + + /** * Creates a new {@link WrappedApplicationKey} instance. * * @return new instance @@ -102,9 +115,10 @@ public final class WrappedApplicationKey implements Parcelable { private WrappedApplicationKey() { } /** - * Deprecated - consider using Builder. + * @deprecated Use the builder instead. * @hide */ + @Deprecated public WrappedApplicationKey(@NonNull String alias, @NonNull byte[] encryptedKeyMaterial) { mAlias = Preconditions.checkNotNull(alias); mEncryptedKeyMaterial = Preconditions.checkNotNull(encryptedKeyMaterial); @@ -124,6 +138,11 @@ public final class WrappedApplicationKey implements Parcelable { return mEncryptedKeyMaterial; } + /** The metadata with the key. */ + public @Nullable byte[] getMetadata() { + return mMetadata; + } + public static final Parcelable.Creator<WrappedApplicationKey> CREATOR = new Parcelable.Creator<WrappedApplicationKey>() { public WrappedApplicationKey createFromParcel(Parcel in) { @@ -139,6 +158,7 @@ public final class WrappedApplicationKey implements Parcelable { public void writeToParcel(Parcel out, int flags) { out.writeString(mAlias); out.writeByteArray(mEncryptedKeyMaterial); + out.writeByteArray(mMetadata); } /** @@ -147,6 +167,10 @@ public final class WrappedApplicationKey implements Parcelable { protected WrappedApplicationKey(Parcel in) { mAlias = in.readString(); mEncryptedKeyMaterial = in.createByteArray(); + // Check if there is still data to be read. + if (in.dataAvail() > 0) { + mMetadata = in.createByteArray(); + } } @Override diff --git a/core/java/android/service/attention/AttentionService.java b/core/java/android/service/attention/AttentionService.java new file mode 100644 index 000000000000..f6e448dc4757 --- /dev/null +++ b/core/java/android/service/attention/AttentionService.java @@ -0,0 +1,160 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.service.attention; + +import android.annotation.IntDef; +import android.annotation.NonNull; +import android.annotation.SystemApi; +import android.app.Service; +import android.content.Intent; +import android.os.IBinder; +import android.os.RemoteException; + +import com.android.internal.util.Preconditions; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + + +/** + * Abstract base class for Attention service. + * + * <p> An attention service provides attention estimation related features to the system. + * The system's default AttentionService implementation is configured in + * {@code config_AttentionComponent}. If this config has no value, a stub is returned. + * + * See: {@link AttentionManagerService}. + * + * <pre> + * {@literal + * <service android:name=".YourAttentionService" + * android:permission="android.permission.BIND_ATTENTION_SERVICE"> + * </service>} + * </pre> + * + * @hide + */ +@SystemApi +public abstract class AttentionService extends Service { + /** + * The {@link Intent} that must be declared as handled by the service. To be supported, the + * service must also require the {@link android.Manifest.permission#BIND_ATTENTION_SERVICE} + * permission so that other applications can not abuse it. + */ + public static final String SERVICE_INTERFACE = + "android.service.attention.AttentionService"; + + /** Attention is absent. */ + public static final int ATTENTION_SUCCESS_ABSENT = 0; + + /** Attention is present. */ + public static final int ATTENTION_SUCCESS_PRESENT = 1; + + /** Preempted by other camera user. */ + public static final int ATTENTION_FAILURE_PREEMPTED = 2; + + /** Preempted by other camera user. */ + public static final int ATTENTION_FAILURE_TIMED_OUT = 3; + + /** Unknown reasons for failing to determine the attention. */ + public static final int ATTENTION_FAILURE_UNKNOWN = 4; + + /** + * Result codes for when attention check was successful. + * + * @hide + */ + @IntDef(prefix = {"ATTENTION_SUCCESS_"}, value = {ATTENTION_SUCCESS_ABSENT, + ATTENTION_SUCCESS_PRESENT}) + @Retention(RetentionPolicy.SOURCE) + public @interface AttentionSuccessCodes { + } + + /** + * Result codes explaining why attention check was not successful. + * + * @hide + */ + @IntDef(prefix = {"ATTENTION_FAILURE_"}, value = {ATTENTION_FAILURE_PREEMPTED, + ATTENTION_FAILURE_TIMED_OUT, ATTENTION_FAILURE_UNKNOWN}) + @Retention(RetentionPolicy.SOURCE) + public @interface AttentionFailureCodes { + } + + private final IAttentionService.Stub mBinder = new IAttentionService.Stub() { + + /** {@inheritDoc} */ + @Override + public void checkAttention(int requestCode, IAttentionCallback callback) { + Preconditions.checkNotNull(callback); + AttentionService.this.onCheckAttention(requestCode, new AttentionCallback(callback)); + } + + /** {@inheritDoc} */ + @Override + public void cancelAttentionCheck(int requestCode) { + AttentionService.this.onCancelAttentionCheck(requestCode); + } + }; + + @Override + public final IBinder onBind(Intent intent) { + if (SERVICE_INTERFACE.equals(intent.getAction())) { + return mBinder; + } + return null; + } + + /** + * Checks the user attention and calls into the provided callback. + * + * @param requestCode an identifier that could be used to cancel the request + * @param callback the callback to return the result to + */ + public abstract void onCheckAttention(int requestCode, @NonNull AttentionCallback callback); + + /** Cancels the attention check for a given request code. */ + public abstract void onCancelAttentionCheck(int requestCode); + + + /** Callbacks for AttentionService results. */ + public static final class AttentionCallback { + private final IAttentionCallback mCallback; + + private AttentionCallback(IAttentionCallback callback) { + mCallback = callback; + } + + /** Returns the result. */ + public void onSuccess(int requestCode, @AttentionSuccessCodes int result, long timestamp) { + try { + mCallback.onSuccess(requestCode, result, timestamp); + } catch (RemoteException e) { + e.rethrowFromSystemServer(); + } + } + + /** Signals a failure. */ + public void onFailure(int requestCode, @AttentionFailureCodes int error) { + try { + mCallback.onFailure(requestCode, error); + } catch (RemoteException e) { + e.rethrowFromSystemServer(); + } + } + } +} diff --git a/core/java/android/hardware/location/IActivityRecognitionHardwareSink.aidl b/core/java/android/service/attention/IAttentionCallback.aidl index 21c8e87e6c6d..0e8a1e75c14b 100644 --- a/core/java/android/hardware/location/IActivityRecognitionHardwareSink.aidl +++ b/core/java/android/service/attention/IAttentionCallback.aidl @@ -1,11 +1,11 @@ -/* - * Copyright (C) 2014, The Android Open Source Project + /* + * Copyright (C) 2019 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/license/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -14,19 +14,14 @@ * limitations under the License. */ -package android.hardware.location; - -import android.hardware.location.ActivityChangedEvent; +package android.service.attention; /** - * Activity Recognition Hardware provider Sink interface. - * This interface can be used to implement sinks to receive activity notifications. + * Callback for onCheckAttention request. * * @hide */ -interface IActivityRecognitionHardwareSink { - /** - * Activity changed event. - */ - void onActivityChanged(in ActivityChangedEvent event); -}
\ No newline at end of file +oneway interface IAttentionCallback { + void onSuccess(int requestCode, int result, long timestamp); + void onFailure(int requestCode, int error); +} diff --git a/services/core/java/com/android/server/wm/StackWindowListener.java b/core/java/android/service/attention/IAttentionService.aidl index c763c175687f..c3b6f48a5b2e 100644 --- a/services/core/java/com/android/server/wm/StackWindowListener.java +++ b/core/java/android/service/attention/IAttentionService.aidl @@ -1,5 +1,5 @@ /* - * Copyright (C) 2017 The Android Open Source Project + * Copyright (C) 2019 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -11,19 +11,19 @@ * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and - * limitations under the License + * limitations under the License. */ -package com.android.server.wm; +package android.service.attention; -import android.graphics.Rect; +import android.service.attention.IAttentionCallback; /** - * Interface used by the creator of {@link StackWindowController} to listen to changes with - * the stack container. + * Interface for a concrete implementation to provide to the AttentionManagerService. + * + * @hide */ -public interface StackWindowListener extends WindowContainerListener { - - /** Called when the stack container would like its controller to resize. */ - void requestResize(Rect bounds); -} +oneway interface IAttentionService { + void checkAttention(int requestCode, IAttentionCallback callback); + void cancelAttentionCheck(int requestCode); +}
\ No newline at end of file diff --git a/core/java/android/service/euicc/EuiccService.java b/core/java/android/service/euicc/EuiccService.java index 4be1f9cd6ae5..4dc10cd2e4cc 100644 --- a/core/java/android/service/euicc/EuiccService.java +++ b/core/java/android/service/euicc/EuiccService.java @@ -184,6 +184,12 @@ public abstract class EuiccService extends Service { public static final String EXTRA_RESOLUTION_CONFIRMATION_CODE_RETRIED = "android.service.euicc.extra.RESOLUTION_CONFIRMATION_CODE_RETRIED"; + /** + * Intent extra set for resolution requests containing an int indicating the current card Id. + */ + public static final String EXTRA_RESOLUTION_CARD_ID = + "android.service.euicc.extra.RESOLUTION_CARD_ID"; + /** @hide */ @Retention(RetentionPolicy.SOURCE) @IntDef(prefix = { "RESULT_" }, value = { diff --git a/core/java/android/service/voice/VoiceInteractionSession.java b/core/java/android/service/voice/VoiceInteractionSession.java index 163e3d5fab56..6f274477431f 100644 --- a/core/java/android/service/voice/VoiceInteractionSession.java +++ b/core/java/android/service/voice/VoiceInteractionSession.java @@ -121,6 +121,12 @@ public class VoiceInteractionSession implements KeyEvent.Callback, ComponentCall */ public static final int SHOW_SOURCE_NOTIFICATION = 1 << 6; + /** + * Flag for use with {@link #onShow}: indicates that the voice interaction service was invoked + * from an Android automotive system Ui. + */ + public static final int SHOW_SOURCE_AUTOMOTIVE_SYSTEM_UI = 1 << 7; + final Context mContext; final HandlerCaller mHandlerCaller; diff --git a/core/java/android/util/Half.java b/core/java/android/util/Half.java index 5718d994620d..70d049a6e985 100644 --- a/core/java/android/util/Half.java +++ b/core/java/android/util/Half.java @@ -162,6 +162,7 @@ public final class Half extends Number implements Comparable<Half> { private static final int FP32_EXPONENT_MASK = 0xff; private static final int FP32_SIGNIFICAND_MASK = 0x7fffff; private static final int FP32_EXPONENT_BIAS = 127; + private static final int FP32_QNAN_MASK = 0x400000; private static final int FP32_DENORMAL_MAGIC = 126 << 23; private static final float FP32_DENORMAL_FLOAT = Float.intBitsToFloat(FP32_DENORMAL_MAGIC); @@ -903,6 +904,9 @@ public final class Half extends Number implements Comparable<Half> { outM = m << 13; if (e == 0x1f) { // Infinite or NaN outE = 0xff; + if (outM != 0) { // SNaNs are quieted + outM |= FP32_QNAN_MASK; + } } else { outE = e - FP16_EXPONENT_BIAS + FP32_EXPONENT_BIAS; } diff --git a/core/java/android/util/TimeUtils.java b/core/java/android/util/TimeUtils.java index 91bc3eb5f83a..e4c8eeb3b9b0 100644 --- a/core/java/android/util/TimeUtils.java +++ b/core/java/android/util/TimeUtils.java @@ -43,6 +43,9 @@ public class TimeUtils { /** {@hide} */ private static SimpleDateFormat sLoggingFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); + /** @hide */ + public static final SimpleDateFormat sDumpDateFormat = + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS"); /** * Tries to return a time zone that would have had the specified offset * and DST value at the specified moment in the specified country. @@ -360,4 +363,28 @@ public class TimeUtils { return sLoggingFormat.format(new Date(millis)); } } -} + + /** + * Dump a currentTimeMillis style timestamp for dumpsys. + * + * @hide + */ + public static void dumpTime(PrintWriter pw, long time) { + pw.print(sDumpDateFormat.format(new Date(time))); + } + + /** + * Dump a currentTimeMillis style timestamp for dumpsys, with the delta time from now. + * + * @hide + */ + public static void dumpTimeWithDelta(PrintWriter pw, long time, long now) { + pw.print(sDumpDateFormat.format(new Date(time))); + if (time == now) { + pw.print(" (now)"); + } else { + pw.print(" ("); + TimeUtils.formatDuration(time, now, pw); + pw.print(")"); + } + }} diff --git a/core/java/android/view/Display.java b/core/java/android/view/Display.java index 4ead34ed2f97..f58efc900427 100644 --- a/core/java/android/view/Display.java +++ b/core/java/android/view/Display.java @@ -1391,11 +1391,17 @@ public final class Display { */ public static final int HDR_TYPE_HLG = 3; + /** + * HDR10+ display. + */ + public static final int HDR_TYPE_HDR10_PLUS = 4; + /** @hide */ @IntDef(prefix = { "HDR_TYPE_" }, value = { HDR_TYPE_DOLBY_VISION, HDR_TYPE_HDR10, HDR_TYPE_HLG, + HDR_TYPE_HDR10_PLUS, }) @Retention(RetentionPolicy.SOURCE) public @interface HdrType {} diff --git a/core/java/android/view/KeyEvent.java b/core/java/android/view/KeyEvent.java index 9cced4e0052f..f9a46b13d0e1 100644 --- a/core/java/android/view/KeyEvent.java +++ b/core/java/android/view/KeyEvent.java @@ -818,7 +818,10 @@ public class KeyEvent extends InputEvent implements Parcelable { public static final int KEYCODE_THUMBS_UP = 286; /** Key code constant: Thumbs down key. Apps can use this to let user downvote content. */ public static final int KEYCODE_THUMBS_DOWN = 287; - /** Key code constant: Consumed by system to switch current viewer profile. */ + /** + * Key code constant: Used to switch current {@link android.accounts.Account} that is + * consuming content. May be consumed by system to set account globally. + */ public static final int KEYCODE_PROFILE_SWITCH = 288; /** diff --git a/core/java/android/view/LayoutInflater.java b/core/java/android/view/LayoutInflater.java index ffd4156b5bfd..dc7c343c2c3e 100644 --- a/core/java/android/view/LayoutInflater.java +++ b/core/java/android/view/LayoutInflater.java @@ -22,6 +22,7 @@ import android.annotation.Nullable; import android.annotation.SystemService; import android.annotation.UnsupportedAppUsage; import android.content.Context; +import android.content.pm.ApplicationInfo; import android.content.res.Resources; import android.content.res.TypedArray; import android.content.res.XmlResourceParser; @@ -29,6 +30,7 @@ import android.graphics.Canvas; import android.os.Build; import android.os.Handler; import android.os.Message; +import android.os.SystemProperties; import android.os.Trace; import android.util.AttributeSet; import android.util.Log; @@ -38,6 +40,9 @@ import android.widget.FrameLayout; import com.android.internal.R; +import dalvik.system.PathClassLoader; +import java.io.File; +import java.lang.reflect.Method; import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParserException; @@ -72,6 +77,10 @@ public abstract class LayoutInflater { private static final String TAG = LayoutInflater.class.getSimpleName(); private static final boolean DEBUG = false; + private static final String USE_PRECOMPILED_LAYOUT_SYSTEM_PROPERTY + = "view.precompiled_layout_enabled"; + private static final String COMPILED_VIEW_DEX_FILE_NAME = "/compiled_view.dex"; + /** Empty stack trace used to avoid log spam in re-throw exceptions. */ private static final StackTraceElement[] EMPTY_STACK_TRACE = new StackTraceElement[0]; @@ -93,6 +102,13 @@ public abstract class LayoutInflater { private Factory2 mPrivateFactory; private Filter mFilter; + // Indicates whether we should try to inflate layouts using a precompiled layout instead of + // inflating from the XML resource. + private boolean mUseCompiledView; + // This variable holds the classloader that will be used to look for precompiled layouts. The + // The classloader includes the generated compiled_view.dex file. + private ClassLoader mPrecompiledClassLoader; + @UnsupportedAppUsage final Object[] mConstructorArgs = new Object[2]; @@ -223,6 +239,7 @@ public abstract class LayoutInflater { */ protected LayoutInflater(Context context) { mContext = context; + initPrecompiledViews(); } /** @@ -239,6 +256,7 @@ public abstract class LayoutInflater { mFactory2 = original.mFactory2; mPrivateFactory = original.mPrivateFactory; setFilter(original.mFilter); + initPrecompiledViews(); } /** @@ -380,6 +398,41 @@ public abstract class LayoutInflater { } } + private void initPrecompiledViews() { + // Check if precompiled layouts are enabled by a system property. + mUseCompiledView = + SystemProperties.getBoolean(USE_PRECOMPILED_LAYOUT_SYSTEM_PROPERTY, false); + if (!mUseCompiledView) { + return; + } + + // Make sure the application allows code generation + ApplicationInfo appInfo = mContext.getApplicationInfo(); + if ((appInfo.privateFlags & ApplicationInfo.PRIVATE_FLAG_PREFER_CODE_INTEGRITY) != 0 + || appInfo.isPrivilegedApp()) { + mUseCompiledView = false; + return; + } + + // Try to load the precompiled layout file. + try { + mPrecompiledClassLoader = mContext.getClassLoader(); + String dexFile = mContext.getCodeCacheDir() + COMPILED_VIEW_DEX_FILE_NAME; + if (new File(dexFile).exists()) { + mPrecompiledClassLoader = new PathClassLoader(dexFile, mPrecompiledClassLoader); + } else { + // If the precompiled layout file doesn't exist, then disable precompiled + // layouts. + mUseCompiledView = false; + } + } catch (Throwable e) { + if (DEBUG) { + Log.e(TAG, "Failed to initialized precompiled views layouts", e); + } + mUseCompiledView = false; + } + } + /** * Inflate a new view hierarchy from the specified xml resource. Throws * {@link InflateException} if there is an error. @@ -436,10 +489,14 @@ public abstract class LayoutInflater { final Resources res = getContext().getResources(); if (DEBUG) { Log.d(TAG, "INFLATING from resource: \"" + res.getResourceName(resource) + "\" (" - + Integer.toHexString(resource) + ")"); + + Integer.toHexString(resource) + ")"); } - final XmlResourceParser parser = res.getLayout(resource); + View view = tryInflatePrecompiled(resource, res, root, attachToRoot); + if (view != null) { + return view; + } + XmlResourceParser parser = res.getLayout(resource); try { return inflate(parser, root, attachToRoot); } finally { @@ -447,6 +504,73 @@ public abstract class LayoutInflater { } } + private @Nullable + View tryInflatePrecompiled(@LayoutRes int resource, Resources res, @Nullable ViewGroup root, + boolean attachToRoot) { + if (!mUseCompiledView) { + return null; + } + + Trace.traceBegin(Trace.TRACE_TAG_VIEW, "inflate (precompiled)"); + + // Try to inflate using a precompiled layout. + String pkg = res.getResourcePackageName(resource); + String layout = res.getResourceEntryName(resource); + + try { + Class clazz = mPrecompiledClassLoader.loadClass("" + pkg + ".CompiledView"); + Method inflater = clazz.getMethod(layout, Context.class, int.class); + View view = (View) inflater.invoke(null, mContext, resource); + + if (view != null && root != null) { + // We were able to use the precompiled inflater, but now we need to do some work to + // attach the view to the root correctly. + XmlResourceParser parser = res.getLayout(resource); + try { + AttributeSet attrs = Xml.asAttributeSet(parser); + advanceToRootNode(parser); + ViewGroup.LayoutParams params = root.generateLayoutParams(attrs); + + if (attachToRoot) { + root.addView(view, params); + } else { + view.setLayoutParams(params); + } + } finally { + parser.close(); + } + } + + return view; + } catch (Throwable e) { + if (DEBUG) { + Log.e(TAG, "Failed to use precompiled view", e); + } + } finally { + Trace.traceEnd(Trace.TRACE_TAG_VIEW); + } + return null; + } + + /** + * Advances the given parser to the first START_TAG. Throws InflateException if no start tag is + * found. + */ + private void advanceToRootNode(XmlPullParser parser) + throws InflateException, IOException, XmlPullParserException { + // Look for the root node. + int type; + while ((type = parser.next()) != XmlPullParser.START_TAG && + type != XmlPullParser.END_DOCUMENT) { + // Empty + } + + if (type != XmlPullParser.START_TAG) { + throw new InflateException(parser.getPositionDescription() + + ": No start tag found!"); + } + } + /** * Inflate a new view hierarchy from the specified XML node. Throws * {@link InflateException} if there is an error. @@ -480,18 +604,7 @@ public abstract class LayoutInflater { View result = root; try { - // Look for the root node. - int type; - while ((type = parser.next()) != XmlPullParser.START_TAG && - type != XmlPullParser.END_DOCUMENT) { - // Empty - } - - if (type != XmlPullParser.START_TAG) { - throw new InflateException(parser.getPositionDescription() - + ": No start tag found!"); - } - + advanceToRootNode(parser); final String name = parser.getName(); if (DEBUG) { @@ -994,82 +1107,85 @@ public abstract class LayoutInflater { + "reference. The layout ID " + value + " is not valid."); } - final XmlResourceParser childParser = context.getResources().getLayout(layout); + final View precompiled = tryInflatePrecompiled(layout, context.getResources(), + (ViewGroup) parent, /*attachToRoot=*/true); + if (precompiled == null) { + final XmlResourceParser childParser = context.getResources().getLayout(layout); - try { - final AttributeSet childAttrs = Xml.asAttributeSet(childParser); + try { + final AttributeSet childAttrs = Xml.asAttributeSet(childParser); - while ((type = childParser.next()) != XmlPullParser.START_TAG && - type != XmlPullParser.END_DOCUMENT) { - // Empty. - } + while ((type = childParser.next()) != XmlPullParser.START_TAG && + type != XmlPullParser.END_DOCUMENT) { + // Empty. + } - if (type != XmlPullParser.START_TAG) { - throw new InflateException(childParser.getPositionDescription() + - ": No start tag found!"); - } + if (type != XmlPullParser.START_TAG) { + throw new InflateException(childParser.getPositionDescription() + + ": No start tag found!"); + } - final String childName = childParser.getName(); + final String childName = childParser.getName(); - if (TAG_MERGE.equals(childName)) { - // The <merge> tag doesn't support android:theme, so - // nothing special to do here. - rInflate(childParser, parent, context, childAttrs, false); - } else { - final View view = createViewFromTag(parent, childName, - context, childAttrs, hasThemeOverride); - final ViewGroup group = (ViewGroup) parent; - - final TypedArray a = context.obtainStyledAttributes( - attrs, R.styleable.Include); - final int id = a.getResourceId(R.styleable.Include_id, View.NO_ID); - final int visibility = a.getInt(R.styleable.Include_visibility, -1); - a.recycle(); - - // We try to load the layout params set in the <include /> tag. - // If the parent can't generate layout params (ex. missing width - // or height for the framework ViewGroups, though this is not - // necessarily true of all ViewGroups) then we expect it to throw - // a runtime exception. - // We catch this exception and set localParams accordingly: true - // means we successfully loaded layout params from the <include> - // tag, false means we need to rely on the included layout params. - ViewGroup.LayoutParams params = null; - try { - params = group.generateLayoutParams(attrs); - } catch (RuntimeException e) { - // Ignore, just fail over to child attrs. - } - if (params == null) { - params = group.generateLayoutParams(childAttrs); - } - view.setLayoutParams(params); + if (TAG_MERGE.equals(childName)) { + // The <merge> tag doesn't support android:theme, so + // nothing special to do here. + rInflate(childParser, parent, context, childAttrs, false); + } else { + final View view = createViewFromTag(parent, childName, + context, childAttrs, hasThemeOverride); + final ViewGroup group = (ViewGroup) parent; + + final TypedArray a = context.obtainStyledAttributes( + attrs, R.styleable.Include); + final int id = a.getResourceId(R.styleable.Include_id, View.NO_ID); + final int visibility = a.getInt(R.styleable.Include_visibility, -1); + a.recycle(); + + // We try to load the layout params set in the <include /> tag. + // If the parent can't generate layout params (ex. missing width + // or height for the framework ViewGroups, though this is not + // necessarily true of all ViewGroups) then we expect it to throw + // a runtime exception. + // We catch this exception and set localParams accordingly: true + // means we successfully loaded layout params from the <include> + // tag, false means we need to rely on the included layout params. + ViewGroup.LayoutParams params = null; + try { + params = group.generateLayoutParams(attrs); + } catch (RuntimeException e) { + // Ignore, just fail over to child attrs. + } + if (params == null) { + params = group.generateLayoutParams(childAttrs); + } + view.setLayoutParams(params); - // Inflate all children. - rInflateChildren(childParser, view, childAttrs, true); + // Inflate all children. + rInflateChildren(childParser, view, childAttrs, true); - if (id != View.NO_ID) { - view.setId(id); - } + if (id != View.NO_ID) { + view.setId(id); + } - switch (visibility) { - case 0: - view.setVisibility(View.VISIBLE); - break; - case 1: - view.setVisibility(View.INVISIBLE); - break; - case 2: - view.setVisibility(View.GONE); - break; - } + switch (visibility) { + case 0: + view.setVisibility(View.VISIBLE); + break; + case 1: + view.setVisibility(View.INVISIBLE); + break; + case 2: + view.setVisibility(View.GONE); + break; + } - group.addView(view); + group.addView(view); + } + } finally { + childParser.close(); } - } finally { - childParser.close(); } - LayoutInflater.consumeChildElements(parser); } diff --git a/core/java/android/view/PointerIcon.java b/core/java/android/view/PointerIcon.java index cf11fd04efdf..c3d13bd46eb3 100644 --- a/core/java/android/view/PointerIcon.java +++ b/core/java/android/view/PointerIcon.java @@ -31,6 +31,7 @@ import android.graphics.RectF; import android.graphics.drawable.AnimationDrawable; import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.Drawable; +import android.hardware.display.DisplayManager; import android.os.Build; import android.os.Parcel; import android.os.Parcelable; @@ -144,7 +145,8 @@ public final class PointerIcon implements Parcelable { public static final int TYPE_DEFAULT = TYPE_ARROW; private static final PointerIcon gNullIcon = new PointerIcon(TYPE_NULL); - private static final SparseArray<PointerIcon> gSystemIcons = new SparseArray<PointerIcon>(); + private static final SparseArray<SparseArray<PointerIcon>> gSystemIconsByDisplay = + new SparseArray<SparseArray<PointerIcon>>(); private static boolean sUseLargeIcons = false; @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023) @@ -163,6 +165,12 @@ public final class PointerIcon implements Parcelable { @UnsupportedAppUsage private int mDurationPerFrame; + /** + * Listener for displays lifecycle. + * @hide + */ + private static DisplayManager.DisplayListener sDisplayListener; + private PointerIcon(int type) { mType = type; } @@ -211,7 +219,19 @@ public final class PointerIcon implements Parcelable { return gNullIcon; } - PointerIcon icon = gSystemIcons.get(type); + if (sDisplayListener == null) { + registerDisplayListener(context); + } + + final int displayId = context.getDisplayId(); + SparseArray<PointerIcon> systemIcons = gSystemIconsByDisplay.get(displayId); + if (systemIcons == null) { + systemIcons = new SparseArray<>(); + gSystemIconsByDisplay.put(displayId, systemIcons); + } + + PointerIcon icon = systemIcons.get(type); + // Reload if not in the same display. if (icon != null) { return icon; } @@ -240,7 +260,7 @@ public final class PointerIcon implements Parcelable { } else { icon.loadResource(context, context.getResources(), resourceId); } - gSystemIcons.append(type, icon); + systemIcons.append(type, icon); return icon; } @@ -250,7 +270,7 @@ public final class PointerIcon implements Parcelable { */ public static void setUseLargeIcons(boolean use) { sUseLargeIcons = use; - gSystemIcons.clear(); + gSystemIconsByDisplay.clear(); } /** @@ -576,4 +596,30 @@ public final class PointerIcon implements Parcelable { return 0; } } + + /** + * Manage system icon cache handled by display lifecycle. + * @param context The context. + */ + private static void registerDisplayListener(@NonNull Context context) { + sDisplayListener = new DisplayManager.DisplayListener() { + @Override + public void onDisplayAdded(int displayId) { + } + + @Override + public void onDisplayRemoved(int displayId) { + gSystemIconsByDisplay.remove(displayId); + } + + @Override + public void onDisplayChanged(int displayId) { + gSystemIconsByDisplay.remove(displayId); + } + }; + + DisplayManager displayManager = context.getSystemService(DisplayManager.class); + displayManager.registerDisplayListener(sDisplayListener, null /* handler */); + } + } diff --git a/core/java/android/view/SurfaceControl.java b/core/java/android/view/SurfaceControl.java index ff5120d09e25..5e98236f7535 100644 --- a/core/java/android/view/SurfaceControl.java +++ b/core/java/android/view/SurfaceControl.java @@ -30,6 +30,7 @@ import static android.view.SurfaceControlProto.NAME; import android.annotation.Size; import android.annotation.UnsupportedAppUsage; import android.graphics.Bitmap; +import android.graphics.ColorSpace; import android.graphics.GraphicBuffer; import android.graphics.Matrix; import android.graphics.PixelFormat; @@ -141,6 +142,7 @@ public class SurfaceControl implements Parcelable { private static native int nativeGetActiveConfig(IBinder displayToken); private static native boolean nativeSetActiveConfig(IBinder displayToken, int id); private static native int[] nativeGetDisplayColorModes(IBinder displayToken); + private static native int[] nativeGetCompositionDataspaces(); private static native int nativeGetActiveColorMode(IBinder displayToken); private static native boolean nativeSetActiveColorMode(IBinder displayToken, int colorMode); @@ -167,6 +169,7 @@ public class SurfaceControl implements Parcelable { InputWindowHandle handle); private static native void nativeTransferTouchFocus(long transactionObj, IBinder fromToken, IBinder toToken); + private static native boolean nativeGetProtectedContentSupport(); private final CloseGuard mCloseGuard = CloseGuard.get(); private String mName; @@ -374,6 +377,13 @@ public class SurfaceControl implements Parcelable { */ public static final int WINDOW_TYPE_DONT_SCREENSHOT = 441731; + /** + * internal representation of how to interpret pixel value, used only to convert to ColorSpace. + */ + private static final int INTERNAL_DATASPACE_SRGB = 142671872; + private static final int INTERNAL_DATASPACE_DISPLAY_P3 = 143261696; + private static final int INTERNAL_DATASPACE_SCRGB = 411107328; + private void assignNativeObject(long nativeObject) { if (mNativeObject != 0) { release(); @@ -1516,6 +1526,35 @@ public class SurfaceControl implements Parcelable { } /** + * Returns an array of color spaces with 2 elements. The first color space is the + * default color space and second one is wide color gamut color space. + * @hide + */ + public static ColorSpace[] getCompositionColorSpaces() { + int[] dataspaces = nativeGetCompositionDataspaces(); + ColorSpace srgb = ColorSpace.get(ColorSpace.Named.SRGB); + ColorSpace[] colorSpaces = { srgb, srgb }; + if (dataspaces.length == 2) { + for (int i = 0; i < 2; ++i) { + switch(dataspaces[i]) { + case INTERNAL_DATASPACE_DISPLAY_P3: + colorSpaces[i] = ColorSpace.get(ColorSpace.Named.DISPLAY_P3); + break; + case INTERNAL_DATASPACE_SCRGB: + colorSpaces[i] = ColorSpace.get(ColorSpace.Named.EXTENDED_SRGB); + break; + case INTERNAL_DATASPACE_SRGB: + // Other dataspace is not recognized, use SRGB color space instead, + // the default value of the array is already SRGB, thus do nothing. + default: + break; + } + } + } + return colorSpaces; + } + + /** * @hide */ @UnsupportedAppUsage @@ -1730,6 +1769,14 @@ public class SurfaceControl implements Parcelable { } /** + * Returns whether protected content is supported in GPU composition. + * @hide + */ + public static boolean getProtectedContentSupport() { + return nativeGetProtectedContentSupport(); + } + + /** * @hide */ public static class Transaction implements Closeable { diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java index 32974acdcbbd..a1aa06e901dc 100644 --- a/core/java/android/view/View.java +++ b/core/java/android/view/View.java @@ -8219,6 +8219,10 @@ public class View implements Drawable.Callback, KeyEvent.Callback, * <li>{@link ViewStructure#newHtmlInfoBuilder(String)} * <li>{@link ViewStructure#setHtmlInfo(android.view.ViewStructure.HtmlInfo)} * <li>{@link ViewStructure#setDataIsSensitive(boolean)} + * <li>{@link ViewStructure#setAlpha(float)} + * <li>{@link ViewStructure#setElevation(float)} + * <li>{@link ViewStructure#setTransformation(Matrix)} + * * </ul> */ public void onProvideContentCaptureStructure(@NonNull ViewStructure structure, int flags) { @@ -8283,8 +8287,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, structure.setDimens(ignoredParentLeft + mLeft, ignoredParentTop + mTop, mScrollX, mScrollY, mRight - mLeft, mBottom - mTop); - if (viewFor == VIEW_STRUCTURE_FOR_ASSIST - || viewFor == VIEW_STRUCTURE_FOR_CONTENT_CAPTURE) { + if (viewFor == VIEW_STRUCTURE_FOR_ASSIST) { if (!hasIdentityMatrix()) { structure.setTransformation(getMatrix()); } @@ -9028,11 +9031,12 @@ public class View implements Drawable.Callback, KeyEvent.Callback, if (session == null) return; if (appeared) { - if (!isLaidOut() || !isVisibleToUser() + if (!isLaidOut() || getVisibility() != VISIBLE || (mPrivateFlags4 & PFLAG4_NOTIFIED_CONTENT_CAPTURE_APPEARED) != 0) { if (Log.isLoggable(CONTENT_CAPTURE_LOG_TAG, Log.VERBOSE)) { Log.v(CONTENT_CAPTURE_LOG_TAG, "Ignoring 'appeared' on " + this + ": laid=" - + isLaidOut() + ", visible=" + isVisibleToUser() + + isLaidOut() + ", visibleToUser=" + isVisibleToUser() + + ", visible=" + (getVisibility() == VISIBLE) + ": alreadyNotifiedAppeared=" + ((mPrivateFlags4 & PFLAG4_NOTIFIED_CONTENT_CAPTURE_APPEARED) != 0)); } diff --git a/core/java/android/view/contentcapture/ChildContentCaptureSession.java b/core/java/android/view/contentcapture/ChildContentCaptureSession.java index 04e725e64e9c..63c21f352e74 100644 --- a/core/java/android/view/contentcapture/ChildContentCaptureSession.java +++ b/core/java/android/view/contentcapture/ChildContentCaptureSession.java @@ -68,8 +68,8 @@ final class ChildContentCaptureSession extends ContentCaptureSession { } @Override - void flush() { - mParent.flush(); + void flush(@FlushReason int reason) { + mParent.flush(reason); } @Override @@ -88,10 +88,10 @@ final class ChildContentCaptureSession extends ContentCaptureSession { } @Override - void internalNotifyViewTextChanged(@NonNull AutofillId id, @Nullable CharSequence text, - int flags) { - getMainCaptureSession().notifyViewTextChanged(mId, id, text, flags); + void internalNotifyViewTextChanged(@NonNull AutofillId id, @Nullable CharSequence text) { + getMainCaptureSession().notifyViewTextChanged(mId, id, text); } + @Override boolean isContentCaptureEnabled() { return getMainCaptureSession().isContentCaptureEnabled(); diff --git a/core/java/android/view/contentcapture/ContentCaptureEvent.java b/core/java/android/view/contentcapture/ContentCaptureEvent.java index 0d064307ce54..43963c3054e5 100644 --- a/core/java/android/view/contentcapture/ContentCaptureEvent.java +++ b/core/java/android/view/contentcapture/ContentCaptureEvent.java @@ -21,6 +21,7 @@ import android.annotation.Nullable; import android.annotation.SystemApi; import android.os.Parcel; import android.os.Parcelable; +import android.util.Log; import android.view.autofill.AutofillId; import com.android.internal.util.Preconditions; @@ -28,11 +29,15 @@ import com.android.internal.util.Preconditions; import java.io.PrintWriter; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; +import java.util.ArrayList; +import java.util.List; /** @hide */ @SystemApi public final class ContentCaptureEvent implements Parcelable { + private static final String TAG = ContentCaptureEvent.class.getSimpleName(); + /** @hide */ public static final int TYPE_SESSION_FINISHED = -2; /** @hide */ @@ -46,9 +51,11 @@ public final class ContentCaptureEvent implements Parcelable { public static final int TYPE_VIEW_APPEARED = 1; /** - * Called when a node has been removed from the screen and is not visible to the user anymore. + * Called when one or more nodes have been removed from the screen and is not visible to the + * user anymore. * - * <p>The id of the node is available through {@link #getId()}. + * <p>To get the id(s), first call {@link #getIds()} - if it returns {@code null}, then call + * {@link #getId()}. */ public static final int TYPE_VIEW_DISAPPEARED = 2; @@ -74,29 +81,23 @@ public final class ContentCaptureEvent implements Parcelable { private final @NonNull String mSessionId; private final int mType; private final long mEventTime; - private final int mFlags; private @Nullable AutofillId mId; + private @Nullable ArrayList<AutofillId> mIds; private @Nullable ViewNode mNode; private @Nullable CharSequence mText; private @Nullable String mParentSessionId; private @Nullable ContentCaptureContext mClientContext; /** @hide */ - public ContentCaptureEvent(@NonNull String sessionId, int type, long eventTime, int flags) { + public ContentCaptureEvent(@NonNull String sessionId, int type, long eventTime) { mSessionId = sessionId; mType = type; mEventTime = eventTime; - mFlags = flags; - } - - /** @hide */ - public ContentCaptureEvent(@NonNull String sessionId, int type, int flags) { - this(sessionId, type, System.currentTimeMillis(), flags); } /** @hide */ public ContentCaptureEvent(@NonNull String sessionId, int type) { - this(sessionId, type, /* flags= */ 0); + this(sessionId, type, System.currentTimeMillis()); } /** @hide */ @@ -105,6 +106,27 @@ public final class ContentCaptureEvent implements Parcelable { return this; } + private void setAutofillIds(@NonNull ArrayList<AutofillId> ids) { + mIds = Preconditions.checkNotNull(ids); + } + + /** + * Adds an autofill id to the this event, merging the single id into a list if necessary. + * @hide */ + public ContentCaptureEvent addAutofillId(@NonNull AutofillId id) { + if (mIds == null) { + mIds = new ArrayList<>(); + if (mId == null) { + Log.w(TAG, "addAutofillId(" + id + ") called without an initial id"); + } else { + mIds.add(mId); + mId = null; + } + } + mIds.add(id); + return this; + } + /** * Used by {@link #TYPE_SESSION_STARTED} and {@link #TYPE_SESSION_FINISHED}. * @@ -183,16 +205,6 @@ public final class ContentCaptureEvent implements Parcelable { } /** - * Gets optional flags associated with the event. - * - * @return either {@code 0} or - * {@link android.view.contentcapture.ContentCaptureSession#FLAG_USER_INPUT}. - */ - public int getFlags() { - return mFlags; - } - - /** * Gets the whole metadata of the node associated with the event. * * <p>Only set on {@link #TYPE_VIEW_APPEARED} events. @@ -205,7 +217,9 @@ public final class ContentCaptureEvent implements Parcelable { /** * Gets the {@link AutofillId} of the node associated with the event. * - * <p>Only set on {@link #TYPE_VIEW_DISAPPEARED} and {@link #TYPE_VIEW_TEXT_CHANGED} events. + * <p>Only set on {@link #TYPE_VIEW_DISAPPEARED} (when the event contains just one node - if + * it contains more than one, this method returns {@code null} and the actual ids should be + * retrived by {@link #getIds()}) and {@link #TYPE_VIEW_TEXT_CHANGED} events. */ @Nullable public AutofillId getId() { @@ -213,6 +227,17 @@ public final class ContentCaptureEvent implements Parcelable { } /** + * Gets the {@link AutofillId AutofillIds} of the nodes associated with the event. + * + * <p>Only set on {@link #TYPE_VIEW_DISAPPEARED}, when the event contains more than one node + * (if it contains just one node, it's returned by {@link #getId()} instead. + */ + @Nullable + public List<AutofillId> getIds() { + return mIds; + } + + /** * Gets the current text of the node associated with the event. * * <p>Only set on {@link #TYPE_VIEW_TEXT_CHANGED} events. @@ -226,12 +251,12 @@ public final class ContentCaptureEvent implements Parcelable { public void dump(@NonNull PrintWriter pw) { pw.print("type="); pw.print(getTypeAsString(mType)); pw.print(", time="); pw.print(mEventTime); - if (mFlags > 0) { - pw.print(", flags="); pw.print(mFlags); - } if (mId != null) { pw.print(", id="); pw.print(mId); } + if (mIds != null) { + pw.print(", ids="); pw.print(mIds); + } if (mNode != null) { pw.print(", mNode.id="); pw.print(mNode.getAutofillId()); } @@ -255,12 +280,12 @@ public final class ContentCaptureEvent implements Parcelable { if (mType == TYPE_SESSION_STARTED && mParentSessionId != null) { string.append(", parent=").append(mParentSessionId); } - if (mFlags > 0) { - string.append(", flags=").append(mFlags); - } if (mId != null) { string.append(", id=").append(mId); } + if (mIds != null) { + string.append(", ids=").append(mIds); + } if (mNode != null) { final String className = mNode.getClassName(); if (mNode != null) { @@ -281,8 +306,8 @@ public final class ContentCaptureEvent implements Parcelable { parcel.writeString(mSessionId); parcel.writeInt(mType); parcel.writeLong(mEventTime); - parcel.writeInt(mFlags); parcel.writeParcelable(mId, flags); + parcel.writeTypedList(mIds); ViewNode.writeToParcel(parcel, mNode, flags); parcel.writeCharSequence(mText); if (mType == TYPE_SESSION_STARTED || mType == TYPE_SESSION_FINISHED) { @@ -301,13 +326,15 @@ public final class ContentCaptureEvent implements Parcelable { final String sessionId = parcel.readString(); final int type = parcel.readInt(); final long eventTime = parcel.readLong(); - final int flags = parcel.readInt(); - final ContentCaptureEvent event = - new ContentCaptureEvent(sessionId, type, eventTime, flags); + final ContentCaptureEvent event = new ContentCaptureEvent(sessionId, type, eventTime); final AutofillId id = parcel.readParcelable(null); if (id != null) { event.setAutofillId(id); } + final ArrayList<AutofillId> ids = parcel.createTypedArrayList(AutofillId.CREATOR); + if (ids != null) { + event.setAutofillIds(ids); + } final ViewNode node = ViewNode.readFromParcel(parcel); if (node != null) { event.setViewNode(node); diff --git a/core/java/android/view/contentcapture/ContentCaptureManager.java b/core/java/android/view/contentcapture/ContentCaptureManager.java index 81b2e01dfbc7..413f1a5a8955 100644 --- a/core/java/android/view/contentcapture/ContentCaptureManager.java +++ b/core/java/android/view/contentcapture/ContentCaptureManager.java @@ -24,10 +24,11 @@ import android.annotation.UiThread; import android.content.ComponentName; import android.content.Context; import android.os.Handler; -import android.os.HandlerThread; import android.os.IBinder; +import android.os.Looper; import android.os.RemoteException; import android.util.Log; +import android.view.contentcapture.ContentCaptureSession.FlushReason; import com.android.internal.annotations.GuardedBy; import com.android.internal.os.IResultReceiver; @@ -51,8 +52,6 @@ public final class ContentCaptureManager { private static final String TAG = ContentCaptureManager.class.getSimpleName(); - private static final String BG_THREAD_NAME = "intel_svc_streamer_thread"; - /** * Timeout for calls to system_server. */ @@ -89,24 +88,13 @@ public final class ContentCaptureManager { public ContentCaptureManager(@NonNull Context context, @Nullable IContentCaptureManager service) { mContext = Preconditions.checkNotNull(context, "context cannot be null"); - if (VERBOSE) { - Log.v(TAG, "Constructor for " + context.getPackageName()); - } - mService = service; - // TODO(b/119220549): use an existing bg thread instead... - final HandlerThread bgThread = new HandlerThread(BG_THREAD_NAME); - bgThread.start(); - mHandler = Handler.createAsync(bgThread.getLooper()); - } + if (VERBOSE) Log.v(TAG, "Constructor for " + context.getPackageName()); - @NonNull - private static Handler newHandler() { - // TODO(b/119220549): use an existing bg thread instead... - // TODO(b/119220549): use UI Thread directly (as calls are one-way) or an existing bgThread - // or a shared thread / handler held at the Application level - final HandlerThread bgThread = new HandlerThread(BG_THREAD_NAME); - bgThread.start(); - return Handler.createAsync(bgThread.getLooper()); + mService = service; + // TODO(b/119220549): we might not even need a handler, as the IPCs are oneway. But if we + // do, then we should optimize it to run the tests after the Choreographer finishes the most + // important steps of the frame. + mHandler = Handler.createAsync(Looper.getMainLooper()); } /** @@ -154,8 +142,8 @@ public final class ContentCaptureManager { * * @hide */ - public void flush() { - getMainContentCaptureSession().flush(); + public void flush(@FlushReason int reason) { + getMainContentCaptureSession().flush(reason); } /** diff --git a/core/java/android/view/contentcapture/ContentCaptureSession.java b/core/java/android/view/contentcapture/ContentCaptureSession.java index 2123308dbdeb..b620ab1eb7c3 100644 --- a/core/java/android/view/contentcapture/ContentCaptureSession.java +++ b/core/java/android/view/contentcapture/ContentCaptureSession.java @@ -19,6 +19,7 @@ import static android.view.contentcapture.ContentCaptureManager.DEBUG; import static android.view.contentcapture.ContentCaptureManager.VERBOSE; import android.annotation.CallSuper; +import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; import android.util.DebugUtils; @@ -30,11 +31,14 @@ import android.view.contentcapture.ViewNode.ViewStructureImpl; import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.VisibleForTesting; +import com.android.internal.util.ArrayUtils; import com.android.internal.util.Preconditions; import dalvik.system.CloseGuard; import java.io.PrintWriter; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; import java.util.ArrayList; import java.util.UUID; @@ -47,12 +51,6 @@ public abstract class ContentCaptureSession implements AutoCloseable { private static final String TAG = ContentCaptureSession.class.getSimpleName(); /** - * Used on {@link #notifyViewTextChanged(AutofillId, CharSequence, int)} to indicate that the - * text change was caused by user input (for example, through IME). - */ - public static final int FLAG_USER_INPUT = 0x1; - - /** * Initial state, when there is no session. * * @hide @@ -109,9 +107,48 @@ public abstract class ContentCaptureSession implements AutoCloseable { */ public static final int STATE_BY_APP = 0x40; + /** + * Session is disabled because session start was never replied. + * + * @hide + */ + public static final int STATE_NO_RESPONSE = 0x80; + + /** + * Session is disabled because an internal error. + * + * @hide + */ + public static final int STATE_INTERNAL_ERROR = 0x100; private static final int INITIAL_CHILDREN_CAPACITY = 5; + /** @hide */ + public static final int FLUSH_REASON_FULL = 1; + /** @hide */ + public static final int FLUSH_REASON_ACTIVITY_PAUSED = 2; + /** @hide */ + public static final int FLUSH_REASON_ACTIVITY_RESUMED = 3; + /** @hide */ + public static final int FLUSH_REASON_SESSION_STARTED = 4; + /** @hide */ + public static final int FLUSH_REASON_SESSION_FINISHED = 5; + /** @hide */ + public static final int FLUSH_REASON_IDLE_TIMEOUT = 6; + + /** @hide */ + @IntDef(prefix = { "FLUSH_REASON_" }, value = { + FLUSH_REASON_FULL, + FLUSH_REASON_ACTIVITY_PAUSED, + FLUSH_REASON_ACTIVITY_RESUMED, + FLUSH_REASON_SESSION_STARTED, + FLUSH_REASON_SESSION_FINISHED, + FLUSH_REASON_IDLE_TIMEOUT + }) + @Retention(RetentionPolicy.SOURCE) + @interface FlushReason{} + + private final CloseGuard mCloseGuard = CloseGuard.get(); private final Object mLock = new Object(); @@ -199,7 +236,7 @@ public abstract class ContentCaptureSession implements AutoCloseable { /** * Flushes the buffered events to the service. */ - abstract void flush(); + abstract void flush(@FlushReason int reason); /** * Destroys this session, flushing out all pending notifications to the service. @@ -237,7 +274,7 @@ public abstract class ContentCaptureSession implements AutoCloseable { } try { - flush(); + flush(FLUSH_REASON_SESSION_FINISHED); } finally { onDestroy(); } @@ -303,12 +340,36 @@ public abstract class ContentCaptureSession implements AutoCloseable { abstract void internalNotifyViewDisappeared(@NonNull AutofillId id); /** + * Notifies the Content Capture Service that many nodes has been removed from a virtual view + * structure. + * + * <p>Should only be called by views that handle their own virtual view hierarchy. + * + * @param hostId id of the view hosting the virtual hierarchy. + * @param virtualIds ids of the virtual children. + * + * @throws IllegalArgumentException if the {@code hostId} is an autofill id for a virtual view. + * @throws IllegalArgumentException if {@code virtualIds} is empty + */ + public final void notifyViewsDisappeared(@NonNull AutofillId hostId, + @NonNull int[] virtualIds) { + Preconditions.checkArgument(!hostId.isVirtual(), "parent cannot be virtual"); + Preconditions.checkArgument(!ArrayUtils.isEmpty(virtualIds), "virtual ids cannot be empty"); + if (!isContentCaptureEnabled()) return; + + // TODO(b/123036895): use a internalNotifyViewsDisappeared that optimizes how the event is + // parcelized + for (int id : virtualIds) { + internalNotifyViewDisappeared(new AutofillId(hostId, id, getIdAsInt())); + } + } + + /** * Notifies the Intelligence Service that the value of a text node has been changed. * * @param id of the node. * @param text new text. - * @param flags either {@code 0} or {@link #FLAG_USER_INPUT} when the value was explicitly - * changed by the user (for example, through the keyboard). + * @param flags currently ignored. */ public final void notifyViewTextChanged(@NonNull AutofillId id, @Nullable CharSequence text, int flags) { @@ -316,11 +377,11 @@ public abstract class ContentCaptureSession implements AutoCloseable { if (!isContentCaptureEnabled()) return; - internalNotifyViewTextChanged(id, text, flags); + internalNotifyViewTextChanged(id, text); } - abstract void internalNotifyViewTextChanged(@NonNull AutofillId id, @Nullable CharSequence text, - int flags); + abstract void internalNotifyViewTextChanged(@NonNull AutofillId id, + @Nullable CharSequence text); /** * Creates a {@link ViewStructure} for a "standard" view. @@ -394,12 +455,31 @@ public abstract class ContentCaptureSession implements AutoCloseable { return mId; } - /** - * @hide - */ + /** @hide */ @NonNull protected static String getStateAsString(int state) { return state + " (" + (state == UNKNWON_STATE ? "UNKNOWN" : DebugUtils.flagsToString(ContentCaptureSession.class, "STATE_", state)) + ")"; } + + /** @hide */ + @NonNull + static String getflushReasonAsString(@FlushReason int reason) { + switch (reason) { + case FLUSH_REASON_FULL: + return "FULL"; + case FLUSH_REASON_ACTIVITY_PAUSED: + return "PAUSED"; + case FLUSH_REASON_ACTIVITY_RESUMED: + return "RESUMED"; + case FLUSH_REASON_SESSION_STARTED: + return "STARTED"; + case FLUSH_REASON_SESSION_FINISHED: + return "FINISHED"; + case FLUSH_REASON_IDLE_TIMEOUT: + return "IDLE"; + default: + return "UNKOWN-" + reason; + } + } } diff --git a/core/java/android/view/contentcapture/MainContentCaptureSession.java b/core/java/android/view/contentcapture/MainContentCaptureSession.java index 1d9018c1682c..103d7e6dc256 100644 --- a/core/java/android/view/contentcapture/MainContentCaptureSession.java +++ b/core/java/android/view/contentcapture/MainContentCaptureSession.java @@ -35,7 +35,7 @@ import android.os.Handler; import android.os.IBinder; import android.os.IBinder.DeathRecipient; import android.os.RemoteException; -import android.os.SystemClock; +import android.util.LocalLog; import android.util.Log; import android.util.TimeUtils; import android.view.autofill.AutofillId; @@ -131,6 +131,9 @@ public final class MainContentCaptureSession extends ContentCaptureSession { // Used just for debugging purposes (on dump) private long mNextFlush; + // TODO(b/121044064): use settings to set size + private final LocalLog mFlushHistory = new LocalLog(10); + /** @hide */ protected MainContentCaptureSession(@NonNull Context context, @NonNull Handler handler, @Nullable IContentCaptureManager systemServerInterface, @@ -172,8 +175,9 @@ public final class MainContentCaptureSession extends ContentCaptureSession { } @Override - void flush() { - mHandler.sendMessage(obtainMessage(MainContentCaptureSession::handleForceFlush, this)); + void flush(@FlushReason int reason) { + mHandler.sendMessage( + obtainMessage(MainContentCaptureSession::handleForceFlush, this, reason)); } @Override @@ -185,10 +189,13 @@ public final class MainContentCaptureSession extends ContentCaptureSession { private void handleStartSession(@NonNull IBinder token, @NonNull ComponentName componentName, int flags) { - if (mState != UNKNWON_STATE) { - // TODO(b/111276913): revisit this scenario - Log.w(TAG, "ignoring handleStartSession(" + token + ") while on state " - + getStateAsString(mState)); + if (handleHasStarted()) { + // TODO(b/122959591): make sure this is expected (and when), or use Log.w + if (DEBUG) { + Log.d(TAG, "ignoring handleStartSession(" + token + "/" + + ComponentName.flattenToShortString(componentName) + " while on state " + + getStateAsString(mState)); + } return; } mState = STATE_WAITING_FOR_SERVER; @@ -197,7 +204,7 @@ public final class MainContentCaptureSession extends ContentCaptureSession { if (VERBOSE) { Log.v(TAG, "handleStartSession(): token=" + token + ", act=" - + getActivityDebugName() + ", id=" + mId); + + getDebugState() + ", id=" + mId); } try { @@ -212,7 +219,7 @@ public final class MainContentCaptureSession extends ContentCaptureSession { binder = resultData.getBinder(EXTRA_BINDER); if (binder == null) { Log.wtf(TAG, "No " + EXTRA_BINDER + " extra result"); - handleResetState(); + handleResetSession(STATE_DISABLED | STATE_INTERNAL_ERROR); return; } } @@ -234,7 +241,6 @@ public final class MainContentCaptureSession extends ContentCaptureSession { * @param binder handle to {@code IContentCaptureDirectManager} */ private void handleSessionStarted(int resultCode, @Nullable IBinder binder) { - mState = resultCode; if (binder != null) { mDirectServiceInterface = IContentCaptureDirectManager.Stub.asInterface(binder); mDirectServiceVulture = () -> { @@ -248,28 +254,42 @@ public final class MainContentCaptureSession extends ContentCaptureSession { } } - if ((mState & STATE_DISABLED) != 0) { - mDisabled.set(true); - handleResetSession(/* resetState= */ false); + if ((resultCode & STATE_DISABLED) != 0) { + handleResetSession(resultCode); } else { + mState = resultCode; mDisabled.set(false); } if (VERBOSE) { - Log.v(TAG, "handleSessionStarted() result: id=" + mId + Log.v(TAG, "handleSessionStarted() result: id=" + mId + " resultCode=" + resultCode + ", state=" + getStateAsString(mState) + ", disabled=" + mDisabled.get() + ", binder=" + binder + ", events=" + (mEvents == null ? 0 : mEvents.size())); } } private void handleSendEvent(@NonNull ContentCaptureEvent event, boolean forceFlush) { + final int eventType = event.getType(); + if (!handleHasStarted() && eventType != ContentCaptureEvent.TYPE_SESSION_STARTED) { + // TODO(b/120494182): comment when this could happen (dialogs?) + Log.v(TAG, "handleSendEvent(" + getDebugState() + ", " + + ContentCaptureEvent.getTypeAsString(eventType) + + "): session not started yet"); + return; + } + if (VERBOSE) Log.v(TAG, "handleSendEvent(" + getDebugState() + "): " + event); if (mEvents == null) { if (VERBOSE) { - Log.v(TAG, "Creating buffer for " + MAX_BUFFER_SIZE + " events"); + Log.v(TAG, "handleSendEvent(" + getDebugState() + ", " + + ContentCaptureEvent.getTypeAsString(eventType) + + "): creating buffer for " + MAX_BUFFER_SIZE + " events"); } mEvents = new ArrayList<>(MAX_BUFFER_SIZE); } - if (!mEvents.isEmpty() && event.getType() == TYPE_VIEW_TEXT_CHANGED) { + // Some type of events can be merged together + boolean addEvent = true; + + if (!mEvents.isEmpty() && eventType == TYPE_VIEW_TEXT_CHANGED) { final ContentCaptureEvent lastEvent = mEvents.get(mEvents.size() - 1); // TODO(b/121045053): check if flags match @@ -280,10 +300,24 @@ public final class MainContentCaptureSession extends ContentCaptureSession { + event.getText()); } lastEvent.setText(event.getText()); - } else { - mEvents.add(event); + addEvent = false; } - } else { + } + + if (!mEvents.isEmpty() && eventType == TYPE_VIEW_DISAPPEARED) { + final ContentCaptureEvent lastEvent = mEvents.get(mEvents.size() - 1); + if (lastEvent.getType() == TYPE_VIEW_DISAPPEARED + && event.getSessionId().equals(lastEvent.getSessionId())) { + if (VERBOSE) { + Log.v(TAG, "Buffering TYPE_VIEW_DISAPPEARED events for session " + + lastEvent.getSessionId()); + } + lastEvent.addAutofillId(event.getId()); + addEvent = false; + } + } + + if (addEvent) { mEvents.add(event); } @@ -292,76 +326,104 @@ public final class MainContentCaptureSession extends ContentCaptureSession { final boolean bufferEvent = numberEvents < MAX_BUFFER_SIZE; if (bufferEvent && !forceFlush) { - handleScheduleFlush(/* checkExisting= */ true); + handleScheduleFlush(FLUSH_REASON_IDLE_TIMEOUT, /* checkExisting= */ true); return; } if (mState != STATE_ACTIVE && numberEvents >= MAX_BUFFER_SIZE) { // Callback from startSession hasn't been called yet - typically happens on system // apps that are started before the system service - // TODO(b/111276913): try to ignore session while system is not ready / boot + // TODO(b/122959591): try to ignore session while system is not ready / boot // not complete instead. Similarly, the manager service should return right away // when the user does not have a service set if (DEBUG) { - Log.d(TAG, "Closing session for " + getActivityDebugName() - + " after " + numberEvents + " delayed events and state " - + getStateAsString(mState)); + Log.d(TAG, "Closing session for " + getDebugState() + + " after " + numberEvents + " delayed events"); } - handleResetState(); + handleResetSession(STATE_DISABLED | STATE_NO_RESPONSE); // TODO(b/111276913): blacklist activity / use special flag to indicate that // when it's launched again return; } + final int flushReason; + switch (eventType) { + case ContentCaptureEvent.TYPE_SESSION_STARTED: + flushReason = FLUSH_REASON_SESSION_STARTED; + break; + case ContentCaptureEvent.TYPE_SESSION_FINISHED: + flushReason = FLUSH_REASON_SESSION_FINISHED; + break; + default: + flushReason = FLUSH_REASON_FULL; + } + + handleForceFlush(flushReason); + } - handleForceFlush(); + private boolean handleHasStarted() { + return mState != UNKNWON_STATE; } - private void handleScheduleFlush(boolean checkExisting) { + private void handleScheduleFlush(@FlushReason int reason, boolean checkExisting) { + if (!handleHasStarted()) { + Log.v(TAG, "handleScheduleFlush(" + getDebugState() + "): session not started yet"); + return; + } if (checkExisting && mHandler.hasMessages(MSG_FLUSH)) { // "Renew" the flush message by removing the previous one mHandler.removeMessages(MSG_FLUSH); } - mNextFlush = SystemClock.elapsedRealtime() + FLUSHING_FREQUENCY_MS; + mNextFlush = System.currentTimeMillis() + FLUSHING_FREQUENCY_MS; if (VERBOSE) { - Log.v(TAG, "Scheduled to flush in " + FLUSHING_FREQUENCY_MS + "ms: " + mNextFlush); + Log.v(TAG, "handleScheduleFlush(" + getDebugState() + + ", reason=" + getflushReasonAsString(reason) + "): scheduled to flush in " + + FLUSHING_FREQUENCY_MS + "ms: " + TimeUtils.logTimeOfDay(mNextFlush)); } mHandler.sendMessageDelayed( - obtainMessage(MainContentCaptureSession::handleFlushIfNeeded, this) + obtainMessage(MainContentCaptureSession::handleFlushIfNeeded, this, reason) .setWhat(MSG_FLUSH), FLUSHING_FREQUENCY_MS); } - private void handleFlushIfNeeded() { + private void handleFlushIfNeeded(@FlushReason int reason) { if (mEvents.isEmpty()) { if (VERBOSE) Log.v(TAG, "Nothing to flush"); return; } - handleForceFlush(); + handleForceFlush(reason); } - private void handleForceFlush() { + private void handleForceFlush(@FlushReason int reason) { if (mEvents == null) return; if (mDirectServiceInterface == null) { if (VERBOSE) { - Log.v(TAG, "handleForceFlush(): hold your horses, client not ready: " + mEvents); + Log.v(TAG, "handleForceFlush(" + getDebugState() + + ", reason=" + getflushReasonAsString(reason) + + "): hold your horses, client not ready: " + mEvents); } if (!mHandler.hasMessages(MSG_FLUSH)) { - handleScheduleFlush(/* checkExisting= */ false); + handleScheduleFlush(reason, /* checkExisting= */ false); } return; } final int numberEvents = mEvents.size(); + final String reasonString = getflushReasonAsString(reason); + if (DEBUG) { + Log.d(TAG, "Flushing " + numberEvents + " event(s) for " + getDebugState() + + ". Reason: " + reasonString); + } + // Logs reason, size, max size, idle timeout + final String logRecord = "r=" + reasonString + " s=" + numberEvents + + " m=" + MAX_BUFFER_SIZE + " i=" + FLUSHING_FREQUENCY_MS; try { - if (DEBUG) { - Log.d(TAG, "Flushing " + numberEvents + " event(s) for " + getActivityDebugName()); - } + mFlushHistory.log(logRecord); mHandler.removeMessages(MSG_FLUSH); final ParceledListSlice<ContentCaptureEvent> events = handleClearEvents(); mDirectServiceInterface.sendEvents(events); } catch (RemoteException e) { - Log.w(TAG, "Error sending " + numberEvents + " for " + getActivityDebugName() + Log.w(TAG, "Error sending " + numberEvents + " for " + getDebugState() + ": " + e); } } @@ -384,7 +446,7 @@ public final class MainContentCaptureSession extends ContentCaptureSession { if (DEBUG) { Log.d(TAG, "Destroying session (ctx=" + mContext + ", id=" + mId + ") with " + (mEvents == null ? 0 : mEvents.size()) + " event(s) for " - + getActivityDebugName()); + + getDebugState()); } try { @@ -393,21 +455,19 @@ public final class MainContentCaptureSession extends ContentCaptureSession { mSystemServerInterface.finishSession(mContext.getUserId(), mId); } catch (RemoteException e) { Log.e(TAG, "Error destroying system-service session " + mId + " for " - + getActivityDebugName() + ": " + e); + + getDebugState() + ": " + e); } } - private void handleResetState() { - handleResetSession(/* resetState= */ true); - } - // TODO(b/122454205): once we support multiple sessions, we might need to move some of these // clearings out. - private void handleResetSession(boolean resetState) { - if (resetState) { - mState = UNKNWON_STATE; + private void handleResetSession(int newState) { + if (VERBOSE) { + Log.v(TAG, "handleResetSession(" + getActivityName() + "): from " + + getStateAsString(mState) + " to " + getStateAsString(newState)); } - + mState = newState; + mDisabled.set((newState & STATE_DISABLED) != 0); // TODO(b/122454205): must reset children (which currently is owned by superclass) mApplicationToken = null; mComponentName = null; @@ -430,9 +490,8 @@ public final class MainContentCaptureSession extends ContentCaptureSession { } @Override - void internalNotifyViewTextChanged(@NonNull AutofillId id, @Nullable CharSequence text, - int flags) { - notifyViewTextChanged(mId, id, text, flags); + void internalNotifyViewTextChanged(@NonNull AutofillId id, @Nullable CharSequence text) { + notifyViewTextChanged(mId, id, text); } @Override @@ -473,15 +532,14 @@ public final class MainContentCaptureSession extends ContentCaptureSession { } void notifyViewTextChanged(@NonNull String sessionId, @NonNull AutofillId id, - @Nullable CharSequence text, int flags) { + @Nullable CharSequence text) { mHandler.sendMessage(obtainMessage(MainContentCaptureSession::handleSendEvent, this, - new ContentCaptureEvent(sessionId, TYPE_VIEW_TEXT_CHANGED, flags).setAutofillId(id) + new ContentCaptureEvent(sessionId, TYPE_VIEW_TEXT_CHANGED).setAutofillId(id) .setText(text), /* forceFlush= */ false)); } @Override void dump(@NonNull String prefix, @NonNull PrintWriter pw) { - pw.print(prefix); pw.print("id: "); pw.println(mId); pw.print(prefix); pw.print("mContext: "); pw.println(mContext); pw.print(prefix); pw.print("user: "); pw.println(mContext.getUserId()); if (mSystemServerInterface != null) { @@ -516,16 +574,25 @@ public final class MainContentCaptureSession extends ContentCaptureSession { } pw.print(prefix); pw.print("flush frequency: "); pw.println(FLUSHING_FREQUENCY_MS); pw.print(prefix); pw.print("next flush: "); - TimeUtils.formatDuration(mNextFlush - SystemClock.elapsedRealtime(), pw); pw.println(); + TimeUtils.formatDuration(mNextFlush - System.currentTimeMillis(), pw); + pw.print(" ("); pw.print(TimeUtils.logTimeOfDay(mNextFlush)); pw.println(")"); } + pw.print(prefix); pw.println("flush history:"); + mFlushHistory.reverseDump(/* fd= */ null, pw, /* args= */ null); pw.println(); + super.dump(prefix, pw); } /** * Gets a string that can be used to identify the activity on logging statements. */ - private String getActivityDebugName() { - return mComponentName == null ? mContext.getPackageName() - : mComponentName.flattenToShortString(); + private String getActivityName() { + return mComponentName == null + ? "pkg:" + mContext.getPackageName() + : "act:" + mComponentName.flattenToShortString(); + } + + private String getDebugState() { + return getActivityName() + " (state=" + getStateAsString(mState) + ")"; } } diff --git a/core/java/android/view/contentcapture/ViewNode.java b/core/java/android/view/contentcapture/ViewNode.java index ddfecb0fae14..cbc946b773ca 100644 --- a/core/java/android/view/contentcapture/ViewNode.java +++ b/core/java/android/view/contentcapture/ViewNode.java @@ -45,7 +45,6 @@ import com.android.internal.util.Preconditions; public final class ViewNode extends AssistStructure.ViewNode { private static final String TAG = ViewNode.class.getSimpleName(); - private static final boolean VERBOSE = false; private static final long FLAGS_HAS_TEXT = 1L << 0; private static final long FLAGS_HAS_COMPLEX_TEXT = 1L << 1; @@ -69,21 +68,18 @@ public final class ViewNode extends AssistStructure.ViewNode { private static final long FLAGS_SELECTED = 1L << 20; private static final long FLAGS_ACTIVATED = 1L << 21; private static final long FLAGS_OPAQUE = 1L << 22; - private static final long FLAGS_HAS_MATRIX = 1L << 23; - private static final long FLAGS_HAS_ELEVATION = 1L << 24; - private static final long FLAGS_HAS_ALPHA = 1L << 25; - private static final long FLAGS_HAS_CONTENT_DESCRIPTION = 1L << 26; - private static final long FLAGS_HAS_EXTRAS = 1L << 27; - private static final long FLAGS_HAS_LOCALE_LIST = 1L << 28; - private static final long FLAGS_HAS_INPUT_TYPE = 1L << 29; - private static final long FLAGS_HAS_MIN_TEXT_EMS = 1L << 30; - private static final long FLAGS_HAS_MAX_TEXT_EMS = 1L << 31; - private static final long FLAGS_HAS_MAX_TEXT_LENGTH = 1L << 32; - private static final long FLAGS_HAS_TEXT_ID_ENTRY = 1L << 33; - private static final long FLAGS_HAS_AUTOFILL_TYPE = 1L << 34; - private static final long FLAGS_HAS_AUTOFILL_VALUE = 1L << 35; - private static final long FLAGS_HAS_AUTOFILL_HINTS = 1L << 36; - private static final long FLAGS_HAS_AUTOFILL_OPTIONS = 1L << 37; + private static final long FLAGS_HAS_CONTENT_DESCRIPTION = 1L << 23; + private static final long FLAGS_HAS_EXTRAS = 1L << 24; + private static final long FLAGS_HAS_LOCALE_LIST = 1L << 25; + private static final long FLAGS_HAS_INPUT_TYPE = 1L << 26; + private static final long FLAGS_HAS_MIN_TEXT_EMS = 1L << 27; + private static final long FLAGS_HAS_MAX_TEXT_EMS = 1L << 28; + private static final long FLAGS_HAS_MAX_TEXT_LENGTH = 1L << 29; + private static final long FLAGS_HAS_TEXT_ID_ENTRY = 1L << 30; + private static final long FLAGS_HAS_AUTOFILL_TYPE = 1L << 31; + private static final long FLAGS_HAS_AUTOFILL_VALUE = 1L << 32; + private static final long FLAGS_HAS_AUTOFILL_HINTS = 1L << 33; + private static final long FLAGS_HAS_AUTOFILL_OPTIONS = 1L << 34; /** Flags used to optimize what's written to the parcel */ private long mFlags; @@ -103,9 +99,6 @@ public final class ViewNode extends AssistStructure.ViewNode { private int mScrollY; private int mWidth; private int mHeight; - private Matrix mMatrix; - private float mElevation; - private float mAlpha = 1.0f; private CharSequence mContentDescription; private Bundle mExtras; private LocaleList mLocaleList; @@ -165,18 +158,6 @@ public final class ViewNode extends AssistStructure.ViewNode { mScrollX = parcel.readInt(); mScrollY = parcel.readInt(); } - if ((nodeFlags & FLAGS_HAS_MATRIX) != 0) { - mMatrix = new Matrix(); - final float[] tmpMatrix = new float[9]; - parcel.readFloatArray(tmpMatrix); - mMatrix.setValues(tmpMatrix); - } - if ((nodeFlags & FLAGS_HAS_ELEVATION) != 0) { - mElevation = parcel.readFloat(); - } - if ((nodeFlags & FLAGS_HAS_ALPHA) != 0) { - mAlpha = parcel.readFloat(); - } if ((nodeFlags & FLAGS_HAS_CONTENT_DESCRIPTION) != 0) { mContentDescription = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(parcel); } @@ -355,21 +336,6 @@ public final class ViewNode extends AssistStructure.ViewNode { } @Override - public Matrix getTransformation() { - return mMatrix; - } - - @Override - public float getElevation() { - return mElevation; - } - - @Override - public float getAlpha() { - return mAlpha; - } - - @Override public CharSequence getContentDescription() { return mContentDescription; } @@ -509,15 +475,6 @@ public final class ViewNode extends AssistStructure.ViewNode { if (mScrollX != 0 || mScrollY != 0) { nodeFlags |= FLAGS_HAS_SCROLL; } - if (mMatrix != null) { - nodeFlags |= FLAGS_HAS_MATRIX; - } - if (mElevation != 0) { - nodeFlags |= FLAGS_HAS_ELEVATION; - } - if (mAlpha != 1.0f) { - nodeFlags |= FLAGS_HAS_ALPHA; - } if (mContentDescription != null) { nodeFlags |= FLAGS_HAS_CONTENT_DESCRIPTION; } @@ -591,18 +548,6 @@ public final class ViewNode extends AssistStructure.ViewNode { parcel.writeInt(mScrollX); parcel.writeInt(mScrollY); } - if ((nodeFlags & FLAGS_HAS_MATRIX) != 0) { - //TODO(b/122484602): use a singleton tmpMatrix (if logic is not moved to superclass) - final float[] tmpMatrix = new float[9]; - mMatrix.getValues(tmpMatrix); - parcel.writeFloatArray(tmpMatrix); - } - if ((nodeFlags & FLAGS_HAS_ELEVATION) != 0) { - parcel.writeFloat(mElevation); - } - if ((nodeFlags & FLAGS_HAS_ALPHA) != 0) { - parcel.writeFloat(mAlpha); - } if ((nodeFlags & FLAGS_HAS_CONTENT_DESCRIPTION) != 0) { TextUtils.writeToParcel(mContentDescription, parcel, 0); } @@ -702,21 +647,17 @@ public final class ViewNode extends AssistStructure.ViewNode { @Override public void setTransformation(Matrix matrix) { - if (matrix == null) { - mNode.mMatrix = null; - } else { - mNode.mMatrix = new Matrix(matrix); - } + Log.w(TAG, "setTransformation() is not supported"); } @Override public void setElevation(float elevation) { - mNode.mElevation = elevation; + Log.w(TAG, "setElevation() is not supported"); } @Override public void setAlpha(float alpha) { - mNode.mAlpha = alpha; + Log.w(TAG, "setAlpha() is not supported"); } @Override diff --git a/core/java/android/view/inputmethod/EditorInfo.java b/core/java/android/view/inputmethod/EditorInfo.java index 28d9fcf57370..f99afe6cdab9 100644 --- a/core/java/android/view/inputmethod/EditorInfo.java +++ b/core/java/android/view/inputmethod/EditorInfo.java @@ -16,11 +16,15 @@ package android.view.inputmethod; +import static android.Manifest.permission.INTERACT_ACROSS_USERS_FULL; + import android.annotation.Nullable; +import android.annotation.RequiresPermission; import android.os.Bundle; import android.os.LocaleList; import android.os.Parcel; import android.os.Parcelable; +import android.os.UserHandle; import android.text.InputType; import android.text.TextUtils; import android.util.Printer; @@ -472,6 +476,26 @@ public class EditorInfo implements InputType, Parcelable { public String[] contentMimeTypes = null; /** + * If not {@code null}, this editor needs to talk to IMEs that run for the specified user, no + * matter what user ID the calling process has. + * + * <p>Note: This field is silently ignored when:</p> + * <ul> + * <li>{@link android.view.inputmethod.InputMethodSystemProperty#PER_PROFILE_IME_ENABLED} is + * {@code false}.</li> + * <li>{@link android.view.inputmethod.InputMethodSystemProperty#MULTI_CLIENT_IME_ENABLED} + * is {@code true}.</li> + * </ul> + * + * <p>Note also that pseudo handles such as {@link UserHandle#ALL} are not supported.</p> + * + * @hide + */ + @RequiresPermission(INTERACT_ACROSS_USERS_FULL) + @Nullable + public UserHandle targetInputMethodUser = null; + + /** * Ensure that the data in this EditorInfo is compatible with an application * that was developed against the given target API version. This can * impact the following input types: @@ -527,6 +551,9 @@ public class EditorInfo implements InputType, Parcelable { pw.println(prefix + "extras=" + extras); pw.println(prefix + "hintLocales=" + hintLocales); pw.println(prefix + "contentMimeTypes=" + Arrays.toString(contentMimeTypes)); + if (targetInputMethodUser != null) { + pw.println(prefix + "targetInputMethodUserId=" + targetInputMethodUser.getIdentifier()); + } } /** @@ -556,6 +583,7 @@ public class EditorInfo implements InputType, Parcelable { LocaleList.getEmptyLocaleList().writeToParcel(dest, flags); } dest.writeStringArray(contentMimeTypes); + UserHandle.writeToParcel(targetInputMethodUser, dest); } /** @@ -582,6 +610,7 @@ public class EditorInfo implements InputType, Parcelable { LocaleList hintLocales = LocaleList.CREATOR.createFromParcel(source); res.hintLocales = hintLocales.isEmpty() ? null : hintLocales; res.contentMimeTypes = source.readStringArray(); + res.targetInputMethodUser = UserHandle.readFromParcel(source); return res; } diff --git a/core/java/android/view/inspector/InspectableNodeName.java b/core/java/android/view/inspector/InspectableNodeName.java index ea94ad4c5df8..7b9a507ee45d 100644 --- a/core/java/android/view/inspector/InspectableNodeName.java +++ b/core/java/android/view/inspector/InspectableNodeName.java @@ -19,6 +19,8 @@ package android.view.inspector; import static java.lang.annotation.ElementType.TYPE; import static java.lang.annotation.RetentionPolicy.SOURCE; +import android.annotation.TestApi; + import java.lang.annotation.Retention; import java.lang.annotation.Target; @@ -39,6 +41,7 @@ import java.lang.annotation.Target; */ @Target({TYPE}) @Retention(SOURCE) +@TestApi public @interface InspectableNodeName { /** * The display name for nodes of this type. diff --git a/core/java/android/view/inspector/InspectableProperty.java b/core/java/android/view/inspector/InspectableProperty.java index e2a763e22288..355ff1d85e1f 100644 --- a/core/java/android/view/inspector/InspectableProperty.java +++ b/core/java/android/view/inspector/InspectableProperty.java @@ -20,7 +20,8 @@ import static java.lang.annotation.ElementType.METHOD; import static java.lang.annotation.ElementType.TYPE; import static java.lang.annotation.RetentionPolicy.SOURCE; -import android.content.res.ResourceId; +import android.annotation.TestApi; +import android.content.res.Resources; import java.lang.annotation.Retention; import java.lang.annotation.Target; @@ -40,6 +41,7 @@ import java.lang.annotation.Target; */ @Target({METHOD}) @Retention(SOURCE) +@TestApi public @interface InspectableProperty { /** * The name of the property. @@ -57,16 +59,16 @@ public @interface InspectableProperty { * If left as {ID_NULL}, and {@link #hasAttributeId()} is true, the attribute ID will be * inferred from {@link #name()}. * - * @return The attribute ID of the property or {@link ResourceId#ID_NULL} + * @return The attribute ID of the property or {@link Resources#ID_NULL} */ - int attributeId() default ResourceId.ID_NULL; + int attributeId() default Resources.ID_NULL; /** * If this property has an attribute ID. * * Set to false if the annotated property does not have an attribute ID, that is, it is not * inflated from an XML attribute. This will prevent the automatic inference of the attribute - * ID if {@link #attributeId()} is set to {@link ResourceId#ID_NULL}. + * ID if {@link #attributeId()} is set to {@link Resources#ID_NULL}. * * @return Whether to infer an attribute ID if not supplied */ @@ -86,7 +88,6 @@ public @interface InspectableProperty { * * @return An array of {@link EnumMap}, empty if not applicable * @see android.annotation.IntDef - * @see IntEnumMapping */ EnumMap[] enumMapping() default {}; @@ -109,6 +110,7 @@ public @interface InspectableProperty { */ @Target({TYPE}) @Retention(SOURCE) + @TestApi @interface EnumMap { /** * The string name of this enumeration value. @@ -133,6 +135,7 @@ public @interface InspectableProperty { */ @Target({TYPE}) @Retention(SOURCE) + @TestApi @interface FlagMap { /** * The string name of this flag. @@ -167,15 +170,22 @@ public @interface InspectableProperty { * * @hide */ + @TestApi enum ValueType { /** * No special handling, property is considered to be a numeric value. + * + * @hide */ + @TestApi NONE, /** * The default the annotation processor infers the value type from context. + * + * @hide */ + @TestApi INFERRED, /** @@ -184,7 +194,9 @@ public @interface InspectableProperty { * This is inferred if {@link #enumMapping()} is specified. * * @see EnumMap + * @hide */ + @TestApi INT_ENUM, /** @@ -193,7 +205,9 @@ public @interface InspectableProperty { * This is inferred if {@link #flagMapping()} is specified. * * @see FlagMap + * @hide */ + @TestApi INT_FLAG, /** @@ -203,7 +217,9 @@ public @interface InspectableProperty { * {@link android.annotation.ColorLong} on the getter method. * * @see android.graphics.Color + * @hide */ + @TestApi COLOR, /** @@ -212,7 +228,9 @@ public @interface InspectableProperty { * This type is not inferred, and is non-trivial to represent using {@link FlagMap}. * * @see android.view.Gravity + * @hide */ + @TestApi GRAVITY } } diff --git a/core/java/android/view/textservice/SpellCheckerSession.java b/core/java/android/view/textservice/SpellCheckerSession.java index 9733701ee0f0..f553ca512881 100644 --- a/core/java/android/view/textservice/SpellCheckerSession.java +++ b/core/java/android/view/textservice/SpellCheckerSession.java @@ -27,7 +27,6 @@ import android.util.Log; import com.android.internal.textservice.ISpellCheckerSession; import com.android.internal.textservice.ISpellCheckerSessionListener; -import com.android.internal.textservice.ITextServicesManager; import com.android.internal.textservice.ITextServicesSessionListener; import dalvik.system.CloseGuard; @@ -96,7 +95,7 @@ public class SpellCheckerSession { private static final int MSG_ON_GET_SUGGESTION_MULTIPLE_FOR_SENTENCE = 2; private final InternalListener mInternalListener; - private final ITextServicesManager mTextServicesManager; + private final TextServicesManager mTextServicesManager; private final SpellCheckerInfo mSpellCheckerInfo; @UnsupportedAppUsage private final SpellCheckerSessionListener mSpellCheckerSessionListener; @@ -124,7 +123,7 @@ public class SpellCheckerSession { * @hide */ public SpellCheckerSession( - SpellCheckerInfo info, ITextServicesManager tsm, SpellCheckerSessionListener listener) { + SpellCheckerInfo info, TextServicesManager tsm, SpellCheckerSessionListener listener) { if (info == null || listener == null || tsm == null) { throw new NullPointerException(); } @@ -166,12 +165,8 @@ public class SpellCheckerSession { */ public void close() { mGuard.close(); - try { - mSpellCheckerSessionListenerImpl.close(); - mTextServicesManager.finishSpellCheckerService(mSpellCheckerSessionListenerImpl); - } catch (RemoteException e) { - // do nothing - } + mSpellCheckerSessionListenerImpl.close(); + mTextServicesManager.finishSpellCheckerService(mSpellCheckerSessionListenerImpl); } /** diff --git a/core/java/android/view/textservice/TextServicesManager.java b/core/java/android/view/textservice/TextServicesManager.java index 5dc8b19444b0..9ff64d9b268a 100644 --- a/core/java/android/view/textservice/TextServicesManager.java +++ b/core/java/android/view/textservice/TextServicesManager.java @@ -16,16 +16,20 @@ package android.view.textservice; +import android.annotation.NonNull; import android.annotation.SystemService; import android.annotation.UnsupportedAppUsage; +import android.annotation.UserIdInt; import android.content.Context; import android.os.Bundle; import android.os.RemoteException; import android.os.ServiceManager; import android.os.ServiceManager.ServiceNotFoundException; +import android.os.UserHandle; import android.util.Log; import android.view.textservice.SpellCheckerSession.SpellCheckerSessionListener; +import com.android.internal.textservice.ISpellCheckerSessionListener; import com.android.internal.textservice.ITextServicesManager; import java.util.Locale; @@ -67,17 +71,41 @@ public final class TextServicesManager { private static final String TAG = TextServicesManager.class.getSimpleName(); private static final boolean DBG = false; + /** + * @deprecated Do not use. Just kept because of {@link UnsupportedAppUsage} in + * {@link #getInstance()}. + */ + @Deprecated private static TextServicesManager sInstance; private final ITextServicesManager mService; - private TextServicesManager() throws ServiceNotFoundException { + @UserIdInt + private final int mUserId; + + private TextServicesManager(@UserIdInt int userId) throws ServiceNotFoundException { mService = ITextServicesManager.Stub.asInterface( ServiceManager.getServiceOrThrow(Context.TEXT_SERVICES_MANAGER_SERVICE)); + mUserId = userId; + } + + /** + * The factory method of {@link TextServicesManager}. + * + * @param context {@link Context} from which {@link TextServicesManager} should be instantiated. + * @return {@link TextServicesManager} that is associated with {@link Context#getUserId()}. + * @throws ServiceNotFoundException When {@link TextServicesManager} is not available. + * @hide + */ + @NonNull + public static TextServicesManager createInstance(@NonNull Context context) + throws ServiceNotFoundException { + return new TextServicesManager(context.getUserId()); } /** - * Retrieve the global TextServicesManager instance, creating it if it doesn't already exist. + * @deprecated Do not use. Just kept because of {@link UnsupportedAppUsage} in + * {@link #getInstance()}. * @hide */ @UnsupportedAppUsage @@ -85,7 +113,7 @@ public final class TextServicesManager { synchronized (TextServicesManager.class) { if (sInstance == null) { try { - sInstance = new TextServicesManager(); + sInstance = new TextServicesManager(UserHandle.myUserId()); } catch (ServiceNotFoundException e) { throw new IllegalStateException(e); } @@ -136,7 +164,7 @@ public final class TextServicesManager { final SpellCheckerInfo sci; try { - sci = mService.getCurrentSpellChecker(null); + sci = mService.getCurrentSpellChecker(mUserId, null); } catch (RemoteException e) { return null; } @@ -174,9 +202,9 @@ public final class TextServicesManager { if (subtypeInUse == null) { return null; } - final SpellCheckerSession session = new SpellCheckerSession(sci, mService, listener); + final SpellCheckerSession session = new SpellCheckerSession(sci, this, listener); try { - mService.getSpellCheckerService(sci.getId(), subtypeInUse.getLocale(), + mService.getSpellCheckerService(mUserId, sci.getId(), subtypeInUse.getLocale(), session.getTextServicesSessionListener(), session.getSpellCheckerSessionListener(), bundle); } catch (RemoteException e) { @@ -191,7 +219,7 @@ public final class TextServicesManager { @UnsupportedAppUsage public SpellCheckerInfo[] getEnabledSpellCheckers() { try { - final SpellCheckerInfo[] retval = mService.getEnabledSpellCheckers(); + final SpellCheckerInfo[] retval = mService.getEnabledSpellCheckers(mUserId); if (DBG) { Log.d(TAG, "getEnabledSpellCheckers: " + (retval != null ? retval.length : "null")); } @@ -208,7 +236,7 @@ public final class TextServicesManager { public SpellCheckerInfo getCurrentSpellChecker() { try { // Passing null as a locale for ICS - return mService.getCurrentSpellChecker(null); + return mService.getCurrentSpellChecker(mUserId, null); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -221,7 +249,7 @@ public final class TextServicesManager { public SpellCheckerSubtype getCurrentSpellCheckerSubtype( boolean allowImplicitlySelectedSubtype) { try { - return mService.getCurrentSpellCheckerSubtype(allowImplicitlySelectedSubtype); + return mService.getCurrentSpellCheckerSubtype(mUserId, allowImplicitlySelectedSubtype); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -233,7 +261,15 @@ public final class TextServicesManager { @UnsupportedAppUsage public boolean isSpellCheckerEnabled() { try { - return mService.isSpellCheckerEnabled(); + return mService.isSpellCheckerEnabled(mUserId); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + void finishSpellCheckerService(ISpellCheckerSessionListener listener) { + try { + mService.finishSpellCheckerService(mUserId, listener); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java index bad2dbfebdc5..60393502bbe7 100644 --- a/core/java/android/webkit/WebView.java +++ b/core/java/android/webkit/WebView.java @@ -16,6 +16,7 @@ package android.webkit; +import android.annotation.CallbackExecutor; import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; @@ -69,6 +70,7 @@ import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.util.List; import java.util.Map; +import java.util.concurrent.Executor; /** * A View that displays web pages. @@ -1688,6 +1690,84 @@ public class WebView extends AbsoluteLayout return mProvider.getWebViewClient(); } + + /** + * Gets the WebView renderer associated with this WebView. + * + * <p>In {@link android.os.Build.VERSION_CODES#O} and above, WebView may + * run in "multiprocess" mode. In multiprocess mode, rendering of web + * content is performed by a sandboxed renderer process separate to the + * application process. This renderer process may be shared with other + * WebViews in the application, but is not shared with other application + * processes. + * + * <p>If WebView is running in multiprocess mode, this method returns a + * handle to the renderer process associated with the WebView, which can + * be used to control the renderer process. + * + * @return the {@link WebViewRenderer} renderer handle associated + * with this {@link WebView}, or {@code null} if + * WebView is not runing in multiprocess mode. + */ + @Nullable + public WebViewRenderer getWebViewRenderer() { + checkThread(); + return mProvider.getWebViewRenderer(); + } + + /** + * Sets the renderer client object associated with this WebView. + * + * <p>The renderer client encapsulates callbacks relevant to WebView renderer + * state. See {@link WebViewRendererClient} for details. + * + * <p>Although many WebView instances may share a single underlying + * renderer, and renderers may live either in the application + * process, or in a sandboxed process that is isolated from the + * application process, instances of {@link WebViewRendererClient} + * are set per-WebView. Callbacks represent renderer events from + * the perspective of this WebView, and may or may not be correlated + * with renderer events affecting other WebViews. + * + * @param executor the Executor on which {@link WebViewRendererClient} callbacks will execute. + * @param webViewRendererClient the {@link WebViewRendererClient} object. + */ + public void setWebViewRendererClient( + @NonNull @CallbackExecutor Executor executor, + @NonNull WebViewRendererClient webViewRendererClient) { + checkThread(); + mProvider.setWebViewRendererClient(executor, webViewRendererClient); + } + + /** + * Sets the renderer client object associated with this WebView. + * + * See {@link #setWebViewRendererClient(Executor,WebViewRendererClient)} for details. + * + * <p> {@link WebViewRendererClient} callbacks will run on the thread that this WebView was + * initialized on. + * + * @param webViewRendererClient the {@link WebViewRendererClient} object. + */ + public void setWebViewRendererClient( + @Nullable WebViewRendererClient webViewRendererClient) { + checkThread(); + mProvider.setWebViewRendererClient(null, webViewRendererClient); + } + + /** + * Gets the renderer client object associated with this WebView. + * + * @return the {@link WebViewRendererClient} object associated with this WebView, if one has + * been set via {@link #setWebViewRendererClient(WebViewRendererClient)} or {@code null} + * otherwise. + */ + @Nullable + public WebViewRendererClient getWebViewRendererClient() { + checkThread(); + return mProvider.getWebViewRendererClient(); + } + /** * Registers the interface to be used when content can not be handled by * the rendering engine, and should be downloaded instead. This will replace diff --git a/core/java/android/webkit/WebViewClient.java b/core/java/android/webkit/WebViewClient.java index 300bb6fd4890..090640e48aec 100644 --- a/core/java/android/webkit/WebViewClient.java +++ b/core/java/android/webkit/WebViewClient.java @@ -379,11 +379,16 @@ public class WebViewClient { /** * Notify the host application that an SSL error occurred while loading a - * resource. The host application must call either handler.cancel() or - * handler.proceed(). Note that the decision may be retained for use in + * resource. The host application must call either {@link SslErrorHandler#cancel} or + * {@link SslErrorHandler#proceed}. Note that the decision may be retained for use in * response to future SSL errors. The default behavior is to cancel the * load. * <p> + * This API is only called for recoverable SSL certificate errors. In the case of + * non-recoverable errors (such as when the server fails the client), WebView will call {@link + * #onReceivedError(WebView, WebResourceRequest, WebResourceError)} with {@link + * #ERROR_FAILED_SSL_HANDSHAKE}. + * <p> * Applications are advised not to prompt the user about SSL errors, as * the user is unlikely to be able to make an informed security decision * and WebView does not provide any UI for showing the details of the @@ -391,10 +396,10 @@ public class WebViewClient { * <p> * Application overrides of this method may display custom error pages or * silently log issues, but it is strongly recommended to always call - * handler.cancel() and never allow proceeding past errors. + * {@link SslErrorHandler#cancel} and never allow proceeding past errors. * * @param view The WebView that is initiating the callback. - * @param handler An SslErrorHandler object that will handle the user's + * @param handler An {@link SslErrorHandler} that will handle the user's * response. * @param error The SSL error object. */ diff --git a/core/java/android/webkit/WebViewProvider.java b/core/java/android/webkit/WebViewProvider.java index 95e7a986efd2..baf582693bd8 100644 --- a/core/java/android/webkit/WebViewProvider.java +++ b/core/java/android/webkit/WebViewProvider.java @@ -54,6 +54,7 @@ import android.webkit.WebView.VisualStateCallback; import java.io.BufferedWriter; import java.io.File; import java.util.Map; +import java.util.concurrent.Executor; /** * WebView backend provider interface: this interface is the abstract backend to a WebView @@ -237,6 +238,14 @@ public interface WebViewProvider { public WebViewClient getWebViewClient(); + public WebViewRenderer getWebViewRenderer(); + + public void setWebViewRendererClient( + @Nullable Executor executor, + @Nullable WebViewRendererClient client); + + public WebViewRendererClient getWebViewRendererClient(); + public void setDownloadListener(DownloadListener listener); public void setWebChromeClient(WebChromeClient client); diff --git a/core/java/android/webkit/WebViewRenderer.java b/core/java/android/webkit/WebViewRenderer.java new file mode 100644 index 000000000000..532825485ed3 --- /dev/null +++ b/core/java/android/webkit/WebViewRenderer.java @@ -0,0 +1,45 @@ +/* + * Copyright 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.webkit; + +/** + * WebViewRenderer provides an opaque handle to a {@link WebView} renderer. + */ +public abstract class WebViewRenderer { + /** + * Cause this renderer to terminate. + * + * <p>Calling this on a not yet started, or an already terminated renderer will have no effect. + * + * <p>Terminating a renderer process may have an effect on multiple {@link WebView} instances. + * + * <p>Renderer termination must be handled by properly overriding + * {@link WebViewClient#onRenderProcessGone} for every WebView that shares this + * renderer. If termination is not handled by all associated WebViews, then the application + * process will also be terminated. + * + * @return {@code true} if it was possible to terminate this renderer, {@code false} otherwise. + */ + public abstract boolean terminate(); + + /** + * This class cannot be created by applications. + * @hide + */ + public WebViewRenderer() { + } +} diff --git a/core/java/android/webkit/WebViewRendererClient.java b/core/java/android/webkit/WebViewRendererClient.java new file mode 100644 index 000000000000..2fadf54fd434 --- /dev/null +++ b/core/java/android/webkit/WebViewRendererClient.java @@ -0,0 +1,77 @@ +/* + * Copyright 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.webkit; + +import android.annotation.NonNull; +import android.annotation.Nullable; + +/** + * Used to receive callbacks on {@link WebView} renderer events. + * + * WebViewRendererClient instances may be set or retrieved via {@link + * WebView#setWebViewRendererClient(WebViewRendererClient)} and {@link + * WebView#getWebViewRendererClient()}. + * + * Instances may be attached to multiple WebViews, and thus a single renderer event may cause + * a callback to be called multiple times with different WebView parameters. + */ +public abstract class WebViewRendererClient { + /** + * Called when the renderer currently associated with {@code view} becomes unresponsive as a + * result of a long running blocking task such as the execution of JavaScript. + * + * <p>If a WebView fails to process an input event, or successfully navigate to a new URL within + * a reasonable time frame, the renderer is considered to be unresponsive, and this callback + * will be called. + * + * <p>This callback will continue to be called at regular intervals as long as the renderer + * remains unresponsive. If the renderer becomes responsive again, {@link + * WebViewRendererClient#onRendererResponsive} will be called once, and this method will not + * subsequently be called unless another period of unresponsiveness is detected. + * + * <p>No action is taken by WebView as a result of this method call. Applications may + * choose to terminate the associated renderer via the object that is passed to this callback, + * if in multiprocess mode, however this must be accompanied by correctly handling + * {@link WebViewClient#onRenderProcessGone} for this WebView, and all other WebViews associated + * with the same renderer. Failure to do so will result in application termination. + * + * @param view The {@link WebView} for which unresponsiveness was detected. + * @param renderer The {@link WebViewRenderer} that has become unresponsive, + * or {@code null} if WebView is running in single process mode. + */ + public abstract void onRendererUnresponsive( + @NonNull WebView view, @Nullable WebViewRenderer renderer); + + /** + * Called once when an unresponsive renderer currently associated with {@code view} becomes + * responsive. + * + * <p>After a WebView renderer becomes unresponsive, which is notified to the application by + * {@link WebViewRendererClient#onRendererUnresponsive}, it is possible for the blocking + * renderer task to complete, returning the renderer to a responsive state. In that case, + * this method is called once to indicate responsiveness. + * + * <p>No action is taken by WebView as a result of this method call. + * + * @param view The {@link WebView} for which responsiveness was detected. + * + * @param renderer The {@link WebViewRenderer} that has become responsive, or {@code null} if + * WebView is running in single process mode. + */ + public abstract void onRendererResponsive( + @NonNull WebView view, @Nullable WebViewRenderer renderer); +} diff --git a/core/java/android/webkit/WebViewZygote.java b/core/java/android/webkit/WebViewZygote.java index 9f7aa6a2852a..29b3b3cff044 100644 --- a/core/java/android/webkit/WebViewZygote.java +++ b/core/java/android/webkit/WebViewZygote.java @@ -160,7 +160,9 @@ public class WebViewZygote { "webview_zygote", // seInfo sPackage.applicationInfo.primaryCpuAbi, // abi TextUtils.join(",", Build.SUPPORTED_ABIS), - null); // instructionSet + null, // instructionSet + Process.FIRST_ISOLATED_UID, + Process.LAST_ISOLATED_UID); // All the work below is usually done by LoadedApk, but the zygote can't talk to // PackageManager or construct a LoadedApk since it's single-threaded pre-fork, so diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java index 0d16998d17ee..4a6095464b42 100644 --- a/core/java/android/widget/TextView.java +++ b/core/java/android/widget/TextView.java @@ -48,7 +48,6 @@ import android.content.UndoManager; import android.content.res.ColorStateList; import android.content.res.CompatibilityInfo; import android.content.res.Configuration; -import android.content.res.ResourceId; import android.content.res.Resources; import android.content.res.TypedArray; import android.content.res.XmlResourceParser; @@ -889,7 +888,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener // sanitize autofill requests. private boolean mTextSetFromXmlOrResourceId = false; // Resource id used to set the text. - private @StringRes int mTextId = ResourceId.ID_NULL; + private @StringRes int mTextId = Resources.ID_NULL; // // End of autofill-related attributes @@ -1180,7 +1179,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener case com.android.internal.R.styleable.TextView_text: textIsSetFromXml = true; - mTextId = a.getResourceId(attr, ResourceId.ID_NULL); + mTextId = a.getResourceId(attr, Resources.ID_NULL); text = a.getText(attr); break; @@ -11031,7 +11030,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener if (viewFor == VIEW_STRUCTURE_FOR_AUTOFILL) { structure.setDataIsSensitive(!mTextSetFromXmlOrResourceId); } - if (mTextId != ResourceId.ID_NULL) { + if (mTextId != Resources.ID_NULL) { try { structure.setTextIdEntry(getResources().getResourceEntryName(mTextId)); } catch (Resources.NotFoundException e) { diff --git a/core/java/com/android/internal/app/ChooserActivity.java b/core/java/com/android/internal/app/ChooserActivity.java index 4523d3b2739f..b4d8322c7552 100644 --- a/core/java/com/android/internal/app/ChooserActivity.java +++ b/core/java/com/android/internal/app/ChooserActivity.java @@ -21,19 +21,24 @@ import android.app.ActivityManager; import android.content.ComponentName; import android.content.Context; import android.content.Intent; +import android.content.IntentFilter; import android.content.IntentSender; import android.content.IntentSender.SendIntentException; import android.content.ServiceConnection; import android.content.SharedPreferences; import android.content.pm.ActivityInfo; import android.content.pm.LabeledIntent; +import android.content.pm.LauncherApps; import android.content.pm.PackageManager; import android.content.pm.PackageManager.NameNotFoundException; import android.content.pm.ResolveInfo; +import android.content.pm.ShortcutInfo; +import android.content.pm.ShortcutManager; import android.database.DataSetObserver; import android.graphics.Color; import android.graphics.drawable.Drawable; import android.graphics.drawable.Icon; +import android.os.AsyncTask; import android.os.Bundle; import android.os.Environment; import android.os.Handler; @@ -75,6 +80,7 @@ import com.google.android.collect.Lists; import java.io.File; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collections; import java.util.Comparator; import java.util.List; @@ -92,6 +98,15 @@ public class ChooserActivity extends ResolverActivity { private static final boolean DEBUG = false; + /** + * If set to true, use ShortcutManager to retrieve the matching direct share targets, instead of + * binding to every ChooserTargetService implementation. + */ + // TODO(b/121287573): Replace with a system flag (setprop?) + private static final boolean USE_SHORTCUT_MANAGER_FOR_DIRECT_TARGETS = false; + // TODO(b/121287224): Re-evaluate this limit + private static final int SHARE_TARGET_QUERY_PACKAGE_LIMIT = 20; + private static final int QUERY_TARGET_SERVICE_LIMIT = 5; private static final int WATCHDOG_TIMEOUT_MILLIS = 2000; @@ -120,6 +135,7 @@ public class ChooserActivity extends ResolverActivity { private static final int CHOOSER_TARGET_SERVICE_RESULT = 1; private static final int CHOOSER_TARGET_SERVICE_WATCHDOG_TIMEOUT = 2; + private static final int SHORTCUT_MANAGER_SHARE_TARGET_RESULT = 3; private final Handler mChooserHandler = new Handler() { @Override @@ -158,6 +174,18 @@ public class ChooserActivity extends ResolverActivity { mChooserListAdapter.setShowServiceTargets(true); break; + case SHORTCUT_MANAGER_SHARE_TARGET_RESULT: + if (DEBUG) Log.d(TAG, "SHORTCUT_MANAGER_SHARE_TARGET_RESULT"); + if (isDestroyed()) break; + final ServiceResultInfo resultInfo = (ServiceResultInfo) msg.obj; + if (resultInfo.resultTargets != null) { + mChooserListAdapter.addServiceResults(resultInfo.originalTarget, + resultInfo.resultTargets); + } + sendVoiceChoicesIfNeeded(); + mChooserListAdapter.setShowServiceTargets(true); + break; + default: super.handleMessage(msg); } @@ -552,6 +580,94 @@ public class ChooserActivity extends ResolverActivity { } } + private IntentFilter getTargetIntentFilter() { + try { + final Intent intent = getTargetIntent(); + String dataString = intent.getDataString(); + if (TextUtils.isEmpty(dataString)) { + dataString = intent.getType(); + } + return new IntentFilter(intent.getAction(), dataString); + } catch (Exception e) { + Log.e(TAG, "failed to get target intent filter " + e); + return null; + } + } + + private void queryDirectShareTargets(ChooserListAdapter adapter) { + final IntentFilter filter = getTargetIntentFilter(); + if (filter == null) { + return; + } + + // Need to keep the original DisplayResolveInfos to be able to reconstruct ServiceResultInfo + // and use the old code path. This Ugliness should go away when Sharesheet is refactored. + final List<DisplayResolveInfo> driList = new ArrayList<>(); + int targetsToQuery = 0; + for (int i = 0, n = adapter.getDisplayResolveInfoCount(); i < n; i++) { + final DisplayResolveInfo dri = adapter.getDisplayResolveInfo(i); + if (adapter.getScore(dri) == 0) { + // A score of 0 means the app hasn't been used in some time; + // don't query it as it's not likely to be relevant. + continue; + } + driList.add(dri); + targetsToQuery++; + // TODO(b/121287224): Do we need this here? (similar to queryTargetServices) + if (targetsToQuery >= SHARE_TARGET_QUERY_PACKAGE_LIMIT) { + if (DEBUG) { + Log.d(TAG, "queryTargets hit query target limit " + + SHARE_TARGET_QUERY_PACKAGE_LIMIT); + } + break; + } + } + + AsyncTask.execute(() -> { + ShortcutManager sm = (ShortcutManager) getSystemService(Context.SHORTCUT_SERVICE); + List<ShortcutManager.ShareShortcutInfo> resultList = sm.getShareTargets(filter); + + // Match ShareShortcutInfos with DisplayResolveInfos to be able to use the old code path + // for direct share targets. After ShareSheet is refactored we should use the + // ShareShortcutInfos directly. + for (int i = 0; i < driList.size(); i++) { + List<ChooserTarget> chooserTargets = new ArrayList<>(); + for (int j = 0; j < resultList.size(); j++) { + if (driList.get(i).getResolvedComponentName().equals( + resultList.get(j).getTargetComponent())) { + chooserTargets.add(convertToChooserTarget(resultList.get(j))); + } + } + if (chooserTargets.isEmpty()) { + continue; + } + + final Message msg = Message.obtain(); + msg.what = SHORTCUT_MANAGER_SHARE_TARGET_RESULT; + msg.obj = new ServiceResultInfo(driList.get(i), chooserTargets, null); + mChooserHandler.sendMessage(msg); + } + }); + } + + private ChooserTarget convertToChooserTarget(ShortcutManager.ShareShortcutInfo shareShortcut) { + ShortcutInfo shortcutInfo = shareShortcut.getShortcutInfo(); + Bundle extras = new Bundle(); + extras.putString(Intent.EXTRA_SHORTCUT_ID, shortcutInfo.getId()); + return new ChooserTarget( + // The name of this target. + shortcutInfo.getShortLabel(), + // Don't load the icon until it is selected to be shown + null, + // The ranking score for this target (0.0-1.0); the system will omit items with low + // scores when there are too many Direct Share items. + 0.5f, + // The name of the component to be launched if this target is chosen. + shareShortcut.getTargetComponent().clone(), + // The extra values here will be merged into the Intent when this target is chosen. + extras); + } + private String convertServiceName(String packageName, String serviceName) { if (TextUtils.isEmpty(serviceName)) { return null; @@ -765,9 +881,8 @@ public class ChooserActivity extends ResolverActivity { } } } - final Icon icon = chooserTarget.getIcon(); - // TODO do this in the background - mDisplayIcon = icon != null ? icon.loadDrawable(ChooserActivity.this) : null; + // TODO(b/121287224): do this in the background thread, and only for selected targets + mDisplayIcon = getChooserTargetIconDrawable(chooserTarget); if (sourceInfo != null) { mBackupResolveInfo = null; @@ -791,6 +906,39 @@ public class ChooserActivity extends ResolverActivity { mModifiedScore = other.mModifiedScore; } + /** + * Since ShortcutInfos are returned by ShortcutManager, we can cache the shortcuts and skip + * the call to LauncherApps#getShortcuts(ShortcutQuery). + */ + // TODO(121287224): Refactor code to apply the suggestion above + private Drawable getChooserTargetIconDrawable(ChooserTarget target) { + final Icon icon = target.getIcon(); + if (icon != null) { + return icon.loadDrawable(ChooserActivity.this); + } + if (!USE_SHORTCUT_MANAGER_FOR_DIRECT_TARGETS) { + return null; + } + + Bundle extras = target.getIntentExtras(); + if (extras == null || !extras.containsKey(Intent.EXTRA_SHORTCUT_ID)) { + return null; + } + CharSequence shortcutId = extras.getCharSequence(Intent.EXTRA_SHORTCUT_ID); + LauncherApps launcherApps = (LauncherApps) getSystemService( + Context.LAUNCHER_APPS_SERVICE); + final LauncherApps.ShortcutQuery q = new LauncherApps.ShortcutQuery(); + q.setPackage(target.getComponentName().getPackageName()); + q.setShortcutIds(Arrays.asList(shortcutId.toString())); + q.setQueryFlags(LauncherApps.ShortcutQuery.FLAG_MATCH_DYNAMIC); + final List<ShortcutInfo> shortcuts = launcherApps.getShortcuts(q, getUser()); + if (shortcuts != null && shortcuts.size() > 0) { + return launcherApps.getShortcutIconDrawable(shortcuts.get(0), 0); + } + + return null; + } + public float getModifiedScore() { return mModifiedScore; } @@ -1030,8 +1178,15 @@ public class ChooserActivity extends ResolverActivity { mTargetsNeedPruning = true; } } - if (DEBUG) Log.d(TAG, "List built querying services"); - queryTargetServices(this); + if (USE_SHORTCUT_MANAGER_FOR_DIRECT_TARGETS) { + if (DEBUG) { + Log.d(TAG, "querying direct share targets from ShortcutManager"); + } + queryDirectShareTargets(this); + } else { + if (DEBUG) Log.d(TAG, "List built querying services"); + queryTargetServices(this); + } } @Override diff --git a/core/java/com/android/internal/app/SuspendedAppActivity.java b/core/java/com/android/internal/app/SuspendedAppActivity.java index 498de53b65e9..70935d4ac076 100644 --- a/core/java/com/android/internal/app/SuspendedAppActivity.java +++ b/core/java/com/android/internal/app/SuspendedAppActivity.java @@ -16,7 +16,7 @@ package com.android.internal.app; -import static android.content.res.ResourceId.ID_NULL; +import static android.content.res.Resources.ID_NULL; import android.Manifest; import android.app.AlertDialog; diff --git a/core/java/com/android/internal/hardware/AmbientDisplayConfiguration.java b/core/java/com/android/internal/hardware/AmbientDisplayConfiguration.java index 2995a8f43268..7a00a51647f6 100644 --- a/core/java/com/android/internal/hardware/AmbientDisplayConfiguration.java +++ b/core/java/com/android/internal/hardware/AmbientDisplayConfiguration.java @@ -58,6 +58,15 @@ public class AmbientDisplayConfiguration { return mContext.getResources().getBoolean(R.bool.config_dozePulsePickup); } + public boolean tapGestureEnabled(int user) { + return boolSettingDefaultOn(Settings.Secure.DOZE_TAP_SCREEN_GESTURE, user) + && tapSensorAvailable(); + } + + public boolean tapSensorAvailable() { + return !TextUtils.isEmpty(tapSensorType()); + } + public boolean doubleTapGestureEnabled(int user) { return boolSettingDefaultOn(Settings.Secure.DOZE_DOUBLE_TAP_GESTURE, user) && doubleTapSensorAvailable(); @@ -86,6 +95,10 @@ public class AmbientDisplayConfiguration { return mContext.getResources().getString(R.string.config_dozeDoubleTapSensorType); } + public String tapSensorType() { + return mContext.getResources().getString(R.string.config_dozeTapSensorType); + } + public String longPressSensorType() { return mContext.getResources().getString(R.string.config_dozeLongPressSensorType); } diff --git a/core/java/com/android/internal/infra/AbstractRemoteService.java b/core/java/com/android/internal/infra/AbstractRemoteService.java index 594595843ca7..72c67d7ddc08 100644 --- a/core/java/com/android/internal/infra/AbstractRemoteService.java +++ b/core/java/com/android/internal/infra/AbstractRemoteService.java @@ -139,6 +139,14 @@ public abstract class AbstractRemoteService<S extends AbstractRemoteService<S, I return mDestroyed; } + /** + * Gets the name of the service. + */ + @NonNull + public final ComponentName getComponentName() { + return mComponentName; + } + private void handleOnConnectedStateChangedInternal(boolean connected) { if (connected) { handlePendingRequests(); diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java index 5125f5c8c3da..17cc6afcd8f0 100644 --- a/core/java/com/android/internal/os/BatteryStatsImpl.java +++ b/core/java/com/android/internal/os/BatteryStatsImpl.java @@ -337,6 +337,25 @@ public class BatteryStatsImpl extends BatteryStats { private final PlatformIdleStateCallback mPlatformIdleStateCallback; + private final Runnable mDeferSetCharging = new Runnable() { + @Override + public void run() { + synchronized (BatteryStatsImpl.this) { + if (mOnBattery) { + // if the device gets unplugged in the time between this runnable being + // executed and the lock being taken, we don't want to set charging state + return; + } + boolean changed = setChargingLocked(true); + if (changed) { + final long uptime = mClocks.uptimeMillis(); + final long elapsedRealtime = mClocks.elapsedRealtime(); + addHistoryRecordLocked(elapsedRealtime, uptime); + } + } + } + }; + /** * This handler is running on {@link BackgroundThread}. */ @@ -12340,6 +12359,14 @@ public class BatteryStatsImpl extends BatteryStats { } boolean setChargingLocked(boolean charging) { + // if the device is no longer charging, remove the callback + // if the device is now charging, it means that this is either called + // 1. directly when level >= 90 + // 2. or from within the runnable that we deferred + // For 1. if we have an existing callback, remove it, since we will immediatelly send a + // ACTION_CHARGING + // For 2. we remove existing callback so we don't send multiple ACTION_CHARGING + mHandler.removeCallbacks(mDeferSetCharging); if (mCharging != charging) { mCharging = charging; if (charging) { @@ -12678,12 +12705,23 @@ public class BatteryStatsImpl extends BatteryStats { // charging even if it happens to go down a level. changed |= setChargingLocked(true); mLastChargeStepLevel = level; - } if (!mCharging) { + } + if (!mCharging) { if (mLastChargeStepLevel < level) { - // We have not reporting that we are charging, but the level has now - // gone up, so consider the state to be charging. - changed |= setChargingLocked(true); + // We have not reported that we are charging, but the level has gone up, + // but we would like to not have tons of activity from charging-constraint + // jobs, so instead of reporting ACTION_CHARGING immediately, we defer it. mLastChargeStepLevel = level; + if (!mHandler.hasCallbacks(mDeferSetCharging)) { + mHandler.postDelayed( + mDeferSetCharging, + mConstants.BATTERY_CHARGED_DELAY_MS); + } + } else if (mLastChargeStepLevel > level) { + // if we had deferred a runnable due to charge level increasing, but then + // later the charge level drops (could be due to thermal issues), we don't + // want to trigger the deferred runnable, so remove it here + mHandler.removeCallbacks(mDeferSetCharging); } } else { if (mLastChargeStepLevel > level) { @@ -13300,6 +13338,8 @@ public class BatteryStatsImpl extends BatteryStats { = "battery_level_collection_delay_ms"; public static final String KEY_MAX_HISTORY_FILES = "max_history_files"; public static final String KEY_MAX_HISTORY_BUFFER_KB = "max_history_buffer_kb"; + public static final String KEY_BATTERY_CHARGED_DELAY_MS = + "battery_charged_delay_ms"; private static final boolean DEFAULT_TRACK_CPU_TIMES_BY_PROC_STATE = false; private static final boolean DEFAULT_TRACK_CPU_ACTIVE_CLUSTER_TIME = true; @@ -13312,6 +13352,7 @@ public class BatteryStatsImpl extends BatteryStats { private static final int DEFAULT_MAX_HISTORY_BUFFER_KB = 128; /*Kilo Bytes*/ private static final int DEFAULT_MAX_HISTORY_FILES_LOW_RAM_DEVICE = 64; private static final int DEFAULT_MAX_HISTORY_BUFFER_LOW_RAM_DEVICE_KB = 64; /*Kilo Bytes*/ + private static final int DEFAULT_BATTERY_CHARGED_DELAY_MS = 900000; /* 15 min */ public boolean TRACK_CPU_TIMES_BY_PROC_STATE = DEFAULT_TRACK_CPU_TIMES_BY_PROC_STATE; public boolean TRACK_CPU_ACTIVE_CLUSTER_TIME = DEFAULT_TRACK_CPU_ACTIVE_CLUSTER_TIME; @@ -13324,6 +13365,7 @@ public class BatteryStatsImpl extends BatteryStats { = DEFAULT_BATTERY_LEVEL_COLLECTION_DELAY_MS; public int MAX_HISTORY_FILES; public int MAX_HISTORY_BUFFER; /*Bytes*/ + public int BATTERY_CHARGED_DELAY_MS = DEFAULT_BATTERY_CHARGED_DELAY_MS; private ContentResolver mResolver; private final KeyValueListParser mParser = new KeyValueListParser(','); @@ -13392,6 +13434,9 @@ public class BatteryStatsImpl extends BatteryStats { DEFAULT_MAX_HISTORY_BUFFER_LOW_RAM_DEVICE_KB : DEFAULT_MAX_HISTORY_BUFFER_KB) * 1024; + BATTERY_CHARGED_DELAY_MS = mParser.getInt( + KEY_BATTERY_CHARGED_DELAY_MS, + DEFAULT_BATTERY_CHARGED_DELAY_MS); } } @@ -13449,6 +13494,8 @@ public class BatteryStatsImpl extends BatteryStats { pw.println(MAX_HISTORY_FILES); pw.print(KEY_MAX_HISTORY_BUFFER_KB); pw.print("="); pw.println(MAX_HISTORY_BUFFER/1024); + pw.print(KEY_BATTERY_CHARGED_DELAY_MS); pw.print("="); + pw.println(BATTERY_CHARGED_DELAY_MS); } } diff --git a/core/java/com/android/internal/os/ChildZygoteInit.java b/core/java/com/android/internal/os/ChildZygoteInit.java index f90cd0224596..a052a3b3ab6a 100644 --- a/core/java/com/android/internal/os/ChildZygoteInit.java +++ b/core/java/com/android/internal/os/ChildZygoteInit.java @@ -15,6 +15,7 @@ */ package com.android.internal.os; +import android.os.Process; import android.system.ErrnoException; import android.system.Os; import android.system.OsConstants; @@ -49,6 +50,22 @@ public class ChildZygoteInit { return null; } + static int parseIntFromArg(String[] argv, String desiredArg) { + int value = -1; + for (String arg : argv) { + if (arg.startsWith(desiredArg)) { + String valueStr = arg.substring(arg.indexOf('=') + 1); + try { + value = Integer.parseInt(valueStr); + } catch (NumberFormatException e) { + throw new IllegalArgumentException("Invalid int argument: " + + valueStr, e); + } + } + } + return value; + } + /** * Starts a ZygoteServer and listens for requests * @@ -72,6 +89,27 @@ public class ChildZygoteInit { throw new RuntimeException("Failed to set PR_SET_NO_NEW_PRIVS", ex); } + int uidGidMin = parseIntFromArg(args, Zygote.CHILD_ZYGOTE_UID_RANGE_START); + int uidGidMax = parseIntFromArg(args, Zygote.CHILD_ZYGOTE_UID_RANGE_END); + if (uidGidMin == -1 || uidGidMax == -1) { + throw new RuntimeException("Couldn't parse UID range start/end"); + } + if (uidGidMin > uidGidMax) { + throw new RuntimeException("Passed in UID range is invalid, min > max."); + } + + // Verify the UIDs are in the isolated UID range, as that's the only thing that we should + // be forking right now + if (!Process.isIsolated(uidGidMin) || !Process.isIsolated(uidGidMax)) { + throw new RuntimeException("Passed in UID range does not map to isolated processes."); + } + + /** + * Install a seccomp filter that ensure this Zygote can only setuid()/setgid() + * to the passed in range. + */ + Zygote.nativeInstallSeccompUidGidFilter(uidGidMin, uidGidMax); + final Runnable caller; try { server.registerServerSocketAtAbstractName(socketName); diff --git a/core/java/com/android/internal/os/Zygote.java b/core/java/com/android/internal/os/Zygote.java index d720c689f5de..f5746ca65f5e 100644 --- a/core/java/com/android/internal/os/Zygote.java +++ b/core/java/com/android/internal/os/Zygote.java @@ -104,6 +104,20 @@ public final class Zygote { */ public static final String CHILD_ZYGOTE_ABI_LIST_ARG = "--abi-list="; + /** + * An extraArg passed when a zygote process is forking a child-zygote, specifying the + * start of the UID range the children of the Zygote may setuid()/setgid() to. This + * will be enforced with a seccomp filter. + */ + public static final String CHILD_ZYGOTE_UID_RANGE_START = "--uid-range-start="; + + /** + * An extraArg passed when a zygote process is forking a child-zygote, specifying the + * end of the UID range the children of the Zygote may setuid()/setgid() to. This + * will be enforced with a seccomp filter. + */ + public static final String CHILD_ZYGOTE_UID_RANGE_END = "--uid-range-end="; + private Zygote() {} /** Called for some security initialization before any fork. */ @@ -222,6 +236,13 @@ public final class Zygote { native protected static void nativeAllowFileAcrossFork(String path); /** + * Installs a seccomp filter that limits setresuid()/setresgid() to the passed-in range + * @param uidGidMin The smallest allowed uid/gid + * @param uidGidMax The largest allowed uid/gid + */ + native protected static void nativeInstallSeccompUidGidFilter(int uidGidMin, int uidGidMax); + + /** * Zygote unmount storage space on initializing. * This method is called once. */ diff --git a/core/java/com/android/internal/textservice/ITextServicesManager.aidl b/core/java/com/android/internal/textservice/ITextServicesManager.aidl index 20f2aa06cf1e..8022949d1728 100644 --- a/core/java/com/android/internal/textservice/ITextServicesManager.aidl +++ b/core/java/com/android/internal/textservice/ITextServicesManager.aidl @@ -29,12 +29,13 @@ import android.view.textservice.SpellCheckerSubtype; * @hide */ interface ITextServicesManager { - SpellCheckerInfo getCurrentSpellChecker(String locale); - SpellCheckerSubtype getCurrentSpellCheckerSubtype(boolean allowImplicitlySelectedSubtype); - oneway void getSpellCheckerService(String sciId, in String locale, + SpellCheckerInfo getCurrentSpellChecker(int userId, String locale); + SpellCheckerSubtype getCurrentSpellCheckerSubtype(int userId, + boolean allowImplicitlySelectedSubtype); + oneway void getSpellCheckerService(int userId, String sciId, in String locale, in ITextServicesSessionListener tsListener, in ISpellCheckerSessionListener scListener, in Bundle bundle); - oneway void finishSpellCheckerService(in ISpellCheckerSessionListener listener); - boolean isSpellCheckerEnabled(); - SpellCheckerInfo[] getEnabledSpellCheckers(); + oneway void finishSpellCheckerService(int userId, in ISpellCheckerSessionListener listener); + boolean isSpellCheckerEnabled(int userId); + SpellCheckerInfo[] getEnabledSpellCheckers(int userId); } diff --git a/core/java/com/android/internal/view/InputBindResult.java b/core/java/com/android/internal/view/InputBindResult.java index 901cfe3602b1..9fe49b4b045d 100644 --- a/core/java/com/android/internal/view/InputBindResult.java +++ b/core/java/com/android/internal/view/InputBindResult.java @@ -127,8 +127,10 @@ public final class InputBindResult implements Parcelable { */ int ERROR_IME_NOT_CONNECTED = 8; /** - * Indicates that the caller is not the foreground user (or does not have - * {@link android.Manifest.permission#INTERACT_ACROSS_USERS_FULL} permission). + * Indicates that the caller is not the foreground user, does not have + * {@link android.Manifest.permission#INTERACT_ACROSS_USERS_FULL} permission, or the user + * specified in {@link android.view.inputmethod.EditorInfo#targetInputMethodUser} is not + * running. */ int ERROR_INVALID_USER = 9; /** diff --git a/core/java/com/android/internal/widget/ILockSettings.aidl b/core/java/com/android/internal/widget/ILockSettings.aidl index 591f15fd5676..9a77802aa541 100644 --- a/core/java/com/android/internal/widget/ILockSettings.aidl +++ b/core/java/com/android/internal/widget/ILockSettings.aidl @@ -62,7 +62,9 @@ interface ILockSettings { in byte[] recoveryServiceCertFile, in byte[] recoveryServiceSigFile); KeyChainSnapshot getKeyChainSnapshot(); String generateKey(String alias); + String generateKeyWithMetadata(String alias, in byte[] metadata); String importKey(String alias, in byte[] keyBytes); + String importKeyWithMetadata(String alias, in byte[] keyBytes, in byte[] metadata); String getKey(String alias); void removeKey(String alias); void setSnapshotCreatedPendingIntent(in PendingIntent intent); diff --git a/core/jni/Android.bp b/core/jni/Android.bp index 088e13ff92bc..5be70ef46d31 100644 --- a/core/jni/Android.bp +++ b/core/jni/Android.bp @@ -185,7 +185,6 @@ cc_library_shared { "android_hardware_UsbDevice.cpp", "android_hardware_UsbDeviceConnection.cpp", "android_hardware_UsbRequest.cpp", - "android_hardware_location_ActivityRecognitionHardware.cpp", "android_util_FileObserver.cpp", "android/opengl/poly_clip.cpp", // TODO: .arm "android/opengl/util.cpp", diff --git a/core/jni/AndroidRuntime.cpp b/core/jni/AndroidRuntime.cpp index 109222298fe5..a586dc1e6d7e 100644 --- a/core/jni/AndroidRuntime.cpp +++ b/core/jni/AndroidRuntime.cpp @@ -101,7 +101,6 @@ extern int register_android_hardware_SoundTrigger(JNIEnv *env); extern int register_android_hardware_UsbDevice(JNIEnv *env); extern int register_android_hardware_UsbDeviceConnection(JNIEnv *env); extern int register_android_hardware_UsbRequest(JNIEnv *env); -extern int register_android_hardware_location_ActivityRecognitionHardware(JNIEnv* env); extern int register_android_media_AudioEffectDescriptor(JNIEnv *env); extern int register_android_media_AudioRecord(JNIEnv *env); @@ -1457,7 +1456,6 @@ static const RegJNIRec gRegJNI[] = { REG_JNI(register_android_hardware_UsbDevice), REG_JNI(register_android_hardware_UsbDeviceConnection), REG_JNI(register_android_hardware_UsbRequest), - REG_JNI(register_android_hardware_location_ActivityRecognitionHardware), REG_JNI(register_android_media_AudioEffectDescriptor), REG_JNI(register_android_media_AudioSystem), REG_JNI(register_android_media_AudioRecord), diff --git a/core/jni/android/graphics/Paint.cpp b/core/jni/android/graphics/Paint.cpp index bc49771c380b..e2e3042ee5b9 100644 --- a/core/jni/android/graphics/Paint.cpp +++ b/core/jni/android/graphics/Paint.cpp @@ -557,8 +557,9 @@ namespace PaintGlue { return result; } - // FIXME: Should this be FastNative? - static void setColorLong(JNIEnv* env, jobject clazz, jlong paintHandle, jobject jColorSpace, + // FIXME: Make this CriticalNative when we no longer need to use JNIEnv. b/122514935 will allow + // passing the SkColorSpace directly from JNI. + static void setColor(JNIEnv* env, jobject clazz, jlong paintHandle, jobject jColorSpace, jfloat r, jfloat g, jfloat b, jfloat a) { sk_sp<SkColorSpace> cs = GraphicsJNI::getNativeColorSpace(env, jColorSpace); if (GraphicsJNI::hasException(env)) { @@ -569,9 +570,11 @@ namespace PaintGlue { reinterpret_cast<Paint*>(paintHandle)->setColor4f(color, cs.get()); } - static void setShadowLayerLong(JNIEnv* env, jobject clazz, jlong paintHandle, jfloat radius, - jfloat dx, jfloat dy, jobject jColorSpace, - jfloat r, jfloat g, jfloat b, jfloat a) { + // FIXME: Make this CriticalNative when we no longer need to use JNIEnv. b/122514935 will allow + // passing the SkColorSpace directly from JNI. + static void setShadowLayer(JNIEnv* env, jobject clazz, jlong paintHandle, jfloat radius, + jfloat dx, jfloat dy, jobject jColorSpace, + jfloat r, jfloat g, jfloat b, jfloat a) { sk_sp<SkColorSpace> cs = GraphicsJNI::getNativeColorSpace(env, jColorSpace); if (GraphicsJNI::hasException(env)) { return; @@ -784,22 +787,6 @@ namespace PaintGlue { obj->setStyle(style); } - static jint getColor(jlong paintHandle) { - int color; - color = reinterpret_cast<Paint*>(paintHandle)->getColor(); - return static_cast<jint>(color); - } - - static jint getAlpha(jlong paintHandle) { - int alpha; - alpha = reinterpret_cast<Paint*>(paintHandle)->getAlpha(); - return static_cast<jint>(alpha); - } - - static void setColor(jlong paintHandle, jint color) { - reinterpret_cast<Paint*>(paintHandle)->setColor(color); - } - static void setAlpha(jlong paintHandle, jint a) { reinterpret_cast<Paint*>(paintHandle)->setAlpha(a); } @@ -1047,18 +1034,6 @@ namespace PaintGlue { return SkScalarToFloat(Paint::kStdStrikeThru_Thickness * textSize); } - static void setShadowLayer(jlong paintHandle, jfloat radius, - jfloat dx, jfloat dy, jint color) { - Paint* paint = reinterpret_cast<Paint*>(paintHandle); - if (radius <= 0) { - paint->setLooper(nullptr); - } - else { - SkScalar sigma = android::uirenderer::Blur::convertRadiusToSigma(radius); - paint->setLooper(SkBlurDrawLooper::Make((SkColor)color, sigma, dx, dy)); - } - } - static jboolean hasShadowLayer(jlong paintHandle) { Paint* paint = reinterpret_cast<Paint*>(paintHandle); return paint->getLooper() && paint->getLooper()->asABlurShadow(nullptr); @@ -1107,9 +1082,9 @@ static const JNINativeMethod methods[] = { {"nGetRunAdvance", "(J[CIIIIZI)F", (void*) PaintGlue::getRunAdvance___CIIIIZI_F}, {"nGetOffsetForAdvance", "(J[CIIIIZF)I", (void*) PaintGlue::getOffsetForAdvance___CIIIIZF_I}, - {"nSetColor","(JLandroid/graphics/ColorSpace;FFFF)V", (void*) PaintGlue::setColorLong}, + {"nSetColor","(JLandroid/graphics/ColorSpace;FFFF)V", (void*) PaintGlue::setColor}, {"nSetShadowLayer", "(JFFFLandroid/graphics/ColorSpace;FFFF)V", - (void*)PaintGlue::setShadowLayerLong}, + (void*)PaintGlue::setShadowLayer}, // --------------- @FastNative ---------------------- @@ -1139,9 +1114,6 @@ static const JNINativeMethod methods[] = { {"nSetDither","(JZ)V", (void*) PaintGlue::setDither}, {"nGetStyle","(J)I", (void*) PaintGlue::getStyle}, {"nSetStyle","(JI)V", (void*) PaintGlue::setStyle}, - {"nGetColor","(J)I", (void*) PaintGlue::getColor}, - {"nSetColor","(JI)V", (void*) PaintGlue::setColor}, - {"nGetAlpha","(J)I", (void*) PaintGlue::getAlpha}, {"nSetAlpha","(JI)V", (void*) PaintGlue::setAlpha}, {"nGetStrokeWidth","(J)F", (void*) PaintGlue::getStrokeWidth}, {"nSetStrokeWidth","(JF)V", (void*) PaintGlue::setStrokeWidth}, @@ -1182,7 +1154,6 @@ static const JNINativeMethod methods[] = { {"nGetUnderlineThickness","(J)F", (void*) PaintGlue::getUnderlineThickness}, {"nGetStrikeThruPosition","(J)F", (void*) PaintGlue::getStrikeThruPosition}, {"nGetStrikeThruThickness","(J)F", (void*) PaintGlue::getStrikeThruThickness}, - {"nSetShadowLayer", "(JFFFI)V", (void*)PaintGlue::setShadowLayer}, {"nHasShadowLayer", "(J)Z", (void*)PaintGlue::hasShadowLayer}, {"nEqualsForTextMeasurement", "(JJ)Z", (void*)PaintGlue::equalsForTextMeasurement}, }; diff --git a/core/jni/android_hardware_location_ActivityRecognitionHardware.cpp b/core/jni/android_hardware_location_ActivityRecognitionHardware.cpp deleted file mode 100644 index 1c9ab9403298..000000000000 --- a/core/jni/android_hardware_location_ActivityRecognitionHardware.cpp +++ /dev/null @@ -1,132 +0,0 @@ -/* - * Copyright 2014, The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#define LOG_TAG "ActivityRecognitionHardware" - -#include <jni.h> -#include <nativehelper/JNIHelp.h> - -#include <android_runtime/AndroidRuntime.h> -#include <android_runtime/Log.h> - -// #include <hardware/activity_recognition.h> -// The activity recognition HAL is being deprecated. This means - -// i) Android framework code shall not depend on activity recognition -// being provided through the activity_recognition.h interface. -// ii) activity recognition HAL will not be binderized as the other HALs. -// - -/** - * Initializes the ActivityRecognitionHardware class from the native side. - */ -static void class_init(JNIEnv* /*env*/, jclass /*clazz*/) { - ALOGE("activity_recognition HAL is deprecated. %s is effectively a no-op", - __FUNCTION__); -} - -/** - * Initializes and connect the callbacks handlers in the HAL. - */ -static void initialize(JNIEnv* /*env*/, jobject /*obj*/) { - ALOGE("activity_recognition HAL is deprecated. %s is effectively a no-op", - __FUNCTION__); -} - -/** - * De-initializes the ActivityRecognitionHardware from the native side. - */ -static void release(JNIEnv* /*env*/, jobject /*obj*/) { - ALOGE("activity_recognition HAL is deprecated. %s is effectively a no-op", - __FUNCTION__); -} - -/** - * Returns true if ActivityRecognition HAL is supported, false otherwise. - */ -static jboolean is_supported(JNIEnv* /*env*/, jclass /*clazz*/) { - ALOGE("activity_recognition HAL is deprecated. %s is effectively a no-op", - __FUNCTION__); - return JNI_FALSE; -} - -/** - * Gets an array representing the supported activities. - */ -static jobjectArray get_supported_activities(JNIEnv* /*env*/, jobject /*obj*/) { - ALOGE("activity_recognition HAL is deprecated. %s is effectively a no-op", - __FUNCTION__); - return NULL; -} - -/** - * Enables a given activity event to be actively monitored. - */ -static int enable_activity_event( - JNIEnv* /*env*/, - jobject /*obj*/, - jint /*activity_handle*/, - jint /*event_type*/, - jlong /*report_latency_ns*/) { - ALOGE("activity_recognition HAL is deprecated. %s is effectively a no-op", - __FUNCTION__); - return android::NO_INIT; -} - -/** - * Disables a given activity event from being actively monitored. - */ -static int disable_activity_event( - JNIEnv* /*env*/, - jobject /*obj*/, - jint /*activity_handle*/, - jint /*event_type*/) { - ALOGE("activity_recognition HAL is deprecated. %s is effectively a no-op", - __FUNCTION__); - return android::NO_INIT; -} - -/** - * Request flush for al batch buffers. - */ -static int flush(JNIEnv* /*env*/, jobject /*obj*/) { - ALOGE("activity_recognition HAL is deprecated. %s is effectively a no-op", - __FUNCTION__); - return android::NO_INIT; -} - - -static const JNINativeMethod sMethods[] = { - // {"name", "signature", (void*) functionPointer }, - { "nativeClassInit", "()V", (void*) class_init }, - { "nativeInitialize", "()V", (void*) initialize }, - { "nativeRelease", "()V", (void*) release }, - { "nativeIsSupported", "()Z", (void*) is_supported }, - { "nativeGetSupportedActivities", "()[Ljava/lang/String;", (void*) get_supported_activities }, - { "nativeEnableActivityEvent", "(IIJ)I", (void*) enable_activity_event }, - { "nativeDisableActivityEvent", "(II)I", (void*) disable_activity_event }, - { "nativeFlush", "()I", (void*) flush }, -}; - -/** - * Registration method invoked in JNI load. - */ -int register_android_hardware_location_ActivityRecognitionHardware(JNIEnv* env) { - return jniRegisterNativeMethods( - env, - "android/hardware/location/ActivityRecognitionHardware", - sMethods, - NELEM(sMethods)); -} diff --git a/core/jni/android_media_AudioRecord.cpp b/core/jni/android_media_AudioRecord.cpp index 12a8343b4a5c..67c306413bb2 100644 --- a/core/jni/android_media_AudioRecord.cpp +++ b/core/jni/android_media_AudioRecord.cpp @@ -841,6 +841,43 @@ static jint android_media_AudioRecord_get_active_microphones(JNIEnv *env, return jStatus; } +static int android_media_AudioRecord_set_microphone_direction(JNIEnv *env, jobject thiz, + jint direction) { + sp<AudioRecord> lpRecorder = getAudioRecord(env, thiz); + if (lpRecorder == NULL) { + jniThrowException(env, "java/lang/IllegalStateException", + "Unable to retrieve AudioRecord pointer for setMicrophoneDirection()"); + return (jint)AUDIO_JAVA_ERROR; + } + + jint jStatus = AUDIO_JAVA_SUCCESS; + status_t status = + lpRecorder->setMicrophoneDirection(static_cast<audio_microphone_direction_t>(direction)); + if (status != NO_ERROR) { + jStatus = nativeToJavaStatus(status); + } + + return jStatus; +} + +static int android_media_AudioRecord_set_microphone_field_dimension(JNIEnv *env, jobject thiz, + jfloat zoom) { + sp<AudioRecord> lpRecorder = getAudioRecord(env, thiz); + if (lpRecorder == NULL) { + jniThrowException(env, "java/lang/IllegalStateException", + "Unable to retrieve AudioRecord pointer for setMicrophoneFieldDimension()"); + return (jint)AUDIO_JAVA_ERROR; + } + + jint jStatus = AUDIO_JAVA_SUCCESS; + status_t status = lpRecorder->setMicrophoneFieldDimension(zoom); + if (status != NO_ERROR) { + jStatus = nativeToJavaStatus(status); + } + + return jStatus; +} + // ---------------------------------------------------------------------------- static jint android_media_AudioRecord_get_port_id(JNIEnv *env, jobject thiz) { sp<AudioRecord> lpRecorder = getAudioRecord(env, thiz); @@ -896,6 +933,10 @@ static const JNINativeMethod gMethods[] = { {"native_get_active_microphones", "(Ljava/util/ArrayList;)I", (void *)android_media_AudioRecord_get_active_microphones}, {"native_getPortId", "()I", (void *)android_media_AudioRecord_get_port_id}, + {"native_set_microphone_direction", "(I)I", + (void *)android_media_AudioRecord_set_microphone_direction}, + {"native_set_microphone_field_dimension", "(F)I", + (void *)android_media_AudioRecord_set_microphone_field_dimension}, }; // field names found in android/media/AudioRecord.java diff --git a/core/jni/android_util_Process.cpp b/core/jni/android_util_Process.cpp index 798825fbe4a9..26a474cfecba 100644 --- a/core/jni/android_util_Process.cpp +++ b/core/jni/android_util_Process.cpp @@ -22,12 +22,12 @@ #include <utils/Log.h> #include <binder/IPCThreadState.h> #include <binder/IServiceManager.h> -#include <cutils/sched_policy.h> #include <utils/String8.h> #include <utils/Vector.h> #include <meminfo/procmeminfo.h> #include <meminfo/sysmeminfo.h> #include <processgroup/processgroup.h> +#include <processgroup/sched_policy.h> #include <string> #include <vector> diff --git a/core/jni/android_view_InputEventSender.cpp b/core/jni/android_view_InputEventSender.cpp index 10da89227f51..aa10a2f98a7e 100644 --- a/core/jni/android_view_InputEventSender.cpp +++ b/core/jni/android_view_InputEventSender.cpp @@ -138,6 +138,7 @@ status_t NativeInputEventSender::sendMotionEvent(uint32_t seq, const MotionEvent event->getDeviceId(), event->getSource(), event->getDisplayId(), event->getAction(), event->getActionButton(), event->getFlags(), event->getEdgeFlags(), event->getMetaState(), event->getButtonState(), + event->getClassification(), event->getXOffset(), event->getYOffset(), event->getXPrecision(), event->getYPrecision(), event->getDownTime(), event->getHistoricalEventTime(i), diff --git a/core/jni/android_view_SurfaceControl.cpp b/core/jni/android_view_SurfaceControl.cpp index 9ce6df1832a6..897427fd8787 100644 --- a/core/jni/android_view_SurfaceControl.cpp +++ b/core/jni/android_view_SurfaceControl.cpp @@ -642,6 +642,27 @@ static jint nativeGetActiveColorMode(JNIEnv* env, jclass, jobject tokenObj) { return static_cast<jint>(SurfaceComposerClient::getActiveColorMode(token)); } +static jintArray nativeGetCompositionDataspaces(JNIEnv* env, jclass) { + ui::Dataspace defaultDataspace, wcgDataspace; + ui::PixelFormat defaultPixelFormat, wcgPixelFormat; + if (SurfaceComposerClient::getCompositionPreference(&defaultDataspace, + &defaultPixelFormat, + &wcgDataspace, + &wcgPixelFormat) != NO_ERROR) { + return nullptr; + } + jintArray array = env->NewIntArray(2); + if (array == nullptr) { + jniThrowException(env, "java/lang/OutOfMemoryError", nullptr); + return nullptr; + } + jint* arrayValues = env->GetIntArrayElements(array, 0); + arrayValues[0] = static_cast<jint>(defaultDataspace); + arrayValues[1] = static_cast<jint>(wcgDataspace); + env->ReleaseIntArrayElements(array, arrayValues, 0); + return array; +} + static jboolean nativeSetActiveColorMode(JNIEnv* env, jclass, jobject tokenObj, jint colorMode) { sp<IBinder> token(ibinderForJavaObject(env, tokenObj)); @@ -660,6 +681,10 @@ static void nativeSetDisplayPowerMode(JNIEnv* env, jclass clazz, jobject tokenOb if (t.duration() > 100ms) ALOGD("Excessive delay in setPowerMode()"); } +static jboolean nativeGetProtectedContentSupport(JNIEnv* env, jclass) { + return static_cast<jboolean>(SurfaceComposerClient::getProtectedContentSupport()); +} + static jboolean nativeClearContentFrameStats(JNIEnv* env, jclass clazz, jlong nativeObject) { SurfaceControl* const ctrl = reinterpret_cast<SurfaceControl *>(nativeObject); status_t err = ctrl->clearLayerFrameStats(); @@ -1016,6 +1041,8 @@ static const JNINativeMethod sSurfaceControlMethods[] = { (void*)nativeGetActiveColorMode}, {"nativeSetActiveColorMode", "(Landroid/os/IBinder;I)Z", (void*)nativeSetActiveColorMode}, + {"nativeGetCompositionDataspaces", "()[I", + (void*)nativeGetCompositionDataspaces}, {"nativeGetHdrCapabilities", "(Landroid/os/IBinder;)Landroid/view/Display$HdrCapabilities;", (void*)nativeGetHdrCapabilities }, {"nativeClearContentFrameStats", "(J)Z", @@ -1028,6 +1055,8 @@ static const JNINativeMethod sSurfaceControlMethods[] = { (void*)nativeGetAnimationFrameStats }, {"nativeSetDisplayPowerMode", "(Landroid/os/IBinder;I)V", (void*)nativeSetDisplayPowerMode }, + {"nativeGetProtectedContentSupport", "()Z", + (void*)nativeGetProtectedContentSupport }, {"nativeDeferTransactionUntil", "(JJLandroid/os/IBinder;J)V", (void*)nativeDeferTransactionUntil }, {"nativeDeferTransactionUntilSurface", "(JJJJ)V", diff --git a/core/jni/com_android_internal_os_Zygote.cpp b/core/jni/com_android_internal_os_Zygote.cpp index a8e142784397..7aee8338d3c4 100644 --- a/core/jni/com_android_internal_os_Zygote.cpp +++ b/core/jni/com_android_internal_os_Zygote.cpp @@ -14,6 +14,15 @@ * limitations under the License. */ +/* + * Disable optimization of this file if we are compiling with the address + * sanitizer. This is a mitigation for b/122921367 and can be removed once the + * bug is fixed. + */ +#if __has_feature(address_sanitizer) +#pragma clang optimize off +#endif + #define LOG_TAG "Zygote" // sys/mount.h has to come before linux/fs.h due to redefinition of MS_RDONLY, MS_BIND, etc @@ -53,13 +62,13 @@ #include <android-base/stringprintf.h> #include <cutils/fs.h> #include <cutils/multiuser.h> -#include <cutils/sched_policy.h> #include <private/android_filesystem_config.h> #include <utils/String8.h> #include <selinux/android.h> #include <seccomp_policy.h> #include <stats_event_list.h> #include <processgroup/processgroup.h> +#include <processgroup/sched_policy.h> #include "core_jni_helpers.h" #include <nativehelper/JNIHelp.h> @@ -86,6 +95,7 @@ using android::base::GetBoolProperty; static pid_t gSystemServerPid = 0; static const char kIsolatedStorage[] = "persist.sys.isolated_storage"; +static const char kIsolatedStorageSnapshot[] = "sys.isolated_storage_snapshot"; static const char kZygoteClassName[] = "com/android/internal/os/Zygote"; static jclass gZygoteClass; static jmethodID gCallPostForkSystemServerHooks; @@ -303,7 +313,7 @@ static void PreApplicationInit() { mallopt(M_DECAY_TIME, 1); } -static void SetUpSeccompFilter(uid_t uid) { +static void SetUpSeccompFilter(uid_t uid, bool is_child_zygote) { if (!g_is_security_enforced) { ALOGI("seccomp disabled by setenforce 0"); return; @@ -311,7 +321,14 @@ static void SetUpSeccompFilter(uid_t uid) { // Apply system or app filter based on uid. if (uid >= AID_APP_START) { - set_app_seccomp_filter(); + if (is_child_zygote) { + // set_app_zygote_seccomp_filter(); + // TODO(b/111434506) install the filter; for now, install the app filter + // which is more restrictive. + set_app_seccomp_filter(); + } else { + set_app_seccomp_filter(); + } } else { set_system_seccomp_filter(); } @@ -530,7 +547,7 @@ static bool MountEmulatedStorage(uid_t uid, jint mount_mode, return true; } - if (GetBoolProperty(kIsolatedStorage, false)) { + if (GetBoolProperty(kIsolatedStorageSnapshot, GetBoolProperty(kIsolatedStorage, false))) { if (mount_mode == MOUNT_EXTERNAL_FULL) { storageSource = "/mnt/runtime/write"; if (TEMP_FAILURE_RETRY(mount(storageSource.string(), "/storage", @@ -996,7 +1013,7 @@ static void SpecializeCommon(JNIEnv* env, uid_t uid, gid_t gid, jintArray gids, // alternative is to call prctl(PR_SET_NO_NEW_PRIVS, 1) afterward, but that // breaks SELinux domain transition (see b/71859146). As the result, // privileged syscalls used below still need to be accessible in app process. - SetUpSeccompFilter(uid); + SetUpSeccompFilter(uid, is_child_zygote); if (setresuid(uid, uid, uid) == -1) { fail_fn(CREATE_ERROR("setresuid(%d) failed: %s", uid, strerror(errno))); @@ -1295,6 +1312,23 @@ static void com_android_internal_os_Zygote_nativeUnmountStorageOnInit(JNIEnv* en UnmountTree("/storage"); } +static void com_android_internal_os_Zygote_nativeInstallSeccompUidGidFilter( + JNIEnv* env, jclass, jint uidGidMin, jint uidGidMax) { + if (!g_is_security_enforced) { + ALOGI("seccomp disabled by setenforce 0"); + return; + } + + // TODO(b/111434506) install the filter + + /* + bool installed = install_setuidgid_seccomp_filter(uidGidMin, uidGidMax); + if (!installed) { + RuntimeAbort(env, __LINE__, "Could not install setuid/setgid seccomp filter."); + } + */ +} + static const JNINativeMethod gMethods[] = { { "nativeSecurityInit", "()V", (void *) com_android_internal_os_Zygote_nativeSecurityInit }, @@ -1308,7 +1342,9 @@ static const JNINativeMethod gMethods[] = { { "nativeUnmountStorageOnInit", "()V", (void *) com_android_internal_os_Zygote_nativeUnmountStorageOnInit }, { "nativePreApplicationInit", "()V", - (void *) com_android_internal_os_Zygote_nativePreApplicationInit } + (void *) com_android_internal_os_Zygote_nativePreApplicationInit }, + { "nativeInstallSeccompUidGidFilter", "(II)V", + (void *) com_android_internal_os_Zygote_nativeInstallSeccompUidGidFilter } }; int register_com_android_internal_os_Zygote(JNIEnv* env) { diff --git a/core/proto/android/app/settings_enums.proto b/core/proto/android/app/settings_enums.proto index 49ca378ef0e2..f68c760a9dbb 100644 --- a/core/proto/android/app/settings_enums.proto +++ b/core/proto/android/app/settings_enums.proto @@ -27,9 +27,569 @@ enum Action { PAGE_VISIBLE = 1; PAGE_HIDE = 2; + // ACTION: Settings > Wi-Fi > [Long press network] > Connect to network + // SUBTYPE: true if connecting to a saved network, false if not + // CATEGORY: SETTINGS + // OS: 6.0 + ACTION_WIFI_CONNECT = 135; + + // ACTION: Settings > Wi-Fi > [Long press network] > Forget network + // CATEGORY: SETTINGS + // OS: 6.0 + ACTION_WIFI_FORGET = 137; + + // ACTION: Settings > Wi-Fi > Toggle off + // SUBTYPE: true if connected to network before toggle, false if not + // CATEGORY: SETTINGS + // OS: 6.0 + ACTION_WIFI_OFF = 138; + + // ACTION: Settings > Wi-Fi > Toggle on + // CATEGORY: SETTINGS + // OS: 6.0 + ACTION_WIFI_ON = 139; + + // ACTION: Settings > Bluetooth > Overflow > Rename this device + // CATEGORY: SETTINGS + // OS: 6.0 + ACTION_BLUETOOTH_RENAME = 161; + + // ACTION: Settings > Bluetooth > Overflow > Show received files + // CATEGORY: SETTINGS + // OS: 6.0 + ACTION_BLUETOOTH_FILES = 162; + + // ACTION: DND Settings > Priority only allows > Reminder toggle + // SUBTYPE: 0 is off, 1 is on + // CATEGORY: SETTINGS + // OS: 6.0 + ACTION_ZEN_ALLOW_REMINDERS = 167; + + // ACTION: DND Settings > Priority only allows > Event toggle + // SUBTYPE: 0 is off, 1 is on + // CATEGORY: SETTINGS + // OS: 6.0 + ACTION_ZEN_ALLOW_EVENTS = 168; + + // ACTION: DND Settings > Priority only allows > Messages + // SUBTYPE: 0 is off, 1 is on + // CATEGORY: SETTINGS + // OS: 6.0 + ACTION_ZEN_ALLOW_MESSAGES = 169; + + // ACTION: DND Settings > Priority only allows > Calls + // SUBTYPE: 0 is off, 1 is on + // CATEGORY: SETTINGS + // OS: 6.0 + ACTION_ZEN_ALLOW_CALLS = 170; + + // ACTION: DND Settings > Priority only allows > Repeat callers toggle + // SUBTYPE: 0 is off, 1 is on + // CATEGORY: SETTINGS + // OS: 6.0 + ACTION_ZEN_ALLOW_REPEAT_CALLS = 171; + + // ACTION: DND Settings > Automatic rules > [Rule] > Delete rule > Delete + // CATEGORY: SETTINGS + // OS: 6.0 + ACTION_ZEN_DELETE_RULE_OK = 175; + + // ACTION: Settings > More > Airplane mode toggle + // SUBTYPE: 0 is off, 1 is on + // CATEGORY: SETTINGS + // OS: 6.0 + ACTION_AIRPLANE_TOGGLE = 177; + + // ACTION: Settings > Data usage > Cellular data toggle + // SUBTYPE: 0 is off, 1 is on + // CATEGORY: SETTINGS + // OS: 6.0 + ACTION_CELL_DATA_TOGGLE = 178; + + // ACTION: Settings > Display > When device is rotated + // CATEGORY: SETTINGS + // OS: 6.0 + ACTION_ROTATION_LOCK = 203; + + // OPEN: Settings > Search > Perform search + // CATEGORY: SETTINGS + // OS: 6.0 + ACTION_SEARCH_RESULTS = 226; + + // ACTION: Settings > Security > Nexus Imprint > [Fingerprint] > Delete + // CATEGORY: SETTINGS + // OS: 6.0 + ACTION_FINGERPRINT_DELETE = 253; + + // ACTION: Settings > Security > Nexus Imprint > [Fingerprint] > Rename + // CATEGORY: SETTINGS + // OS: 6.0 + ACTION_FINGERPRINT_RENAME = 254; + + // ACTION: Settings -> Developer Options -> Take bug report -> Interactive report + // CATEGORY: SETTINGS + // OS: N + // Interactive bug report initiated from Settings. + ACTION_BUGREPORT_FROM_SETTINGS_INTERACTIVE = 294; + + // ACTION: Settings -> Developer Options -> Take bug report -> Full report + // CATEGORY: SETTINGS + // OS: N + // Interactive bug report initiated from Settings. + ACTION_BUGREPORT_FROM_SETTINGS_FULL = 295; + + // click on collapsed conditional or clicks expand button + ACTION_SETTINGS_CONDITION_EXPAND = 373; + + // click main area of expanded conditional + ACTION_SETTINGS_CONDITION_CLICK = 375; + + // click a direct button on expanded conditional + ACTION_SETTINGS_CONDITION_BUTTON = 376; + + // Action: user enable / disabled data saver using Settings + // OPEN: Settings -> Data Usage -> Data saver -> On/off toggle + // VALUE: 1 for enabled, 0 for disabled + // CATEGORY: SETTINGS + // OS: N + ACTION_DATA_SAVER_MODE = 394; + + // User whitelisted an app for Data Saver mode; action pass package name of app + // Action: user enable / disabled data saver using Settings + // OPEN: Settings -> Data Usage -> Data saver -> Unrestricted data access > APP toggle turned on + // or + // Settings -> Apps -> APP -> Data usage -> Unrestricted data usage toggle turned on + // VALUE: package name of APP + // CATEGORY: SETTINGS + // OS: N + ACTION_DATA_SAVER_WHITELIST = 395; + + // User blacklisted an app for Data Saver mode; action pass package name of app + // OPEN: Settings -> Apps -> APP -> Data usage -> Background data toggle turned off + // VALUE: package name of APP + // CATEGORY: SETTINGS + // OS: N + ACTION_DATA_SAVER_BLACKLIST = 396; + + // ACTION: Settings -> Storage -> Manage storage -> Click Storage Manager + // SUBTYPE: false is off, true is on + ACTION_TOGGLE_STORAGE_MANAGER = 489; + + // OPEN: Settings > Display -> Ambient Display + // CATEGORY: SETTINGS + ACTION_AMBIENT_DISPLAY = 495; + + // ACTION: Allow Battery optimization for an app + APP_SPECIAL_PERMISSION_BATTERY_ALLOW = 764; + + // ACTION: Deny Battery optimization for an app + APP_SPECIAL_PERMISSION_BATTERY_DENY = 765; + + // ACTION: Enable Device Admin app + APP_SPECIAL_PERMISSION_ADMIN_ALLOW = 766; + + // ACTION: Disable Device Admin app + APP_SPECIAL_PERMISSION_ADMIN_DENY = 767; + + // ACTION: Allow "Do Not Disturb access" for an app + APP_SPECIAL_PERMISSION_DND_ALLOW = 768; + + // ACTION: Deny "Do Not Disturb access" for an app + APP_SPECIAL_PERMISSION_DND_DENY = 769; + + // ACTION: Allow "Draw over other apps" for an app + APP_SPECIAL_PERMISSION_APPDRAW_ALLOW = 770; + + // ACTION: Deny "Display over other apps" for an app + APP_SPECIAL_PERMISSION_APPDRAW_DENY = 771; + + // ACTION: Allow "VR helper services" for an app + APP_SPECIAL_PERMISSION_VRHELPER_ALLOW = 772; + + // ACTION: Deny "VR helper services" for an app + APP_SPECIAL_PERMISSION_VRHELPER_DENY = 773; + + // ACTION: Allow "Modify system settings" for an app + APP_SPECIAL_PERMISSION_SETTINGS_CHANGE_ALLOW = 774; + + // ACTION: Deny "Modify system settings" for an app + APP_SPECIAL_PERMISSION_SETTINGS_CHANGE_DENY = 775; + + // ACTION: Allow "Notification access" for an app + APP_SPECIAL_PERMISSION_NOTIVIEW_ALLOW = 776; + + // ACTION: Deny "Notification access" for an app + APP_SPECIAL_PERMISSION_NOTIVIEW_DENY = 777; + + // ACTION: "Premium SMS access" for an app - "ask user" option + APP_SPECIAL_PERMISSION_PREMIUM_SMS_ASK = 778; + + // ACTION: "Premium SMS access" for an app - "never allow" option + APP_SPECIAL_PERMISSION_PREMIUM_SMS_DENY = 779; + + // ACTION: "Premium SMS access" for an app - "always allow" option + APP_SPECIAL_PERMISSION_PREMIUM_SMS_ALWAYS_ALLOW = 780; + + // ACTION: Allow "Unrestricted data access" for an app + APP_SPECIAL_PERMISSION_UNL_DATA_ALLOW = 781; + + // ACTION: Deny "Unrestricted data access" for an app + APP_SPECIAL_PERMISSION_UNL_DATA_DENY = 782; + + // ACTION: Allow "Usage access" for an app + APP_SPECIAL_PERMISSION_USAGE_VIEW_ALLOW = 783; + + // ACTION: Deny "Usage access" for an app + APP_SPECIAL_PERMISSION_USAGE_VIEW_DENY = 784; + + // ACTION: "Force stop" action on an app + ACTION_APP_FORCE_STOP = 807; + + // ACTION: Allow "Enable picture-in-picture" for an app + APP_PICTURE_IN_PICTURE_ALLOW = 813; + + // ACTION: Create a Settings shortcut item. + ACTION_SETTINGS_CREATE_SHORTCUT = 829; + + // ACTION: Settings advanced button is expanded + ACTION_SETTINGS_ADVANCED_BUTTON_EXPAND = 834; + + // ACTION: Deny "Enable picture-in-picture" for an app + APP_PICTURE_IN_PICTURE_DENY = 814; + + // ACTION: Settings -> Display -> Theme + ACTION_THEME = 816; + + // ACTION: Settings > About device > Build number + ACTION_SETTINGS_BUILD_NUMBER_PREF = 847; + + // ACTION: Settings > Battery > Menu > Optimization + ACTION_SETTINGS_MENU_BATTERY_OPTIMIZATION = 851; + + // ACTION: Settings > Battery > Menu > Apps Toggle + ACTION_SETTINGS_MENU_BATTERY_APPS_TOGGLE = 852; + // ACTION: Settings > Any preference is changed ACTION_SETTINGS_PREFERENCE_CHANGE = 853; + // ACTION: Settings > Connected devices > Bluetooth -> Available devices + ACTION_SETTINGS_BLUETOOTH_PAIR = 866; + + // ACTION: Settings > Connected devices > Bluetooth -> Paired devices + ACTION_SETTINGS_BLUETOOTH_CONNECT = 867; + + // ACTION: Settings > Connected devices > Bluetooth -> Connected device + ACTION_SETTINGS_BLUETOOTH_DISCONNECT = 868; + + // ACTION: Settings > Connected devices > Bluetooth -> Error dialog + ACTION_SETTINGS_BLUETOOTH_CONNECT_ERROR = 869; + + // ACTION: Settings > Connected devices > Bluetooth master switch Toggle + ACTION_SETTINGS_MASTER_SWITCH_BLUETOOTH_TOGGLE = 870; + + // ACTION: Settings > App detail > Uninstall + ACTION_SETTINGS_UNINSTALL_APP = 872; + + // ACTION: Settings > App detail > Uninstall Device admin app + ACTION_SETTINGS_UNINSTALL_DEVICE_ADMIN = 873; + + // ACTION: Settings > App detail > Disable app + ACTION_SETTINGS_DISABLE_APP = 874; + + // ACTION: Settings > App detail > Enable app + ACTION_SETTINGS_ENABLE_APP = 875; + + // ACTION: Settings > App detail > Clear data + ACTION_SETTINGS_CLEAR_APP_DATA = 876; + + // ACTION: Settings > App detail > Clear cache + ACTION_SETTINGS_CLEAR_APP_CACHE = 877; + + // ACTION: Logs pressing the "Clear app" button in the app info settings page for an instant + // app. + // VALUE: The package name of the app + ACTION_SETTINGS_CLEAR_INSTANT_APP = 923; + + // OPEN: Assist Gesture training intro in Settings + // CATEGORY: SETTINGS + // OS: O DR + SETTINGS_ASSIST_GESTURE_TRAINING_INTRO = 991; + + // OPEN: Assist Gesture training enrolling in Settings + // CATEGORY: SETTINGS + // OS: O DR + SETTINGS_ASSIST_GESTURE_TRAINING_ENROLLING = 992; + + // OPEN: Assist Gesture training finished in Settings + // CATEGORY: SETTINGS + // OS: O DR + SETTINGS_ASSIST_GESTURE_TRAINING_FINISHED = 993; + + // ACTION: Update default app from Settings + ACTION_SETTINGS_UPDATE_DEFAULT_APP = 1000; + + // ACTION: Settings > Wi-Fi > [Long press network] > Sign in to network + // CATEGORY: SETTINGS + // OS: O DR + ACTION_WIFI_SIGNIN = 1008; + + // ACTION: Settings > Notification Settings > Open application notification + // CATEGORY: SETTINGS + // OS: O DR + ACTION_OPEN_APP_NOTIFICATION_SETTING = 1016; + + // ACTION: Settings > App Info > Open app settings + // CATEGORY: SETTINGS + // OS: O DR + ACTION_OPEN_APP_SETTING = 1017; + + // ACTION: Collect PSD Signals + // CATEGORY: SETTINGS + // OS: O DR + ACTION_PSD_LOADER = 1019; + + // OPEN: Settings > Trampoline Intent > Settings page + // CATEGORY: SETTINGS + // OS: O DR + TRAMPOLINE_SETTINGS_EVENT = 1033; + + // ACTION: Logged when user tries to pair a Bluetooth device without name from Settings app + // CATEGORY: SETTINGS + // OS: O MR + ACTION_SETTINGS_BLUETOOTH_PAIR_DEVICES_WITHOUT_NAMES = 1096; + + // ACTION: Settings > Network & Internet > Mobile network > Network + // CATEGORY: SETTINGS + ACTION_MOBILE_NETWORK_MANUAL_SELECT_NETWORK = 1210; + + // ACTION: DND Settings > Priority only allows > Alarms toggle + // SUBTYPE: 0 is off, 1 is on + // CATEGORY: SETTINGS + // OS: P + ACTION_ZEN_ALLOW_ALARMS = 1226; + + // ACTION: DND Settings > Priority only allows > Media toggle + // SUBTYPE: 0 is off, 1 is on + // CATEGORY: SETTINGS + // OS: P + ACTION_ZEN_ALLOW_MEDIA = 1227; + + // ACTION: A private dns mode been selected by user + // CATEGORY: SETTINGS + // OS: P + ACTION_PRIVATE_DNS_MODE = 1249; + + // OPEN: Settings > Sound > Do Not Disturb > Turn on automatically > Select rule ("Event") > Rule name > OK + // CATEGORY: SETTINGS + // OS: P + ACTION_ZEN_MODE_RULE_NAME_CHANGE_OK = 1267; + + // OPEN: Settings > Sound > Do Not Disturb > TURN ON NOW/TURN OFF NOW + // CATEGORY: SETTINGS + // OS: P + ACTION_ZEN_TOGGLE_DND_BUTTON = 1268; + + // ACTION: DND Settings > What to block > full screen intents + // SUBTYPE: false is allowed, true is blocked + // CATEGORY: SETTINGS + // OS: 6.0 + ACTION_ZEN_BLOCK_FULL_SCREEN_INTENTS = 1332; + + // ACTION: DND Settings > What to block + // SUBTYPE: false is allowed, true is blocked + // OS: P + ACTION_ZEN_BLOCK_LIGHT = 1333; + + // ACTION: DND Settings > What to block + // SUBTYPE: false is allowed, true is blocked + // OS: P + ACTION_ZEN_BLOCK_PEEK = 1334; + + // ACTION: DND Settings > What to block + // SUBTYPE: false is allowed, true is blocked + // OS: P + ACTION_ZEN_BLOCK_STATUS = 1335; + + // ACTION: DND Settings > What to block + // SUBTYPE: false is allowed, true is blocked + // OS: P + ACTION_ZEN_BLOCK_BADGE = 1336; + + // ACTION: DND Settings > What to block + // SUBTYPE: false is allowed, true is blocked + // OS: P + ACTION_ZEN_BLOCK_AMBIENT = 1337; + + // ACTION: DND Settings > What to block + // SUBTYPE: false is allowed, true is blocked + // OS: P + ACTION_ZEN_BLOCK_NOTIFICATION_LIST = 1338; + + // ACTION: DND Settings > Priority only allows > System toggle + // SUBTYPE: 0 is off, 1 is on + // CATEGORY: SETTINGS + // OS: P + ACTION_ZEN_ALLOW_SYSTEM = 1340; + + // ACTION: Settings > Battery settings > Battery tip > App restriction tip + // OS: P + ACTION_APP_RESTRICTION_TIP = 1347; + + // ACTION: Settings > Battery settings > Battery tip > High usage tip + // OS: P + ACTION_HIGH_USAGE_TIP = 1348; + + // ACTION: Settings > Battery settings > Battery tip > Summary tip + // OS: P + ACTION_SUMMARY_TIP = 1349; + + // ACTION: Settings > Battery settings > Battery tip > Smart battery tip + // OS: P + ACTION_SMART_BATTERY_TIP = 1350; + + // ACTION: Settings > Battery settings > Battery tip > Early warning tip + // OS: P + ACTION_EARLY_WARNING_TIP = 1351; + + // ACTION: Settings > Battery settings > Battery tip > Low battery tip + // OS: P + ACTION_LOW_BATTERY_TIP = 1352; + + // ACTION: Settings > Battery settings > Battery tip > App restriction list shown + // OS: P + ACTION_APP_RESTRICTION_TIP_LIST = 1353; + + // ACTION: Settings > Battery settings > Battery tip > High usage list shown + // OS: P + ACTION_HIGH_USAGE_TIP_LIST = 1354; + + // ACTION: Settings > Battery settings > Battery tip > Open app restriction page + // CATEGORY: SETTINGS + // OS: P + ACTION_TIP_OPEN_APP_RESTRICTION_PAGE = 1361; + + // ACTION: Settings > Battery settings > Battery tip > Restrict app + // CATEGORY: SETTINGS + // OS: P + ACTION_TIP_RESTRICT_APP = 1362; + + // ACTION: Settings > Battery settings > Battery tip > Unrestrict app + // CATEGORY: SETTINGS + // OS: P + ACTION_TIP_UNRESTRICT_APP = 1363; + + // ACTION: Settings > Battery settings > Battery tip > Open smart battery page + // CATEGORY: SETTINGS + // OS: P + ACTION_TIP_OPEN_SMART_BATTERY = 1364; + + // ACTION: Settings > Battery settings > Battery tip > Turn on battery saver + // CATEGORY: SETTINGS + // OS: P + ACTION_TIP_TURN_ON_BATTERY_SAVER = 1365; + + // ACTION: Settings > Anomaly receiver > Anomaly received + // CATEGORY: SETTINGS + // OS: P + ACTION_ANOMALY_TRIGGERED = 1367; + + // ACTION: A Settings Slice is requested + // CATEGORY: SETTINGS + // OS: P + ACTION_SETTINGS_SLICE_REQUESTED = 1371; + + // ACTION: A Settings Slice is updated with new value + // CATEGORY: SETTINGS + // OS: P + ACTION_SETTINGS_SLICE_CHANGED = 1372; + + // OPEN: DND onboarding activity > Ok button + // CATEGORY: SETTINGS + // OS: P + ACTION_ZEN_ONBOARDING_OK = 1378; + + // OPEN: DND onboarding activity > Settings link + // CATEGORY: SETTINGS + // OS: P + ACTION_ZEN_ONBOARDING_SETTINGS = 1379; + + // ACTION: Settings > Anomaly receiver > Anomaly ignored, don't show up in battery settings + // CATEGORY: SETTINGS + // OS: P + ACTION_ANOMALY_IGNORED = 1387; + + // ACTION: Settings > Battery settings > Battery tip > Open battery saver page + // CATEGORY: SETTINGS + // OS: P + ACTION_TIP_OPEN_BATTERY_SAVER_PAGE = 1388; + + // ACTION: DND Settings > What to block + // OS: P + ACTION_ZEN_SOUND_ONLY = 1396; + + // ACTION: DND Settings > Notifications + // OS: P + ACTION_ZEN_SOUND_AND_VIS_EFFECTS = 1397; + + // ACTION: DND Settings > Notifications + // OS: P + ACTION_ZEN_SHOW_CUSTOM = 1398; + + // ACTION: DND Settings > Notifications + // OS: P + ACTION_ZEN_CUSTOM = 1399; + + // OPEN: DND onboarding activity > don't update button + // CATEGORY: SETTINGS + // OS: P + ACTION_ZEN_ONBOARDING_KEEP_CURRENT_SETTINGS = 1406; + + // ACTION: Storage initialization wizard initialization choice of external/portable + // CATEGORY: SETTINGS + // OS: P + ACTION_STORAGE_INIT_EXTERNAL = 1407; + + // ACTION: Storage initialization wizard initialization choice of internal/adoptable + // CATEGORY: SETTINGS + // OS: P + ACTION_STORAGE_INIT_INTERNAL = 1408; + + // ACTION: Storage initialization wizard benchmark fast choice of continue + // CATEGORY: SETTINGS + // OS: P + ACTION_STORAGE_BENCHMARK_FAST_CONTINUE = 1409; + + // ACTION: Storage initialization wizard benchmark slow choice of continue + // CATEGORY: SETTINGS + // OS: P + ACTION_STORAGE_BENCHMARK_SLOW_CONTINUE = 1410; + + // ACTION: Storage initialization wizard benchmark slow choice of abort + // CATEGORY: SETTINGS + // OS: P + ACTION_STORAGE_BENCHMARK_SLOW_ABORT = 1411; + + // ACTION: Storage initialization wizard migration choice of now + // CATEGORY: SETTINGS + // OS: P + ACTION_STORAGE_MIGRATE_NOW = 1412; + + // ACTION: Storage initialization wizard migration choice of later + // CATEGORY: SETTINGS + // OS: P + ACTION_STORAGE_MIGRATE_LATER = 1413; + + // OPEN: Settings > Sound > Switch a2dp devices dialog + // CATEGORY: SETTINGS + // OS: P + DIALOG_SWITCH_A2DP_DEVICES = 1415; + + + // OPEN: Settings > Sound > Switch hfp devices dialog + // CATEGORY: SETTINGS + // OS: P + DIALOG_SWITCH_HFP_DEVICES = 1416; + // ACTION: Tap & Pay -> Default Application Setting -> Use Forground ACTION_NFC_PAYMENT_FOREGROUND_SETTING = 1622; @@ -44,15 +604,1454 @@ enum PageId { // Unknown page. Should not be used in production code. PAGE_UNKNOWN = 0; + // OPEN: Settings > Accessibility + // CATEGORY: SETTINGS + // OS: 6.0 + ACCESSIBILITY = 2; + + // OPEN: Settings > Accessibility > Captions + // CATEGORY: SETTINGS + // OS: 6.0 + ACCESSIBILITY_CAPTION_PROPERTIES = 3; + + // OPEN: Settings > Accessibility > [Service] + // CATEGORY: SETTINGS + // OS: 6.0 + ACCESSIBILITY_SERVICE = 4; + + // OPEN: Settings > Accessibility > Color correction + // CATEGORY: SETTINGS + // OS: 6.0 + ACCESSIBILITY_TOGGLE_DALTONIZER = 5; + + // OPEN: Settings > Accessibility > Accessibility shortcut + // CATEGORY: SETTINGS + // OS: 6.0 + ACCESSIBILITY_TOGGLE_GLOBAL_GESTURE = 6; + + // OPEN: Settings > Accessibility > Magnification gestures (Renamed in O) + // OPEN: Settings > Accessibility > Magnification > Magnify with triple-tap + // OPEN: Settings > Accessibility > Magnification > Magnify with button + // CATEGORY: SETTINGS + // OS: 6.0 + ACCESSIBILITY_TOGGLE_SCREEN_MAGNIFICATION = 7; + + // OPEN: Settings > Accounts + // CATEGORY: SETTINGS + // OS: 6.0 + ACCOUNT = 8; + + // OPEN: Settings > Accounts > [Single Account Sync Settings] + // CATEGORY: SETTINGS + // OS: 6.0 + ACCOUNTS_ACCOUNT_SYNC = 9; + + // OPEN: Settings > Accounts > Add an account + // CATEGORY: SETTINGS + // OS: 6.0 + ACCOUNTS_CHOOSE_ACCOUNT_ACTIVITY = 10; + + // OPEN: Settings > Cellular network settings > APNs + // CATEGORY: SETTINGS + // OS: 6.0 + APN = 12; + + // OPEN: Settings > More > Cellular network settings > APNs > [Edit APN] + // CATEGORY: SETTINGS + // OS: 6.0 + APN_EDITOR = 13; + + // OPEN: Settings > Apps > Configure apps > App links > [App] + // CATEGORY: SETTINGS + // OS: 6.0 + APPLICATIONS_APP_LAUNCH = 17; + + // OPEN: Settings > Internal storage > Apps storage > [App] + // CATEGORY: SETTINGS + // OS: 6.0 + APPLICATIONS_APP_STORAGE = 19; + + // OPEN: Settings > Apps > [App info] + // CATEGORY: SETTINGS + // OS: 6.0 + APPLICATIONS_INSTALLED_APP_DETAILS = 20; + + // OPEN: Settings > Memory > App usage > [App Memory usage] + // CATEGORY: SETTINGS + // OS: 6.0 + APPLICATIONS_PROCESS_STATS_DETAIL = 21; + + // OPEN: Settings > Memory > App usage + // CATEGORY: SETTINGS + // OS: 6.0 + APPLICATIONS_PROCESS_STATS_UI = 23; + + // OPEN: Choose Bluetooth device (ex: when sharing) + // CATEGORY: SETTINGS + // OS: 6.0 + BLUETOOTH_DEVICE_PICKER = 25; + + // OPEN: Settings > Security > Choose screen lock + // CATEGORY: SETTINGS + // OS: 6.0 + CHOOSE_LOCK_GENERIC = 27; + + // OPEN: Settings > Security > Choose screen lock > Choose your password + // CATEGORY: SETTINGS + // OS: 6.0 + CHOOSE_LOCK_PASSWORD = 28; + + // OPEN: Settings > Security > Choose screen lock > Choose your pattern + // CATEGORY: SETTINGS + // OS: 6.0 + CHOOSE_LOCK_PATTERN = 29; + + // OPEN: Settings > Security > Choose screen lock > Confirm your password + // CATEGORY: SETTINGS + // OS: 6.0 + CONFIRM_LOCK_PASSWORD = 30; + + // OPEN: Settings > Security > Choose screen lock > Confirm your pattern + // CATEGORY: SETTINGS + // OS: 6.0 + CONFIRM_LOCK_PATTERN = 31; + + // OPEN: Settings > Security > Encrypt phone + // CATEGORY: SETTINGS + // OS: 6.0 + CRYPT_KEEPER = 32; + + // OPEN: Settings > Security > Encrypt phone > Confirm + // CATEGORY: SETTINGS + // OS: 6.0 + CRYPT_KEEPER_CONFIRM = 33; + + // OPEN: Settings (Root page) + // CATEGORY: SETTINGS + // OS: 6.0 + DASHBOARD_SUMMARY = 35; + + // OPEN: Settings > Data usage + // CATEGORY: SETTINGS + // OS: 6.0 + DATA_USAGE_SUMMARY = 37; + + // OPEN: Settings > Date & time + // CATEGORY: SETTINGS + // OS: 6.0 + DATE_TIME = 38; + + // OPEN: Settings > Developer options + // CATEGORY: SETTINGS + // OS: 6.0 + DEVELOPMENT = 39; + + // OPEN: Settings > About phone + // CATEGORY: SETTINGS + // OS: 6.0 + DEVICEINFO = 40; + + // OPEN: Settings > Internal storage + // CATEGORY: SETTINGS + // OS: 6.0 + DEVICEINFO_STORAGE = 42; + + // OPEN: Settings > Display + // CATEGORY: SETTINGS + // OS: 6.0 + DISPLAY = 46; + + // OPEN: Settings > Display > Daydream + // CATEGORY: SETTINGS + // OS: 6.0 + DREAM = 47; + + // OPEN: Settings > Security > Screen lock > Secure start-up + // CATEGORY: SETTINGS + // OS: 6.0 + ENCRYPTION = 48; + + // OPEN: Settings > Security > Nexus Imprint + // CATEGORY: SETTINGS + // OS: 6.0 + FINGERPRINT = 49; + + // OPEN: Settings > Battery > History details + // CATEGORY: SETTINGS + // OS: 6.0 + FUELGAUGE_BATTERY_HISTORY_DETAIL = 51; + + // OPEN: Settings > Battery > Battery saver + // CATEGORY: SETTINGS + // OS: 6.0 + FUELGAUGE_BATTERY_SAVER = 52; + + // OPEN: Settings > Battery > [App Use details] + // CATEGORY: SETTINGS + // OS: 6.0 + FUELGAUGE_POWER_USAGE_DETAIL = 53; + + // OPEN: Settings > Security > SIM card lock settings + // CATEGORY: SETTINGS + // OS: 6.0 + ICC_LOCK = 56; + + // OPEN: Settings > Language & input > Physical keyboard + // CATEGORY: SETTINGS + // OS: 6.0 + INPUTMETHOD_KEYBOARD = 58; + + // OPEN: Settings > Language & input > Spell checker + // CATEGORY: SETTINGS + // OS: 6.0 + INPUTMETHOD_SPELL_CHECKERS = 59; + + // OBSOLETE + INPUTMETHOD_SUBTYPE_ENABLER = 60; + + // OPEN: Settings > Language & input > Personal dictionary + // CATEGORY: SETTINGS + // OS: 6.0 + INPUTMETHOD_USER_DICTIONARY = 61; + + // OPEN: Settings > Language & input > Add word + // CATEGORY: SETTINGS + // OS: 6.0 + INPUTMETHOD_USER_DICTIONARY_ADD_WORD = 62; + + // OPEN: Settings > Location + // CATEGORY: SETTINGS + // OS: 6.0 + LOCATION = 63; + + // OPEN: Settings > Apps + // CATEGORY: SETTINGS + // OS: 6.0 + MANAGE_APPLICATIONS = 65; + + // OPEN: Settings > Backup & reset > Factory data reset + // CATEGORY: SETTINGS + // OS: 6.0 + MASTER_CLEAR = 66; + + // OPEN: Settings > Backup & reset > Factory data reset > Confirm + // CATEGORY: SETTINGS + // OS: 6.0 + MASTER_CLEAR_CONFIRM = 67; + + // OPEN: Settings > More > Android Beam + // CATEGORY: SETTINGS + // OS: 6.0 + NFC_BEAM = 69; + + // OPEN: Settings > Tap & pay + // CATEGORY: SETTINGS + // OS: 6.0 + NFC_PAYMENT = 70; + + // OPEN: Settings > Sound & notification > App notifications > [App] + // CATEGORY: SETTINGS + // OS: 6.0 + NOTIFICATION_APP_NOTIFICATION = 72; + + // OBSOLETE + NOTIFICATION_REDACTION = 74; + + // OPEN: Settings Widget > Notification log + // CATEGORY: SETTINGS + // OS: 6.0 + NOTIFICATION_STATION = 75; + + // OPEN: Settings > Sound & notification > Do not disturb + // CATEGORY: SETTINGS + // OS: 6.0 + NOTIFICATION_ZEN_MODE = 76; + + + // OPEN: Print job notification > Print job settings + // CATEGORY: SETTINGS + // OS: 6.0 + PRINT_JOB_SETTINGS = 78; + + // OPEN: Settings > Printing > [Print Service] + // CATEGORY: SETTINGS + // OS: 6.0 + PRINT_SERVICE_SETTINGS = 79; + + // OPEN: Settings > Printing + // CATEGORY: SETTINGS + // OS: 6.0 + PRINT_SETTINGS = 80; + + // OPEN: Settings > Backup & reset + // CATEGORY: SETTINGS + // OS: 6.0 + PRIVACY = 81; + + //OBSOLETE + PROXY_SELECTOR = 82; + + // OPEN: Settings > Backup & reset > Network settings reset + // CATEGORY: SETTINGS + // OS: 6.0 + RESET_NETWORK = 83; + + // OPEN: Settings > Backup & reset > Network settings reset > Confirm + // CATEGORY: SETTINGS + // OS: 6.0 + RESET_NETWORK_CONFIRM = 84; + + // OPEN: Settings > Developer Options > Running Services + // CATEGORY: SETTINGS + // OS: 6.0 + RUNNING_SERVICE_DETAILS = 85; + + // OPEN: Settings > Security > Screen pinning + // CATEGORY: SETTINGS + // OS: 6.0 + SCREEN_PINNING = 86; + + // OPEN: Settings > Security + // CATEGORY: SETTINGS + // OS: 6.0 + SECURITY = 87; + + // OPEN: Settings > SIM cards + // CATEGORY: SETTINGS + // OS: 6.0 + SIM = 88; + + // OBSOLETE + TESTING = 89; + + // OPEN: Settings > More > Tethering & portable hotspot + // CATEGORY: SETTINGS + // OS: 6.0 + TETHER = 90; + + // OPEN: Settings > Security > Trust agents + // CATEGORY: SETTINGS + // OS: 6.0 + TRUST_AGENT = 91; + + // OPEN: Settings > Security > Trusted credentials + // CATEGORY: SETTINGS + // OS: 6.0 + TRUSTED_CREDENTIALS = 92; + + // OPEN: Settings > Language & input > TTS output > [Engine] > Settings + // CATEGORY: SETTINGS + // OS: 6.0 + TTS_ENGINE_SETTINGS = 93; + + // OPEN: Settings > Language & input > Text-to-speech output + // CATEGORY: SETTINGS + // OS: 6.0 + TTS_TEXT_TO_SPEECH = 94; + + // OPEN: Settings > Security > Apps with usage access + // CATEGORY: SETTINGS + // OS: 6.0 + USAGE_ACCESS = 95; + + // OPEN: Settings > Users + // CATEGORY: SETTINGS + // OS: 6.0 + USER = 96; + + // OPEN: Settings > Users > [Restricted profile app & content access] + // CATEGORY: SETTINGS + // OS: 6.0 + USERS_APP_RESTRICTIONS = 97; + + // OPEN: Settings > Users > [User settings] + // CATEGORY: SETTINGS + // OS: 6.0 + USER_DETAILS = 98; + + // OPEN: Settings > More > VPN + // CATEGORY: SETTINGS + // OS: 6.0 + VPN = 100; + + // OPEN: Settings > Display > Choose wallpaper from + // CATEGORY: SETTINGS + // OS: 6.0 + WALLPAPER_TYPE = 101; + + // OPEN: Settings > Display > Cast + // CATEGORY: SETTINGS + // OS: 6.0 + WFD_WIFI_DISPLAY = 102; + + // OPEN: Settings > Wi-Fi + // CATEGORY: SETTINGS + // OS: 6.0 + WIFI = 103; + + // OPEN: Settings > More > Wi-Fi Calling + // CATEGORY: SETTINGS + // OS: 6.0 + WIFI_CALLING = 105; + + // OPEN: Settings > Wi-Fi > Saved networks + // CATEGORY: SETTINGS + // OS: 6.0 + WIFI_SAVED_ACCESS_POINTS = 106; + + // OPEN: Settings > Wi-Fi > Advanced Wi-Fi > Wi-Fi Direct + // CATEGORY: SETTINGS + // OS: 6.0 + WIFI_P2P = 109; + + // OPEN: Settings > Apps > Configure apps > App permissions + // CATEGORY: SETTINGS + // OS: 6.0 + APPLICATIONS_ADVANCED = 130; + + // OPEN: Settings > Location > Scanning + // CATEGORY: SETTINGS + // OS: 6.0 + LOCATION_SCANNING = 131; + + // OPEN: Settings > Sound & notification > App notifications + // CATEGORY: SETTINGS + // OS: 6.0 + MANAGE_APPLICATIONS_NOTIFICATIONS = 133; + + // OPEN: Settings > Sound & notification > DND > Priority only allows + // CATEGORY: SETTINGS + // OS: 6.0 + NOTIFICATION_ZEN_MODE_PRIORITY = 141; + + // OPEN: Settings > Sound & notification > DND > Automatic rules + // CATEGORY: SETTINGS + // OS: 6.0 + NOTIFICATION_ZEN_MODE_AUTOMATION = 142; + + // OPEN: Settings > Sound & notification > DND > [Time based rule] + // CATEGORY: SETTINGS + // OS: 6.0 + NOTIFICATION_ZEN_MODE_SCHEDULE_RULE = 144; + + // OPEN: Settings > Apps > Configure apps > App links + // CATEGORY: SETTINGS + // OS: 6.0 + MANAGE_DOMAIN_URLS = 143; + + // OPEN: Settings > Sound & notification > DND > [Event rule] + // CATEGORY: SETTINGS + // OS: 6.0 + NOTIFICATION_ZEN_MODE_EVENT_RULE = 146; + + // OPEN: Settings > Sound & notification > Notification access + // CATEGORY: SETTINGS + // OS: 6.0 + NOTIFICATION_ACCESS = 179; + + // OPEN: Settings > Sound & notification > Do Not Disturb access + // CATEGORY: SETTINGS + // OS: 6.0 + NOTIFICATION_ZEN_MODE_ACCESS = 180; + + // OPEN: Settings > Internal storage > Apps storage + // CATEGORY: SETTINGS + // OS: 6.0 + APPLICATIONS_STORAGE_APPS = 182; + + // OPEN: Settings > Security > Usage access + // CATEGORY: SETTINGS + // OS: 6.0 + APPLICATIONS_USAGE_ACCESS_DETAIL = 183; + + // OPEN: Settings > Battery > Battery optimization + // CATEGORY: SETTINGS + // OS: 6.0 + APPLICATIONS_HIGH_POWER_APPS = 184; + + // OPEN: Settings > Apps > Configure > Default apps > Assist & voice input + // CATEGORY: SETTINGS + // OS: 6.0 + APPLICATIONS_MANAGE_ASSIST = 201; + + // OPEN: Settings > Memory + // CATEGORY: SETTINGS + // OS: 6.0 + PROCESS_STATS_SUMMARY = 202; + + // OPEN: Settings > Apps > Configure Apps > Display over other apps + // CATEGORY: SETTINGS + // OS: 6.0 + SYSTEM_ALERT_WINDOW_APPS = 221; + + // OPEN: Settings > About phone > Legal information + // CATEGORY: SETTINGS + // OS: 6.0 + ABOUT_LEGAL_SETTINGS = 225; + + + // OPEN: Settings > Developer options > Inactive apps + // CATEGORY: SETTINGS + // OS: 6.0 + FUELGAUGE_INACTIVE_APPS = 238; + + // OPEN: Settings > Security > Nexus Imprint > Add Fingerprint + // CATEGORY: SETTINGS + // OS: 6.0 + FINGERPRINT_ENROLLING = 240; + // OPEN: Fingerprint Enroll > Find Sensor + // CATEGORY: SETTINGS + // OS: 6.0 + FINGERPRINT_FIND_SENSOR = 241; + + // OPEN: Fingerprint Enroll > Fingerprint Enrolled! + // CATEGORY: SETTINGS + // OS: 6.0 + FINGERPRINT_ENROLL_FINISH = 242; + + // OPEN: Fingerprint Enroll introduction + // CATEGORY: SETTINGS + // OS: 6.0 + FINGERPRINT_ENROLL_INTRO = 243; + + // OPEN: Fingerprint Enroll > Let's Start! + // CATEGORY: SETTINGS + // OS: 6.0 + FINGERPRINT_ENROLL_SIDECAR = 245; + + // OPEN: Fingerprint Enroll SUW > Let's Start! + // CATEGORY: SETTINGS + // OS: 6.0 + FINGERPRINT_ENROLLING_SETUP = 246; + + // OPEN: Fingerprint Enroll SUW > Find Sensor + // CATEGORY: SETTINGS + // OS: 6.0 + FINGERPRINT_FIND_SENSOR_SETUP = 247; + + // OPEN: Fingerprint Enroll SUW > Fingerprint Enrolled! + // CATEGORY: SETTINGS + // OS: 6.0 + FINGERPRINT_ENROLL_FINISH_SETUP = 248; + + // OPEN: Fingerprint Enroll SUW introduction + // CATEGORY: SETTINGS + // OS: 6.0 + FINGERPRINT_ENROLL_INTRO_SETUP = 249; + + // OPEN: Settings > Developer Options > Background Check + // CATEGORY: SETTINGS + // OS: N + BACKGROUND_CHECK_SUMMARY = 258; + + // OPEN: Settings > Notifications > [App] > Channel Notifications + // CATEGORY: SETTINGS + // OS: N + NOTIFICATION_TOPIC_NOTIFICATION = 265; + + // OPEN: Settings > Security > User credentials + // CATEGORY: Settings + // OS: N + USER_CREDENTIALS = 285; + + // Logs that the user has edited the enabled VR listeners. + // CATEGORY: SETTINGS + // OS: N + VR_MANAGE_LISTENERS = 334; + + // Settings -> Accessibility -> Click after pointer stops moving + // CATEGORY: SETTINGS + // OS: N + ACCESSIBILITY_TOGGLE_AUTOCLICK = 335; + + // Settings -> Sound + // CATEGORY: SETTINGS + // OS: N + SOUND = 336; + + // Settings -> Notifications -> Gear + // CATEGORY: SETTINGS + // OS: N + CONFIGURE_NOTIFICATION = 337; + + // Settings -> Wi-Fi -> Gear + // CATEGORY: SETTINGS + // OS: N + CONFIGURE_WIFI = 338; + + // Settings -> Display -> Display size + // OS: N + DISPLAY_SCREEN_ZOOM = 339; + + // Settings -> Display -> Font size + // CATEGORY: SETTINGS + // OS: N + ACCESSIBILITY_FONT_SIZE = 340; + + // Settings -> Data usage -> Cellular/Wi-Fi data usage + // CATEGORY: SETTINGS + // OS: N + DATA_USAGE_LIST = 341; + + // Settings -> Data usage -> Billing cycle or DATA_USAGE_LIST -> Gear + // CATEGORY: SETTINGS + // OS: N + BILLING_CYCLE = 342; + + // DATA_USAGE_LIST -> Any item or App info -> Data usage + // CATEGORY: SETTINGS + // OS: N + APP_DATA_USAGE = 343; + + // Settings -> Language & input -> Language + // CATEGORY: SETTINGS + // OS: N + USER_LOCALE_LIST = 344; + + // Settings -> Language & input -> Virtual keyboard + // CATEGORY: SETTINGS + // OS: N + VIRTUAL_KEYBOARDS = 345; + + // Settings -> Language & input -> Physical keyboard + // CATEGORY: SETTINGS + // OS: N + PHYSICAL_KEYBOARDS = 346; + + // Settings -> Language & input -> Virtual keyboard -> Add a virtual keyboard + // CATEGORY: SETTINGS + // OS: N + ENABLE_VIRTUAL_KEYBOARDS = 347; + + // Settings -> Data usage -> Data Saver + // CATEGORY: SETTINGS + // OS: N + DATA_SAVER_SUMMARY = 348; + + // Settings -> Data usage -> Data Saver -> Unrestricted data access + // CATEGORY: SETTINGS + // OS: N + DATA_USAGE_UNRESTRICTED_ACCESS = 349; + + // Settings -> Apps -> Gear -> Special access + SPECIAL_ACCESS = 351; + + // OPEN: SUW Welcome Screen -> Vision Settings + // CATEGORY: SETTINGS + // OS: N + SUW_ACCESSIBILITY = 367; + + // OPEN: SUW Welcome Screen -> Vision Settings -> Magnification gestures (Renamed in O) + // OPEN: SUW Welcome Screen -> Vision Settings -> Magnification -> Magnify with triple-tap + // OPEN: SUW Welcome Screen -> Vision Settings -> Magnification -> Magnify with button + // ACTION: New magnification gesture configuration is chosen + // SUBTYPE: 0 is off, 1 is on + // CATEGORY: SETTINGS + // OS: N + SUW_ACCESSIBILITY_TOGGLE_SCREEN_MAGNIFICATION = 368; + + // OPEN: SUW Welcome Screen -> Vision Settings -> Font size + // ACTION: New font size is chosen + // SUBTYPE: 0 is small, 1 is default, 2 is large, 3 is largest + // CATEGORY: SETTINGS + // OS: N + SUW_ACCESSIBILITY_FONT_SIZE = 369; + + // OPEN: SUW Welcome Screen -> Vision Settings -> Display size + // ACTION: New display size is chosen + // SUBTYPE: 0 is small, 1 is default, 2 is large, 3 is larger, 4 is largest + // CATEGORY: SETTINGS + // OS: N + SUW_ACCESSIBILITY_DISPLAY_SIZE = 370; + + // OPEN: SUW Welcome Screen -> Vision Settings -> TalkBack + // ACTION: New screen reader configuration is chosen + // SUBTYPE: 0 is off, 1 is on + // CATEGORY: SETTINGS + // OS: N + SUW_ACCESSIBILITY_TOGGLE_SCREEN_READER = 371; + + // Airplane mode on + SETTINGS_CONDITION_AIRPLANE_MODE = 377; + // AKA Data saver on + SETTINGS_CONDITION_BACKGROUND_DATA = 378; + // Battery saver on + SETTINGS_CONDITION_BATTERY_SAVER = 379; + // Cellular data off + SETTINGS_CONDITION_CELLULAR_DATA = 380; + // Do not disturb on + SETTINGS_CONDITION_DND = 381; + // Hotspot on + SETTINGS_CONDITION_HOTSPOT = 382; + // Work profile off + SETTINGS_CONDITION_WORK_MODE = 383; + + // Settings > Apps > Gear > Special Access > Premium SMS access + PREMIUM_SMS_ACCESS = 388; + + // OPEN: Settings > Accounts > Work profile settings + // CATEGORY: SETTINGS + ACCOUNTS_WORK_PROFILE_SETTINGS = 401; + + // Settings -> Dev options -> Convert to file encryption + CONVERT_FBE = 402; + + // Settings -> Dev options -> Convert to file encryption -> WIPE AND CONVERT... + CONVERT_FBE_CONFIRM = 403; + + // Settings -> Dev options -> Running services + RUNNING_SERVICES = 404; + + // The dialog shown by 3P intent to change current webview implementation. + WEBVIEW_IMPLEMENTATION = 405; + + // OPEN: Settings > Internal storage > Storage manager + // CATEGORY: SETTINGS + STORAGE_MANAGER_SETTINGS = 458; + + // OPEN: Settings -> Gestures + // CATEGORY: SETTINGS + SETTINGS_GESTURES = 459; + + // OPEN: Settings > Display > Night Light + // CATEGORY: SETTINGS + NIGHT_DISPLAY_SETTINGS = 488; + + // Night Light on + SETTINGS_CONDITION_NIGHT_DISPLAY = 492; + + // OPEN: Settings > Language & input > Personal dictionary (single locale) + USER_DICTIONARY_SETTINGS = 514; + + // OPEN: Settings > Date & time > Select time zone + ZONE_PICKER = 515; + + // OPEN: Settings > Security > Device administrators + DEVICE_ADMIN_SETTINGS = 516; + + // OPEN: Settings > Security > Factory Reset Protection dialog + DIALOG_FRP = 528; + + // OPEN: Settings > Custom list preference with confirmation message + DIALOG_CUSTOM_LIST_CONFIRMATION = 529; + + // OPEN: Settings > APN Editor > Error dialog + DIALOG_APN_EDITOR_ERROR = 530; + + // OPEN: Settings > Users > Edit owner info dialog + DIALOG_OWNER_INFO_SETTINGS = 531; + + // OPEN: Settings > Security > Use one lock dialog + DIALOG_UNIFICATION_CONFIRMATION = 532; + + // OPEN: Settings > Security > User Credential + DIALOG_USER_CREDENTIAL = 533; + + // OPEN: Settings > Accounts > Remove account + DIALOG_REMOVE_USER = 534; + + // OPEN: Settings > Accounts > Confirm auto sync dialog + DIALOG_CONFIRM_AUTO_SYNC_CHANGE = 535; + + // OPEN: Settings > Apps > Dialog for running service details + DIALOG_RUNNIGN_SERVICE = 536; + + // OPEN: Settings > Bluetooth > Rename this device + DIALOG_BLUETOOTH_RENAME = 538; + + // OPEN: Settings > Battery optimization > details for app + DIALOG_HIGH_POWER_DETAILS = 540; + + // OPEN: Settings > Keyboard > Show keyboard layout dialog + DIALOG_KEYBOARD_LAYOUT = 541; + + // OPEN: Settings > WIFI Scan permission dialog + DIALOG_WIFI_SCAN_MODE = 543; + + // OPEN: Settings > Wireless > VPN > Config dialog + DIALOG_LEGACY_VPN_CONFIG = 545; + + // OPEN: Settings > Wireless > VPN > Config dialog for app + DIALOG_VPN_APP_CONFIG = 546; + + // OPEN: Settings > Wireless > VPN > Cannot connect dialog + DIALOG_VPN_CANNOT_CONNECT = 547; + + // OPEN: Settings > Wireless > VPN > Replace existing VPN dialog + DIALOG_VPN_REPLACE_EXISTING = 548; + + // OPEN: Settings > Billing cycle > Edit billing cycle dates dialog + DIALOG_BILLING_CYCLE = 549; + + // OPEN: Settings > Billing cycle > Edit data limit/warning dialog + DIALOG_BILLING_BYTE_LIMIT = 550; + + // OPEN: Settings > Billing cycle > turn on data limit dialog + DIALOG_BILLING_CONFIRM_LIMIT = 551; + + // OPEN: Settings > Service > Turn off notification access dialog + DIALOG_DISABLE_NOTIFICATION_ACCESS = 552; + + // OPEN: Settings > Sound > Use personal sound for work profile dialog + DIALOG_UNIFY_SOUND_SETTINGS = 553; + + // OPEN: Settings > Zen mode > Dialog warning about the zen access privileges being granted. + DIALOG_ZEN_ACCESS_GRANT = 554; + + // OPEN: Settings > Zen mode > Dialog warning about the zen access privileges being revoked. + DIALOG_ZEN_ACCESS_REVOKE = 555; + + // OPEN: Settings > Zen mode > Dialog that picks time for zen mode. + DIALOG_ZEN_TIMEPICKER = 556; + + // OPEN: Settings > Apps > Dialog that informs user to allow service access for app. + DIALOG_SERVICE_ACCESS_WARNING = 557; + + // OPEN: Settings > Apps > Dialog for app actions (such as force stop/clear data) + DIALOG_APP_INFO_ACTION = 558; + + // OPEN: Settings > Storage > Dialog for forgetting a storage device + DIALOG_VOLUME_FORGET = 559; + + // OPEN: Settings > Storage > Dialog for initializing a volume + DIALOG_VOLUME_INIT = 561; + + // OPEN: Settings > Storage > Dialog for unmounting a volume + DIALOG_VOLUME_UNMOUNT = 562; + + // OPEN: Settings > Storage > Dialog for renaming a volume + DIALOG_VOLUME_RENAME = 563; + + // OPEN: Settings > Storage > Dialog for clear cache + DIALOG_STORAGE_CLEAR_CACHE = 564; + + // OPEN: Settings > Storage > Dialog for system info + DIALOG_STORAGE_SYSTEM_INFO = 565; + + // OPEN: Settings > Storage > Dialog for other info + DIALOG_STORAGE_OTHER_INFO = 566; + + // OPEN: Settings > Storage > Dialog for user info + DIALOG_STORAGE_USER_INFO = 567; + // OPEN: Settings > Add fingerprint > Dialog when user touches fingerprint icon. + DIALOG_FINGERPRINT_ICON_TOUCH = 568; + + // OPEN: Settings > Add fingerprint > Error dialog + DIALOG_FINGERPINT_ERROR = 569; + + // OPEN: Settings > Fingerprint > Rename or delete dialog + DIALOG_FINGERPINT_EDIT = 570; + + // OPEN: Settings > Fingerprint > Dialog for deleting last fingerprint + DIALOG_FINGERPINT_DELETE_LAST = 571; + + // OPEN: SUW > Fingerprint > Dialog to confirm skip fingerprint setup entirely. + DIALOG_FINGERPRINT_SKIP_SETUP = 573; + + // OPEN: Settings > Proxy Selector error dialog + DIALOG_PROXY_SELECTOR_ERROR = 574; + + // OPEN: Settings > Wifi > P2P Settings > Disconnect dialog + DIALOG_WIFI_P2P_DISCONNECT = 575; + + // OPEN: Settings > Wifi > P2P Settings > Cancel connection dialog + DIALOG_WIFI_P2P_CANCEL_CONNECT = 576; + + // OPEN: Settings > Wifi > P2P Settings > Rename dialog + DIALOG_WIFI_P2P_RENAME = 577; + + // OPEN: Settings > Wifi > P2P Settings > Forget group dialog + DIALOG_WIFI_P2P_DELETE_GROUP = 578; + + // OPEN: Settings > APN > Restore default dialog + DIALOG_APN_RESTORE_DEFAULT = 579; + + // OPEN: Settings > Encryption interstitial accessibility warning dialog + DIALOG_ENCRYPTION_INTERSTITIAL_ACCESSIBILITY = 581; + + // OPEN: Settings > Acessibility > Enable accessiblity service dialog + DIALOG_ACCESSIBILITY_SERVICE_ENABLE = 583; + + // OPEN: Settings > Acessibility > Disable accessiblity service dialog + DIALOG_ACCESSIBILITY_SERVICE_DISABLE = 584; + + // OPEN: Settings > Account > Remove account dialog + DIALOG_ACCOUNT_SYNC_REMOVE = 585; + + // OPEN: Settings > Account > Remove account failed dialog + DIALOG_ACCOUNT_SYNC_FAILED_REMOVAL = 586; + + // OPEN: Settings > Account > Cannot do onetime sync dialog + DIALOG_ACCOUNT_SYNC_CANNOT_ONETIME_SYNC = 587; + + // OPEN: Settings > Display > Night light > Set start time dialog + DIALOG_NIGHT_DISPLAY_SET_START_TIME = 588; + + // OPEN: Settings > Display > Night light > Set end time dialog + DIALOG_NIGHT_DISPLAY_SET_END_TIME = 589; + + + + // OPEN: Settings > User > Edit info dialog + DIALOG_USER_EDIT = 590; + + // OPEN: Settings > User > Confirm remove dialog + DIALOG_USER_REMOVE = 591; + + // OPEN: Settings > User > Enable calling dialog + DIALOG_USER_ENABLE_CALLING = 592; + + // OPEN: Settings > User > Enable calling and sms dialog + DIALOG_USER_ENABLE_CALLING_AND_SMS = 593; + + // OPEN: Settings > User > Cannot manage device message dialog + DIALOG_USER_CANNOT_MANAGE = 594; + + // OPEN: Settings > User > Add user dialog + DIALOG_USER_ADD = 595; + + // OPEN: Settings > User > Setup user dialog + DIALOG_USER_SETUP = 596; + + // OPEN: Settings > User > Setup profile dialog + DIALOG_USER_SETUP_PROFILE = 597; + + // OPEN: Settings > User > Choose user type dialog + DIALOG_USER_CHOOSE_TYPE = 598; + + // OPEN: Settings > User > Need lockscreen dialog + DIALOG_USER_NEED_LOCKSCREEN = 599; + + // OPEN: Settings > User > Confirm exit guest mode dialog + DIALOG_USER_CONFIRM_EXIT_GUEST = 600; + + // OPEN: Settings > User > Edit user profile dialog + DIALOG_USER_EDIT_PROFILE = 601; + + + // OPEN: Settings > Wifi > Saved AP > Edit dialog + DIALOG_WIFI_SAVED_AP_EDIT = 602; + + // OPEN: Settings > Wifi > Edit AP dialog + DIALOG_WIFI_AP_EDIT = 603; + + // OPEN: Settings > Wifi > Write config to NFC dialog + DIALOG_WIFI_WRITE_NFC = 606; + + // OPEN: Settings > Date > Date picker dialog + DIALOG_DATE_PICKER = 607; + + // OPEN: Settings > Date > Time picker dialog + DIALOG_TIME_PICKER = 608; + + // OPEN: Settings > Wireless > Manage wireless plan dialog + DIALOG_MANAGE_MOBILE_PLAN = 609; + + // OPEN Settings > Bluetooth > Attempt to connect to device that shows dialog + BLUETOOTH_DIALOG_FRAGMENT = 613; + + // OPEN: Settings > Security + // CATEGORY: SETTINGS + // OS: O + ENTERPRISE_PRIVACY_SETTINGS = 628; + + // OPEN: Settings > System + SETTINGS_SYSTEM_CATEGORY = 744; + + // OPEN: Settings > Storage + SETTINGS_STORAGE_CATEGORY = 745; + + // OPEN: Settings > Network & Internet + SETTINGS_NETWORK_CATEGORY = 746; + + // OPEN: Settings > Connected Device + SETTINGS_CONNECTED_DEVICE_CATEGORY = 747; + + // OPEN: Settings > App & Notification + SETTINGS_APP_NOTIF_CATEGORY = 748; + + // OPEN: Settings > System > Language & Region + SETTINGS_LANGUAGE_CATEGORY = 750; + + // OPEN: Settings > System > Input & Gesture > Swipe to notification gesture + SETTINGS_GESTURE_SWIPE_TO_NOTIFICATION = 751; + + // OPEN: Settings > System > Input & Gesture > Double tap power button gesture + SETTINGS_GESTURE_DOUBLE_TAP_POWER = 752; + + // OPEN: Settings > System > Input & Gesture > Pick up gesture + SETTINGS_GESTURE_PICKUP = 753; + + // OPEN: Settings > System > Input & Gesture > Double tap screen gesture + SETTINGS_GESTURE_DOUBLE_TAP_SCREEN = 754; + + // OPEN: Settings > System > Input & Gesture > Double twist gesture + SETTINGS_GESTURE_DOUBLE_TWIST = 755; + + // OPEN: Settings > Apps > Default Apps > Default browser + DEFAULT_BROWSER_PICKER = 785; + // OPEN: Settings > Apps > Default Apps > Default emergency app + DEFAULT_EMERGENCY_APP_PICKER = 786; + + // OPEN: Settings > Apps > Default Apps > Default home + DEFAULT_HOME_PICKER = 787; + + // OPEN: Settings > Apps > Default Apps > Default phone + DEFAULT_PHONE_PICKER = 788; + + // OPEN: Settings > Apps > Default Apps > Default sms + DEFAULT_SMS_PICKER = 789; + + // OPEN: Settings > Apps > Default Apps > Warning dialog to confirm selection + DEFAULT_APP_PICKER_CONFIRMATION_DIALOG = 791; + + // OPEN: Settings > Apps > Default Apps > Default autofill app + DEFAULT_AUTOFILL_PICKER = 792; + + // OPEN: Settings > Apps > Gear > Special Access > Install other apps + // CATEGORY: SETTINGS + // OS: 8.0 + MANAGE_EXTERNAL_SOURCES = 808; + + // Logs that the user has edited the picture-in-picture settings. + // CATEGORY: SETTINGS + SETTINGS_MANAGE_PICTURE_IN_PICTURE = 812; + + // OPEN: SUW Welcome Screen -> Vision Settings -> Select to Speak + // ACTION: Select to Speak configuration is chosen + // SUBTYPE: 0 is off, 1 is on + // CATEGORY: SETTINGS + // OS: N + SUW_ACCESSIBILITY_TOGGLE_SELECT_TO_SPEAK = 817; + + // OPEN: Settings > System > Backup + // CATEGORY: SETTINGS + // OS: O + BACKUP_SETTINGS = 818; + + // OPEN: Settings > Storage > Games + // CATEGORY: SETTINGS + // OS: O + APPLICATIONS_STORAGE_GAMES = 838; + + // OPEN: Settings > Storage > Audio and Music + // CATEGORY: SETTINGS + // OS: O + APPLICATIONS_STORAGE_MUSIC = 839; + + // ACTION: Settings > Storage > Free Up Space to launch Deletion Helper + // CATEGORY: SETTINGS + // OS: O + STORAGE_FREE_UP_SPACE_NOW = 840; + + // ACTION: Settings > Storage > Files to open the File Manager + // CATEGORY: SETTINGS + // OS: O + STORAGE_FILES = 841; + + // OPEN: Settings > Apps > Default Apps > Assist > Default assist + DEFAULT_ASSIST_PICKER = 843; + + // OPEN: Settings > Apps > Default Apps > Assist > Default voice input + DEFAULT_VOICE_INPUT_PICKER = 844; + + // OPEN: Settings > Storage > [Profile] + SETTINGS_STORAGE_PROFILE = 845; + + // OPEN: Settings > Security & screen lock -> Encryption & crendentials + // CATEGORY: SETTINGS + // OS: O + ENCRYPTION_AND_CREDENTIAL = 846; + + // OPEN: Settings > Wi-Fi > Network Details (click on Access Point) + // CATEGORY: SETTINGS + // OS: O + WIFI_NETWORK_DETAILS = 849; + + // OPEN: Settings > Wi-Fi > Wifi Preferences -> Advanced -> Network Scorer + // CATEGORY: SETTINGS + // OS: O + SETTINGS_NETWORK_SCORER = 861; + + // OPEN: Settings > About device > Model > Hardware info dialog + DIALOG_SETTINGS_HARDWARE_INFO = 862; + + // OPEN: Settings > Security & screen lock -> Lock screen preferences + // CATEGORY: SETTINGS + SETTINGS_LOCK_SCREEN_PREFERENCES = 882; + + + // OPEN: Settings -> Display -> When in VR Mode + VR_DISPLAY_PREFERENCE = 921; + + // OPEN: Settings > Accessibility > Magnification + // CATEGORY: SETTINGS + // OS: O + ACCESSIBILITY_SCREEN_MAGNIFICATION_SETTINGS = 922; + + // OPEN: Settings -> System -> Reset options + RESET_DASHBOARD = 924; + + // OPEN: Settings > Security > Nexus Imprint > [Fingerprint] > Delete + // CATEGORY: SETTINGS + // OS: O + FINGERPRINT_REMOVE_SIDECAR = 934; + + // OPEN: Settings > Storage > Movies & TV + // CATEGORY: SETTINGS + // OS: O + APPLICATIONS_STORAGE_MOVIES = 935; + + // OPEN: Settings > Security > Managed Device Info > Apps installed + // CATEGORY: SETTINGS + // OS: O + ENTERPRISE_PRIVACY_INSTALLED_APPS = 938; + + // OPEN: Settings > Security > Managed Device Info > nnn permissions + // CATEGORY: SETTINGS + // OS: O + ENTERPRISE_PRIVACY_PERMISSIONS = 939; + + + // OPEN: Settings > Security > Managed Device Info > Default apps + // CATEGORY: SETTINGS + // OS: O + ENTERPRISE_PRIVACY_DEFAULT_APPS = 940; + + // OPEN: Choose screen lock dialog in Settings + // CATEGORY: SETTINGS + // OS: O DR + SETTINGS_CHOOSE_LOCK_DIALOG = 990; + + // OPEN: Settings > System > Languages & input > Assist gesture + // CATEGORY: SETTINGS + // OS: O DR + SETTINGS_ASSIST_GESTURE = 996; + // OPEN: Settings > Connected Devices > Bluetooth > (click on details link for a paired device) BLUETOOTH_DEVICE_DETAILS = 1009; + // OPEN: Settings > credential pages - prompt for key guard configuration confirmation + CONFIGURE_KEYGUARD_DIALOG = 1010; + + // OPEN: Settings > Network > Tether > Wi-Fi hotspot + WIFI_TETHER_SETTINGS = 1014; + + // OPEN: Settings->Connected Devices->Bluetooth->(click on details link for a paired device) + // -> Edit name button. + // CATEGORY: SETTINGS + // OS: O DR + DIALOG_BLUETOOTH_PAIRED_DEVICE_RENAME = 1015; + // OPEN: Settings > Connected devices > Bluetooth > Pair new device + // CATEGORY: SETTINGS + // OS: O DR BLUETOOTH_PAIRING = 1018; + // OPEN: Settings->Connected Devices->Bluetooth->(click on details link for a paired device) + // -> Forget button. + // CATEGORY: SETTINGS + // OS: O DR + DIALOG_BLUETOOTH_PAIRED_DEVICE_FORGET = 1031; + + // OPEN: Settings > Storage > Photos & Videos + // CATEGORY: SETTINGS + // OS: O MR + APPLICATIONS_STORAGE_PHOTOS = 1092; + + // OPEN: Settings > Display > Colors + // CATEGORY: SETTINGS + // OS: O MR + COLOR_MODE_SETTINGS = 1143; + + // OPEN: Settings > Developer Options > Experiment dashboard + // CATEGORY: SETTINGS + SETTINGS_FEATURE_FLAGS_DASHBOARD = 1217; + + // OPEN: Settings > Notifications > [App] > Topic Notifications + // CATEGORY: SETTINGS + // OS: P + NOTIFICATION_CHANNEL_GROUP = 1218; + + // OPEN: Settings > Developer options > Enable > Info dialog + // CATEGORY: SETTINGS + // OS: P + DIALOG_ENABLE_DEVELOPMENT_OPTIONS = 1219; + + // OPEN: Settings > Developer options > OEM unlocking > Info dialog + // CATEGORY: SETTINGS + // OS: P + DIALOG_ENABLE_OEM_UNLOCKING = 1220; + + // OPEN: Settings > Developer options > USB debugging > Info dialog + // CATEGORY: SETTINGS + // OS: P + DIALOG_ENABLE_ADB = 1222; + + // OPEN: Settings > Security > Nexus Imprint > [Fingerprint] + // CATEGORY: SETTINGS + // OS: P + FINGERPRINT_AUTHENTICATE_SIDECAR = 1221; + + // OPEN: Settings > Developer options > Revoke USB debugging authorizations > Info dialog + // CATEGORY: SETTINGS + // OS: P + DIALOG_CLEAR_ADB_KEYS = 1223; + + // Open: Settings > Developer options > Quick setting tile config + // CATEGORY: SETTINGS + // OS: P + DEVELOPMENT_QS_TILE_CONFIG = 1224; + + // OPEN: Settings > Developer options > Store logger data persistently on device > Info dialog + // CATEGORY: SETTINGS + // OS: P + DIALOG_LOG_PERSIST = 1225; + + // OPEN: Settings > Network & Internet > Mobile network > Wi-Fi calling + // CATEGORY: SETTINGS + // OS: P + WIFI_CALLING_FOR_SUB = 1230; + + // Open: Settings > Dev options > Oem unlock > lock it > warning dialog. + // OS: P + DIALOG_OEM_LOCK_INFO = 1238; + + // Open: Settings > System > About phone > IMEI + // CATEGORY: SETTINGS + // OS: P + DIALOG_IMEI_INFO = 1240; + + // OPEN: Settings > System > About Phone > Sim status + // CATEGORY: SETTINGS + // OS: P + DIALOG_SIM_STATUS = 1246; + + // OPEN: Settings > System > About Phone > Android Version + // CATEGORY: SETTINGS + // OS: P + DIALOG_FIRMWARE_VERSION = 1247; + + // OPEN: Settings > Battery(version 2) + // CATEGORY: SETTINGS + // OS: P + FUELGAUGE_POWER_USAGE_SUMMARY_V2 = 1263; + + // OPEN: Settings > Connected devices > Connection preferences + // CATEGORY: SETTINGS + // OS: P + CONNECTION_DEVICE_ADVANCED = 1264; + + // OPEN: Settings > Security > Screen lock gear icon + // CATEGORY: SETTINGS + // OS: P + SCREEN_LOCK_SETTINGS = 1265; + + // OPEN: Settings > Sound > Do Not Disturb > Turn on automatically > Delete rule (trash can icon) + // CATEGORY: SETTINGS + // OS: P + NOTIFICATION_ZEN_MODE_DELETE_RULE_DIALOG = 1266; + + // OPEN: Settings > Sound > Do Not Disturb > Turn on automatically > Add rule > Event/Time + // OPEN: Settings > Sound > Do Not Disturb > Turn on automatically > Select rule ("Event") > Rule name + // CATEGORY: SETTINGS + // OS: P + NOTIFICATION_ZEN_MODE_RULE_NAME_DIALOG = 1269; + + // OPEN: Settings > Sound > Do Not Disturb > Turn on automatically > Add rule + // CATEGORY: SETTINGS + // OS: P + NOTIFICATION_ZEN_MODE_RULE_SELECTION_DIALOG = 1270; + + // OPEN: Settings > Battery > Smart Battery + // CATEGORY: SETTINGS + // OS: P + FUELGAUGE_SMART_BATTERY = 1281; + + // OPEN: Settings > Battery > Smart Battery > Restricted apps + // CATEGORY: SETTINGS + // OS: P + FUELGAUGE_RESTRICTED_APP_DETAILS = 1285; + + // OPEN: Settings > Sound & notification > Do Not Disturb > Turn on now + // CATEGORY: SETTINGS + // OS: P + NOTIFICATION_ZEN_MODE_ENABLE_DIALOG = 1286; + + // OPEN: Settings->Connected Devices->USB->(click on details link) + // CATEGORY: SETTINGS + // OS: P + USB_DEVICE_DETAILS = 1291; + + // OPEN: Settings > Accessibility > Vibration + // CATEGORY: SETTINGS + // OS: P + ACCESSIBILITY_VIBRATION = 1292; + + // OPEN: Settings > Accessibility > Vibration > Notification vibration + // CATEGORY: SETTINGS + // OS: P + ACCESSIBILITY_VIBRATION_NOTIFICATION = 1293; + + // OPEN: Settings > Accessibility > Vibration > Touch vibration + // CATEGORY: SETTINGS + // OS: P + ACCESSIBILITY_VIBRATION_TOUCH = 1294; + + // OPEN: Settings->Developer Options->Default USB + // CATEGORY: SETTINGS + // OS: P + USB_DEFAULT = 1312; + + // OPEN: Settings > Battery > Battery tip > Battery tip Dialog + // CATEGORY: SETTINGS + // OS: P + FUELGAUGE_BATTERY_TIP_DIALOG = 1323; + + // OPEN: DND Settings > What to block + // OS: P + ZEN_WHAT_TO_BLOCK = 1339; + + // OPEN: Settings > Sounds > Do Not Disturb > Duration + // CATEGORY: SETTINGS + // OS: P + NOTIFICATION_ZEN_MODE_DURATION_DIALOG = 1341; + + // OPEN: Settings > Date & time > Select time zone -> Region + // CATEGORY: SETTINGS + // OS: P + SETTINGS_ZONE_PICKER_REGION = 1355; + + // OPEN: Settings > Date & time > Select time zone -> Time Zone + // CATEGORY: SETTINGS + // OS: P + SETTINGS_ZONE_PICKER_TIME_ZONE = 1356; + // OPEN: Settings > Date & time > Select time zone -> Select UTC Offset + // CATEGORY: SETTINGS + // OS: P + SETTINGS_ZONE_PICKER_FIXED_OFFSET = 1357; + + // OPEN: Settings > Gestures > Prevent Ringing + // OS: P + SETTINGS_PREVENT_RINGING = 1360; + + // Settings > Condition > Device muted + // CATEGORY: SETTINGS + // OS: P + SETTINGS_CONDITION_DEVICE_MUTED = 1368; + + // Settings > Condition > Device vibrate + // CATEGORY: SETTINGS + // OS: P + SETTINGS_CONDITION_DEVICE_VIBRATE = 1369; + + // OPEN: Settings > Connected devices > previously connected devices + // CATEGORY: SETTINGS + // OS: P + PREVIOUSLY_CONNECTED_DEVICES = 1370; + + // OPEN: Settings > Network & Internet > Wi-Fi > Wi-Fi Preferences > Turn on Wi-Fi automatically + // note: Wifi Scanning must be off for this dialog to show + // CATEGORY: SETTINGS + // OS: P + WIFI_SCANNING_NEEDED_DIALOG = 1373; + + // OPEN: Settings > System > Gestures > Swipe up gesture + // CATEGORY: SETTINGS + // OS: P + SETTINGS_GESTURE_SWIPE_UP = 1374; + + // OPEN: Settings > Storage > Dialog to format a storage volume + // CATEGORY: SETTINGS + // OS: P + DIALOG_VOLUME_FORMAT = 1375; + + // OPEN: DND onboarding activity + // CATEGORY: SETTINGS + // OS: P + SETTINGS_ZEN_ONBOARDING = 1380; + + // OPEN: Settings > Display > Auto brightness + // CATEGORY: SETTINGS + // OS: P + SETTINGS_AUTO_BRIGHTNESS = 1381; + + // OPEN: Settings > Connected Devices > Bluetooth + // CATEGORY: SETTINGS + // OS: P + BLUETOOTH_FRAGMENT = 1390; + + // Screen: DND Settings > Notifications + // OS: P + SETTINGS_ZEN_NOTIFICATIONS = 1400; + + // An event category for slices. + // OPEN: Slice became visible. + // CLOSE: Slice became invisible. + // ACTION: Slice was tapped. + SLICE = 1401; + + // OPEN: Settings -> Developer Options -> Disable Bluetooth A2DP hardware + // offload + // CATEGORY: SETTINGS + // OS: P + DIALOG_BLUETOOTH_DISABLE_A2DP_HW_OFFLOAD = 1441; + // OPEN: Settings homepage SETTINGS_HOMEPAGE = 1502; + // OPEN: Settings > Create shortcut(widget) + // CATEGORY: SETTINGS + // OS: Q + SETTINGS_CREATE_SHORTCUT = 1503; + + // OPEN: Face Enroll introduction + // CATEGORY: SETTINGS + // OS: Q + FACE_ENROLL_INTRO = 1506; + + // OPEN: Face Enroll introduction + // CATEGORY: SETTINGS + // OS: Q + FACE_ENROLL_ENROLLING = 1507; + + // OPEN: Face Enroll introduction + // CATEGORY: SETTINGS + // OS: Q + FACE_ENROLL_FINISHED = 1508; + + // OPEN: Face Enroll sidecar + // CATEGORY: SETTINGS + // OS: Q + FACE_ENROLL_SIDECAR = 1509; + + // OPEN: Settings > Add face > Error dialog + // OS: Q + DIALOG_FACE_ERROR = 1510; + + // OPEN: Settings > Security > Face + // CATEGORY: SETTINGS + // OS: Q + FACE = 1511; + + // OPEN: Settings > Acessibility > HearingAid pairing instructions dialog + // CATEGORY: SETTINGS + // OS: Q + DIALOG_ACCESSIBILITY_HEARINGAID = 1512; + + // OPEN: Settings > Add face + // OS: Q + FACE_ENROLL_PREVIEW = 1554; + + // OPEN: Settings > Network & Internet > Wi-Fi > Add network + // CATEGORY: SETTINGS + // OS: Q + SETTINGS_WIFI_ADD_NETWORK = 1556; + + // OPEN: Settings > System > Input & Gesture > Reach up gesture + // OS: Q + SETTINGS_GESTURE_WAKE_LOCK_SCREEN = 1557; + // OPEN: Settings > System > Input & Gesture > Wake screen SETTINGS_GESTURE_WAKE_SCREEN = 1570; @@ -80,6 +2079,19 @@ enum PageId { // OPEN: Settings > Privacy TOP_LEVEL_PRIVACY = 1587; + // OPEN: Settings > Sound & notification > Do Not Disturb > See all exceptions > + // Allow apps to override + // CATEGORY: SETTINGS + // OS: Q + NOTIFICATION_ZEN_MODE_OVERRIDING_APPS = 1588; + + + // OPEN: Settings > Sound & notification > Do Not Disturb > See all exceptions > + // Allow apps to override > Choose app + // CATEGORY: SETTINGS + // OS: Q + NOTIFICATION_ZEN_MODE_OVERRIDING_APP = 1589; + // OPEN: Settings > Developer options > Disable > Info dialog DIALOG_DISABLE_DEVELOPMENT_OPTIONS = 1591; @@ -92,9 +2104,79 @@ enum PageId { // OPEN: Settings > Apps & Notifications -> Special app access -> Financial Apps Sms Access SETTINGS_FINANCIAL_APPS_SMS_ACCESS = 1597; + + + // OPEN: Settings > Sound > Do Not Disturb > Schedules > (Click on system rule) + // > Do Not Disturb behavior + // CATEGORY: SETTINGS + // OS: Q + ZEN_CUSTOM_RULE_SETTINGS = 1604; + + // OPEN: Settings > Sound > Do Not Disturb > Schedules > (Click on system rule) + // > Do Not Disturb behavior > Custom + // CATEGORY: SETTINGS + // OS: Q + ZEN_CUSTOM_RULE_SOUND_SETTINGS = 1605; + + // OPEN: Settings > Sound > Do Not Disturb > Schedules > (Click on system rule) + // > Do Not Disturb behavior > Use default Do Not Disturb behavior + // CATEGORY: SETTINGS + // OS: Q + ZEN_CUSTOM_RULE_DEFAULT_SETTINGS = 1606; + + // OPEN: Settings > Sound > Do Not Disturb > Schedules > (Click on system rule) + // > Do Not Disturb behavior > Use default Do Not Disturb behavior + // > Notification restriction + // CATEGORY: SETTINGS + // OS: Q + ZEN_CUSTOM_RULE_NOTIFICATION_RESTRICTIONS = 1608; + + // OPEN: Settings > Sound > Do Not Disturb > Schedules > (Click on system rule) + // > Do Not Disturb behavior > Use default Do Not Disturb behavior + // > Notification restriction > Custom + // CATEGORY: SETTINGS + // OS: Q + ZEN_CUSTOM_RULE_VIS_EFFECTS = 1609; + + // OPEN: Settings > Sound > Do Not Disturb > Schedules > (Click on system rule) + // > Do Not Disturb behavior > Use default Do Not Disturb behavior + // > Notification restriction > Custom > Allow messages + // CATEGORY: SETTINGS + // OS: Q + ZEN_CUSTOM_RULE_MESSAGES = 1610; + + // OPEN: Settings > Sound > Do Not Disturb > Schedules > (Click on system rule) + // > Do Not Disturb behavior > Use default Do Not Disturb behavior + // > Notification restriction > Custom > Allow calls + // CATEGORY: SETTINGS + // OS: Q + ZEN_CUSTOM_RULE_CALLS = 1611; + + // OPEN: Settings > Sound > Do Not Disturb > Click footer link if custom settings applied + // CATEGORY: SETTINGS + // OS: Q + ZEN_CUSTOM_SETTINGS_DIALOG = 1612; + + // OPEN: Settings > Developer Options > Game Update Packages + // CATEGORY: SETTINGS + // OS: Q + SETTINGS_GUP_DASHBOARD = 1613; + + // OPEN: Settings > Accessibility > Vibration > Ring vibration + // CATEGORY: SETTINGS + // OS: Q + ACCESSIBILITY_VIBRATION_RING = 1620; + // OPEN: Settings > System > Input & Gesture > Skip songs SETTINGS_GESTURE_SKIP = 1624; // OPEN: Settings > System > Input & Gesture > Silence alerts SETTINGS_GESTURE_SILENCE = 1625; + + // OPEN: Settings > System > Input & Gesture > Tap to check + SETTINGS_GESTURE_TAP_SCREEN = 1626; + + // OPEN: Settings > Network & internet > Click Mobile network to land on a page with a list of + // SIM/eSIM subscriptions. + MOBILE_NETWORK_LIST = 1627; } diff --git a/core/proto/android/bluetooth/hfp/enums.proto b/core/proto/android/bluetooth/hfp/enums.proto new file mode 100644 index 000000000000..d286e4b64d67 --- /dev/null +++ b/core/proto/android/bluetooth/hfp/enums.proto @@ -0,0 +1,28 @@ +/* + * Copyright 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +syntax = "proto2"; +package android.bluetooth.hfp; + +option java_outer_classname = "BluetoothHfpProtoEnums"; +option java_multiple_files = true; + +enum ScoCodec { + SCO_CODEC_UNKNOWN = 0; + SCO_CODEC_CVSD = 1; + // Default codec behind Wide Band Speech + SCO_CODEC_MSBC = 2; +}
\ No newline at end of file diff --git a/core/proto/android/providers/settings/global.proto b/core/proto/android/providers/settings/global.proto index cc5aa20258ce..415857771899 100644 --- a/core/proto/android/providers/settings/global.proto +++ b/core/proto/android/providers/settings/global.proto @@ -436,12 +436,19 @@ message GlobalSettingsProto { // Ordered GPU debug layer list for GLES // i.e. <layer1>:<layer2>:...:<layerN> optional SettingProto debug_layers_gles = 7; - // GUP - List of Apps selected to use Game Update Packages - optional SettingProto gup_dev_opt_in_apps = 8; - // GUP - List of Apps selected not to use Game Update Packages - optional SettingProto gup_dev_opt_out_apps = 9; - // GUP - List of Apps that are forbidden to use Game Update Packages - optional SettingProto gup_black_list = 10; + // GUP - Game Update Package global preference for all Apps + // 0 = Default + // 1 = All Apps use Game Update Package + // 2 = All Apps use system graphics driver + optional SettingProto gup_dev_all_apps = 8; + // GUP - List of Apps selected to use Game Update Package + // i.e. <pkg1>,<pkg2>,...,<pkgN> + optional SettingProto gup_dev_opt_in_apps = 9; + // GUP - List of Apps selected not to use Game Update Package + // i.e. <pkg1>,<pkg2>,...,<pkgN> + optional SettingProto gup_dev_opt_out_apps = 10; + // GUP - List of Apps that are forbidden to use Game Update Package + optional SettingProto gup_blacklist = 11; } optional Gpu gpu = 59; diff --git a/core/proto/android/providers/settings/secure.proto b/core/proto/android/providers/settings/secure.proto index 9f4345d4668f..4bfd4d236abb 100644 --- a/core/proto/android/providers/settings/secure.proto +++ b/core/proto/android/providers/settings/secure.proto @@ -182,6 +182,7 @@ message SecureSettingsProto { optional SettingProto pulse_on_pick_up = 3 [ (android.privacy).dest = DEST_AUTOMATIC ]; optional SettingProto pulse_on_long_press = 4 [ (android.privacy).dest = DEST_AUTOMATIC ]; optional SettingProto pulse_on_double_tap = 5 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto pulse_on_tap = 6 [ (android.privacy).dest = DEST_AUTOMATIC ]; } optional Doze doze = 21; diff --git a/core/proto/android/server/location/enums.proto b/core/proto/android/server/location/enums.proto index b6dc58932ce7..943ff181fe14 100644 --- a/core/proto/android/server/location/enums.proto +++ b/core/proto/android/server/location/enums.proto @@ -28,3 +28,105 @@ enum GpsSignalQualityEnum { GPS_SIGNAL_QUALITY_POOR = 0; GPS_SIGNAL_QUALITY_GOOD = 1; } + +// A type which distinguishes different categories of NI request, such as VOICE, UMTS_SUPL etc. +enum GnssNiType { + VOICE = 1; + UMTS_SUPL = 2; + UMTS_CTRL_PLANE = 3; + EMERGENCY_SUPL = 4; +}; + +// GNSS NI responses, used to define the response in NI structures. +enum GnssUserResponseType { + RESPONSE_ACCEPT = 1; + RESPONSE_DENY = 2; + RESPONSE_NORESP = 3; +}; + +// GNSS NI data encoding scheme. +enum GnssNiEncodingType { + ENC_NONE = 0; + ENC_SUPL_GSM_DEFAULT = 1; + ENC_SUPL_UTF8 = 2; + ENC_SUPL_UCS2 = 3; + ENC_UNKNOWN = -1; +}; + +// Protocol stack that initiated the non-framework location request. +enum NfwProtocolStack { + // Cellular control plane requests. + CTRL_PLANE = 0; + // All types of SUPL requests. + SUPL = 1; + // All types of requests from IMS. + IMS = 10; + // All types of requests from SIM. + SIM = 11; + // Requests from other protocol stacks. + OTHER_PROTOCOL_STACK = 100; +}; + +// Source initiating/receiving the location information. +enum NfwRequestor { + // Wireless service provider. + CARRIER = 0; + // Device manufacturer. + OEM = 10; + // Modem chipset vendor. + MODEM_CHIPSET_VENDOR = 11; + // GNSS chipset vendor. + GNSS_CHIPSET_VENDOR = 12; + // Other chipset vendor. + OTHER_CHIPSET_VENDOR = 13; + // Automobile client. + AUTOMOBILE_CLIENT = 20; + // Other sources. + OTHER_REQUESTOR = 100; +}; + +// Indicates whether location information was provided for this request. +enum NfwResponseType { + // Request rejected because framework has not given permission for this use case. + REJECTED = 0; + // Request accepted but could not provide location because of a failure. + ACCEPTED_NO_LOCATION_PROVIDED = 1; + // Request accepted and location provided. + ACCEPTED_LOCATION_PROVIDED = 2; +}; + +// The SUPL mode. +enum SuplMode { + // Mobile Station Based. + MSB = 0x01; + // Mobile Station Assisted. + MSA = 0x02; +}; + +// Enum that hold the bit masks for various LTE Positioning Profile settings (LPP_PROFILE +// configuration parameter). If none of the bits in the enum are set, the default setting is +// Radio Resource Location Protocol(RRLP). +enum LppProfile { + // Enable LTE Positioning Protocol user plane. + USER_PLANE = 0x01; + // Enable LTE Positioning Protocol Control plane. + CONTROL_PLANE = 0x02; +}; + +// Positioning protocol on A-Glonass system. +enum GlonassPosProtocol { + // Radio Resource Control(RRC) control-plane. + RRC_CPLANE = 0x01; + // Radio Resource Location user-plane. + RRLP_CPLANE = 0x02; + // LTE Positioning Protocol User plane. + LPP_UPLANE = 0x04; +}; + +// Configurations of how GPS functionalities should be locked when user turns off GPS On setting. +enum GpsLock { + // Lock Mobile Originated GPS functionalitues. + MO = 0x01; + // Lock Network Initiated GPS functionalities. + NI = 0x02; +}; diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml index 7813128d46c7..ea0c8e250fe2 100644 --- a/core/res/AndroidManifest.xml +++ b/core/res/AndroidManifest.xml @@ -1186,6 +1186,7 @@ <!-- Used for permissions that are associated with activity recognition. TODO(zezeozue). STOPSHIP: Add icon --> <permission-group android:name="android.permission-group.ACTIVITY_RECOGNITION" + android:icon="@drawable/perm_group_activity_recognition" android:label="@string/permgrouplab_activityRecognition" android:description="@string/permgroupdesc_activityRecognition" android:request="@string/permgrouprequest_activityRecognition" @@ -2209,8 +2210,9 @@ <permission android:name="android.permission.INTERACT_ACROSS_USERS_FULL" android:protectionLevel="signature|installer" /> - <!-- @SystemApi Allows an application to start an activity within its managed profile from - the personal profile. + <!-- @SystemApi Allows an application to start its own activities, but on a different profile + associated with the user. For example, an application running on the main profile of a user + can start an activity on a managed profile of that user. This permission is not available to third party applications. @hide --> <permission android:name="android.permission.INTERACT_ACROSS_PROFILES" @@ -2532,6 +2534,16 @@ <permission android:name="android.permission.WRITE_GSERVICES" android:protectionLevel="signature|privileged" /> + <!-- @SystemApi @hide Allows an application to modify config settings. + <p>Not for use by third-party applications. --> + <permission android:name="android.permission.WRITE_DEVICE_CONFIG" + android:protectionLevel="signature|configurator"/> + + <!-- @SystemApi @hide Allows an application to read config settings. + <p>Not for use by third-party applications. --> + <permission android:name="android.permission.READ_DEVICE_CONFIG" + android:protectionLevel="signature|preinstalled" /> + <!-- @SystemApi @TestApi Allows an application to call {@link android.app.ActivityManager#forceStopPackage}. @hide --> @@ -3045,6 +3057,15 @@ <permission android:name="android.permission.BIND_TEXT_SERVICE" android:protectionLevel="signature" /> + <!-- @SystemApi Must be required by a AttentionService + to ensure that only the system can bind to it. + <p>Protection level: signature + @hide + --> + <permission android:name="android.permission.BIND_ATTENTION_SERVICE" + android:protectionLevel="signature" /> + <uses-permission android:name="android.permission.BIND_ATTENTION_SERVICE" /> + <!-- Must be required by a {@link android.net.VpnService}, to ensure that only the system can bind to it. <p>Protection level: signature @@ -4744,6 +4765,11 @@ android:permission="android.permission.BIND_JOB_SERVICE" > </service> + <service android:name="com.android.server.ZramWriteback" + android:exported="false" + android:permission="android.permission.BIND_JOB_SERVICE" > + </service> + <service android:name="com.android.server.backup.FullBackupJob" android:exported="true" android:permission="android.permission.BIND_JOB_SERVICE" > diff --git a/core/res/res/drawable/perm_group_activity_recognition.xml b/core/res/res/drawable/perm_group_activity_recognition.xml new file mode 100644 index 000000000000..0ade6c674171 --- /dev/null +++ b/core/res/res/drawable/perm_group_activity_recognition.xml @@ -0,0 +1,29 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + Copyright (C) 2019 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + + <path + android:fillColor="#000000" + android:pathData="M13.49 5.48c1.1 0 2-.9 2-2s-.9-2-2-2-2 .9-2 2 .9 2 2 2zm-3.6 13.9l1-4.4 2.1 +2v6h2v-7.5l-2.1-2 .6-3c1.3 1.5 3.3 2.5 5.5 2.5v-2c-1.9 +0-3.5-1-4.3-2.4l-1-1.6c-.4-.6-1-1-1.7-1-.3 0-.5 .1 -.8 .1 l-5.2 +2.2v4.7h2v-3.4l1.8-.7-1.6 8.1-4.9-1-.4 2 7 1.4z" /> +</vector> diff --git a/core/res/res/drawable/perm_group_sensors.xml b/core/res/res/drawable/perm_group_sensors.xml index ce36c13e1690..e4663d7206fc 100644 --- a/core/res/res/drawable/perm_group_sensors.xml +++ b/core/res/res/drawable/perm_group_sensors.xml @@ -19,11 +19,11 @@ android:height="24dp" android:viewportWidth="24" android:viewportHeight="24"> - - <path - android:fillColor="#000000" - android:pathData="M13.49 5.48c1.1 0 2-.9 2-2s-.9-2-2-2-2 .9-2 2 .9 2 2 2zm-3.6 13.9l1-4.4 2.1 -2v6h2v-7.5l-2.1-2 .6-3c1.3 1.5 3.3 2.5 5.5 2.5v-2c-1.9 -0-3.5-1-4.3-2.4l-1-1.6c-.4-.6-1-1-1.7-1-.3 0-.5 .1 -.8 .1 l-5.2 -2.2v4.7h2v-3.4l1.8-.7-1.6 8.1-4.9-1-.4 2 7 1.4z" /> -</vector>
\ No newline at end of file + <path + android:fillColor="#000000" + android:pathData="M16.5,3c-1.74,0 -3.41,0.81 -4.5,2.09C10.91,3.81 9.24,3 7.5,3C4.42,3 2,5.42 2, + 8.5c0,3.78 3.4,6.86 8.55,11.54L12,21.35l1.45,-1.32C18.6,15.36 22,12.28 22,8.5C22, + 5.42 19.58,3 16.5,3zM12.1,18.55l-0.1,0.1l-0.1,-0.1C7.14,14.24 4,11.39 4,8.5C4,6.5 5.5, + 5 7.5,5c1.54,0 3.04,0.99 3.57,2.36h1.87C13.46,5.99 14.96,5 16.5,5c2,0 3.5,1.5 3.5,3.5C20, + 11.39 16.86,14.24 12.1,18.55z"/> +</vector> diff --git a/core/res/res/layout/notification_template_material_ambient.xml b/core/res/res/layout/notification_template_material_ambient.xml deleted file mode 100644 index 2c6064ea6243..000000000000 --- a/core/res/res/layout/notification_template_material_ambient.xml +++ /dev/null @@ -1,94 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- - ~ Copyright (C) 2017 The Android Open Source Project - ~ - ~ Licensed under the Apache License, Version 2.0 (the "License"); - ~ you may not use this file except in compliance with the License. - ~ You may obtain a copy of the License at - ~ - ~ http://www.apache.org/licenses/LICENSE-2.0 - ~ - ~ Unless required by applicable law or agreed to in writing, software - ~ distributed under the License is distributed on an "AS IS" BASIS, - ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - ~ See the License for the specific language governing permissions and - ~ limitations under the License. - --> - -<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" - android:id="@+id/status_bar_latest_event_content" - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:tag="ambient" - android:paddingStart="@dimen/notification_extra_margin_ambient" - android:paddingEnd="@dimen/notification_extra_margin_ambient" - > - <include layout="@layout/notification_template_ambient_header" - android:theme="@style/Theme.DeviceDefault.Notification.Ambient" /> - - <LinearLayout - android:id="@+id/notification_action_list_margin_target" - android:layout_width="match_parent" - android:layout_height="match_parent" - android:layout_gravity="top" - android:layout_marginTop="@dimen/notification_content_margin_top" - android:layout_marginBottom="@dimen/notification_action_list_height" - android:paddingTop="4dp" - android:paddingBottom="6dp" - android:clipToPadding="false" - android:orientation="vertical"> - - <LinearLayout - android:id="@+id/notification_main_column" - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:layout_gravity="top" - android:layout_weight="1" - android:paddingStart="@dimen/notification_content_margin_start" - android:paddingEnd="@dimen/notification_content_margin_end" - android:clipToPadding="false" - android:minHeight="@dimen/notification_min_content_height" - android:orientation="vertical" - > - <TextView android:id="@+id/title" - android:textAppearance="@style/TextAppearance.DeviceDefault.Notification.Title" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:gravity="top|center_horizontal" - android:singleLine="true" - android:ellipsize="marquee" - android:fadingEdge="horizontal" - android:textSize="@dimen/notification_ambient_title_text_size" - android:textColor="#ffffffff" - /> - <TextView android:id="@+id/text" - android:layout_width="match_parent" - android:layout_height="0dp" - android:textAppearance="@style/TextAppearance.DeviceDefault.Notification" - android:singleLine="false" - android:layout_weight="1" - android:gravity="top|center_horizontal" - android:visibility="gone" - android:textSize="@dimen/notification_ambient_text_size" - android:textColor="#eeffffff" - android:layout_marginTop="4dp" - android:ellipsize="end" - android:maxLines="3" - /> - </LinearLayout> - <FrameLayout android:id="@+id/actions_container" - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:layout_gravity="bottom"> - <com.android.internal.widget.NotificationActionListLayout - android:id="@+id/actions" - android:layout_width="match_parent" - android:layout_height="@dimen/notification_action_list_height" - android:paddingEnd="4dp" - android:orientation="horizontal" - android:gravity="center" - android:visibility="gone" - /> - </FrameLayout> - </LinearLayout> -</FrameLayout> diff --git a/core/res/res/values/attrs_manifest.xml b/core/res/res/values/attrs_manifest.xml index 18a42bc5ed0b..8ef264a84efb 100644 --- a/core/res/res/values/attrs_manifest.xml +++ b/core/res/res/values/attrs_manifest.xml @@ -274,6 +274,9 @@ <!-- Additional flag from base permission type: this permission can be automatically granted to the document manager --> <flag name="documenter" value="0x40000" /> + <!-- Additional flag from base permission type: this permission automatically + granted to device configurator --> + <flag name="configurator" value="0x80000" /> </attr> <!-- Flags indicating more context for a permission group. --> @@ -2794,6 +2797,9 @@ <attr name="requiredSystemPropertyName" format="string" /> <!-- @hide This shouldn't be public. --> <attr name="requiredSystemPropertyValue" format="string" /> + + <!-- The name of the overlayable whose resources will be overlaid. --> + <attr name="targetName" /> </declare-styleable> <!-- Declaration of an {@link android.content.Intent} object in XML. May diff --git a/core/res/res/values/colors_device_defaults.xml b/core/res/res/values/colors_device_defaults.xml index ded916fbe7a3..824b4b5977d1 100644 --- a/core/res/res/values/colors_device_defaults.xml +++ b/core/res/res/values/colors_device_defaults.xml @@ -43,6 +43,6 @@ <color name="error_color_device_default_dark">@color/error_color_material_dark</color> <color name="error_color_device_default_light">@color/error_color_material_light</color> - <color name="list_divider_color_light">#64000000</color> + <color name="list_divider_color_light">#ffdadce0</color> <color name="list_divider_color_dark">#85ffffff</color> </resources> diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml index 75f8d6f66826..5995640c7659 100644 --- a/core/res/res/values/config.xml +++ b/core/res/res/values/config.xml @@ -618,15 +618,6 @@ <!-- Integer indicating wpa_supplicant scan interval when p2p is connected in milliseconds --> <integer translatable="false" name="config_wifi_scan_interval_p2p_connected">60000</integer> - <!-- Integer indicating the framework scan interval in milliseconds. This is used in the scenario - where the chipset does not support background scanning (config_wifi_background_scan_suport - is false) to set up a periodic wake up scan so that the device can connect to a new access - point on the move. A value of 0 means no periodic scans will be used in the framework. --> - <integer translatable="false" name="config_wifi_framework_scan_interval">300000</integer> - - <!-- Integer indicating the framework no networks periodic scan interval in milliseconds. --> - <integer translatable="false" name="config_wifi_no_network_periodic_scan_interval">300000</integer> - <!-- Integer indicating disconnect mode short scan interval in milliseconds --> <integer translatable="false" name="config_wifi_disconnected_short_scan_interval">15000</integer> @@ -648,6 +639,9 @@ <!-- Integer indicating RSSI boost given to current network --> <integer translatable="false" name="config_wifi_framework_current_network_boost">16</integer> + <!-- Integer delay in milliseconds before set wlan interface up during watchdog recovery --> + <integer translatable="false" name="config_wifi_framework_recovery_timeout_delay">2000</integer> + <!-- Integer indicating how to handle beacons with uninitialized RSSI value of 0 --> <integer translatable="false" name="config_wifi_framework_scan_result_rssi_level_patchup_value">-85</integer> @@ -692,6 +686,11 @@ <!-- Wifi driver supports Automatic channel selection (ACS) for softap --> <bool translatable="false" name="config_wifi_softap_acs_supported">false</bool> + <!-- Channel list restriction to Automatic channel selection (ACS) for softap. If the device + doesn't want to restrict channels this should be empty. Value is a comma separated channel + string and/or channel range string like '1-6,11' --> + <string translatable="false" name="config_wifi_softap_acs_supported_channel_list"></string> + <!-- Wifi driver supports IEEE80211AC for softap --> <bool translatable="false" name="config_wifi_softap_ieee80211ac_supported">false</bool> @@ -699,6 +698,9 @@ for automotive builds only (the one that have PackageManager#FEATURE_AUTOMOTIVE) --> <bool translatable="false" name="config_wifi_local_only_hotspot_5ghz">false</bool> + <!-- Indicates that connected MAC randomization is supported on this device --> + <bool translatable="false" name="config_wifi_connected_mac_randomization_supported">false</bool> + <!-- Flag indicating whether we should enable the automatic brightness. Software implementation will be used if config_hardware_auto_brightness_available is not set --> <bool name="config_automatic_brightness_available">false</bool> @@ -1741,19 +1743,6 @@ config_enableGeofenceOverlay is false. --> <string name="config_geofenceProviderPackageName" translatable="false">@null</string> - <!-- Whether to enable Hardware Activity-Recognition overlay which allows Hardware - Activity-Recognition to be replaced by an app at run-time. When disabled, only the - config_activityRecognitionHardwarePackageName package will be searched for - its implementation, otherwise packages whose signature matches the - signatures of config_locationProviderPackageNames will be searched, and - the service with the highest version number will be picked. Anyone who - wants to disable the overlay mechanism can set it to false. - --> - <bool name="config_enableActivityRecognitionHardwareOverlay" translatable="false">true</bool> - <!-- Package name providing Hardware Activity-Recognition API support. Used only when - config_enableActivityRecognitionHardwareOverlay is false. --> - <string name="config_activityRecognitionHardwarePackageName" translatable="false">@null</string> - <!-- Package name(s) containing location provider support. These packages can contain services implementing location providers, such as the Geocode Provider, Network Location Provider, and @@ -1892,6 +1881,8 @@ cell broadcasting sms, and MMS. --> <bool name="config_sms_capable">true</bool> + <!-- TODO: STOPSHIP(b/110557011): Remove this from framework and overlays as we use + config_defaultRoleHolders now. --> <!-- Default SMS Application. This will be the default SMS application when the phone first boots. The user can then change the default app to one of their choosing. @@ -1910,6 +1901,12 @@ the behavior will be as though no app was named as an explicit default. --> <string name="default_browser" translatable="false"></string> + <!-- Default role holders. This will be an array of roles and package names of their default + holders, with each item in the format of "ROLE_NAME: PACKAGE_NAME_1, PACKAGE_NAME_2". --> + <string-array name="config_defaultRoleHolders" translatable="false"> + <item>android.app.role.SMS: com.android.messaging</item> + </string-array> + <!-- Enable/disable default bluetooth profiles: HSP_AG, ObexObjectPush, Audio, NAP --> <bool name="config_bluetooth_default_profiles">true</bool> @@ -2205,6 +2202,9 @@ <!-- Type of the double tap sensor. Empty if double tap is not supported. --> <string name="config_dozeDoubleTapSensorType" translatable="false"></string> + <!-- Type of the tap sensor. Empty if tap is not supported. --> + <string name="config_dozeTapSensorType" translatable="false"></string> + <!-- Type of the long press sensor. Empty if long press is not supported. --> <string name="config_dozeLongPressSensorType" translatable="false"></string> @@ -2802,6 +2802,9 @@ <!-- Flag indicating which package name can access the persistent data partition --> <string name="config_persistentDataPackageName" translatable="false"></string> + <!-- Flag indicating which package name can access DeviceConfig table --> + <string name="config_deviceConfiguratorPackageName" translatable="false"></string> + <!-- Flag indicating apps will skip sending hold request before merge. In this case IMS service implementation will do both.i.e.hold followed by merge. --> <bool name="skipHoldBeforeMerge">true</bool> @@ -3436,7 +3439,7 @@ See android.view.textclassifier.TextClassificationManager. --> <string name="config_defaultTextClassifierPackage" translatable="false"></string> - + <!-- The package name for the default wellbeing app. This package must be trusted, as it has the permissions to control other applications on the device. @@ -3444,6 +3447,12 @@ --> <string name="config_defaultWellbeingPackage" translatable="false"></string> + <!-- The component name for the default system attention service. + This service must be trusted, as it can be activated without explicit consent of the user. + See android.attention.AttentionManagerService. + --> + <string name="config_defaultAttentionService" translatable="false"></string> + <!-- The package name for the system's content capture service. This service must be trusted, as it can be activated without explicit consent of the user. If no service with the specified name exists on the device, content capture will be @@ -3716,4 +3725,7 @@ <!-- If the sensor that silences alerts is available or not. --> <bool name="config_silenceSensorAvailable">false</bool> + + <!-- Enable Zram writeback feature to allow unused pages in zram be written to flash. --> + <bool name="config_zramWriteback">false</bool> </resources> diff --git a/core/res/res/values/dimens.xml b/core/res/res/values/dimens.xml index 05a156b69371..c8706838df57 100644 --- a/core/res/res/values/dimens.xml +++ b/core/res/res/values/dimens.xml @@ -194,9 +194,6 @@ <!-- The margin for text at the end of the image view for media notifications --> <dimen name="notification_media_image_margin_end">72dp</dimen> - <!-- The additional margin on the sides of the ambient view. --> - <dimen name="notification_extra_margin_ambient">16dp</dimen> - <!-- The height of the notification action list --> <dimen name="notification_action_list_height">60dp</dimen> @@ -233,9 +230,6 @@ <!-- The bottom padding for the notification header --> <dimen name="notification_header_padding_bottom">16dp</dimen> - <!-- The margin at the top of the notification header when dozing. --> - <dimen name="notification_header_margin_top_ambient">3dp</dimen> - <!-- The margin at the bottom of the notification header. --> <dimen name="notification_header_margin_bottom">0dp</dimen> @@ -400,11 +394,6 @@ <dimen name="notification_title_text_size">14sp</dimen> <!-- Size of smaller notification text (see TextAppearance.StatusBar.EventContent.Line2, Info, Time) --> <dimen name="notification_subtext_size">12sp</dimen> - <!-- Size of notification text (see TextAppearance.StatusBar.EventContent) --> - <dimen name="notification_ambient_text_size">16sp</dimen> - <!-- Size of notification text titles (see TextAppearance.StatusBar.EventContent.Title) --> - <dimen name="notification_ambient_title_text_size">24sp</dimen> - <!-- Top padding for notifications in the standard layout. --> <dimen name="notification_top_pad">10dp</dimen> diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml index b3b30e992302..777886a9911c 100644 --- a/core/res/res/values/public.xml +++ b/core/res/res/values/public.xml @@ -2985,6 +2985,11 @@ <public name="system_notification_accent_color" /> </public-group> + <public-group type="array" first-id="0x01070006"> + <!-- @hide @SystemApi --> + <public name="config_defaultRoleHolders" /> + </public-group> + <!-- =============================================================== DO NOT ADD UN-GROUPED ITEMS HERE diff --git a/core/res/res/values/styles_device_defaults.xml b/core/res/res/values/styles_device_defaults.xml index 200ef2f56f51..79afe697c504 100644 --- a/core/res/res/values/styles_device_defaults.xml +++ b/core/res/res/values/styles_device_defaults.xml @@ -271,9 +271,6 @@ easier. <style name="TextAppearance.DeviceDefault.Notification.Info" parent="TextAppearance.Material.Notification.Info"> <item name="fontFamily">@string/config_bodyFontFamily</item> </style> - <style name="TextAppearance.DeviceDefault.Notification.Info.Ambient" parent="TextAppearance.Material.Notification.Info.Ambient"> - <item name="fontFamily">@string/config_bodyFontFamily</item> - </style> <style name="TextAppearance.DeviceDefault.Widget" parent="TextAppearance.Material.Widget"> <item name="fontFamily">@string/config_bodyFontFamily</item> </style> diff --git a/core/res/res/values/styles_material.xml b/core/res/res/values/styles_material.xml index 5a7199d6f445..63ac0e6bfc3e 100644 --- a/core/res/res/values/styles_material.xml +++ b/core/res/res/values/styles_material.xml @@ -487,10 +487,6 @@ please see styles_device_defaults.xml. <style name="TextAppearance.Material.Notification.Time" parent="TextAppearance.Material.Notification.Info" /> - <style name="TextAppearance.Material.Notification.Info.Ambient"> - <item name="textSize">@dimen/notification_text_size</item> - </style> - <style name="TextAppearance.Material.Notification.Emphasis"> <item name="textColor">#66000000</item> </style> @@ -1308,10 +1304,5 @@ please see styles_device_defaults.xml. <item name="gravity">top</item> </style> - <style name="Notification.Header.Ambient"> - <item name="layout_marginTop">@dimen/notification_header_margin_top_ambient</item> - <item name="gravity">top|center_horizontal</item> - </style> - </resources> diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml index e5c9b84bda3f..53c33a3855dd 100644 --- a/core/res/res/values/symbols.xml +++ b/core/res/res/values/symbols.xml @@ -325,6 +325,7 @@ <java-symbol type="bool" name="config_forceDefaultOrientation" /> <java-symbol type="bool" name="config_wifi_batched_scan_supported" /> <java-symbol type="bool" name="config_wifi_softap_acs_supported" /> + <java-symbol type="string" name="config_wifi_softap_acs_supported_channel_list" /> <java-symbol type="bool" name="config_wifi_softap_ieee80211ac_supported" /> <java-symbol type="bool" name="config_enableMultiUserUI"/> <java-symbol type="bool" name="config_enableNewAutoSelectNetworkUI"/> @@ -421,6 +422,7 @@ <java-symbol type="integer" name="config_wifi_framework_network_switch_tx_packet_threshold" /> <java-symbol type="integer" name="config_wifi_framework_network_switch_rx_packet_threshold" /> <java-symbol type="integer" name="config_wifi_framework_current_network_boost" /> + <java-symbol type="integer" name="config_wifi_framework_recovery_timeout_delay" /> <java-symbol type="integer" name="config_bluetooth_max_advertisers" /> <java-symbol type="integer" name="config_bluetooth_max_scan_filters" /> <java-symbol type="integer" name="config_bluetooth_max_connected_audio_devices" /> @@ -458,9 +460,7 @@ <java-symbol type="integer" name="config_toastDefaultGravity" /> <java-symbol type="integer" name="config_triplePressOnPowerBehavior" /> <java-symbol type="integer" name="config_shortPressOnSleepBehavior" /> - <java-symbol type="integer" name="config_wifi_framework_scan_interval" /> <java-symbol type="integer" name="config_wifi_supplicant_scan_interval" /> - <java-symbol type="integer" name="config_wifi_no_network_periodic_scan_interval" /> <java-symbol type="integer" name="config_wifi_scan_interval_p2p_connected" /> <java-symbol type="integer" name="config_windowOutsetBottom" /> <java-symbol type="integer" name="db_connection_pool_size" /> @@ -1853,7 +1853,6 @@ <java-symbol type="bool" name="config_enableNightMode" /> <java-symbol type="bool" name="config_tintNotificationActionButtons" /> <java-symbol type="bool" name="config_dozeAfterScreenOffByDefault" /> - <java-symbol type="bool" name="config_enableActivityRecognitionHardwareOverlay" /> <java-symbol type="bool" name="config_enableFusedLocationOverlay" /> <java-symbol type="bool" name="config_enableHardwareFlpOverlay" /> <java-symbol type="bool" name="config_enableGeocoderOverlay" /> @@ -1880,6 +1879,7 @@ <java-symbol type="bool" name="config_wifi_dual_band_support" /> <java-symbol type="bool" name="config_wifi_convert_apband_5ghz_to_any" /> <java-symbol type="bool" name="config_wifi_local_only_hotspot_5ghz" /> + <java-symbol type="bool" name="config_wifi_connected_mac_randomization_supported" /> <java-symbol type="bool" name="config_wifi_fast_bss_transition_enabled" /> <java-symbol type="bool" name="config_wimaxEnabled" /> <java-symbol type="bool" name="show_ongoing_ime_switcher" /> @@ -2021,7 +2021,6 @@ <java-symbol type="string" name="car_mode_disable_notification_title" /> <java-symbol type="string" name="chooser_wallpaper" /> <java-symbol type="string" name="config_datause_iface" /> - <java-symbol type="string" name="config_activityRecognitionHardwarePackageName" /> <java-symbol type="string" name="config_fusedLocationProviderPackageName" /> <java-symbol type="string" name="config_hardwareFlpPackageName" /> <java-symbol type="string" name="config_geocoderProviderPackageName" /> @@ -2140,6 +2139,7 @@ <java-symbol type="string" name="config_carrierAppInstallDialogComponent" /> <java-symbol type="string" name="config_defaultNetworkScorerPackageName" /> <java-symbol type="string" name="config_persistentDataPackageName" /> + <java-symbol type="string" name="config_deviceConfiguratorPackageName" /> <java-symbol type="layout" name="resolver_list" /> <java-symbol type="id" name="resolver_list" /> @@ -3002,6 +3002,7 @@ <java-symbol type="array" name="config_emergency_mcc_codes" /> <java-symbol type="string" name="config_dozeDoubleTapSensorType" /> + <java-symbol type="string" name="config_dozeTapSensorType" /> <java-symbol type="bool" name="config_dozePulsePickup" /> <!-- Used for MimeIconUtils. --> @@ -3074,8 +3075,6 @@ <java-symbol type="dimen" name="config_appTransitionAnimationDurationScaleDefault" /> - <java-symbol type="layout" name="notification_template_material_ambient" /> - <!-- Network Recommendation --> <java-symbol type="string" name="config_defaultNetworkRecommendationProviderPackage" /> @@ -3235,8 +3234,6 @@ <java-symbol type="string" name="time_picker_text_input_mode_description"/> <java-symbol type="string" name="time_picker_radial_mode_description"/> - <java-symbol type="layout" name="notification_template_ambient_header" /> - <!-- resolver activity --> <java-symbol type="drawable" name="resolver_icon_placeholder" /> @@ -3285,6 +3282,7 @@ <java-symbol type="string" name="config_defaultAugmentedAutofillService" /> <java-symbol type="string" name="config_defaultAppPredictionService" /> <java-symbol type="string" name="config_defaultContentSuggestionsService" /> + <java-symbol type="string" name="config_defaultAttentionService" /> <java-symbol type="string" name="notification_channel_foreground_service" /> <java-symbol type="string" name="foreground_service_app_in_background" /> @@ -3540,4 +3538,6 @@ <java-symbol type="bool" name="config_skipSensorAvailable" /> <java-symbol type="bool" name="config_silenceSensorAvailable" /> + + <java-symbol type="bool" name="config_zramWriteback" /> </resources> diff --git a/core/res/res/values/themes_device_defaults.xml b/core/res/res/values/themes_device_defaults.xml index d60313a4402c..75a727bdcfdf 100644 --- a/core/res/res/values/themes_device_defaults.xml +++ b/core/res/res/values/themes_device_defaults.xml @@ -1711,8 +1711,4 @@ easier. <item name="notificationHeaderTextAppearance">@style/TextAppearance.DeviceDefault.Notification.Info</item> </style> - <style name="Theme.DeviceDefault.Notification.Ambient" parent="@style/Theme.Material.Notification.Ambient"> - <item name="notificationHeaderTextAppearance">@style/TextAppearance.DeviceDefault.Notification.Info.Ambient</item> - </style> - </resources> diff --git a/core/res/res/values/themes_material.xml b/core/res/res/values/themes_material.xml index ccaf04160dc5..6b7698e344ad 100644 --- a/core/res/res/values/themes_material.xml +++ b/core/res/res/values/themes_material.xml @@ -1341,14 +1341,6 @@ please see themes_device_defaults.xml. <item name="notificationHeaderIconSize">@dimen/notification_header_icon_size</item> </style> - <!-- Theme for inflating ambient notification --> - <style name="Theme.Material.Notification.Ambient"> - <item name="notificationHeaderStyle">@style/Notification.Header.Ambient</item> - <item name="notificationHeaderTextAppearance">@style/TextAppearance.Material.Notification.Info.Ambient</item> - <item name="notificationHeaderAppNameVisibility">gone</item> - <item name="notificationHeaderIconSize">@dimen/notification_header_icon_size_ambient</item> - </style> - <!-- Default theme for Settings and activities launched from Settings. --> <style name="Theme.Material.Settings" parent="Theme.Material.Light.LightStatusBar"> <item name="homeAsUpIndicator">@drawable/ic_ab_back_material_settings</item> diff --git a/core/tests/BroadcastRadioTests/Android.mk b/core/tests/BroadcastRadioTests/Android.mk index 24f0cf07f443..6b0484ec366d 100644 --- a/core/tests/BroadcastRadioTests/Android.mk +++ b/core/tests/BroadcastRadioTests/Android.mk @@ -25,7 +25,7 @@ LOCAL_MODULE_TAGS := tests # LOCAL_SDK_VERSION := current LOCAL_PRIVATE_PLATFORM_APIS := true -LOCAL_STATIC_JAVA_LIBRARIES := compatibility-device-util android-support-test testng +LOCAL_STATIC_JAVA_LIBRARIES := compatibility-device-util androidx.test.rules testng LOCAL_JAVA_LIBRARIES := android.test.base diff --git a/core/tests/BroadcastRadioTests/AndroidManifest.xml b/core/tests/BroadcastRadioTests/AndroidManifest.xml index d9b5522693e3..ce12cc99946f 100644 --- a/core/tests/BroadcastRadioTests/AndroidManifest.xml +++ b/core/tests/BroadcastRadioTests/AndroidManifest.xml @@ -24,7 +24,7 @@ </application> <instrumentation - android:name="android.support.test.runner.AndroidJUnitRunner" + android:name="androidx.test.runner.AndroidJUnitRunner" android:targetPackage="android.hardware.radio.tests" android:label="Tests for Broadcast Radio APIs" > </instrumentation> diff --git a/core/tests/BroadcastRadioTests/src/android/hardware/radio/tests/functional/RadioTunerTest.java b/core/tests/BroadcastRadioTests/src/android/hardware/radio/tests/functional/RadioTunerTest.java index fdaba089490e..d2bd1e172ee2 100644 --- a/core/tests/BroadcastRadioTests/src/android/hardware/radio/tests/functional/RadioTunerTest.java +++ b/core/tests/BroadcastRadioTests/src/android/hardware/radio/tests/functional/RadioTunerTest.java @@ -15,22 +15,29 @@ */ package android.hardware.radio.tests.functional; +import static org.junit.Assert.*; +import static org.junit.Assume.*; +import static org.mockito.Matchers.any; +import static org.mockito.Mockito.after; +import static org.mockito.Mockito.atLeast; +import static org.mockito.Mockito.atMost; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.timeout; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.verifyNoMoreInteractions; +import static org.testng.Assert.assertThrows; + import android.Manifest; import android.content.Context; import android.content.pm.PackageManager; import android.hardware.radio.ProgramSelector; import android.hardware.radio.RadioManager; import android.hardware.radio.RadioTuner; -import android.support.test.InstrumentationRegistry; -import android.support.test.runner.AndroidJUnit4; import android.test.suitebuilder.annotation.MediumTest; import android.util.Log; -import java.lang.reflect.Constructor; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; +import androidx.test.InstrumentationRegistry; +import androidx.test.runner.AndroidJUnit4; import org.junit.After; import org.junit.Before; @@ -41,19 +48,10 @@ import org.mockito.Mock; import org.mockito.Mockito; import org.mockito.MockitoAnnotations; -import static org.junit.Assert.*; -import static org.junit.Assume.*; -import static org.mockito.Matchers.any; -import static org.mockito.Matchers.anyInt; -import static org.mockito.Mockito.after; -import static org.mockito.Mockito.atLeast; -import static org.mockito.Mockito.atMost; -import static org.mockito.Mockito.never; -import static org.mockito.Mockito.timeout; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.verifyNoMoreInteractions; -import static org.testng.Assert.assertThrows; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; /** * A test for broadcast radio API. diff --git a/core/tests/coretests/AndroidManifest.xml b/core/tests/coretests/AndroidManifest.xml index e80cb6d0295b..86818c611c1f 100644 --- a/core/tests/coretests/AndroidManifest.xml +++ b/core/tests/coretests/AndroidManifest.xml @@ -56,6 +56,7 @@ <uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.INJECT_EVENTS" /> <uses-permission android:name="android.permission.READ_CONTACTS" /> + <uses-permission android:name="android.permission.READ_DEVICE_CONFIG" /> <uses-permission android:name="android.permission.READ_DREAM_STATE" /> <uses-permission android:name="android.permission.WRITE_DREAM_STATE" /> <uses-permission android:name="android.permission.READ_LOGS"/> @@ -65,6 +66,7 @@ <uses-permission android:name="android.permission.USE_CREDENTIALS" /> <uses-permission android:name="android.permission.WAKE_LOCK" /> <uses-permission android:name="android.permission.WRITE_CONTACTS" /> + <uses-permission android:name="android.permission.WRITE_DEVICE_CONFIG" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.WRITE_SETTINGS" /> <uses-permission android:name="android.permission.WRITE_SECURE_SETTINGS" /> diff --git a/core/tests/coretests/README b/core/tests/coretests/README index ea282a0ebb3a..34beb454b397 100644 --- a/core/tests/coretests/README +++ b/core/tests/coretests/README @@ -30,9 +30,9 @@ Next, install the resulting APK and run tests as you would normal JUnit tests: adb install -r ${ANDROID_PRODUCT_OUT}/data/app/FrameworksCoreTests/FrameworksCoreTests.apk adb shell am instrument -w \ - com.android.frameworks.coretests/android.support.test.runner.AndroidJUnitRunner + com.android.frameworks.coretests/androidx.test.runner.AndroidJUnitRunner -To run a tests within a specific package, add the following argument AFTER -w: +To run a tests within a specific package, add -e AFTER -w and before the runner class: -e package android.content.pm diff --git a/core/tests/coretests/res/color/drawable_in_color_dir_invalid.xml b/core/tests/coretests/res/color/drawable_in_color_dir_invalid.xml new file mode 100644 index 000000000000..8d630b09ef42 --- /dev/null +++ b/core/tests/coretests/res/color/drawable_in_color_dir_invalid.xml @@ -0,0 +1,21 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 2019 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> + +<!-- This drawable is purposely in the color directory to test a backwards compatible fallback. --> +<layer-list + xmlns:android="http://schemas.android.com/apk/res/android"> + <item android:id="@android:id/icon" android:drawable="@string/app_name" /> +</layer-list>
\ No newline at end of file diff --git a/core/tests/coretests/res/color/drawable_in_color_dir_valid.xml b/core/tests/coretests/res/color/drawable_in_color_dir_valid.xml new file mode 100644 index 000000000000..d1404753d57a --- /dev/null +++ b/core/tests/coretests/res/color/drawable_in_color_dir_valid.xml @@ -0,0 +1,22 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 2019 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> + +<!-- This drawable is purposely in the color directory to test a backwards compatible fallback. --> +<layer-list + xmlns:android="http://schemas.android.com/apk/res/android"> + <item android:id="@android:id/background" android:drawable="@drawable/test32x24" /> + <item android:id="@android:id/icon" android:drawable="@drawable/test16x12" /> +</layer-list>
\ No newline at end of file diff --git a/core/tests/coretests/src/android/app/usage/UsageStatsTest.java b/core/tests/coretests/src/android/app/usage/UsageStatsTest.java index 29fd8c527322..1633e1ac50a0 100644 --- a/core/tests/coretests/src/android/app/usage/UsageStatsTest.java +++ b/core/tests/coretests/src/android/app/usage/UsageStatsTest.java @@ -21,6 +21,7 @@ import static android.app.usage.UsageEvents.Event.ACTIVITY_PAUSED; import static android.app.usage.UsageEvents.Event.ACTIVITY_RESUMED; import static android.app.usage.UsageEvents.Event.ACTIVITY_STOPPED; import static android.app.usage.UsageEvents.Event.CONTINUING_FOREGROUND_SERVICE; +import static android.app.usage.UsageEvents.Event.DEVICE_SHUTDOWN; import static android.app.usage.UsageEvents.Event.END_OF_DAY; import static android.app.usage.UsageEvents.Event.FLUSH_TO_DISK; import static android.app.usage.UsageEvents.Event.FOREGROUND_SERVICE_START; @@ -529,6 +530,11 @@ public class UsageStatsTest { } @Test + public void testEvent_DEVICE_SHUTDOWN() { + testClosingEvent(DEVICE_SHUTDOWN); + } + + @Test public void testEvent_FLUSH_TO_DISK() { testClosingEvent(FLUSH_TO_DISK); } @@ -536,8 +542,9 @@ public class UsageStatsTest { private void testClosingEvent(int eventType) { // When these three closing events are received, all open activities/services need to be // closed and usage stats are updated. - if (eventType != FLUSH_TO_DISK) { - fail("Closing eventType must be one of FLUSH_TO_DISK"); + if (eventType != DEVICE_SHUTDOWN + && eventType != FLUSH_TO_DISK) { + fail("Closing eventType must be one of DEVICE_SHUTDOWN, FLUSH_TO_DISK"); } left.mPackageName = "com.test"; diff --git a/core/tests/coretests/src/android/content/res/ResourcesDrawableTest.java b/core/tests/coretests/src/android/content/res/ResourcesDrawableTest.java new file mode 100644 index 000000000000..c4df88b49935 --- /dev/null +++ b/core/tests/coretests/src/android/content/res/ResourcesDrawableTest.java @@ -0,0 +1,81 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.content.res; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +import android.content.Context; +import android.graphics.drawable.ColorStateListDrawable; +import android.graphics.drawable.Drawable; +import android.graphics.drawable.LayerDrawable; + +import androidx.test.InstrumentationRegistry; +import androidx.test.filters.SmallTest; +import androidx.test.runner.AndroidJUnit4; + +import com.android.frameworks.coretests.R; + +import org.junit.Test; +import org.junit.runner.RunWith; + +@SmallTest +@RunWith(AndroidJUnit4.class) +public class ResourcesDrawableTest { + + @Test + public void testLoadColorAsDrawable() { + Context context = InstrumentationRegistry.getInstrumentation().getTargetContext(); + Resources resources = context.getResources(); + Drawable drawable = resources.getDrawable(R.color.color1); + assertTrue(drawable instanceof ColorStateListDrawable); + } + + @Test + public void testLoadColorAsDrawableFailureThrowsOriginalException() throws Throwable { + Context context = InstrumentationRegistry.getInstrumentation().getTargetContext(); + Resources resources = context.getResources(); + + Exception exception = null; + + try { + resources.getDrawable(R.color.drawable_in_color_dir_invalid); + } catch (Exception e) { + exception = e; + } + + assertNotNull( + "Loading drawable_in_color_dir_invalid should throw an exception", + exception + ); + + assertEquals( + "Can't find ColorStateList from drawable resource ID #0x" + + Integer.toHexString(R.color.drawable_in_color_dir_invalid), + exception.getCause().getCause().getMessage() + ); + } + + @Test + public void testLoadNormalDrawableInColorDir() { + Context context = InstrumentationRegistry.getInstrumentation().getTargetContext(); + Resources resources = context.getResources(); + Drawable drawable = resources.getDrawable(R.color.drawable_in_color_dir_valid); + assertTrue(drawable instanceof LayerDrawable); + } +} diff --git a/core/tests/coretests/src/android/hardware/hdmi/HdmiUtilsTest.java b/core/tests/coretests/src/android/hardware/hdmi/HdmiUtilsTest.java new file mode 100644 index 000000000000..16be0b0a27c1 --- /dev/null +++ b/core/tests/coretests/src/android/hardware/hdmi/HdmiUtilsTest.java @@ -0,0 +1,82 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package android.hardware.hdmi; + +import static com.google.common.truth.Truth.assertThat; + +import android.support.test.filters.SmallTest; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +@SmallTest +@RunWith(JUnit4.class) +/** Tests for {@link HdmiUtils} class. */ +public class HdmiUtilsTest { + + @Test + public void pathToPort_isMe() { + int targetPhysicalAddress = 0x1000; + int myPhysicalAddress = 0x1000; + assertThat(HdmiUtils.getLocalPortFromPhysicalAddress( + targetPhysicalAddress, myPhysicalAddress)).isEqualTo( + HdmiUtils.TARGET_SAME_PHYSICAL_ADDRESS); + } + + @Test + public void pathToPort_isDirectlyBelow() { + int targetPhysicalAddress = 0x1100; + int myPhysicalAddress = 0x1000; + assertThat(HdmiUtils.getLocalPortFromPhysicalAddress( + targetPhysicalAddress, myPhysicalAddress)).isEqualTo(1); + } + + @Test + public void pathToPort_isBelow() { + int targetPhysicalAddress = 0x1110; + int myPhysicalAddress = 0x1000; + assertThat(HdmiUtils.getLocalPortFromPhysicalAddress( + targetPhysicalAddress, myPhysicalAddress)).isEqualTo(1); + } + + @Test + public void pathToPort_neitherMeNorBelow() { + int targetPhysicalAddress = 0x3000; + int myPhysicalAddress = 0x2000; + assertThat(HdmiUtils.getLocalPortFromPhysicalAddress( + targetPhysicalAddress, myPhysicalAddress)).isEqualTo( + HdmiUtils.TARGET_NOT_UNDER_LOCAL_DEVICE); + + targetPhysicalAddress = 0x2200; + myPhysicalAddress = 0x3300; + assertThat(HdmiUtils.getLocalPortFromPhysicalAddress( + targetPhysicalAddress, myPhysicalAddress)).isEqualTo( + HdmiUtils.TARGET_NOT_UNDER_LOCAL_DEVICE); + + targetPhysicalAddress = 0x2213; + myPhysicalAddress = 0x2212; + assertThat(HdmiUtils.getLocalPortFromPhysicalAddress( + targetPhysicalAddress, myPhysicalAddress)).isEqualTo( + HdmiUtils.TARGET_NOT_UNDER_LOCAL_DEVICE); + + targetPhysicalAddress = 0x2340; + myPhysicalAddress = 0x2310; + assertThat(HdmiUtils.getLocalPortFromPhysicalAddress( + targetPhysicalAddress, myPhysicalAddress)).isEqualTo( + HdmiUtils.TARGET_NOT_UNDER_LOCAL_DEVICE); + } +} diff --git a/core/tests/coretests/src/android/provider/SettingsBackupTest.java b/core/tests/coretests/src/android/provider/SettingsBackupTest.java index 667519c3908c..0fb1c7c7a7ec 100644 --- a/core/tests/coretests/src/android/provider/SettingsBackupTest.java +++ b/core/tests/coretests/src/android/provider/SettingsBackupTest.java @@ -199,6 +199,7 @@ public class SettingsBackupTest { Settings.Global.DATA_STALL_CONSECUTIVE_DNS_TIMEOUT_THRESHOLD, Settings.Global.DATA_STALL_EVALUATION_TYPE, Settings.Global.DATA_STALL_MIN_EVALUATE_INTERVAL, + Settings.Global.DATA_STALL_RECOVERY_ON_BAD_NETWORK, Settings.Global.DATA_STALL_VALID_DNS_TIME_THRESHOLD, Settings.Global.DEBUG_APP, Settings.Global.DEBUG_VIEW_ATTRIBUTES, @@ -312,6 +313,7 @@ public class SettingsBackupTest { Settings.Global.MDC_INITIAL_MAX_RETRY, Settings.Global.MHL_INPUT_SWITCHING_ENABLED, Settings.Global.MHL_POWER_CHARGE_ENABLED, + Settings.Global.MIN_DURATION_BETWEEN_RECOVERY_STEPS_IN_MS, Settings.Global.MOBILE_DATA, // Candidate for backup? Settings.Global.MOBILE_DATA_ALWAYS_ON, Settings.Global.MODE_RINGER, @@ -478,9 +480,10 @@ public class SettingsBackupTest { Settings.Global.GLOBAL_SETTINGS_ANGLE_GL_DRIVER_ALL_ANGLE, Settings.Global.GLOBAL_SETTINGS_ANGLE_GL_DRIVER_SELECTION_PKGS, Settings.Global.GLOBAL_SETTINGS_ANGLE_GL_DRIVER_SELECTION_VALUES, + Settings.Global.GUP_DEV_ALL_APPS, Settings.Global.GUP_DEV_OPT_IN_APPS, Settings.Global.GUP_DEV_OPT_OUT_APPS, - Settings.Global.GUP_BLACK_LIST, + Settings.Global.GUP_BLACKLIST, Settings.Global.GPU_DEBUG_LAYER_APP, Settings.Global.ENABLE_GNSS_RAW_MEAS_FULL_TRACKING, Settings.Global.INSTALL_CARRIER_APP_NOTIFICATION_PERSISTENT, @@ -667,6 +670,7 @@ public class SettingsBackupTest { Settings.Secure.SMS_DEFAULT_APPLICATION, Settings.Secure.SPELL_CHECKER_ENABLED, // Intentionally removed in Q Settings.Secure.TRUST_AGENTS_INITIALIZED, + Settings.Secure.TV_APP_USES_NON_SYSTEM_INPUTS, Settings.Secure.TV_INPUT_CUSTOM_LABELS, Settings.Secure.TV_INPUT_HIDDEN_INPUTS, Settings.Secure.TV_USER_SETUP_COMPLETE, diff --git a/core/tests/coretests/src/android/security/keystore/recovery/KeyChainSnapshotTest.java b/core/tests/coretests/src/android/security/keystore/recovery/KeyChainSnapshotTest.java index 2a962c222371..37fe22fb532d 100644 --- a/core/tests/coretests/src/android/security/keystore/recovery/KeyChainSnapshotTest.java +++ b/core/tests/coretests/src/android/security/keystore/recovery/KeyChainSnapshotTest.java @@ -45,6 +45,7 @@ public class KeyChainSnapshotTest { private static final int USER_SECRET_TYPE = KeyChainProtectionParams.TYPE_LOCKSCREEN; private static final String KEY_ALIAS = "steph"; private static final byte[] KEY_MATERIAL = new byte[] { 3, 5, 7, 9, 1 }; + private static final byte[] KEY_METADATA = new byte[] { 5, 3, 11, 13 }; private static final CertPath CERT_PATH = TestData.getThmCertPath(); @Test @@ -100,6 +101,7 @@ public class KeyChainSnapshotTest { WrappedApplicationKey wrappedApplicationKey = snapshot.getWrappedApplicationKeys().get(0); assertEquals(KEY_ALIAS, wrappedApplicationKey.getAlias()); assertArrayEquals(KEY_MATERIAL, wrappedApplicationKey.getEncryptedKeyMaterial()); + assertArrayEquals(KEY_METADATA, wrappedApplicationKey.getMetadata()); } @Test @@ -166,6 +168,7 @@ public class KeyChainSnapshotTest { WrappedApplicationKey wrappedApplicationKey = snapshot.getWrappedApplicationKeys().get(0); assertEquals(KEY_ALIAS, wrappedApplicationKey.getAlias()); assertArrayEquals(KEY_MATERIAL, wrappedApplicationKey.getEncryptedKeyMaterial()); + assertArrayEquals(KEY_METADATA, wrappedApplicationKey.getMetadata()); } private static KeyChainSnapshot createKeyChainSnapshot() throws Exception { @@ -197,6 +200,7 @@ public class KeyChainSnapshotTest { return new WrappedApplicationKey.Builder() .setAlias(KEY_ALIAS) .setEncryptedKeyMaterial(KEY_MATERIAL) + .setMetadata(KEY_METADATA) .build(); } diff --git a/core/tests/coretests/src/android/security/keystore/recovery/WrappedApplicationKeyTest.java b/core/tests/coretests/src/android/security/keystore/recovery/WrappedApplicationKeyTest.java index 8522e6203284..aec54e190114 100644 --- a/core/tests/coretests/src/android/security/keystore/recovery/WrappedApplicationKeyTest.java +++ b/core/tests/coretests/src/android/security/keystore/recovery/WrappedApplicationKeyTest.java @@ -35,6 +35,7 @@ public class WrappedApplicationKeyTest { private static final String ALIAS = "karlin"; private static final byte[] KEY_MATERIAL = new byte[] { 0, 1, 2, 3, 4 }; + private static final byte[] METADATA = new byte[] {3, 2, 1, 0}; private Parcel mParcel; @@ -59,8 +60,18 @@ public class WrappedApplicationKeyTest { } @Test + public void build_setsMetadata_nonNull() { + assertArrayEquals(METADATA, buildTestKeyWithMetadata(METADATA).getMetadata()); + } + + @Test + public void build_setsMetadata_null() { + assertArrayEquals(null, buildTestKeyWithMetadata(null).getMetadata()); + } + + @Test public void writeToParcel_writesAliasToParcel() { - buildTestKey().writeToParcel(mParcel, /*flags=*/ 0); + buildTestKeyWithMetadata(/*metadata=*/ null).writeToParcel(mParcel, /*flags=*/ 0); mParcel.setDataPosition(0); WrappedApplicationKey readFromParcel = @@ -70,7 +81,7 @@ public class WrappedApplicationKeyTest { @Test public void writeToParcel_writesKeyMaterial() { - buildTestKey().writeToParcel(mParcel, /*flags=*/ 0); + buildTestKeyWithMetadata(/*metadata=*/ null).writeToParcel(mParcel, /*flags=*/ 0); mParcel.setDataPosition(0); WrappedApplicationKey readFromParcel = @@ -78,10 +89,48 @@ public class WrappedApplicationKeyTest { assertArrayEquals(KEY_MATERIAL, readFromParcel.getEncryptedKeyMaterial()); } + @Test + public void writeToParcel_writesMetadata_nonNull() { + buildTestKeyWithMetadata(METADATA).writeToParcel(mParcel, /*flags=*/ 0); + + mParcel.setDataPosition(0); + WrappedApplicationKey readFromParcel = + WrappedApplicationKey.CREATOR.createFromParcel(mParcel); + assertArrayEquals(METADATA, readFromParcel.getMetadata()); + } + + @Test + public void writeToParcel_writesMetadata_null() { + buildTestKeyWithMetadata(/*metadata=*/ null).writeToParcel(mParcel, /*flags=*/ 0); + + mParcel.setDataPosition(0); + WrappedApplicationKey readFromParcel = + WrappedApplicationKey.CREATOR.createFromParcel(mParcel); + assertArrayEquals(null, readFromParcel.getMetadata()); + } + + @Test + public void writeToParcel_writesMetadata_absent() { + buildTestKey().writeToParcel(mParcel, /*flags=*/ 0); + + mParcel.setDataPosition(0); + WrappedApplicationKey readFromParcel = + WrappedApplicationKey.CREATOR.createFromParcel(mParcel); + assertArrayEquals(null, readFromParcel.getMetadata()); + } + private WrappedApplicationKey buildTestKey() { return new WrappedApplicationKey.Builder() .setAlias(ALIAS) .setEncryptedKeyMaterial(KEY_MATERIAL) .build(); } + + private WrappedApplicationKey buildTestKeyWithMetadata(byte[] metadata) { + return new WrappedApplicationKey.Builder() + .setAlias(ALIAS) + .setEncryptedKeyMaterial(KEY_MATERIAL) + .setMetadata(metadata) + .build(); + } } diff --git a/core/tests/coretests/src/android/view/contentcapture/ContentCaptureSessionTest.java b/core/tests/coretests/src/android/view/contentcapture/ContentCaptureSessionTest.java index a2f0eba0b831..ff97aa1d3914 100644 --- a/core/tests/coretests/src/android/view/contentcapture/ContentCaptureSessionTest.java +++ b/core/tests/coretests/src/android/view/contentcapture/ContentCaptureSessionTest.java @@ -97,6 +97,22 @@ public class ContentCaptureSessionTest { assertThat(structure.getAutofillId()).isEqualTo(childId); } + @Test + public void testNotifyViewsDisappeared_invalid() { + // Null parent + assertThrows(NullPointerException.class, + () -> mSession1.notifyViewsDisappeared(null, new int[] {42})); + // Null child + assertThrows(IllegalArgumentException.class, + () -> mSession1.notifyViewsDisappeared(new AutofillId(42), null)); + // Empty child + assertThrows(IllegalArgumentException.class, + () -> mSession1.notifyViewsDisappeared(new AutofillId(42), new int[] {})); + // Virtual parent + assertThrows(IllegalArgumentException.class, + () -> mSession1.notifyViewsDisappeared(new AutofillId(42, 108), new int[] {666})); + } + // Cannot use @Spy because we need to pass the session id on constructor private class MyContentCaptureSession extends ContentCaptureSession { @@ -115,7 +131,7 @@ public class ContentCaptureSessionTest { } @Override - void flush() { + void flush(int reason) { throw new UnsupportedOperationException("should not have been called"); } @@ -135,7 +151,7 @@ public class ContentCaptureSessionTest { } @Override - void internalNotifyViewTextChanged(AutofillId id, CharSequence text, int flags) { + void internalNotifyViewTextChanged(AutofillId id, CharSequence text) { throw new UnsupportedOperationException("should not have been called"); } } diff --git a/core/tests/coretests/src/android/view/contentcapture/ViewNodeTest.java b/core/tests/coretests/src/android/view/contentcapture/ViewNodeTest.java index 099f41d10e27..eadde6280848 100644 --- a/core/tests/coretests/src/android/view/contentcapture/ViewNodeTest.java +++ b/core/tests/coretests/src/android/view/contentcapture/ViewNodeTest.java @@ -181,6 +181,14 @@ public class ViewNodeTest { structure.setDataIsSensitive(true); assertThat(structure.getTempRect()).isNull(); + + // Graphic properties + structure.setElevation(6.66f); + assertThat(node.getElevation()).isWithin(1.0e-10f).of(0f); + structure.setAlpha(66.6f); + assertThat(node.getAlpha()).isWithin(1.0e-10f).of(1.0f); + structure.setTransformation(Matrix.IDENTITY_MATRIX); + assertThat(node.getTransformation()).isNull(); } @Test @@ -279,11 +287,6 @@ public class ViewNodeTest { structure.setAutofillOptions(new String[] { "Maybe" }); structure.setAutofillValue(AutofillValue.forText("Malkovich")); - // Graphic properties - structure.setElevation(6.66f); - structure.setAlpha(66.6f); - structure.setTransformation(Matrix.IDENTITY_MATRIX); - // Extra text properties structure.setMinTextEms(6); structure.setMaxTextLength(66); @@ -340,11 +343,6 @@ public class ViewNodeTest { assertThat(node.getAutofillOptions()).asList().containsExactly("Maybe").inOrder(); assertThat(node.getAutofillValue().getTextValue()).isEqualTo("Malkovich"); - // Graphic properties - assertThat(node.getElevation()).isWithin(1.0e-10f).of(6.66f); - assertThat(node.getAlpha()).isWithin(1.0e-10f).of(66.6f); - assertThat(node.getTransformation()).isEqualTo(Matrix.IDENTITY_MATRIX); - // Extra text properties assertThat(node.getMinTextEms()).isEqualTo(6); assertThat(node.getMaxTextLength()).isEqualTo(66); diff --git a/core/tests/coretests/src/com/android/internal/os/KernelCpuThreadReaderEndToEndTest.java b/core/tests/coretests/src/com/android/internal/os/KernelCpuThreadReaderEndToEndTest.java new file mode 100644 index 000000000000..c03d1f37ffa7 --- /dev/null +++ b/core/tests/coretests/src/com/android/internal/os/KernelCpuThreadReaderEndToEndTest.java @@ -0,0 +1,214 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.internal.os; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +import android.os.SystemClock; +import android.support.test.filters.LargeTest; +import android.support.test.runner.AndroidJUnit4; + +import com.android.internal.os.KernelCpuThreadReader.ProcessCpuUsage; +import com.android.internal.os.KernelCpuThreadReader.ThreadCpuUsage; + +import org.junit.Test; +import org.junit.runner.RunWith; + +import java.time.Duration; +import java.util.Arrays; +import java.util.List; +import java.util.OptionalDouble; +import java.util.concurrent.CountDownLatch; +import java.util.function.Consumer; +import java.util.stream.Collectors; + +/** + * End to end test for {@link KernelCpuThreadReader} that checks the accuracy of the reported times + * by spawning threads that do a predictable amount of work + */ +@RunWith(AndroidJUnit4.class) +@LargeTest +public class KernelCpuThreadReaderEndToEndTest { + + private static final int TIMED_NUM_SAMPLES = 5; + private static final int TIMED_START_MILLIS = 500; + private static final int TIMED_END_MILLIS = 2000; + private static final int TIMED_INCREMENT_MILLIS = 500; + private static final int TIMED_COMPARISON_DELTA_MILLIS = 200; + + private static final int ITERATIVE_NUM_SAMPLES = 100; + private static final long ITERATIVE_LOW_ITERATIONS = (long) 1e8; + private static final long ITERATIVE_HIGH_ITERATIONS = (long) 2e8; + private static final double ITERATIONS_COMPARISONS_DELTA = 0.25; + + /** + * Test that when we busy-wait for the thread-local time to reach N seconds, the time reported + * is also N seconds. Takes ~10s. + */ + @Test + public void testTimedWork() throws InterruptedException { + for (int millis = TIMED_START_MILLIS; + millis <= TIMED_END_MILLIS; + millis += TIMED_INCREMENT_MILLIS) { + final Duration targetDuration = Duration.ofMillis(millis); + final Runnable work = timedWork(targetDuration); + Duration resultDuration = getAverageWorkTime( + work, String.format("timed%dms", millis), TIMED_NUM_SAMPLES); + assertEquals( + "Time worked according to currentThreadTimeMillis doesn't match " + + "KernelCpuThreadReader", + targetDuration.toMillis(), resultDuration.toMillis(), + TIMED_COMPARISON_DELTA_MILLIS); + } + } + + /** + * Test that when we scale up the amount of work by N, the time reported also scales by N. Takes + * ~15s. + */ + @Test + public void testIterativeWork() throws InterruptedException { + final Runnable lowAmountWork = iterativeWork(ITERATIVE_LOW_ITERATIONS); + final Runnable highAmountWork = iterativeWork(ITERATIVE_HIGH_ITERATIONS); + final Duration lowResultDuration = + getAverageWorkTime(lowAmountWork, "iterlow", ITERATIVE_NUM_SAMPLES); + final Duration highResultDuration = + getAverageWorkTime(highAmountWork, "iterhigh", ITERATIVE_NUM_SAMPLES); + assertEquals( + "Work scale and CPU time scale do not match", + ((double) ITERATIVE_HIGH_ITERATIONS) / ((double) ITERATIVE_LOW_ITERATIONS), + ((double) highResultDuration.toMillis()) / ((double) lowResultDuration.toMillis()), + ITERATIONS_COMPARISONS_DELTA); + } + + /** + * Run some work {@code numSamples} times, and take the average CPU duration used for that work + * according to {@link KernelCpuThreadReader} + */ + private Duration getAverageWorkTime( + Runnable work, String tag, int numSamples) throws InterruptedException { + // Count down every time a thread finishes work, so that we can wait for work to complete + final CountDownLatch workFinishedLatch = new CountDownLatch(numSamples); + // Count down once when threads can terminate (after we get them from + // `KernelCpuThreadReader`) + final CountDownLatch threadFinishedLatch = new CountDownLatch(1); + + // Start `NUM_SAMPLE` threads to do the work + for (int i = 0; i < numSamples; i++) { + final String threadName = String.format("%s%d", tag, i); + // Check the thread name, as we rely on it later to identify threads + assertTrue("Max name length for linux threads is 15", threadName.length() <= 15); + doWork(work, threadName, workFinishedLatch, threadFinishedLatch); + } + + // Wait for threads to finish + workFinishedLatch.await(); + + // Get thread data from KernelCpuThreadReader + final KernelCpuThreadReader kernelCpuThreadReader = KernelCpuThreadReader.create(); + assertNotNull(kernelCpuThreadReader); + final ProcessCpuUsage currentProcessCpuUsage = + kernelCpuThreadReader.getCurrentProcessCpuUsage(); + + // Threads can terminate, as we've finished crawling them from /proc + threadFinishedLatch.countDown(); + + // Check that we've got times for every thread we spawned + final List<ThreadCpuUsage> threadCpuUsages = currentProcessCpuUsage.threadCpuUsages + .stream() + .filter((thread) -> thread.threadName.startsWith(tag)) + .collect(Collectors.toList()); + assertEquals( + "Incorrect number of threads returned by KernelCpuThreadReader", + numSamples, threadCpuUsages.size()); + + // Calculate the average time spent working + final OptionalDouble averageWorkTimeMillis = threadCpuUsages.stream() + .mapToDouble((t) -> Arrays.stream(t.usageTimesMillis).sum()) + .average(); + assertTrue(averageWorkTimeMillis.isPresent()); + return Duration.ofMillis((long) averageWorkTimeMillis.getAsDouble()); + } + + /** + * Work that lasts {@code duration} according to {@link SystemClock#currentThreadTimeMillis()} + */ + private Runnable timedWork(Duration duration) { + return () -> { + // Busy loop until `duration` has elapsed for the thread timer + final long startTimeMillis = SystemClock.currentThreadTimeMillis(); + final long durationMillis = duration.toMillis(); + while (true) { + final long elapsedMillis = SystemClock.currentThreadTimeMillis() - startTimeMillis; + if (elapsedMillis >= durationMillis) { + break; + } + } + }; + } + + /** + * Work that iterates {@code iterations} times + */ + private Runnable iterativeWork(long iterations) { + Consumer<Long> empty = (i) -> { + }; + return () -> { + long count = 0; + for (long i = 0; i < iterations; i++) { + // Alternate branching to reduce effect of branch prediction + if (i % 2 == 0) { + count++; + } + } + // Call empty function with value to avoid loop getting optimized away + empty.accept(count); + }; + } + + /** + * Perform some work in another thread + * + * @param work the work to perform + * @param threadName the name of the spawned thread + * @param workFinishedLatch latch to register that the work has been completed + * @param threadFinishedLatch latch to pause termination of the thread until the latch is + * decremented + */ + private void doWork( + Runnable work, + String threadName, + CountDownLatch workFinishedLatch, + CountDownLatch threadFinishedLatch) { + Runnable workWrapped = () -> { + // Do the work + work.run(); + // Notify that the work is finished + workFinishedLatch.countDown(); + // Wait until `threadFinishLatch` has been released in order to keep the thread alive so + // we can see it in `proc` filesystem + try { + threadFinishedLatch.await(); + } catch (InterruptedException e) { + e.printStackTrace(); + } + }; + new Thread(workWrapped, threadName).start(); + } +} diff --git a/core/tests/hosttests/test-apps/MultiDexLegacyAndException/Android.mk b/core/tests/hosttests/test-apps/MultiDexLegacyAndException/Android.mk index d161059ed024..cc2d8d256e6a 100644 --- a/core/tests/hosttests/test-apps/MultiDexLegacyAndException/Android.mk +++ b/core/tests/hosttests/test-apps/MultiDexLegacyAndException/Android.mk @@ -38,16 +38,11 @@ LOCAL_DX_FLAGS := --multi-dex --main-dex-list=$(mainDexList) --minimal-main-dex LOCAL_MIN_SDK_VERSION := 8 -LOCAL_JACK_FLAGS := -D jack.dex.output.policy=minimal-multidex \ - -D jack.dex.output.multidex.legacy=true - include $(BUILD_PACKAGE) -ifndef LOCAL_JACK_ENABLED -$(mainDexList): $(full_classes_pre_proguard_jar) | $(MAINDEXCLASSES) +$(mainDexList): $(full_classes_pre_proguard_jar) $(MAINDEXCLASSES) $(PROGUARD_DEPS) $(hide) mkdir -p $(dir $@) - $(MAINDEXCLASSES) $< 1>$@ + PROGUARD_HOME=$(PROGUARD_HOME) $(MAINDEXCLASSES) $< 1>$@ echo "com/android/multidexlegacyandexception/Test.class" >> $@ $(built_dex_intermediate): $(mainDexList) -endif diff --git a/core/tests/hosttests/test-apps/MultiDexLegacyTestApp/Android.mk b/core/tests/hosttests/test-apps/MultiDexLegacyTestApp/Android.mk index cf8fc92c7026..c577eeffd488 100644 --- a/core/tests/hosttests/test-apps/MultiDexLegacyTestApp/Android.mk +++ b/core/tests/hosttests/test-apps/MultiDexLegacyTestApp/Android.mk @@ -38,9 +38,9 @@ LOCAL_MIN_SDK_VERSION := 8 include $(BUILD_PACKAGE) -$(mainDexList): $(full_classes_pre_proguard_jar) | $(MAINDEXCLASSES) +$(mainDexList): $(full_classes_pre_proguard_jar) $(MAINDEXCLASSES) $(PROGUARD_DEPS) $(hide) mkdir -p $(dir $@) - $(MAINDEXCLASSES) $< 1>$@ + PROGUARD_HOME=$(PROGUARD_HOME) $(MAINDEXCLASSES) $< 1>$@ echo "com/android/multidexlegacytestapp/Test.class" >> $@ $(built_dex_intermediate): $(mainDexList) @@ -69,9 +69,9 @@ LOCAL_MIN_SDK_VERSION := 8 include $(BUILD_PACKAGE) -$(mainDexList2): $(full_classes_pre_proguard_jar) | $(MAINDEXCLASSES) +$(mainDexList2): $(full_classes_pre_proguard_jar) $(MAINDEXCLASSES) $(PROGUARD_DEPS) $(hide) mkdir -p $(dir $@) - $(MAINDEXCLASSES) $< 1>$@ + PROGUARD_HOME=$(PROGUARD_HOME) $(MAINDEXCLASSES) $< 1>$@ echo "com/android/multidexlegacytestapp/Test.class" >> $@ $(built_dex_intermediate): $(mainDexList2) diff --git a/core/tests/hosttests/test-apps/MultiDexLegacyTestServices/Android.mk b/core/tests/hosttests/test-apps/MultiDexLegacyTestServices/Android.mk index 2ce50b3b7583..da40940e92e9 100644 --- a/core/tests/hosttests/test-apps/MultiDexLegacyTestServices/Android.mk +++ b/core/tests/hosttests/test-apps/MultiDexLegacyTestServices/Android.mk @@ -30,14 +30,13 @@ mainDexList:= \ $(call intermediates-dir-for,APPS,$(LOCAL_PACKAGE_NAME),$(LOCAL_IS_HOST_MODULE),common)/maindex.list LOCAL_DX_FLAGS := --multi-dex --main-dex-list=$(mainDexList) --minimal-main-dex -LOCAL_JACK_FLAGS := -D jack.dex.output.policy=minimal-multidex -D jack.dex.output.multidex.legacy=true LOCAL_DEX_PREOPT := false include $(BUILD_PACKAGE) -$(mainDexList): $(full_classes_pre_proguard_jar) | $(MAINDEXCLASSES) +$(mainDexList): $(full_classes_pre_proguard_jar) $(MAINDEXCLASSES) $(PROGUARD_DEPS) $(hide) mkdir -p $(dir $@) - $(MAINDEXCLASSES) $< 1>$@ + PROGUARD_HOME=$(PROGUARD_HOME) $(MAINDEXCLASSES) $< 1>$@ $(built_dex_intermediate): $(mainDexList) diff --git a/core/tests/hosttests/test-apps/MultiDexLegacyTestServicesTests2/Android.mk b/core/tests/hosttests/test-apps/MultiDexLegacyTestServicesTests2/Android.mk index f3d98a88d485..afbcd4675a78 100644 --- a/core/tests/hosttests/test-apps/MultiDexLegacyTestServicesTests2/Android.mk +++ b/core/tests/hosttests/test-apps/MultiDexLegacyTestServicesTests2/Android.mk @@ -23,7 +23,7 @@ LOCAL_SRC_FILES := $(call all-java-files-under, src) LOCAL_PACKAGE_NAME := MultiDexLegacyTestServicesTests2 LOCAL_JAVA_LIBRARIES := android-support-multidex -LOCAL_STATIC_JAVA_LIBRARIES := android-support-test +LOCAL_STATIC_JAVA_LIBRARIES := androidx.test.rules LOCAL_SDK_VERSION := 9 diff --git a/core/tests/hosttests/test-apps/MultiDexLegacyTestServicesTests2/AndroidManifest.xml b/core/tests/hosttests/test-apps/MultiDexLegacyTestServicesTests2/AndroidManifest.xml index 0ab29591be18..01285e77e3ff 100644 --- a/core/tests/hosttests/test-apps/MultiDexLegacyTestServicesTests2/AndroidManifest.xml +++ b/core/tests/hosttests/test-apps/MultiDexLegacyTestServicesTests2/AndroidManifest.xml @@ -7,7 +7,7 @@ <uses-sdk android:minSdkVersion="9" /> <uses-permission android:name="android.permission.KILL_BACKGROUND_PROCESSES"/> <instrumentation - android:name="android.support.test.runner.AndroidJUnitRunner" + android:name="androidx.test.runner.AndroidJUnitRunner" android:targetPackage="com.android.framework.multidexlegacytestservices" /> <application diff --git a/core/tests/hosttests/test-apps/MultiDexLegacyTestServicesTests2/src/com/android/framework/multidexlegacytestservices/test2/ServicesTests.java b/core/tests/hosttests/test-apps/MultiDexLegacyTestServicesTests2/src/com/android/framework/multidexlegacytestservices/test2/ServicesTests.java index 900f20387c49..f2c72f001646 100644 --- a/core/tests/hosttests/test-apps/MultiDexLegacyTestServicesTests2/src/com/android/framework/multidexlegacytestservices/test2/ServicesTests.java +++ b/core/tests/hosttests/test-apps/MultiDexLegacyTestServicesTests2/src/com/android/framework/multidexlegacytestservices/test2/ServicesTests.java @@ -19,22 +19,26 @@ package com.android.framework.multidexlegacytestservices.test2; import android.app.ActivityManager; import android.content.Context; import android.content.Intent; -import android.support.test.InstrumentationRegistry; -import android.support.test.runner.AndroidJUnit4; import android.util.Log; + +import androidx.test.InstrumentationRegistry; +import androidx.test.runner.AndroidJUnit4; + +import junit.framework.Assert; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; + import java.io.File; import java.io.FileFilter; import java.io.IOException; import java.io.RandomAccessFile; import java.util.concurrent.TimeoutException; -import junit.framework.Assert; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; /** * Run the tests with: <code>adb shell am instrument -w - * com.android.framework.multidexlegacytestservices.test2/android.support.test.runner.AndroidJUnitRunner + * com.android.framework.multidexlegacytestservices.test2/androidx.test.runner.AndroidJUnitRunner * </code> */ @RunWith(AndroidJUnit4.class) diff --git a/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v1/Android.mk b/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v1/Android.mk index 8b0c750a9efc..665e22d5a0bc 100644 --- a/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v1/Android.mk +++ b/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v1/Android.mk @@ -35,9 +35,9 @@ LOCAL_DX_FLAGS := --multi-dex --main-dex-list=$(mainDexList) --minimal-main-dex include $(BUILD_PACKAGE) -$(mainDexList): $(full_classes_pre_proguard_jar) | $(MAINDEXCLASSES) +$(mainDexList): $(full_classes_pre_proguard_jar) $(MAINDEXCLASSES) $(PROGUARD_DEPS) $(hide) mkdir -p $(dir $@) - $(MAINDEXCLASSES) $< 1>$@ + PROGUARD_HOME=$(PROGUARD_HOME) $(MAINDEXCLASSES) $< 1>$@ echo "com/android/framework/multidexlegacyversionedtestapp/MultiDexUpdateTest.class" >> $@ $(built_dex_intermediate): $(mainDexList) diff --git a/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v2/Android.mk b/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v2/Android.mk index a36c9934d87f..c827fa80ebcd 100644 --- a/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v2/Android.mk +++ b/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v2/Android.mk @@ -35,9 +35,9 @@ LOCAL_DX_FLAGS := --multi-dex --main-dex-list=$(mainDexList) --minimal-main-dex include $(BUILD_PACKAGE) -$(mainDexList): $(full_classes_pre_proguard_jar) | $(MAINDEXCLASSES) +$(mainDexList): $(full_classes_pre_proguard_jar) $(MAINDEXCLASSES) $(PROGUARD_DEPS) $(hide) mkdir -p $(dir $@) - $(MAINDEXCLASSES) $< 1>$@ + PROGUARD_HOME=$(PROGUARD_HOME) $(MAINDEXCLASSES) $< 1>$@ echo "com/android/framework/multidexlegacyversionedtestapp/MultiDexUpdateTest.class" >> $@ $(built_dex_intermediate): $(mainDexList) diff --git a/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v3/Android.mk b/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v3/Android.mk index 6b7418c1adb1..3d6ad7d1aa57 100644 --- a/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v3/Android.mk +++ b/core/tests/hosttests/test-apps/MultiDexLegacyVersionedTestApp_v3/Android.mk @@ -35,9 +35,9 @@ LOCAL_DX_FLAGS := --multi-dex --main-dex-list=$(mainDexList) --minimal-main-dex include $(BUILD_PACKAGE) -$(mainDexList): $(full_classes_pre_proguard_jar) | $(MAINDEXCLASSES) +$(mainDexList): $(full_classes_pre_proguard_jar) $(MAINDEXCLASSES) $(PROGUARD_DEPS) $(hide) mkdir -p $(dir $@) - $(MAINDEXCLASSES) $< 1>$@ + PROGUARD_HOME=$(PROGUARD_HOME) $(MAINDEXCLASSES) $< 1>$@ echo "com/android/framework/multidexlegacyversionedtestapp/MultiDexUpdateTest.class" >> $@ $(built_dex_intermediate): $(mainDexList) diff --git a/graphics/java/android/graphics/Paint.java b/graphics/java/android/graphics/Paint.java index cbb780deac8a..54e1abcaf1b7 100644 --- a/graphics/java/android/graphics/Paint.java +++ b/graphics/java/android/graphics/Paint.java @@ -68,26 +68,27 @@ public class Paint { Paint.class.getClassLoader(), nGetNativeFinalizer(), NATIVE_PAINT_SIZE); } - private ColorFilter mColorFilter; - private MaskFilter mMaskFilter; - private PathEffect mPathEffect; - private Shader mShader; + @ColorLong private long mColor; + private ColorFilter mColorFilter; + private MaskFilter mMaskFilter; + private PathEffect mPathEffect; + private Shader mShader; @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023) - private Typeface mTypeface; - private Xfermode mXfermode; + private Typeface mTypeface; + private Xfermode mXfermode; - private boolean mHasCompatScaling; - private float mCompatScaling; - private float mInvCompatScaling; + private boolean mHasCompatScaling; + private float mCompatScaling; + private float mInvCompatScaling; - private LocaleList mLocales; - private String mFontFeatureSettings; - private String mFontVariationSettings; + private LocaleList mLocales; + private String mFontFeatureSettings; + private String mFontVariationSettings; - private float mShadowLayerRadius; - private float mShadowLayerDx; - private float mShadowLayerDy; - private int mShadowLayerColor; + private float mShadowLayerRadius; + private float mShadowLayerDx; + private float mShadowLayerDy; + @ColorLong private long mShadowLayerColor; private static final Object sCacheLock = new Object(); @@ -505,6 +506,7 @@ public class Paint { // ? HINTING_OFF : HINTING_ON); mCompatScaling = mInvCompatScaling = 1; setTextLocales(LocaleList.getAdjustedDefault()); + mColor = Color.pack(Color.BLACK); } /** @@ -530,6 +532,7 @@ public class Paint { // setHinting(DisplayMetrics.DENSITY_DEVICE >= DisplayMetrics.DENSITY_TV // ? HINTING_OFF : HINTING_ON); + mColor = Color.pack(Color.BLACK); mColorFilter = null; mMaskFilter = null; mPathEffect = null; @@ -551,7 +554,7 @@ public class Paint { mShadowLayerRadius = 0.0f; mShadowLayerDx = 0.0f; mShadowLayerDy = 0.0f; - mShadowLayerColor = 0; + mShadowLayerColor = Color.pack(0); } /** @@ -572,6 +575,7 @@ public class Paint { * {@link Paint}. */ private void setClassVariablesFrom(Paint paint) { + mColor = paint.mColor; mColorFilter = paint.mColorFilter; mMaskFilter = paint.mMaskFilter; mPathEffect = paint.mPathEffect; @@ -949,7 +953,7 @@ public class Paint { } /** - * Return the paint's color. Note that the color is a 32bit value + * Return the paint's color in sRGB. Note that the color is a 32bit value * containing alpha as well as r,g,b. This 32bit value is not premultiplied, * meaning that its alpha can be any value, regardless of the values of * r,g,b. See the Color class for more details. @@ -958,7 +962,25 @@ public class Paint { */ @ColorInt public int getColor() { - return nGetColor(mNativePaint); + return Color.toArgb(mColor); + } + + /** + * Return the paint's color. Note that the color is a long with an encoded + * {@link ColorSpace} as well as alpha and r,g,b. These values are not + * premultiplied, meaning that alpha can be any value, regardless of the + * values of r,g,b. See the {@link Color} class for more details. + * + * @see Color for APIs that help manipulate a color long. + * + * @return the paint's color (and alpha). + * + * @hide pending API approval + */ + @TestApi + @ColorLong + public long getColorLong() { + return mColor; } /** @@ -970,7 +992,7 @@ public class Paint { * @param color The new color (including alpha) to set in the paint. */ public void setColor(@ColorInt int color) { - nSetColor(mNativePaint, color); + setColor(Color.pack(color)); } /** @@ -996,6 +1018,7 @@ public class Paint { float a = Color.alpha(color); nSetColor(mNativePaint, cs, r, g, b, a); + mColor = color; } /** @@ -1006,7 +1029,7 @@ public class Paint { * @return the alpha component of the paint's color. */ public int getAlpha() { - return nGetAlpha(mNativePaint); + return Math.round(Color.alpha(mColor) * 255.0f); } /** @@ -1017,6 +1040,13 @@ public class Paint { * @param a set the alpha component [0..255] of the paint's color. */ public void setAlpha(int a) { + // FIXME: No need to unpack this. Instead, just update the alpha bits. + // b/122959599 + ColorSpace cs = Color.colorSpace(mColor); + float r = Color.red(mColor); + float g = Color.green(mColor); + float b = Color.blue(mColor); + mColor = Color.pack(r, g, b, a * (1.0f / 255), cs); nSetAlpha(mNativePaint, a); } @@ -1398,12 +1428,7 @@ public class Paint { * opaque, or the alpha from the shadow color if not. */ public void setShadowLayer(float radius, float dx, float dy, @ColorInt int shadowColor) { - mShadowLayerRadius = radius; - mShadowLayerDx = dx; - mShadowLayerDy = dy; - mShadowLayerColor = shadowColor; - // FIXME: Share a single native method with the ColorLong version. - nSetShadowLayer(mNativePaint, radius, dx, dy, shadowColor); + setShadowLayer(radius, dx, dy, Color.pack(shadowColor)); } /** @@ -1435,7 +1460,7 @@ public class Paint { mShadowLayerRadius = radius; mShadowLayerDx = dx; mShadowLayerDy = dy; - mShadowLayerColor = Color.toArgb(shadowColor); + mShadowLayerColor = shadowColor; } /** @@ -1482,8 +1507,20 @@ public class Paint { /** * Returns the color of the shadow layer. * @see #setShadowLayer(float,float,float,int) + * @see #setShadowLayer(float,float,float,long) */ public @ColorInt int getShadowLayerColor() { + return Color.toArgb(mShadowLayerColor); + } + + /** + * Returns the color of the shadow layer. + * @see #setShadowLayer(float,float,float,int) + * @see #setShadowLayer(float,float,float,long) + * @hide pending API approval + */ + @TestApi + public @ColorLong long getShadowLayerColorLong() { return mShadowLayerColor; } @@ -3074,12 +3111,6 @@ public class Paint { @CriticalNative private static native void nSetFilterBitmap(long paintPtr, boolean filter); @CriticalNative - private static native int nGetColor(long paintPtr); - @CriticalNative - private static native void nSetColor(long paintPtr, @ColorInt int color); - @CriticalNative - private static native int nGetAlpha(long paintPtr); - @CriticalNative private static native void nSetStrikeThruText(long paintPtr, boolean strikeThruText); @CriticalNative private static native boolean nIsElegantTextHeight(long paintPtr); diff --git a/libs/androidfw/include/androidfw/ResourceTypes.h b/libs/androidfw/include/androidfw/ResourceTypes.h index 6b9ebd3e8d12..1655e89a9b97 100644 --- a/libs/androidfw/include/androidfw/ResourceTypes.h +++ b/libs/androidfw/include/androidfw/ResourceTypes.h @@ -1643,10 +1643,6 @@ struct ResTable_overlayable_policy_header // The overlay must reside of the product partition or must have existed on the product // partition before an upgrade to overlay these resources. POLICY_PRODUCT_PARTITION = 0x00000008, - - // The overlay must reside of the product services partition or must have existed on the product - // services partition before an upgrade to overlay these resources. - POLICY_PRODUCT_SERVICES_PARTITION = 0x00000010, }; uint32_t policy_flags; diff --git a/libs/androidfw/tests/LoadedArsc_test.cpp b/libs/androidfw/tests/LoadedArsc_test.cpp index 2e386a083185..b8d3c6bf92fb 100644 --- a/libs/androidfw/tests/LoadedArsc_test.cpp +++ b/libs/androidfw/tests/LoadedArsc_test.cpp @@ -312,7 +312,6 @@ TEST(LoadedArscTest, LoadOverlayable) { EXPECT_THAT(info->actor, Eq("overlay://com.android.overlayable")); EXPECT_THAT(info->policy_flags, Eq(ResTable_overlayable_policy_header::POLICY_VENDOR_PARTITION - | ResTable_overlayable_policy_header::POLICY_PRODUCT_SERVICES_PARTITION | ResTable_overlayable_policy_header::POLICY_PRODUCT_PARTITION)); info = package->GetOverlayableInfo(overlayable::R::string::overlayable4); diff --git a/libs/androidfw/tests/data/overlayable/overlayable.apk b/libs/androidfw/tests/data/overlayable/overlayable.apk Binary files differindex 863474794d00..047e6afde86b 100644 --- a/libs/androidfw/tests/data/overlayable/overlayable.apk +++ b/libs/androidfw/tests/data/overlayable/overlayable.apk diff --git a/libs/androidfw/tests/data/overlayable/res/values/overlayable.xml b/libs/androidfw/tests/data/overlayable/res/values/overlayable.xml index dba7b08628f1..fcdbe94466c1 100644 --- a/libs/androidfw/tests/data/overlayable/res/values/overlayable.xml +++ b/libs/androidfw/tests/data/overlayable/res/values/overlayable.xml @@ -32,9 +32,9 @@ </overlayable> <overlayable name="OverlayableResources2" actor="overlay://com.android.overlayable"> - <!-- Any overlay on the product_services, vendor, or product partition can overlay the value of + <!-- Any overlay on the vendor or product partition can overlay the value of @string/overlayable3 --> - <policy type="product_services|vendor|product"> + <policy type="vendor|product"> <item type="string" name="overlayable3" /> </policy> </overlayable> diff --git a/libs/hwui/pipeline/skia/SkiaOpenGLPipeline.cpp b/libs/hwui/pipeline/skia/SkiaOpenGLPipeline.cpp index e6e6b0e62305..cfbb9956d3dc 100644 --- a/libs/hwui/pipeline/skia/SkiaOpenGLPipeline.cpp +++ b/libs/hwui/pipeline/skia/SkiaOpenGLPipeline.cpp @@ -100,7 +100,8 @@ bool SkiaOpenGLPipeline::draw(const Frame& frame, const SkRect& screenDirty, con mSurfaceColorSpace, &props)); SkiaPipeline::updateLighting(lightGeometry, lightInfo); - renderFrame(*layerUpdateQueue, dirty, renderNodes, opaque, contentDrawBounds, surface); + renderFrame(*layerUpdateQueue, dirty, renderNodes, opaque, contentDrawBounds, surface, + SkMatrix::I()); layerUpdateQueue->clear(); // Draw visual debugging features diff --git a/libs/hwui/pipeline/skia/SkiaPipeline.cpp b/libs/hwui/pipeline/skia/SkiaPipeline.cpp index d7faaf707aa8..df8224372ea7 100644 --- a/libs/hwui/pipeline/skia/SkiaPipeline.cpp +++ b/libs/hwui/pipeline/skia/SkiaPipeline.cpp @@ -312,7 +312,8 @@ void SkiaPipeline::endCapture(SkSurface* surface) { void SkiaPipeline::renderFrame(const LayerUpdateQueue& layers, const SkRect& clip, const std::vector<sp<RenderNode>>& nodes, bool opaque, - const Rect& contentDrawBounds, sk_sp<SkSurface> surface) { + const Rect& contentDrawBounds, sk_sp<SkSurface> surface, + const SkMatrix& preTransform) { renderVectorDrawableCache(); // draw all layers up front @@ -323,12 +324,12 @@ void SkiaPipeline::renderFrame(const LayerUpdateQueue& layers, const SkRect& cli std::unique_ptr<SkPictureRecorder> recorder; SkCanvas* canvas = tryCapture(surface.get()); - renderFrameImpl(layers, clip, nodes, opaque, contentDrawBounds, canvas); + renderFrameImpl(layers, clip, nodes, opaque, contentDrawBounds, canvas, preTransform); endCapture(surface.get()); if (CC_UNLIKELY(Properties::debugOverdraw)) { - renderOverdraw(layers, clip, nodes, contentDrawBounds, surface); + renderOverdraw(layers, clip, nodes, contentDrawBounds, surface, preTransform); } ATRACE_NAME("flush commands"); @@ -344,9 +345,11 @@ static Rect nodeBounds(RenderNode& node) { void SkiaPipeline::renderFrameImpl(const LayerUpdateQueue& layers, const SkRect& clip, const std::vector<sp<RenderNode>>& nodes, bool opaque, - const Rect& contentDrawBounds, SkCanvas* canvas) { + const Rect& contentDrawBounds, SkCanvas* canvas, + const SkMatrix& preTransform) { SkAutoCanvasRestore saver(canvas, true); - canvas->androidFramework_setDeviceClipRestriction(clip.roundOut()); + canvas->androidFramework_setDeviceClipRestriction(preTransform.mapRect(clip).roundOut()); + canvas->concat(preTransform); // STOPSHIP: Revert, temporary workaround to clear always F16 frame buffer for b/74976293 if (!opaque || getSurfaceColorType() == kRGBA_F16_SkColorType) { @@ -486,7 +489,8 @@ static const uint32_t kOverdrawColors[2][6] = { void SkiaPipeline::renderOverdraw(const LayerUpdateQueue& layers, const SkRect& clip, const std::vector<sp<RenderNode>>& nodes, - const Rect& contentDrawBounds, sk_sp<SkSurface> surface) { + const Rect& contentDrawBounds, sk_sp<SkSurface> surface, + const SkMatrix& preTransform) { // Set up the overdraw canvas. SkImageInfo offscreenInfo = SkImageInfo::MakeA8(surface->width(), surface->height()); sk_sp<SkSurface> offscreen = surface->makeSurface(offscreenInfo); @@ -496,7 +500,7 @@ void SkiaPipeline::renderOverdraw(const LayerUpdateQueue& layers, const SkRect& // each time a pixel would have been drawn. // Pass true for opaque so we skip the clear - the overdrawCanvas is already zero // initialized. - renderFrameImpl(layers, clip, nodes, true, contentDrawBounds, &overdrawCanvas); + renderFrameImpl(layers, clip, nodes, true, contentDrawBounds, &overdrawCanvas, preTransform); sk_sp<SkImage> counts = offscreen->makeImageSnapshot(); // Draw overdraw colors to the canvas. The color filter will convert counts to colors. diff --git a/libs/hwui/pipeline/skia/SkiaPipeline.h b/libs/hwui/pipeline/skia/SkiaPipeline.h index 94a699bfee31..cf6f5b284d8c 100644 --- a/libs/hwui/pipeline/skia/SkiaPipeline.h +++ b/libs/hwui/pipeline/skia/SkiaPipeline.h @@ -53,7 +53,8 @@ public: void renderFrame(const LayerUpdateQueue& layers, const SkRect& clip, const std::vector<sp<RenderNode>>& nodes, bool opaque, - const Rect& contentDrawBounds, sk_sp<SkSurface> surface); + const Rect& contentDrawBounds, sk_sp<SkSurface> surface, + const SkMatrix& preTransform); std::vector<VectorDrawableRoot*>* getVectorDrawables() { return &mVectorDrawables; } @@ -116,7 +117,8 @@ protected: private: void renderFrameImpl(const LayerUpdateQueue& layers, const SkRect& clip, const std::vector<sp<RenderNode>>& nodes, bool opaque, - const Rect& contentDrawBounds, SkCanvas* canvas); + const Rect& contentDrawBounds, SkCanvas* canvas, + const SkMatrix& preTransform); /** * Debugging feature. Draws a semi-transparent overlay on each pixel, indicating @@ -124,7 +126,7 @@ private: */ void renderOverdraw(const LayerUpdateQueue& layers, const SkRect& clip, const std::vector<sp<RenderNode>>& nodes, const Rect& contentDrawBounds, - sk_sp<SkSurface>); + sk_sp<SkSurface> surface, const SkMatrix& preTransform); /** * Render mVectorDrawables into offscreen buffers. diff --git a/libs/hwui/pipeline/skia/SkiaVulkanPipeline.cpp b/libs/hwui/pipeline/skia/SkiaVulkanPipeline.cpp index b9aae9839bdc..53495a7d62c0 100644 --- a/libs/hwui/pipeline/skia/SkiaVulkanPipeline.cpp +++ b/libs/hwui/pipeline/skia/SkiaVulkanPipeline.cpp @@ -58,7 +58,8 @@ Frame SkiaVulkanPipeline::getFrame() { return Frame(-1, -1, 0); } - Frame frame(backBuffer->width(), backBuffer->height(), mVkManager.getAge(mVkSurface)); + Frame frame(mVkSurface->windowWidth(), mVkSurface->windowHeight(), + mVkManager.getAge(mVkSurface)); return frame; } @@ -73,7 +74,8 @@ bool SkiaVulkanPipeline::draw(const Frame& frame, const SkRect& screenDirty, con return false; } SkiaPipeline::updateLighting(lightGeometry, lightInfo); - renderFrame(*layerUpdateQueue, dirty, renderNodes, opaque, contentDrawBounds, backBuffer); + renderFrame(*layerUpdateQueue, dirty, renderNodes, opaque, contentDrawBounds, + backBuffer, mVkSurface->preTransform()); ShaderCache::get().onVkFrameFlushed(mRenderThread.getGrContext()); layerUpdateQueue->clear(); diff --git a/libs/hwui/renderthread/VulkanManager.cpp b/libs/hwui/renderthread/VulkanManager.cpp index 6c540f627a68..5c6cb9ad43db 100644 --- a/libs/hwui/renderthread/VulkanManager.cpp +++ b/libs/hwui/renderthread/VulkanManager.cpp @@ -480,6 +480,32 @@ VulkanSurface::BackbufferInfo* VulkanManager::getAvailableBackbuffer(VulkanSurfa return backbuffer; } +static SkMatrix getPreTransformMatrix(int width, int height, + VkSurfaceTransformFlagBitsKHR transform) { + switch (transform) { + case VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR: + return SkMatrix::I(); + case VK_SURFACE_TRANSFORM_ROTATE_90_BIT_KHR: + return SkMatrix::MakeAll(0, -1, height, 1, 0, 0, 0, 0, 1); + case VK_SURFACE_TRANSFORM_ROTATE_180_BIT_KHR: + return SkMatrix::MakeAll(-1, 0, width, 0, -1, height, 0, 0, 1); + case VK_SURFACE_TRANSFORM_ROTATE_270_BIT_KHR: + return SkMatrix::MakeAll(0, 1, 0, -1, 0, width, 0, 0, 1); + case VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_BIT_KHR: + return SkMatrix::MakeAll(-1, 0, width, 0, 1, 0, 0, 0, 1); + case VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_90_BIT_KHR: + return SkMatrix::MakeAll(0, -1, height, -1, 0, width, 0, 0, 1); + case VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_180_BIT_KHR: + return SkMatrix::MakeAll(1, 0, 0, 0, -1, height, 0, 0, 1); + case VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_270_BIT_KHR: + return SkMatrix::MakeAll(0, 1, 0, 1, 0, 0, 0, 0, 1); + default: + LOG_ALWAYS_FATAL("Unsupported pre transform of swapchain."); + } + return SkMatrix::I(); +} + + SkSurface* VulkanManager::getBackbufferSurface(VulkanSurface** surfaceOut) { // Recreate VulkanSurface, if ANativeWindow has been resized. VulkanSurface* surface = *surfaceOut; @@ -516,7 +542,7 @@ SkSurface* VulkanManager::getBackbufferSurface(VulkanSurface** surfaceOut) { // maybe use attach somehow? but need a Window return nullptr; } - if (VK_ERROR_OUT_OF_DATE_KHR == res) { + if (VK_ERROR_OUT_OF_DATE_KHR == res || VK_SUBOPTIMAL_KHR == res) { // tear swapchain down and try again if (!createSwapchain(surface)) { return nullptr; @@ -595,6 +621,10 @@ SkSurface* VulkanManager::getBackbufferSurface(VulkanSurface** surfaceOut) { } backendRT.setVkImageLayout(VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL); + surface->mPreTransform = getPreTransformMatrix(surface->windowWidth(), + surface->windowHeight(), + surface->mTransform); + surface->mBackbuffer = std::move(skSurface); return surface->mBackbuffer.get(); } @@ -749,6 +779,17 @@ bool VulkanManager::createSwapchain(VulkanSurface* surface) { return false; } + if (!SkToBool(caps.supportedTransforms & VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR)) { + return false; + } + VkSurfaceTransformFlagBitsKHR transform; + if (SkToBool(caps.supportedTransforms & caps.currentTransform) && + !SkToBool(caps.currentTransform & VK_SURFACE_TRANSFORM_INHERIT_BIT_KHR)) { + transform = caps.currentTransform; + } else { + transform = VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR; + } + VkExtent2D extent = caps.currentExtent; // clamp width; to handle currentExtent of -1 and protect us from broken hints if (extent.width < caps.minImageExtent.width) { @@ -760,6 +801,16 @@ bool VulkanManager::createSwapchain(VulkanSurface* surface) { extent.height = caps.minImageExtent.height; } SkASSERT(extent.height <= caps.maxImageExtent.height); + + VkExtent2D swapExtent = extent; + if (transform == VK_SURFACE_TRANSFORM_ROTATE_90_BIT_KHR || + transform == VK_SURFACE_TRANSFORM_ROTATE_270_BIT_KHR || + transform == VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_90_BIT_KHR || + transform == VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_270_BIT_KHR) { + swapExtent.width = extent.height; + swapExtent.height = extent.width; + } + surface->mWindowWidth = extent.width; surface->mWindowHeight = extent.height; @@ -775,7 +826,7 @@ bool VulkanManager::createSwapchain(VulkanSurface* surface) { VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT; SkASSERT((caps.supportedUsageFlags & usageFlags) == usageFlags); - SkASSERT(caps.supportedTransforms & caps.currentTransform); + SkASSERT(caps.supportedCompositeAlpha & (VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR | VK_COMPOSITE_ALPHA_INHERIT_BIT_KHR)); VkCompositeAlphaFlagBitsKHR composite_alpha = @@ -822,7 +873,7 @@ bool VulkanManager::createSwapchain(VulkanSurface* surface) { swapchainCreateInfo.minImageCount = imageCount; swapchainCreateInfo.imageFormat = surfaceFormat; swapchainCreateInfo.imageColorSpace = colorSpace; - swapchainCreateInfo.imageExtent = extent; + swapchainCreateInfo.imageExtent = swapExtent; swapchainCreateInfo.imageArrayLayers = 1; swapchainCreateInfo.imageUsage = usageFlags; @@ -837,7 +888,7 @@ bool VulkanManager::createSwapchain(VulkanSurface* surface) { swapchainCreateInfo.pQueueFamilyIndices = nullptr; } - swapchainCreateInfo.preTransform = VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR; + swapchainCreateInfo.preTransform = transform; swapchainCreateInfo.compositeAlpha = composite_alpha; swapchainCreateInfo.presentMode = mode; swapchainCreateInfo.clipped = true; @@ -848,6 +899,8 @@ bool VulkanManager::createSwapchain(VulkanSurface* surface) { return false; } + surface->mTransform = transform; + // destroy the old swapchain if (swapchainCreateInfo.oldSwapchain != VK_NULL_HANDLE) { mDeviceWaitIdle(mDevice); @@ -857,7 +910,7 @@ bool VulkanManager::createSwapchain(VulkanSurface* surface) { mDestroySwapchainKHR(mDevice, swapchainCreateInfo.oldSwapchain, nullptr); } - createBuffers(surface, surfaceFormat, extent); + createBuffers(surface, surfaceFormat, swapExtent); // The window content is not updated (frozen) until a buffer of the window size is received. // This prevents temporary stretching of the window after it is resized, but before the first diff --git a/libs/hwui/renderthread/VulkanManager.h b/libs/hwui/renderthread/VulkanManager.h index 105ee093a057..b06eb82dac79 100644 --- a/libs/hwui/renderthread/VulkanManager.h +++ b/libs/hwui/renderthread/VulkanManager.h @@ -45,6 +45,14 @@ public: sk_sp<SkSurface> getBackBufferSurface() { return mBackbuffer; } + // The width and height are are the logical width and height for when submitting draws to the + // surface. In reality if the window is rotated the underlying VkImage may have the width and + // height swapped. + int windowWidth() const { return mWindowWidth; } + int windowHeight() const { return mWindowHeight; } + + SkMatrix& preTransform() { return mPreTransform; } + private: friend class VulkanManager; struct BackbufferInfo { @@ -84,6 +92,8 @@ private: sk_sp<SkColorSpace> mColorSpace; SkColorSpace::Gamut mColorGamut; SkColorType mColorType; + VkSurfaceTransformFlagBitsKHR mTransform = VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR; + SkMatrix mPreTransform; }; // This class contains the shared global Vulkan objects, such as VkInstance, VkDevice and VkQueue, diff --git a/libs/hwui/tests/unit/SkiaPipelineTests.cpp b/libs/hwui/tests/unit/SkiaPipelineTests.cpp index 3c06dab36fe4..e86cf42fee4d 100644 --- a/libs/hwui/tests/unit/SkiaPipelineTests.cpp +++ b/libs/hwui/tests/unit/SkiaPipelineTests.cpp @@ -51,7 +51,8 @@ RENDERTHREAD_SKIA_PIPELINE_TEST(SkiaPipeline, renderFrame) { auto surface = SkSurface::MakeRasterN32Premul(1, 1); surface->getCanvas()->drawColor(SK_ColorBLUE, SkBlendMode::kSrcOver); ASSERT_EQ(TestUtils::getColor(surface, 0, 0), SK_ColorBLUE); - pipeline->renderFrame(layerUpdateQueue, dirty, renderNodes, opaque, contentDrawBounds, surface); + pipeline->renderFrame(layerUpdateQueue, dirty, renderNodes, opaque, contentDrawBounds, surface, + SkMatrix::I()); ASSERT_EQ(TestUtils::getColor(surface, 0, 0), SK_ColorRED); } @@ -83,7 +84,8 @@ RENDERTHREAD_SKIA_PIPELINE_TEST(SkiaPipeline, testOnPrepareTree) { ASSERT_EQ(TestUtils::getColor(surface, 0, 0), SK_ColorBLUE); // drawFrame will crash if "SkiaPipeline::onPrepareTree" did not clean invalid VD pointer - pipeline->renderFrame(layerUpdateQueue, dirty, renderNodes, opaque, contentDrawBounds, surface); + pipeline->renderFrame(layerUpdateQueue, dirty, renderNodes, opaque, contentDrawBounds, surface, + SkMatrix::I()); ASSERT_EQ(TestUtils::getColor(surface, 0, 0), SK_ColorRED); } @@ -104,10 +106,12 @@ RENDERTHREAD_SKIA_PIPELINE_TEST(SkiaPipeline, renderFrameCheckOpaque) { auto surface = SkSurface::MakeRasterN32Premul(2, 2); surface->getCanvas()->drawColor(SK_ColorBLUE, SkBlendMode::kSrcOver); ASSERT_EQ(TestUtils::getColor(surface, 0, 0), SK_ColorBLUE); - pipeline->renderFrame(layerUpdateQueue, dirty, renderNodes, true, contentDrawBounds, surface); + pipeline->renderFrame(layerUpdateQueue, dirty, renderNodes, true, contentDrawBounds, surface, + SkMatrix::I()); ASSERT_EQ(TestUtils::getColor(surface, 0, 0), SK_ColorBLUE); ASSERT_EQ(TestUtils::getColor(surface, 0, 1), SK_ColorGREEN); - pipeline->renderFrame(layerUpdateQueue, dirty, renderNodes, false, contentDrawBounds, surface); + pipeline->renderFrame(layerUpdateQueue, dirty, renderNodes, false, contentDrawBounds, surface, + SkMatrix::I()); ASSERT_EQ(TestUtils::getColor(surface, 0, 0), (unsigned int)SK_ColorTRANSPARENT); ASSERT_EQ(TestUtils::getColor(surface, 0, 1), SK_ColorGREEN); } @@ -126,7 +130,8 @@ RENDERTHREAD_SKIA_PIPELINE_TEST(SkiaPipeline, renderFrameCheckDirtyRect) { auto surface = SkSurface::MakeRasterN32Premul(2, 2); surface->getCanvas()->drawColor(SK_ColorBLUE, SkBlendMode::kSrcOver); ASSERT_EQ(TestUtils::getColor(surface, 0, 0), SK_ColorBLUE); - pipeline->renderFrame(layerUpdateQueue, dirty, renderNodes, true, contentDrawBounds, surface); + pipeline->renderFrame(layerUpdateQueue, dirty, renderNodes, true, contentDrawBounds, surface, + SkMatrix::I()); ASSERT_EQ(TestUtils::getColor(surface, 0, 0), SK_ColorBLUE); ASSERT_EQ(TestUtils::getColor(surface, 1, 0), SK_ColorBLUE); ASSERT_EQ(TestUtils::getColor(surface, 0, 1), SK_ColorRED); @@ -198,32 +203,38 @@ RENDERTHREAD_SKIA_PIPELINE_TEST(SkiaPipeline, renderOverdraw) { ASSERT_EQ(TestUtils::getColor(surface, 0, 0), SK_ColorBLUE); // Single draw, should be white. - pipeline->renderFrame(layerUpdateQueue, dirty, renderNodes, opaque, contentDrawBounds, surface); + pipeline->renderFrame(layerUpdateQueue, dirty, renderNodes, opaque, contentDrawBounds, surface, + SkMatrix::I()); ASSERT_EQ(TestUtils::getColor(surface, 0, 0), SK_ColorWHITE); // 1 Overdraw, should be blue blended onto white. renderNodes.push_back(whiteNode); - pipeline->renderFrame(layerUpdateQueue, dirty, renderNodes, opaque, contentDrawBounds, surface); + pipeline->renderFrame(layerUpdateQueue, dirty, renderNodes, opaque, contentDrawBounds, surface, + SkMatrix::I()); ASSERT_EQ(TestUtils::getColor(surface, 0, 0), (unsigned)0xffd0d0ff); // 2 Overdraw, should be green blended onto white renderNodes.push_back(whiteNode); - pipeline->renderFrame(layerUpdateQueue, dirty, renderNodes, opaque, contentDrawBounds, surface); + pipeline->renderFrame(layerUpdateQueue, dirty, renderNodes, opaque, contentDrawBounds, surface, + SkMatrix::I()); ASSERT_EQ(TestUtils::getColor(surface, 0, 0), (unsigned)0xffd0ffd0); // 3 Overdraw, should be pink blended onto white. renderNodes.push_back(whiteNode); - pipeline->renderFrame(layerUpdateQueue, dirty, renderNodes, opaque, contentDrawBounds, surface); + pipeline->renderFrame(layerUpdateQueue, dirty, renderNodes, opaque, contentDrawBounds, surface, + SkMatrix::I()); ASSERT_EQ(TestUtils::getColor(surface, 0, 0), (unsigned)0xffffc0c0); // 4 Overdraw, should be red blended onto white. renderNodes.push_back(whiteNode); - pipeline->renderFrame(layerUpdateQueue, dirty, renderNodes, opaque, contentDrawBounds, surface); + pipeline->renderFrame(layerUpdateQueue, dirty, renderNodes, opaque, contentDrawBounds, surface, + SkMatrix::I()); ASSERT_EQ(TestUtils::getColor(surface, 0, 0), (unsigned)0xffff8080); // 5 Overdraw, should be red blended onto white. renderNodes.push_back(whiteNode); - pipeline->renderFrame(layerUpdateQueue, dirty, renderNodes, opaque, contentDrawBounds, surface); + pipeline->renderFrame(layerUpdateQueue, dirty, renderNodes, opaque, contentDrawBounds, surface, + SkMatrix::I()); ASSERT_EQ(TestUtils::getColor(surface, 0, 0), (unsigned)0xffff8080); } @@ -308,7 +319,8 @@ RENDERTHREAD_SKIA_PIPELINE_TEST(SkiaPipeline, deferRenderNodeScene) { SkRect dirty = SkRect::MakeWH(800, 600); auto pipeline = std::make_unique<SkiaOpenGLPipeline>(renderThread); sk_sp<DeferLayer<DeferTestCanvas>> surface(new DeferLayer<DeferTestCanvas>()); - pipeline->renderFrame(layerUpdateQueue, dirty, nodes, true, contentDrawBounds, surface); + pipeline->renderFrame(layerUpdateQueue, dirty, nodes, true, contentDrawBounds, surface, + SkMatrix::I()); EXPECT_EQ(4, surface->canvas()->mDrawCounter); } @@ -339,7 +351,43 @@ RENDERTHREAD_SKIA_PIPELINE_TEST(SkiaPipeline, clipped) { auto pipeline = std::make_unique<SkiaOpenGLPipeline>(renderThread); sk_sp<DeferLayer<ClippedTestCanvas>> surface(new DeferLayer<ClippedTestCanvas>()); pipeline->renderFrame(layerUpdateQueue, dirty, nodes, true, - SkRect::MakeWH(CANVAS_WIDTH, CANVAS_HEIGHT), surface); + SkRect::MakeWH(CANVAS_WIDTH, CANVAS_HEIGHT), surface, SkMatrix::I()); + EXPECT_EQ(1, surface->canvas()->mDrawCounter); +} + +// Test renderFrame with a dirty clip and a pre-transform matrix. +RENDERTHREAD_SKIA_PIPELINE_TEST(SkiaPipeline, clipped_rotated) { + static const int CANVAS_WIDTH = 200; + static const int CANVAS_HEIGHT = 100; + static const SkMatrix rotateMatrix = SkMatrix::MakeAll(0, -1, CANVAS_HEIGHT, 1, 0, 0, 0, 0, 1); + static const SkRect dirty = SkRect::MakeLTRB(10, 20, 20, 40); + class ClippedTestCanvas : public SkCanvas { + public: + ClippedTestCanvas() : SkCanvas(CANVAS_WIDTH, CANVAS_HEIGHT) {} + void onDrawImage(const SkImage*, SkScalar dx, SkScalar dy, const SkPaint*) override { + EXPECT_EQ(0, mDrawCounter++); + // Expect clip to be rotated. + EXPECT_EQ(SkRect::MakeLTRB(CANVAS_HEIGHT - dirty.fTop - dirty.height(), dirty.fLeft, + CANVAS_HEIGHT - dirty.fTop, dirty.fLeft + dirty.width()), + TestUtils::getClipBounds(this)); + EXPECT_EQ(rotateMatrix, getTotalMatrix()); + } + int mDrawCounter = 0; + }; + + std::vector<sp<RenderNode>> nodes; + nodes.push_back(TestUtils::createSkiaNode( + 0, 0, CANVAS_WIDTH, CANVAS_HEIGHT, + [](RenderProperties& props, SkiaRecordingCanvas& canvas) { + sk_sp<Bitmap> bitmap(TestUtils::createBitmap(CANVAS_WIDTH, CANVAS_HEIGHT)); + canvas.drawBitmap(*bitmap, 0, 0, nullptr); + })); + + LayerUpdateQueue layerUpdateQueue; + auto pipeline = std::make_unique<SkiaOpenGLPipeline>(renderThread); + sk_sp<DeferLayer<ClippedTestCanvas>> surface(new DeferLayer<ClippedTestCanvas>()); + pipeline->renderFrame(layerUpdateQueue, dirty, nodes, true, + SkRect::MakeWH(CANVAS_WIDTH, CANVAS_HEIGHT), surface, rotateMatrix); EXPECT_EQ(1, surface->canvas()->mDrawCounter); } @@ -369,7 +417,7 @@ RENDERTHREAD_SKIA_PIPELINE_TEST(SkiaPipeline, clip_replace) { auto pipeline = std::make_unique<SkiaOpenGLPipeline>(renderThread); sk_sp<DeferLayer<ClipReplaceTestCanvas>> surface(new DeferLayer<ClipReplaceTestCanvas>()); pipeline->renderFrame(layerUpdateQueue, dirty, nodes, true, - SkRect::MakeWH(CANVAS_WIDTH, CANVAS_HEIGHT), surface); + SkRect::MakeWH(CANVAS_WIDTH, CANVAS_HEIGHT), surface, SkMatrix::I()); EXPECT_EQ(1, surface->canvas()->mDrawCounter); } diff --git a/libs/input/PointerController.cpp b/libs/input/PointerController.cpp index b4f19c99c6fe..d742cc34b57e 100644 --- a/libs/input/PointerController.cpp +++ b/libs/input/PointerController.cpp @@ -255,7 +255,7 @@ void PointerController::setPresentation(Presentation presentation) { if (presentation == PRESENTATION_POINTER && mLocked.additionalMouseResources.empty()) { mPolicy->loadAdditionalMouseResources(&mLocked.additionalMouseResources, - &mLocked.animationResources); + &mLocked.animationResources, mLocked.viewport.displayId); } if (mLocked.presentation != presentation) { @@ -727,14 +727,14 @@ void PointerController::fadeOutAndReleaseAllSpotsLocked() { } void PointerController::loadResourcesLocked() REQUIRES(mLock) { - mPolicy->loadPointerResources(&mResources); + mPolicy->loadPointerResources(&mResources, mLocked.viewport.displayId); if (mLocked.presentation == PRESENTATION_POINTER) { mLocked.additionalMouseResources.clear(); mLocked.animationResources.clear(); - mPolicy->loadPointerIcon(&mLocked.pointerIcon); + mPolicy->loadPointerIcon(&mLocked.pointerIcon, mLocked.viewport.displayId); mPolicy->loadAdditionalMouseResources(&mLocked.additionalMouseResources, - &mLocked.animationResources); + &mLocked.animationResources, mLocked.viewport.displayId); } mLocked.pointerIconChanged = true; diff --git a/libs/input/PointerController.h b/libs/input/PointerController.h index a32cc42a3342..be057867890d 100644 --- a/libs/input/PointerController.h +++ b/libs/input/PointerController.h @@ -62,10 +62,10 @@ protected: virtual ~PointerControllerPolicyInterface() { } public: - virtual void loadPointerIcon(SpriteIcon* icon) = 0; - virtual void loadPointerResources(PointerResources* outResources) = 0; + virtual void loadPointerIcon(SpriteIcon* icon, int32_t displayId) = 0; + virtual void loadPointerResources(PointerResources* outResources, int32_t displayId) = 0; virtual void loadAdditionalMouseResources(std::map<int32_t, SpriteIcon>* outResources, - std::map<int32_t, PointerAnimation>* outAnimationResources) = 0; + std::map<int32_t, PointerAnimation>* outAnimationResources, int32_t displayId) = 0; virtual int32_t getDefaultPointerIconId() = 0; virtual int32_t getCustomPointerIconId() = 0; }; diff --git a/location/java/android/location/GnssSingleSatCorrection.java b/location/java/android/location/GnssSingleSatCorrection.java index 6c757f949f19..3922d2f9f558 100644 --- a/location/java/android/location/GnssSingleSatCorrection.java +++ b/location/java/android/location/GnssSingleSatCorrection.java @@ -16,11 +16,14 @@ package android.location; +import android.annotation.FloatRange; import android.annotation.Nullable; import android.annotation.SystemApi; import android.os.Parcel; import android.os.Parcelable; +import com.android.internal.util.Preconditions; + /** * A container with measurement corrections for a single visible satellite * @@ -31,9 +34,9 @@ public final class GnssSingleSatCorrection implements Parcelable { /** * Bit mask for {@link #mSingleSatCorrectionFlags} indicating the presence of {@link - * #mSatIsLos}. + * #mProbSatIsLos}. */ - public static final int HAS_SAT_IS_LOS_MASK = 1 << 0; + public static final int HAS_PROB_SAT_IS_LOS_MASK = 1 << 0; /** * Bit mask for {@link #mSingleSatCorrectionFlags} indicating the presence of {@link @@ -78,9 +81,11 @@ public final class GnssSingleSatCorrection implements Parcelable { private float mCarrierFrequencyHz; /** - * True if the satellite is estimated to be in Line-of-Sight condition at the given location. + * The probability that the satellite is estimated to be in Line-of-Sight condition at the given + * location. */ - private boolean mSatIsLos; + @FloatRange(from = 0f, to = 1f) + private float mProbSatIsLos; /** * Excess path length to be subtracted from pseudorange before using it in calculating location. @@ -103,7 +108,7 @@ public final class GnssSingleSatCorrection implements Parcelable { mSatId = builder.mSatId; mConstellationType = builder.mConstellationType; mCarrierFrequencyHz = builder.mCarrierFrequencyHz; - mSatIsLos = builder.mSatIsLos; + mProbSatIsLos = builder.mProbSatIsLos; mExcessPathLengthMeters = builder.mExcessPathLengthMeters; mExcessPathLengthUncertaintyMeters = builder.mExcessPathLengthUncertaintyMeters; mReflectingPlane = builder.mReflectingPlane; @@ -152,9 +157,13 @@ public final class GnssSingleSatCorrection implements Parcelable { return mCarrierFrequencyHz; } - /** True if the satellite is line-of-sight */ - public boolean isSatelliteLineOfSight() { - return mSatIsLos; + /** + * Returns the probability that the satellite is in line-of-sight condition at the given + * location. + */ + @FloatRange(from = 0f, to = 1f) + public float getProbSatIsLos() { + return mProbSatIsLos; } /** @@ -180,9 +189,9 @@ public final class GnssSingleSatCorrection implements Parcelable { return mReflectingPlane; } - /** Returns {@code true} if {@link #isSatelliteLineOfSight()} is valid. */ + /** Returns {@code true} if {@link #getProbSatIsLos()} is valid. */ public boolean hasSatelliteLineOfSight() { - return (mSingleSatCorrectionFlags & HAS_SAT_IS_LOS_MASK) != 0; + return (mSingleSatCorrectionFlags & HAS_PROB_SAT_IS_LOS_MASK) != 0; } /** Returns {@code true} if {@link #getExcessPathLengthMeters()} is valid. */ @@ -215,7 +224,7 @@ public final class GnssSingleSatCorrection implements Parcelable { .setConstellationType(parcel.readInt()) .setSatId(parcel.readInt()) .setCarrierFrequencyHz(parcel.readFloat()) - .setSatIsLos(parcel.readBoolean()) + .setProbSatIsLos(parcel.readFloat()) .setExcessPathLengthMeters(parcel.readFloat()) .setExcessPathLengthUncertaintyMeters(parcel.readFloat()) .setReflectingPlane( @@ -239,7 +248,7 @@ public final class GnssSingleSatCorrection implements Parcelable { builder.append(String.format(format, "ConstellationType = ", mConstellationType)); builder.append(String.format(format, "SatId = ", mSatId)); builder.append(String.format(format, "CarrierFrequencyHz = ", mCarrierFrequencyHz)); - builder.append(String.format(format, "SatIsLos = ", mSatIsLos)); + builder.append(String.format(format, "ProbSatIsLos = ", mProbSatIsLos)); builder.append(String.format(format, "ExcessPathLengthMeters = ", mExcessPathLengthMeters)); builder.append( String.format( @@ -256,7 +265,7 @@ public final class GnssSingleSatCorrection implements Parcelable { parcel.writeInt(mConstellationType); parcel.writeInt(mSatId); parcel.writeFloat(mCarrierFrequencyHz); - parcel.writeBoolean(mSatIsLos); + parcel.writeFloat(mProbSatIsLos); parcel.writeFloat(mExcessPathLengthMeters); parcel.writeFloat(mExcessPathLengthUncertaintyMeters); mReflectingPlane.writeToParcel(parcel, flags); @@ -274,7 +283,7 @@ public final class GnssSingleSatCorrection implements Parcelable { private int mConstellationType; private int mSatId; private float mCarrierFrequencyHz; - private boolean mSatIsLos; + private float mProbSatIsLos; private float mExcessPathLengthMeters; private float mExcessPathLengthUncertaintyMeters; private GnssReflectingPlane mReflectingPlane; @@ -303,10 +312,16 @@ public final class GnssSingleSatCorrection implements Parcelable { return this; } - /** Sets the line=of-sight state of the satellite */ - public Builder setSatIsLos(boolean satIsLos) { - mSatIsLos = satIsLos; - mSingleSatCorrectionFlags = (byte) (mSingleSatCorrectionFlags | HAS_SAT_IS_LOS_MASK); + /** + * Sets the line-of-sight probability of the satellite at the given location in the range + * between 0 and 1. + */ + public Builder setProbSatIsLos(@FloatRange(from = 0f, to = 1f) float probSatIsLos) { + Preconditions.checkArgumentInRange(probSatIsLos, 0, 1, + "probSatIsLos should be between 0 and 1."); + mProbSatIsLos = probSatIsLos; + mSingleSatCorrectionFlags = + (byte) (mSingleSatCorrectionFlags | HAS_PROB_SAT_IS_LOS_MASK); return this; } diff --git a/location/lib/java/com/android/location/provider/ActivityChangedEvent.java b/location/lib/java/com/android/location/provider/ActivityChangedEvent.java deleted file mode 100644 index 843dd670315a..000000000000 --- a/location/lib/java/com/android/location/provider/ActivityChangedEvent.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright (C) 2014 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT 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.location.provider; - -import android.annotation.NonNull; - -import java.security.InvalidParameterException; -import java.util.List; - -/** - * A class representing an event for Activity changes. - * @hide - */ -public class ActivityChangedEvent { - private final List<ActivityRecognitionEvent> mActivityRecognitionEvents; - - public ActivityChangedEvent(List<ActivityRecognitionEvent> activityRecognitionEvents) { - if (activityRecognitionEvents == null) { - throw new InvalidParameterException( - "Parameter 'activityRecognitionEvents' must not be null."); - } - - mActivityRecognitionEvents = activityRecognitionEvents; - } - - @NonNull - public Iterable<ActivityRecognitionEvent> getActivityRecognitionEvents() { - return mActivityRecognitionEvents; - } - - @Override - public String toString() { - StringBuilder builder = new StringBuilder("[ ActivityChangedEvent:"); - - for (ActivityRecognitionEvent event : mActivityRecognitionEvents) { - builder.append("\n "); - builder.append(event.toString()); - } - builder.append("\n]"); - - return builder.toString(); - } -} diff --git a/location/lib/java/com/android/location/provider/ActivityRecognitionEvent.java b/location/lib/java/com/android/location/provider/ActivityRecognitionEvent.java deleted file mode 100644 index e54dea40d690..000000000000 --- a/location/lib/java/com/android/location/provider/ActivityRecognitionEvent.java +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Copyright (C) 2014 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT 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.location.provider; - -/** - * A class that represents an Activity Recognition Event. - * @hide - */ -public class ActivityRecognitionEvent { - private final String mActivity; - private final int mEventType; - private final long mTimestampNs; - - public ActivityRecognitionEvent(String activity, int eventType, long timestampNs) { - mActivity = activity; - mEventType = eventType; - mTimestampNs = timestampNs; - } - - public String getActivity() { - return mActivity; - } - - public int getEventType() { - return mEventType; - } - - public long getTimestampNs() { - return mTimestampNs; - } - - @Override - public String toString() { - String eventString; - switch (mEventType) { - case ActivityRecognitionProvider.EVENT_TYPE_ENTER: - eventString = "Enter"; - break; - case ActivityRecognitionProvider.EVENT_TYPE_EXIT: - eventString = "Exit"; - break; - case ActivityRecognitionProvider.EVENT_TYPE_FLUSH_COMPLETE: - eventString = "FlushComplete"; - break; - default: - eventString = "<Invalid>"; - break; - } - - return String.format( - "Activity='%s', EventType=%s(%s), TimestampNs=%s", - mActivity, - eventString, - mEventType, - mTimestampNs); - } -} diff --git a/location/lib/java/com/android/location/provider/ActivityRecognitionProvider.java b/location/lib/java/com/android/location/provider/ActivityRecognitionProvider.java deleted file mode 100644 index 0eff7d3f2014..000000000000 --- a/location/lib/java/com/android/location/provider/ActivityRecognitionProvider.java +++ /dev/null @@ -1,133 +0,0 @@ -/* - * Copyright (C) 2014 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT 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.location.provider; - -import com.android.internal.util.Preconditions; - -import android.hardware.location.IActivityRecognitionHardware; -import android.hardware.location.IActivityRecognitionHardwareSink; -import android.os.RemoteException; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.HashSet; - -/** - * A class that exposes {@link IActivityRecognitionHardware} functionality to unbundled services. - * @hide - */ -public final class ActivityRecognitionProvider { - private final IActivityRecognitionHardware mService; - private final HashSet<Sink> mSinkSet = new HashSet<>(); - - // the following constants must remain in sync with activity_recognition.h - - public static final String ACTIVITY_IN_VEHICLE = "android.activity_recognition.in_vehicle"; - public static final String ACTIVITY_ON_BICYCLE = "android.activity_recognition.on_bicycle"; - public static final String ACTIVITY_WALKING = "android.activity_recognition.walking"; - public static final String ACTIVITY_RUNNING = "android.activity_recognition.running"; - public static final String ACTIVITY_STILL = "android.activity_recognition.still"; - public static final String ACTIVITY_TILTING = "android.activity_recognition.tilting"; - - // NOTE: when adding an additional EVENT_TYPE_, EVENT_TYPE_COUNT needs to be updated in - // android.hardware.location.ActivityRecognitionHardware - public static final int EVENT_TYPE_FLUSH_COMPLETE = 0; - public static final int EVENT_TYPE_ENTER = 1; - public static final int EVENT_TYPE_EXIT = 2; - - // end constants activity_recognition.h - - /** - * Used to receive Activity-Recognition events. - */ - public interface Sink { - void onActivityChanged(ActivityChangedEvent event); - } - - public ActivityRecognitionProvider(IActivityRecognitionHardware service) - throws RemoteException { - Preconditions.checkNotNull(service); - mService = service; - mService.registerSink(new SinkTransport()); - } - - public String[] getSupportedActivities() throws RemoteException { - return mService.getSupportedActivities(); - } - - public boolean isActivitySupported(String activity) throws RemoteException { - return mService.isActivitySupported(activity); - } - - public void registerSink(Sink sink) { - Preconditions.checkNotNull(sink); - synchronized (mSinkSet) { - mSinkSet.add(sink); - } - } - - // TODO: if this functionality is exposed to 3rd party developers, handle unregistration (here - // and in the service) of all sinks while failing to disable all events - public void unregisterSink(Sink sink) { - Preconditions.checkNotNull(sink); - synchronized (mSinkSet) { - mSinkSet.remove(sink); - } - } - - public boolean enableActivityEvent(String activity, int eventType, long reportLatencyNs) - throws RemoteException { - return mService.enableActivityEvent(activity, eventType, reportLatencyNs); - } - - public boolean disableActivityEvent(String activity, int eventType) throws RemoteException { - return mService.disableActivityEvent(activity, eventType); - } - - public boolean flush() throws RemoteException { - return mService.flush(); - } - - private final class SinkTransport extends IActivityRecognitionHardwareSink.Stub { - @Override - public void onActivityChanged(android.hardware.location.ActivityChangedEvent event) { - Collection<Sink> sinks; - synchronized (mSinkSet) { - if (mSinkSet.isEmpty()) { - return; - } - sinks = new ArrayList<>(mSinkSet); - } - - // translate the event from platform internal and GmsCore types - ArrayList<ActivityRecognitionEvent> gmsEvents = new ArrayList<>(); - for (android.hardware.location.ActivityRecognitionEvent reportingEvent - : event.getActivityRecognitionEvents()) { - ActivityRecognitionEvent gmsEvent = new ActivityRecognitionEvent( - reportingEvent.getActivity(), - reportingEvent.getEventType(), - reportingEvent.getTimestampNs()); - gmsEvents.add(gmsEvent); - } - ActivityChangedEvent gmsEvent = new ActivityChangedEvent(gmsEvents); - - for (Sink sink : sinks) { - sink.onActivityChanged(gmsEvent); - } - } - } -} diff --git a/location/lib/java/com/android/location/provider/ActivityRecognitionProviderClient.java b/location/lib/java/com/android/location/provider/ActivityRecognitionProviderClient.java deleted file mode 100644 index 326d901b9daa..000000000000 --- a/location/lib/java/com/android/location/provider/ActivityRecognitionProviderClient.java +++ /dev/null @@ -1,76 +0,0 @@ -/* - * Copyright (C) 2015 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License - */ - -package com.android.location.provider; - -import android.annotation.NonNull; -import android.hardware.location.IActivityRecognitionHardware; -import android.hardware.location.IActivityRecognitionHardwareClient; -import android.os.Binder; -import android.os.IBinder; -import android.os.Process; -import android.os.RemoteException; -import android.util.Log; - -/** - * A client class for interaction with an Activity-Recognition provider. - * @hide - */ -public abstract class ActivityRecognitionProviderClient { - private static final String TAG = "ArProviderClient"; - - protected ActivityRecognitionProviderClient() {} - - private IActivityRecognitionHardwareClient.Stub mClient = - new IActivityRecognitionHardwareClient.Stub() { - @Override - public void onAvailabilityChanged( - boolean isSupported, - IActivityRecognitionHardware instance) { - int callingUid = Binder.getCallingUid(); - if (callingUid != Process.SYSTEM_UID) { - Log.d(TAG, "Ignoring calls from non-system server. Uid: " + callingUid); - return; - } - ActivityRecognitionProvider provider; - try { - provider = isSupported ? new ActivityRecognitionProvider(instance) : null; - } catch (RemoteException e) { - Log.e(TAG, "Error creating Hardware Activity-Recognition Provider.", e); - return; - } - onProviderChanged(isSupported, provider); - } - }; - - /** - * Gets the binder needed to interact with proxy provider in the platform. - */ - @NonNull - public IBinder getBinder() { - return mClient; - } - - /** - * Called when a change in the availability of {@link ActivityRecognitionProvider} is detected. - * - * @param isSupported whether the platform supports the provider natively - * @param instance the available provider's instance - */ - public abstract void onProviderChanged( - boolean isSupported, - ActivityRecognitionProvider instance); -} diff --git a/location/lib/java/com/android/location/provider/ActivityRecognitionProviderWatcher.java b/location/lib/java/com/android/location/provider/ActivityRecognitionProviderWatcher.java deleted file mode 100644 index 42f77b42766f..000000000000 --- a/location/lib/java/com/android/location/provider/ActivityRecognitionProviderWatcher.java +++ /dev/null @@ -1,90 +0,0 @@ -/* - * Copyright (C) 2014 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT 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.location.provider; - -import android.annotation.NonNull; -import android.annotation.Nullable; -import android.hardware.location.IActivityRecognitionHardware; -import android.hardware.location.IActivityRecognitionHardwareWatcher; -import android.os.Binder; -import android.os.IBinder; -import android.os.Process; -import android.os.RemoteException; -import android.util.Log; - -/** - * A watcher class for Activity-Recognition instances. - * - * @deprecated use {@link ActivityRecognitionProviderClient} instead. - * @hide - */ -@Deprecated -public class ActivityRecognitionProviderWatcher { - private static final String TAG = "ActivityRecognitionProviderWatcher"; - - private static ActivityRecognitionProviderWatcher sWatcher; - private static final Object sWatcherLock = new Object(); - - private ActivityRecognitionProvider mActivityRecognitionProvider; - - private ActivityRecognitionProviderWatcher() {} - - public static ActivityRecognitionProviderWatcher getInstance() { - synchronized (sWatcherLock) { - if (sWatcher == null) { - sWatcher = new ActivityRecognitionProviderWatcher(); - } - return sWatcher; - } - } - - private IActivityRecognitionHardwareWatcher.Stub mWatcherStub = - new IActivityRecognitionHardwareWatcher.Stub() { - @Override - public void onInstanceChanged(IActivityRecognitionHardware instance) { - int callingUid = Binder.getCallingUid(); - if (callingUid != Process.SYSTEM_UID) { - Log.d(TAG, "Ignoring calls from non-system server. Uid: " + callingUid); - return; - } - - try { - mActivityRecognitionProvider = new ActivityRecognitionProvider(instance); - } catch (RemoteException e) { - Log.e(TAG, "Error creating Hardware Activity-Recognition", e); - } - } - }; - - /** - * Gets the binder needed to interact with proxy provider in the platform. - */ - @NonNull - public IBinder getBinder() { - return mWatcherStub; - } - - /** - * Gets an object that supports the functionality of {@link ActivityRecognitionProvider}. - * - * @return Non-null value if the functionality is supported by the platform, false otherwise. - */ - @Nullable - public ActivityRecognitionProvider getActivityRecognitionProvider() { - return mActivityRecognitionProvider; - } -} diff --git a/location/tests/locationtests/src/android/location/GnssMeasurementCorrectionsTest.java b/location/tests/locationtests/src/android/location/GnssMeasurementCorrectionsTest.java index c18d58f9a704..d6227bbfcd0d 100644 --- a/location/tests/locationtests/src/android/location/GnssMeasurementCorrectionsTest.java +++ b/location/tests/locationtests/src/android/location/GnssMeasurementCorrectionsTest.java @@ -59,7 +59,7 @@ public class GnssMeasurementCorrectionsTest extends TestCase { assertEquals(GnssStatus.CONSTELLATION_GPS, singleSatCorrection.getConstellationType()); assertEquals(11, singleSatCorrection.getSatId()); assertEquals(1575430000f, singleSatCorrection.getCarrierFrequencyHz()); - assertEquals(false, singleSatCorrection.isSatelliteLineOfSight()); + assertEquals(0.9f, singleSatCorrection.getProbSatIsLos()); assertEquals(50.0f, singleSatCorrection.getExcessPathLengthMeters()); assertEquals(55.0f, singleSatCorrection.getExcessPathLengthUncertaintyMeters()); GnssReflectingPlane reflectingPlane = singleSatCorrection.getReflectingPlane(); @@ -88,7 +88,7 @@ public class GnssMeasurementCorrectionsTest extends TestCase { .setConstellationType(GnssStatus.CONSTELLATION_GPS) .setSatId(11) .setCarrierFrequencyHz(1575430000f) - .setSatIsLos(false) + .setProbSatIsLos(0.9f) .setExcessPathLengthMeters(50.0f) .setExcessPathLengthUncertaintyMeters(55.0f) .setReflectingPlane(generateTestReflectingPlane()); diff --git a/location/tests/locationtests/src/android/location/GnssSingleSatCorrectionsTest.java b/location/tests/locationtests/src/android/location/GnssSingleSatCorrectionsTest.java index 2e54ae463595..f358806d0b26 100644 --- a/location/tests/locationtests/src/android/location/GnssSingleSatCorrectionsTest.java +++ b/location/tests/locationtests/src/android/location/GnssSingleSatCorrectionsTest.java @@ -44,7 +44,7 @@ public class GnssSingleSatCorrectionsTest extends TestCase { assertEquals(GnssStatus.CONSTELLATION_GALILEO, singleSatCorrection.getConstellationType()); assertEquals(12, singleSatCorrection.getSatId()); assertEquals(1575420000f, singleSatCorrection.getCarrierFrequencyHz()); - assertEquals(true, singleSatCorrection.isSatelliteLineOfSight()); + assertEquals(0.1f, singleSatCorrection.getProbSatIsLos()); assertEquals(10.0f, singleSatCorrection.getExcessPathLengthMeters()); assertEquals(5.0f, singleSatCorrection.getExcessPathLengthUncertaintyMeters()); GnssReflectingPlane reflectingPlane = singleSatCorrection.getReflectingPlane(); @@ -58,7 +58,7 @@ public class GnssSingleSatCorrectionsTest extends TestCase { .setConstellationType(singleSatCorr.getConstellationType()) .setSatId(singleSatCorr.getSatId()) .setCarrierFrequencyHz(singleSatCorr.getCarrierFrequencyHz()) - .setSatIsLos(singleSatCorr.isSatelliteLineOfSight()) + .setProbSatIsLos(singleSatCorr.getProbSatIsLos()) .setExcessPathLengthMeters(singleSatCorr.getExcessPathLengthMeters()) .setExcessPathLengthUncertaintyMeters( singleSatCorr.getExcessPathLengthUncertaintyMeters()) @@ -72,7 +72,7 @@ public class GnssSingleSatCorrectionsTest extends TestCase { .setConstellationType(GnssStatus.CONSTELLATION_GALILEO) .setSatId(12) .setCarrierFrequencyHz(1575420000f) - .setSatIsLos(true) + .setProbSatIsLos(0.1f) .setExcessPathLengthMeters(10.0f) .setExcessPathLengthUncertaintyMeters(5.0f) .setReflectingPlane(GnssReflectingPlaneTest.generateTestReflectingPlane()); diff --git a/media/Android.bp b/media/Android.bp index d5da6f266952..8ebc91a06f7a 100644 --- a/media/Android.bp +++ b/media/Android.bp @@ -1,4 +1,21 @@ java_library { + name: "media1", + + srcs: [ + ":media1-srcs", + ], + + sdk_version: "system_current", +} + +filegroup { + name: "media1-srcs", + srcs: [ + "java/android/media/session/MediaSessionProviderService.java", + ], +} + +java_library { // TODO: include media2.jar in the media apex and add it to the bootclasspath. name: "media2", diff --git a/media/java/android/media/AudioAttributes.java b/media/java/android/media/AudioAttributes.java index 4f23cca1171f..f5a6f8667fa6 100644 --- a/media/java/android/media/AudioAttributes.java +++ b/media/java/android/media/AudioAttributes.java @@ -736,8 +736,9 @@ public final class AudioAttributes implements Parcelable { * @param preset one of {@link MediaRecorder.AudioSource#DEFAULT}, * {@link MediaRecorder.AudioSource#MIC}, {@link MediaRecorder.AudioSource#CAMCORDER}, * {@link MediaRecorder.AudioSource#VOICE_RECOGNITION}, - * {@link MediaRecorder.AudioSource#VOICE_COMMUNICATION} or - * {@link MediaRecorder.AudioSource#UNPROCESSED} + * {@link MediaRecorder.AudioSource#VOICE_COMMUNICATION}, + * {@link MediaRecorder.AudioSource#UNPROCESSED} or + * {@link MediaRecorder.AudioSource#VOICE_PERFORMANCE} * @return the same Builder instance. */ @SystemApi @@ -749,6 +750,7 @@ public final class AudioAttributes implements Parcelable { case MediaRecorder.AudioSource.VOICE_RECOGNITION: case MediaRecorder.AudioSource.VOICE_COMMUNICATION: case MediaRecorder.AudioSource.UNPROCESSED: + case MediaRecorder.AudioSource.VOICE_PERFORMANCE: mSource = preset; break; default: @@ -760,7 +762,7 @@ public final class AudioAttributes implements Parcelable { /** * @hide * Same as {@link #setCapturePreset(int)} but authorizes the use of HOTWORD, - * REMOTE_SUBMIX, RADIO_TUNER, VOICE_DOWNLINK, VOICE_UPLINK and VOICE_CALL. + * REMOTE_SUBMIX, RADIO_TUNER, VOICE_DOWNLINK, VOICE_UPLINK, VOICE_CALL and ECHO_REFERENCE. * @param preset * @return the same Builder instance. */ @@ -771,7 +773,8 @@ public final class AudioAttributes implements Parcelable { || (preset == MediaRecorder.AudioSource.RADIO_TUNER) || (preset == MediaRecorder.AudioSource.VOICE_DOWNLINK) || (preset == MediaRecorder.AudioSource.VOICE_UPLINK) - || (preset == MediaRecorder.AudioSource.VOICE_CALL)) { + || (preset == MediaRecorder.AudioSource.VOICE_CALL) + || (preset == MediaRecorder.AudioSource.ECHO_REFERENCE)) { mSource = preset; } else { setCapturePreset(preset); diff --git a/media/java/android/media/AudioManager.java b/media/java/android/media/AudioManager.java index 30b5480fba55..202a3cf1d930 100644 --- a/media/java/android/media/AudioManager.java +++ b/media/java/android/media/AudioManager.java @@ -3802,6 +3802,12 @@ public class AudioManager { public static final int DEVICE_IN_HDMI = AudioSystem.DEVICE_IN_HDMI; /** @hide + * The audio input device code for HDMI ARC + */ + public static final int DEVICE_IN_HDMI_ARC = + AudioSystem.DEVICE_IN_HDMI_ARC; + + /** @hide * The audio input device code for telephony voice RX path */ public static final int DEVICE_IN_TELEPHONY_RX = diff --git a/media/java/android/media/AudioRecord.java b/media/java/android/media/AudioRecord.java index 33f81f1db69c..92afe7ede8f2 100644 --- a/media/java/android/media/AudioRecord.java +++ b/media/java/android/media/AudioRecord.java @@ -61,7 +61,8 @@ import java.util.concurrent.Executor; * been read yet. Data should be read from the audio hardware in chunks of sizes inferior to * the total recording buffer size. */ -public class AudioRecord implements AudioRouting, AudioRecordingMonitor, AudioRecordingMonitorClient +public class AudioRecord implements AudioRouting, MicrophoneDirection, + AudioRecordingMonitor, AudioRecordingMonitorClient { //--------------------------------------------------------- // Constants @@ -1657,7 +1658,6 @@ public class AudioRecord implements AudioRouting, AudioRecordingMonitor, AudioRe return activeMicrophones; } - //-------------------------------------------------------------------------- // Implementation of AudioRecordingMonitor interface //-------------------- @@ -1707,6 +1707,33 @@ public class AudioRecord implements AudioRouting, AudioRecordingMonitor, AudioRe return native_getPortId(); } + //-------------------------------------------------------------------------- + // MicrophoneDirection + //-------------------- + /** + * Specifies the logical microphone (for processing). + * + * @param direction Direction constant (MicrophoneDirection.MIC_DIRECTION_*) + * @return retval OK if the call is successful, an error code otherwise. + * @hide + */ + public int setMicrophoneDirection(int direction) { + return native_set_microphone_direction(direction); + } + + /** + * Specifies the zoom factor (i.e. the field dimension) for the selected microphone + * (for processing). The selected microphone is determined by the use-case for the stream. + * + * @param zoom the desired field dimension of microphone capture. Range is from -1 (wide angle), + * though 0 (no zoom) to 1 (maximum zoom). + * @return retval OK if the call is successful, an error code otherwise. + * @hide + */ + public int setMicrophoneFieldDimension(float zoom) { + return native_set_microphone_field_dimension(zoom); + } + //--------------------------------------------------------- // Interface definitions //-------------------- @@ -1860,6 +1887,9 @@ public class AudioRecord implements AudioRouting, AudioRecordingMonitor, AudioRe private native int native_getPortId(); + private native int native_set_microphone_direction(int direction); + private native int native_set_microphone_field_dimension(float zoom); + //--------------------------------------------------------- // Utility methods //------------------ diff --git a/media/java/android/media/AudioRecordingConfiguration.java b/media/java/android/media/AudioRecordingConfiguration.java index de76aeff82c4..52771e4199d8 100644 --- a/media/java/android/media/AudioRecordingConfiguration.java +++ b/media/java/android/media/AudioRecordingConfiguration.java @@ -172,7 +172,8 @@ public final class AudioRecordingConfiguration implements Parcelable { MediaRecorder.AudioSource.CAMCORDER, MediaRecorder.AudioSource.VOICE_RECOGNITION, MediaRecorder.AudioSource.VOICE_COMMUNICATION, - MediaRecorder.AudioSource.UNPROCESSED + MediaRecorder.AudioSource.UNPROCESSED, + MediaRecorder.AudioSource.VOICE_PERFORMANCE }) @Retention(RetentionPolicy.SOURCE) public @interface AudioSource {} diff --git a/media/java/android/media/AudioSystem.java b/media/java/android/media/AudioSystem.java index 45cde0ffecc4..6b7447901cec 100644 --- a/media/java/android/media/AudioSystem.java +++ b/media/java/android/media/AudioSystem.java @@ -541,6 +541,9 @@ public class AudioSystem public static final int DEVICE_IN_BUS = DEVICE_BIT_IN | 0x100000; public static final int DEVICE_IN_PROXY = DEVICE_BIT_IN | 0x1000000; public static final int DEVICE_IN_USB_HEADSET = DEVICE_BIT_IN | 0x2000000; + public static final int DEVICE_IN_BLUETOOTH_BLE = DEVICE_BIT_IN | 0x4000000; + public static final int DEVICE_IN_HDMI_ARC = DEVICE_BIT_IN | 0x8000000; + public static final int DEVICE_IN_ECHO_REFERENCE = DEVICE_BIT_IN | 0x10000000; @UnsupportedAppUsage public static final int DEVICE_IN_DEFAULT = DEVICE_BIT_IN | DEVICE_BIT_DEFAULT; @@ -567,6 +570,9 @@ public class AudioSystem DEVICE_IN_BUS | DEVICE_IN_PROXY | DEVICE_IN_USB_HEADSET | + DEVICE_IN_BLUETOOTH_BLE | + DEVICE_IN_HDMI_ARC | + DEVICE_IN_ECHO_REFERENCE | DEVICE_IN_DEFAULT); public static final int DEVICE_IN_ALL_SCO = DEVICE_IN_BLUETOOTH_SCO_HEADSET; public static final int DEVICE_IN_ALL_USB = (DEVICE_IN_USB_ACCESSORY | @@ -641,6 +647,9 @@ public class AudioSystem public static final String DEVICE_IN_BUS_NAME = "bus"; public static final String DEVICE_IN_PROXY_NAME = "proxy"; public static final String DEVICE_IN_USB_HEADSET_NAME = "usb_headset"; + public static final String DEVICE_IN_BLUETOOTH_BLE_NAME = "bt_ble"; + public static final String DEVICE_IN_ECHO_REFERENCE_NAME = "echo_reference"; + public static final String DEVICE_IN_HDMI_ARC_NAME = "hdmi_arc"; @UnsupportedAppUsage public static String getOutputDeviceName(int device) @@ -757,6 +766,12 @@ public class AudioSystem return DEVICE_IN_PROXY_NAME; case DEVICE_IN_USB_HEADSET: return DEVICE_IN_USB_HEADSET_NAME; + case DEVICE_IN_BLUETOOTH_BLE: + return DEVICE_IN_BLUETOOTH_BLE_NAME; + case DEVICE_IN_ECHO_REFERENCE: + return DEVICE_IN_ECHO_REFERENCE_NAME; + case DEVICE_IN_HDMI_ARC: + return DEVICE_IN_HDMI_ARC_NAME; case DEVICE_IN_DEFAULT: default: return Integer.toString(device); diff --git a/media/java/android/media/Controller2Link.java b/media/java/android/media/Controller2Link.java index a62db5f1fb20..d11f7769ee5e 100644 --- a/media/java/android/media/Controller2Link.java +++ b/media/java/android/media/Controller2Link.java @@ -16,6 +16,7 @@ package android.media; +import android.os.Binder; import android.os.Bundle; import android.os.Parcel; import android.os.Parcelable; @@ -102,6 +103,15 @@ public final class Controller2Link implements Parcelable { } } + /** Interface method for IMediaController2.notifyPlaybackActiveChanged */ + public void notifyPlaybackActiveChanged(int seq, boolean playbackActive) { + try { + mIController.notifyPlaybackActiveChanged(seq, playbackActive); + } catch (RemoteException e) { + throw new RuntimeException(e); + } + } + /** Interface method for IMediaController2.sendSessionCommand */ public void sendSessionCommand(int seq, Session2Command command, Bundle args, ResultReceiver resultReceiver) { @@ -135,6 +145,11 @@ public final class Controller2Link implements Parcelable { mController.onDisconnected(seq); } + /** Stub implementation for IMediaController2.notifyPlaybackActiveChanged */ + public void onPlaybackActiveChanged(int seq, boolean playbackActive) { + mController.onPlaybackActiveChanged(seq, playbackActive); + } + /** Stub implementation for IMediaController2.sendSessionCommand */ public void onSessionCommand(int seq, Session2Command command, Bundle args, ResultReceiver resultReceiver) { @@ -149,23 +164,53 @@ public final class Controller2Link implements Parcelable { private class Controller2Stub extends IMediaController2.Stub { @Override public void notifyConnected(int seq, Bundle connectionResult) { - Controller2Link.this.onConnected(seq, connectionResult); + final long token = Binder.clearCallingIdentity(); + try { + Controller2Link.this.onConnected(seq, connectionResult); + } finally { + Binder.restoreCallingIdentity(token); + } } @Override public void notifyDisconnected(int seq) { - Controller2Link.this.onDisconnected(seq); + final long token = Binder.clearCallingIdentity(); + try { + Controller2Link.this.onDisconnected(seq); + } finally { + Binder.restoreCallingIdentity(token); + } + } + + @Override + public void notifyPlaybackActiveChanged(int seq, boolean playbackActive) { + final long token = Binder.clearCallingIdentity(); + try { + Controller2Link.this.onPlaybackActiveChanged(seq, playbackActive); + } finally { + Binder.restoreCallingIdentity(token); + } } @Override public void sendSessionCommand(int seq, Session2Command command, Bundle args, ResultReceiver resultReceiver) { - Controller2Link.this.onSessionCommand(seq, command, args, resultReceiver); + final long token = Binder.clearCallingIdentity(); + try { + Controller2Link.this.onSessionCommand(seq, command, args, resultReceiver); + } finally { + Binder.restoreCallingIdentity(token); + } } @Override public void cancelSessionCommand(int seq) { - Controller2Link.this.onCancelCommand(seq); + final long token = Binder.clearCallingIdentity(); + try { + Controller2Link.this.onCancelCommand(seq); + } finally { + Binder.restoreCallingIdentity(token); + } } } } diff --git a/media/java/android/media/IMediaController2.aidl b/media/java/android/media/IMediaController2.aidl index ca5394f504cb..42c6e70529ec 100644 --- a/media/java/android/media/IMediaController2.aidl +++ b/media/java/android/media/IMediaController2.aidl @@ -31,8 +31,9 @@ import android.media.Session2Command; oneway interface IMediaController2 { void notifyConnected(int seq, in Bundle connectionResult) = 0; void notifyDisconnected(int seq) = 1; + void notifyPlaybackActiveChanged(int seq, boolean playbackActive) = 2; void sendSessionCommand(int seq, in Session2Command command, in Bundle args, - in ResultReceiver resultReceiver) = 2; - void cancelSessionCommand(int seq) = 3; - // Next Id : 4 + in ResultReceiver resultReceiver) = 3; + void cancelSessionCommand(int seq) = 4; + // Next Id : 5 } diff --git a/media/java/android/media/IMediaSession2Service.aidl b/media/java/android/media/IMediaSession2Service.aidl new file mode 100644 index 000000000000..10ac1be0a36e --- /dev/null +++ b/media/java/android/media/IMediaSession2Service.aidl @@ -0,0 +1,32 @@ +/* + * Copyright 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.media; + +import android.os.Bundle; +import android.media.Controller2Link; + +/** + * Interface from MediaController2 to MediaSession2Service. + * <p> + * Keep this interface oneway. Otherwise a malicious app may implement fake version of this, + * and holds calls from controller to make controller owner(s) frozen. + * @hide + */ +oneway interface IMediaSession2Service { + void connect(in Controller2Link caller, int seq, in Bundle connectionRequest) = 0; + // Next Id : 1 +} diff --git a/media/java/android/media/ImageReader.java b/media/java/android/media/ImageReader.java index 8ec0e353ac73..9ac147b59ee5 100644 --- a/media/java/android/media/ImageReader.java +++ b/media/java/android/media/ImageReader.java @@ -150,7 +150,7 @@ public class ImageReader implements AutoCloseable { * consumer end-points. For example, if the application intends to send the images to * {@link android.media.MediaCodec} or {@link android.media.MediaRecorder} for hardware video * encoding, the format and usage flag combination needs to be - * {@link ImageFormat#PRIVATE PRIVATE} and {@link HardwareBuffer#USAGE0_VIDEO_ENCODE}. When an + * {@link ImageFormat#PRIVATE PRIVATE} and {@link HardwareBuffer#USAGE_VIDEO_ENCODE}. When an * {@link ImageReader} object is created with a valid size and such format/usage flag * combination, the application can send the {@link Image images} to an {@link ImageWriter} that * is created with the input {@link android.view.Surface} provided by the @@ -173,7 +173,7 @@ public class ImageReader implements AutoCloseable { * ImageReaders using other format such as {@link ImageFormat#YUV_420_888 YUV_420_888}. * </p> * <p> - * Note that not all format and usage flag combination is supported by the + * Note that not all format and usage flag combinations are supported by the * {@link ImageReader}. Below are the supported combinations by the {@link ImageReader} * (assuming the consumer end-points support the such image consumption, e.g., hardware video * encoding). @@ -186,13 +186,13 @@ public class ImageReader implements AutoCloseable { * <td>non-{@link android.graphics.ImageFormat#PRIVATE PRIVATE} formats defined by * {@link android.graphics.ImageFormat ImageFormat} or * {@link android.graphics.PixelFormat PixelFormat}</td> - * <td>{@link HardwareBuffer#USAGE0_CPU_READ} or - * {@link HardwareBuffer#USAGE0_CPU_READ_OFTEN}</td> + * <td>{@link HardwareBuffer#USAGE_CPU_READ_RARELY} or + * {@link HardwareBuffer#USAGE_CPU_READ_OFTEN}</td> * </tr> * <tr> * <td>{@link android.graphics.ImageFormat#PRIVATE}</td> - * <td>{@link HardwareBuffer#USAGE0_VIDEO_ENCODE} or - * {@link HardwareBuffer#USAGE0_GPU_SAMPLED_IMAGE}, or combined</td> + * <td>{@link HardwareBuffer#USAGE_VIDEO_ENCODE} or + * {@link HardwareBuffer#USAGE_GPU_SAMPLED_IMAGE}, or combined</td> * </tr> * </table> * Using other combinations may result in {@link IllegalArgumentException}. @@ -208,11 +208,10 @@ public class ImageReader implements AutoCloseable { * become available for access through {@link #acquireLatestImage()} or * {@link #acquireNextImage()}. Must be greater than 0. * @param usage The intended usage of the images produced by this ImageReader. It needs - * to be one of the Usage0 defined by {@link HardwareBuffer}, or an + * to be one of the Usage defined by {@link HardwareBuffer}, or an * {@link IllegalArgumentException} will be thrown. * @see Image * @see HardwareBuffer - * @hide */ public static ImageReader newInstance(int width, int height, int format, int maxImages, long usage) { diff --git a/media/java/android/media/ImageWriter.java b/media/java/android/media/ImageWriter.java index 4c0153f70192..dd09afc3ddb0 100644 --- a/media/java/android/media/ImageWriter.java +++ b/media/java/android/media/ImageWriter.java @@ -168,7 +168,6 @@ public class ImageWriter implements AutoCloseable { * {@link ImageFormat} or {@link PixelFormat}. * * @return a new ImageWriter instance. - * @hide */ public static ImageWriter newInstance(Surface surface, int maxImages, int format) { if (!ImageFormat.isPublicFormat(format) && !PixelFormat.isPublicFormat(format)) { diff --git a/media/java/android/media/MediaCodec.java b/media/java/android/media/MediaCodec.java index bc9500ddb3b7..f756658b4fa8 100644 --- a/media/java/android/media/MediaCodec.java +++ b/media/java/android/media/MediaCodec.java @@ -1829,9 +1829,14 @@ final public class MediaCodec { mBufferLock = new Object(); + // save name used at creation + mNameAtCreation = nameIsType ? null : name; + native_setup(name, nameIsType, encoder); } + private String mNameAtCreation; + @Override protected void finalize() { native_finalize(); @@ -3317,12 +3322,36 @@ final public class MediaCodec { private native void native_setAudioPresentation(int presentationId, int programId); /** - * Get the component name. If the codec was created by createDecoderByType - * or createEncoderByType, what component is chosen is not known beforehand. + * Retrieve the codec name. + * + * If the codec was created by createDecoderByType or createEncoderByType, what component is + * chosen is not known beforehand. This method returns the name of the codec that was + * selected by the platform. + * + * <strong>Note:</strong> Implementations may provide multiple aliases (codec + * names) for the same underlying codec, any of which can be used to instantiate the same + * underlying codec in {@link MediaCodec#createByCodecName}. This method returns the + * name used to create the codec in this case. + * + * @throws IllegalStateException if in the Released state. + */ + @NonNull + public final String getName() { + // get canonical name to handle exception + String canonicalName = getCanonicalName(); + return mNameAtCreation != null ? mNameAtCreation : canonicalName; + } + + /** + * Retrieve the underlying codec name. + * + * This method is similar to {@link #getName}, except that it returns the underlying component + * name even if an alias was used to create this MediaCodec object by name, + * * @throws IllegalStateException if in the Released state. */ @NonNull - public native final String getName(); + public native final String getCanonicalName(); /** * Return Metrics data about the current codec instance. diff --git a/media/java/android/media/MediaCodecInfo.java b/media/java/android/media/MediaCodecInfo.java index 10a1e3a72225..751d57bbdc81 100644 --- a/media/java/android/media/MediaCodecInfo.java +++ b/media/java/android/media/MediaCodecInfo.java @@ -32,8 +32,10 @@ import android.util.Size; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; +import java.util.List; import java.util.Map; import java.util.Set; +import java.util.Vector; /** * Provides information about a given media codec available on the device. You can @@ -61,15 +63,25 @@ import java.util.Set; * */ public final class MediaCodecInfo { - private boolean mIsEncoder; + private static final String TAG = "MediaCodecInfo"; + + private static final int FLAG_IS_ENCODER = (1 << 0); + private static final int FLAG_IS_VENDOR = (1 << 1); + private static final int FLAG_IS_SOFTWARE_ONLY = (1 << 2); + private static final int FLAG_IS_HARDWARE_ACCELERATED = (1 << 3); + + private int mFlags; private String mName; + private String mCanonicalName; private Map<String, CodecCapabilities> mCaps; /* package private */ MediaCodecInfo( - String name, boolean isEncoder, CodecCapabilities[] caps) { + String name, String canonicalName, int flags, CodecCapabilities[] caps) { mName = name; - mIsEncoder = isEncoder; + mCanonicalName = canonicalName; + mFlags = flags; mCaps = new HashMap<String, CodecCapabilities>(); + for (CodecCapabilities c: caps) { mCaps.put(c.getMimeType(), c); } @@ -77,16 +89,69 @@ public final class MediaCodecInfo { /** * Retrieve the codec name. + * + * <strong>Note:</strong> Implementations may provide multiple aliases (codec + * names) for the same underlying codec, any of which can be used to instantiate the same + * underlying codec in {@link MediaCodec#createByCodecName}. + * + * Applications targeting SDK < {@link android.os.Build.VERSION_CODES#Q}, cannot determine if + * the multiple codec names listed in MediaCodecList are in-fact for the same codec. */ + @NonNull public final String getName() { return mName; } /** + * Retrieve the underlying codec name. + * + * Device implementations may provide multiple aliases (codec names) for the same underlying + * codec to maintain backward app compatibility. This method returns the name of the underlying + * codec name, which must not be another alias. For non-aliases this is always the name of the + * codec. + */ + @NonNull + public final String getCanonicalName() { + return mCanonicalName; + } + + /** + * Query if the codec is an alias for another underlying codec. + */ + public final boolean isAlias() { + return !mName.equals(mCanonicalName); + } + + /** * Query if the codec is an encoder. */ public final boolean isEncoder() { - return mIsEncoder; + return (mFlags & FLAG_IS_ENCODER) != 0; + } + + /** + * Query if the codec is provided by the Android platform (false) or the device manufacturer + * (true). + */ + public final boolean isVendor() { + return (mFlags & FLAG_IS_VENDOR) != 0; + } + + /** + * Query if the codec is software only. Software-only codecs are more secure as they run in + * a tighter security sandbox. On the other hand, software-only codecs do not provide any + * performance guarantees. + */ + public final boolean isSoftwareOnly() { + return (mFlags & FLAG_IS_SOFTWARE_ONLY) != 0; + } + + /** + * Query if the codec is hardware accelerated. This attribute is provided by the device + * manufacturer. Note that it cannot be tested for correctness. + */ + public final boolean isHardwareAccelerated() { + return (mFlags & FLAG_IS_HARDWARE_ACCELERATED) != 0; } /** @@ -163,7 +228,7 @@ public final class MediaCodecInfo { // such as B-frame support, arithmetic coding... public CodecProfileLevel[] profileLevels; // NOTE this array is modifiable by user - // from OMX_COLOR_FORMATTYPE + // from MediaCodecConstants /** @deprecated Use {@link #COLOR_Format24bitBGR888}. */ public static final int COLOR_FormatMonochrome = 1; /** @deprecated Use {@link #COLOR_Format24bitBGR888}. */ @@ -344,7 +409,7 @@ public final class MediaCodecInfo { /** @deprecated Use {@link #COLOR_FormatYUV420Flexible}. */ public static final int COLOR_TI_FormatYUV420PackedSemiPlanar = 0x7f000100; // COLOR_FormatSurface indicates that the data will be a GraphicBuffer metadata reference. - // In OMX this is called OMX_COLOR_FormatAndroidOpaque. + // Note: in OMX this is called OMX_COLOR_FormatAndroidOpaque. public static final int COLOR_FormatSurface = 0x7F000789; /** @@ -435,8 +500,7 @@ public final class MediaCodecInfo { public static final int COLOR_QCOM_FormatYUV420SemiPlanar = 0x7fa30c00; /** - * Defined in the OpenMAX IL specs, color format values are drawn from - * OMX_COLOR_FORMATTYPE. + * The color format for the media. This is one of the color constants defined in this class. */ public int[] colorFormats; // NOTE this array is modifiable by user @@ -462,6 +526,26 @@ public final class MediaCodecInfo { public static final String FEATURE_TunneledPlayback = "tunneled-playback"; /** + * If true, the timestamp of each output buffer is derived from the timestamp of the input + * buffer that produced the output. If false, the timestamp of each output buffer is + * derived from the timestamp of the first input buffer. + */ + public static final String FEATURE_DynamicTimestamp = "dynamic-timestamp"; + + /** + * <b>decoder only</b>If true, the codec supports partial (including multiple) access units + * per input buffer. + */ + public static final String FEATURE_FrameParsing = "frame-parsing"; + + /** + * If true, the codec supports multiple access units (for decoding, or to output for + * encoders). If false, the codec only supports single access units. Producing multiple + * access units for output is an optional feature. + */ + public static final String FEATURE_MultipleFrames = "multiple-frames"; + + /** * <b>video decoder only</b>: codec supports queuing partial frames. */ public static final String FEATURE_PartialFrame = "partial-frame"; @@ -497,10 +581,15 @@ public final class MediaCodecInfo { new Feature(FEATURE_SecurePlayback, (1 << 1), false), new Feature(FEATURE_TunneledPlayback, (1 << 2), false), new Feature(FEATURE_PartialFrame, (1 << 3), false), + new Feature(FEATURE_FrameParsing, (1 << 4), false), + new Feature(FEATURE_MultipleFrames, (1 << 5), false), + new Feature(FEATURE_DynamicTimestamp, (1 << 6), false), }; private static final Feature[] encoderFeatures = { new Feature(FEATURE_IntraRefresh, (1 << 0), false), + new Feature(FEATURE_MultipleFrames, (1 << 1), false), + new Feature(FEATURE_DynamicTimestamp, (1 << 2), false), }; /** @hide */ @@ -869,7 +958,7 @@ public final class MediaCodecInfo { CodecCapabilities ret = new CodecCapabilities( new CodecProfileLevel[] { pl }, new int[0], true /* encoder */, - 0 /* flags */, defaultFormat, new MediaFormat() /* info */); + defaultFormat, new MediaFormat() /* info */); if (ret.mError != 0) { return null; } @@ -878,10 +967,10 @@ public final class MediaCodecInfo { /* package private */ CodecCapabilities( CodecProfileLevel[] profLevs, int[] colFmts, - boolean encoder, int flags, + boolean encoder, Map<String, Object>defaultFormatMap, Map<String, Object>capabilitiesMap) { - this(profLevs, colFmts, encoder, flags, + this(profLevs, colFmts, encoder, new MediaFormat(defaultFormatMap), new MediaFormat(capabilitiesMap)); } @@ -889,11 +978,11 @@ public final class MediaCodecInfo { private MediaFormat mCapabilitiesInfo; /* package private */ CodecCapabilities( - CodecProfileLevel[] profLevs, int[] colFmts, boolean encoder, int flags, + CodecProfileLevel[] profLevs, int[] colFmts, boolean encoder, MediaFormat defaultFormat, MediaFormat info) { final Map<String, Object> map = info.getMap(); colorFormats = colFmts; - mFlagsVerified = flags; + mFlagsVerified = 0; // TODO: remove as it is unused mDefaultFormat = defaultFormat; mCapabilitiesInfo = info; mMime = mDefaultFormat.getString(MediaFormat.KEY_MIME); @@ -1243,6 +1332,7 @@ public final class MediaCodecInfo { private Range<Rational> mBlockAspectRatioRange; private Range<Long> mBlocksPerSecondRange; private Map<Size, Range<Long>> mMeasuredFrameRates; + private Vector<PerformancePoint> mPerformancePoints; private Range<Integer> mFrameRateRange; private int mBlockWidth; @@ -1524,6 +1614,158 @@ public final class MediaCodecInfo { } /** + * Video performance points are a set of standard performance points defined by pixel rate. + */ + public static final class PerformancePoint { + /** + * Frame width in pixels. + */ + public final int width; + + /** + * Frame height in pixels. + */ + public final int height; + + /** + * Frame rate in frames per second. + */ + public final int frameRate; + + /* package private */ + PerformancePoint(int width_, int height_, int frameRate_) { + width = width_; + height = height_; + frameRate = frameRate_; + } + + /** + * Checks whether the performance point covers a media format. + * + * @param format Stream format considered + * + * @return {@code true} if the performance point covers the format. + */ + public boolean covers(@NonNull MediaFormat format) { + // for simplicity, this code assumes a 16x16 block size. + long macroBlocks = ((width + 15) / 16) * (long)((height + 15) / 16); + long mbps = macroBlocks * frameRate; + + long formatMacroBlocks = + (long)((format.getInteger(MediaFormat.KEY_WIDTH, 0) + 15) / 16) + * ((format.getInteger(MediaFormat.KEY_HEIGHT, 0) + 15) / 16); + double formatMbps = + Math.ceil(formatMacroBlocks + * format.getNumber(MediaFormat.KEY_FRAME_RATE, 0).doubleValue()); + return formatMacroBlocks > 0 && formatMacroBlocks <= macroBlocks + && formatMbps <= mbps; + } + + @Override + public boolean equals(Object o) { + if (o instanceof PerformancePoint) { + PerformancePoint other = (PerformancePoint)o; + return ((long)width * height) == ((long)other.width * other.height) + && frameRate == other.frameRate; + } + return false; + } + + /** 480p 24fps */ + public static final PerformancePoint SD_24 = new PerformancePoint(720, 480, 24); + /** 576p 25fps */ + public static final PerformancePoint SD_25 = new PerformancePoint(720, 576, 25); + /** 480p 30fps */ + public static final PerformancePoint SD_30 = new PerformancePoint(720, 480, 30); + /** 480p 48fps */ + public static final PerformancePoint SD_48 = new PerformancePoint(720, 480, 48); + /** 576p 50fps */ + public static final PerformancePoint SD_50 = new PerformancePoint(720, 576, 50); + /** 480p 60fps */ + public static final PerformancePoint SD_60 = new PerformancePoint(720, 480, 60); + + /** 720p 24fps */ + public static final PerformancePoint HD_24 = new PerformancePoint(1280, 720, 24); + /** 720p 25fps */ + public static final PerformancePoint HD_25 = new PerformancePoint(1280, 720, 25); + /** 720p 30fps */ + public static final PerformancePoint HD_30 = new PerformancePoint(1280, 720, 30); + /** 720p 50fps */ + public static final PerformancePoint HD_50 = new PerformancePoint(1280, 720, 50); + /** 720p 60fps */ + public static final PerformancePoint HD_60 = new PerformancePoint(1280, 720, 60); + /** 720p 100fps */ + public static final PerformancePoint HD_100 = new PerformancePoint(1280, 720, 100); + /** 720p 120fps */ + public static final PerformancePoint HD_120 = new PerformancePoint(1280, 720, 120); + /** 720p 200fps */ + public static final PerformancePoint HD_200 = new PerformancePoint(1280, 720, 200); + /** 720p 240fps */ + public static final PerformancePoint HD_240 = new PerformancePoint(1280, 720, 240); + + /** 1080p 24fps */ + public static final PerformancePoint FHD_24 = new PerformancePoint(1920, 1080, 24); + /** 1080p 25fps */ + public static final PerformancePoint FHD_25 = new PerformancePoint(1920, 1080, 25); + /** 1080p 30fps */ + public static final PerformancePoint FHD_30 = new PerformancePoint(1920, 1080, 30); + /** 1080p 50fps */ + public static final PerformancePoint FHD_50 = new PerformancePoint(1920, 1080, 50); + /** 1080p 60fps */ + public static final PerformancePoint FHD_60 = new PerformancePoint(1920, 1080, 60); + /** 1080p 100fps */ + public static final PerformancePoint FHD_100 = new PerformancePoint(1920, 1080, 100); + /** 1080p 120fps */ + public static final PerformancePoint FHD_120 = new PerformancePoint(1920, 1080, 120); + /** 1080p 200fps */ + public static final PerformancePoint FHD_200 = new PerformancePoint(1920, 1080, 200); + /** 1080p 240fps */ + public static final PerformancePoint FHD_240 = new PerformancePoint(1920, 1080, 240); + + /** 2160p 24fps */ + public static final PerformancePoint UHD_24 = new PerformancePoint(3840, 2160, 24); + /** 2160p 25fps */ + public static final PerformancePoint UHD_25 = new PerformancePoint(3840, 2160, 25); + /** 2160p 30fps */ + public static final PerformancePoint UHD_30 = new PerformancePoint(3840, 2160, 30); + /** 2160p 50fps */ + public static final PerformancePoint UHD_50 = new PerformancePoint(3840, 2160, 50); + /** 2160p 60fps */ + public static final PerformancePoint UHD_60 = new PerformancePoint(3840, 2160, 60); + /** 2160p 100fps */ + public static final PerformancePoint UHD_100 = new PerformancePoint(3840, 2160, 100); + /** 2160p 120fps */ + public static final PerformancePoint UHD_120 = new PerformancePoint(3840, 2160, 120); + /** 2160p 200fps */ + public static final PerformancePoint UHD_200 = new PerformancePoint(3840, 2160, 200); + /** 2160p 240fps */ + public static final PerformancePoint UHD_240 = new PerformancePoint(3840, 2160, 240); + } + + /** + * Returns the supported performance points. May return {@code null} if the codec did not + * publish any performance point information (e.g. the vendor codecs have not been updated + * to the latest android release). May return an empty list if the codec published that + * if does not guarantee any performance points. + * <p> + * This is a performance guarantee provided by the device manufacturer for hardware codecs + * based on hardware capabilities of the device. + * <p> + * The returned list is sorted first by decreasing number of pixels, then by decreasing + * width, and finally by decreasing frame rate. + * Performance points assume a single active codec. For use cases where multiple + * codecs are active, should use that highest pixel count, and add the frame rates of + * each individual codec. + */ + @Nullable + public List<PerformancePoint> getSupportedPerformancePoints() { + if (mPerformancePoints == null) { + return null; + } + return new ArrayList<PerformancePoint>(mPerformancePoints); + } + + /** * Returns whether a given video size ({@code width} and * {@code height}) and {@code frameRate} combination is supported. */ @@ -1659,6 +1901,50 @@ public final class MediaCodecInfo { mSmallerDimensionUpperLimit = SIZE_RANGE.getUpper(); } + private @Nullable Vector<PerformancePoint> getPerformancePoints(Map<String, Object> map) { + Vector<PerformancePoint> ret = new Vector<>(); + final String prefix = "performance-point-"; + Set<String> keys = map.keySet(); + for (String key : keys) { + // looking for: performance-point-WIDTHxHEIGHT-range + if (!key.startsWith(prefix)) { + continue; + } + String subKey = key.substring(prefix.length()); + if (subKey.equals("none") && ret.size() == 0) { + // This means that component knowingly did not publish performance points. + // This is different from when the component forgot to publish performance + // points. + return ret; + } + String[] temp = key.split("-"); + if (temp.length != 4) { + continue; + } + String sizeStr = temp[2]; + Size size = Utils.parseSize(sizeStr, null); + if (size == null || size.getWidth() * size.getHeight() <= 0) { + continue; + } + Range<Long> range = Utils.parseLongRange(map.get(key), null); + if (range == null || range.getLower() < 0 || range.getUpper() < 0) { + continue; + } + ret.add(new PerformancePoint( + size.getWidth(), size.getHeight(), range.getLower().intValue())); + } + // check if the component specified no performance point indication + if (ret.size() == 0) { + return null; + } + + // sort reversed by area first, then by frame rate + ret.sort((a, b) -> (a.width * a.height != b.width * b.height ? + (b.width * b.height - a.width * a.height) : + (b.frameRate - a.frameRate))); + return ret; + } + private Map<Size, Range<Long>> getMeasuredFrameRates(Map<String, Object> map) { Map<Size, Range<Long>> ret = new HashMap<Size, Range<Long>>(); final String prefix = "measured-frame-rate-"; @@ -1770,6 +2056,7 @@ public final class MediaCodecInfo { blockRates = Utils.parseLongRange(map.get("blocks-per-second-range"), null); mMeasuredFrameRates = getMeasuredFrameRates(map); + mPerformancePoints = getPerformancePoints(map); Pair<Range<Integer>, Range<Integer>> sizeRanges = parseWidthHeightRanges(map.get("size-range")); if (sizeRanges != null) { @@ -2879,7 +3166,9 @@ public final class MediaCodecInfo { * {@link MediaCodecInfo.CodecCapabilities#profileLevels} field. */ public static final class CodecProfileLevel { - // from OMX_VIDEO_AVCPROFILETYPE + // These constants were originally in-line with OMX values, but this + // correspondence is no longer maintained. + public static final int AVCProfileBaseline = 0x01; public static final int AVCProfileMain = 0x02; public static final int AVCProfileExtended = 0x04; @@ -2890,7 +3179,6 @@ public final class MediaCodecInfo { public static final int AVCProfileConstrainedBaseline = 0x10000; public static final int AVCProfileConstrainedHigh = 0x80000; - // from OMX_VIDEO_AVCLEVELTYPE public static final int AVCLevel1 = 0x01; public static final int AVCLevel1b = 0x02; public static final int AVCLevel11 = 0x04; @@ -2908,8 +3196,10 @@ public final class MediaCodecInfo { public static final int AVCLevel5 = 0x4000; public static final int AVCLevel51 = 0x8000; public static final int AVCLevel52 = 0x10000; + public static final int AVCLevel6 = 0x20000; + public static final int AVCLevel61 = 0x40000; + public static final int AVCLevel62 = 0x80000; - // from OMX_VIDEO_H263PROFILETYPE public static final int H263ProfileBaseline = 0x01; public static final int H263ProfileH320Coding = 0x02; public static final int H263ProfileBackwardCompatible = 0x04; @@ -2920,7 +3210,6 @@ public final class MediaCodecInfo { public static final int H263ProfileInterlace = 0x80; public static final int H263ProfileHighLatency = 0x100; - // from OMX_VIDEO_H263LEVELTYPE public static final int H263Level10 = 0x01; public static final int H263Level20 = 0x02; public static final int H263Level30 = 0x04; @@ -2930,7 +3219,6 @@ public final class MediaCodecInfo { public static final int H263Level60 = 0x40; public static final int H263Level70 = 0x80; - // from OMX_VIDEO_MPEG4PROFILETYPE public static final int MPEG4ProfileSimple = 0x01; public static final int MPEG4ProfileSimpleScalable = 0x02; public static final int MPEG4ProfileCore = 0x04; @@ -2948,7 +3236,6 @@ public final class MediaCodecInfo { public static final int MPEG4ProfileAdvancedScalable = 0x4000; public static final int MPEG4ProfileAdvancedSimple = 0x8000; - // from OMX_VIDEO_MPEG4LEVELTYPE public static final int MPEG4Level0 = 0x01; public static final int MPEG4Level0b = 0x02; public static final int MPEG4Level1 = 0x04; @@ -2960,7 +3247,6 @@ public final class MediaCodecInfo { public static final int MPEG4Level5 = 0x80; public static final int MPEG4Level6 = 0x100; - // from OMX_VIDEO_MPEG2PROFILETYPE public static final int MPEG2ProfileSimple = 0x00; public static final int MPEG2ProfileMain = 0x01; public static final int MPEG2Profile422 = 0x02; @@ -2968,14 +3254,12 @@ public final class MediaCodecInfo { public static final int MPEG2ProfileSpatial = 0x04; public static final int MPEG2ProfileHigh = 0x05; - // from OMX_VIDEO_MPEG2LEVELTYPE public static final int MPEG2LevelLL = 0x00; public static final int MPEG2LevelML = 0x01; public static final int MPEG2LevelH14 = 0x02; public static final int MPEG2LevelHL = 0x03; public static final int MPEG2LevelHP = 0x04; - // from OMX_AUDIO_AACPROFILETYPE public static final int AACObjectMain = 1; public static final int AACObjectLC = 2; public static final int AACObjectSSR = 3; @@ -2990,16 +3274,13 @@ public final class MediaCodecInfo { /** xHE-AAC (includes USAC) */ public static final int AACObjectXHE = 42; - // from OMX_VIDEO_VP8LEVELTYPE public static final int VP8Level_Version0 = 0x01; public static final int VP8Level_Version1 = 0x02; public static final int VP8Level_Version2 = 0x04; public static final int VP8Level_Version3 = 0x08; - // from OMX_VIDEO_VP8PROFILETYPE public static final int VP8ProfileMain = 0x01; - // from OMX_VIDEO_VP9PROFILETYPE public static final int VP9Profile0 = 0x01; public static final int VP9Profile1 = 0x02; public static final int VP9Profile2 = 0x04; @@ -3010,7 +3291,6 @@ public final class MediaCodecInfo { public static final int VP9Profile2HDR10Plus = 0x4000; public static final int VP9Profile3HDR10Plus = 0x8000; - // from OMX_VIDEO_VP9LEVELTYPE public static final int VP9Level1 = 0x1; public static final int VP9Level11 = 0x2; public static final int VP9Level2 = 0x4; @@ -3026,14 +3306,12 @@ public final class MediaCodecInfo { public static final int VP9Level61 = 0x1000; public static final int VP9Level62 = 0x2000; - // from OMX_VIDEO_HEVCPROFILETYPE public static final int HEVCProfileMain = 0x01; public static final int HEVCProfileMain10 = 0x02; public static final int HEVCProfileMainStill = 0x04; public static final int HEVCProfileMain10HDR10 = 0x1000; public static final int HEVCProfileMain10HDR10Plus = 0x2000; - // from OMX_VIDEO_HEVCLEVELTYPE public static final int HEVCMainTierLevel1 = 0x1; public static final int HEVCHighTierLevel1 = 0x2; public static final int HEVCMainTierLevel2 = 0x4; @@ -3067,7 +3345,6 @@ public final class MediaCodecInfo { HEVCHighTierLevel51 | HEVCHighTierLevel52 | HEVCHighTierLevel6 | HEVCHighTierLevel61 | HEVCHighTierLevel62; - // from OMX_VIDEO_DOLBYVISIONPROFILETYPE public static final int DolbyVisionProfileDvavPer = 0x1; public static final int DolbyVisionProfileDvavPen = 0x2; public static final int DolbyVisionProfileDvheDer = 0x4; @@ -3079,7 +3356,6 @@ public final class MediaCodecInfo { public static final int DolbyVisionProfileDvheSt = 0x100; public static final int DolbyVisionProfileDvavSe = 0x200; - // from OMX_VIDEO_DOLBYVISIONLEVELTYPE public static final int DolbyVisionLevelHd24 = 0x1; public static final int DolbyVisionLevelHd30 = 0x2; public static final int DolbyVisionLevelFhd24 = 0x4; @@ -3090,17 +3366,44 @@ public final class MediaCodecInfo { public static final int DolbyVisionLevelUhd48 = 0x80; public static final int DolbyVisionLevelUhd60 = 0x100; + public static final int AV1Profile0 = 0x1; + public static final int AV1Profile1 = 0x2; + public static final int AV1Profile2 = 0x4; + + public static final int AV1Level2 = 0x1; + public static final int AV1Level21 = 0x2; + public static final int AV1Level22 = 0x4; + public static final int AV1Level23 = 0x8; + public static final int AV1Level3 = 0x10; + public static final int AV1Level31 = 0x20; + public static final int AV1Level32 = 0x40; + public static final int AV1Level33 = 0x80; + public static final int AV1Level4 = 0x100; + public static final int AV1Level41 = 0x200; + public static final int AV1Level42 = 0x400; + public static final int AV1Level43 = 0x800; + public static final int AV1Level5 = 0x1000; + public static final int AV1Level51 = 0x2000; + public static final int AV1Level52 = 0x4000; + public static final int AV1Level53 = 0x8000; + public static final int AV1Level6 = 0x10000; + public static final int AV1Level61 = 0x20000; + public static final int AV1Level62 = 0x40000; + public static final int AV1Level63 = 0x80000; + public static final int AV1Level7 = 0x100000; + public static final int AV1Level71 = 0x200000; + public static final int AV1Level72 = 0x400000; + public static final int AV1Level73 = 0x800000; + /** - * Defined in the OpenMAX IL specs, depending on the type of media - * this can be OMX_VIDEO_AVCPROFILETYPE, OMX_VIDEO_H263PROFILETYPE, - * OMX_VIDEO_MPEG4PROFILETYPE, OMX_VIDEO_VP8PROFILETYPE or OMX_VIDEO_VP9PROFILETYPE. + * The profile of the media content. Depending on the type of media this can be + * one of the profile values defined in this class. */ public int profile; /** - * Defined in the OpenMAX IL specs, depending on the type of media - * this can be OMX_VIDEO_AVCLEVELTYPE, OMX_VIDEO_H263LEVELTYPE - * OMX_VIDEO_MPEG4LEVELTYPE, OMX_VIDEO_VP8LEVELTYPE or OMX_VIDEO_VP9LEVELTYPE. + * The level of the media content. Depending on the type of media this can be + * one of the level values defined in this class. * * Note that VP9 decoder on platforms before {@link android.os.Build.VERSION_CODES#N} may * not advertise a profile level support. For those VP9 decoders, please use @@ -3157,7 +3460,7 @@ public final class MediaCodecInfo { } return new MediaCodecInfo( - mName, mIsEncoder, + mName, mCanonicalName, mFlags, caps.toArray(new CodecCapabilities[caps.size()])); } } diff --git a/media/java/android/media/MediaCodecList.java b/media/java/android/media/MediaCodecList.java index 2e4786579d97..a46095484fe7 100644 --- a/media/java/android/media/MediaCodecList.java +++ b/media/java/android/media/MediaCodecList.java @@ -111,12 +111,14 @@ final public class MediaCodecList { caps[typeIx++] = getCodecCapabilities(index, type); } return new MediaCodecInfo( - getCodecName(index), isEncoder(index), caps); + getCodecName(index), getCanonicalName(index), getAttributes(index), caps); } /* package private */ static native final String getCodecName(int index); - /* package private */ static native final boolean isEncoder(int index); + /* package private */ static native final String getCanonicalName(int index); + + /* package private */ static native final int getAttributes(int index); /* package private */ static native final String[] getSupportedTypes(int index); diff --git a/media/java/android/media/MediaConstants.java b/media/java/android/media/MediaConstants.java index 5a5747ae4bab..65b6f55a068a 100644 --- a/media/java/android/media/MediaConstants.java +++ b/media/java/android/media/MediaConstants.java @@ -26,6 +26,7 @@ class MediaConstants { // Bundle key for Parcelable static final String KEY_SESSION2LINK = "android.media.key.SESSION2LINK"; static final String KEY_ALLOWED_COMMANDS = "android.media.key.ALLOWED_COMMANDS"; + static final String KEY_PLAYBACK_ACTIVE = "android.media.key.PLAYBACK_ACTIVE"; private MediaConstants() { } diff --git a/media/java/android/media/MediaController2.java b/media/java/android/media/MediaController2.java index 774ea185f57c..7c5335b71627 100644 --- a/media/java/android/media/MediaController2.java +++ b/media/java/android/media/MediaController2.java @@ -19,6 +19,7 @@ package android.media; import static android.media.MediaConstants.KEY_ALLOWED_COMMANDS; import static android.media.MediaConstants.KEY_PACKAGE_NAME; import static android.media.MediaConstants.KEY_PID; +import static android.media.MediaConstants.KEY_PLAYBACK_ACTIVE; import static android.media.MediaConstants.KEY_SESSION2LINK; import static android.media.Session2Command.RESULT_ERROR_UNKNOWN_ERROR; import static android.media.Session2Command.RESULT_INFO_SKIPPED; @@ -26,12 +27,15 @@ import static android.media.Session2Token.TYPE_SESSION; import android.annotation.NonNull; import android.annotation.Nullable; +import android.content.ComponentName; import android.content.Context; -import android.os.Binder; +import android.content.Intent; +import android.content.ServiceConnection; import android.os.Bundle; import android.os.Handler; import android.os.IBinder; import android.os.Process; +import android.os.RemoteException; import android.os.ResultReceiver; import android.util.ArrayMap; import android.util.ArraySet; @@ -63,6 +67,7 @@ public class MediaController2 implements AutoCloseable { private final Executor mCallbackExecutor; private final Controller2Link mControllerStub; private final Handler mResultHandler; + private final SessionServiceConnection mServiceConnection; private final Object mLock = new Object(); //@GuardedBy("mLock") @@ -77,6 +82,8 @@ public class MediaController2 implements AutoCloseable { private ArrayMap<ResultReceiver, Integer> mPendingCommands; //@GuardedBy("mLock") private ArraySet<Integer> mRequestedCommandSeqNumbers; + //@GuardedBy("mLock") + private boolean mPlaybackActive; /** * Create a {@link MediaController2} from the {@link Session2Token}. @@ -118,16 +125,25 @@ public class MediaController2 implements AutoCloseable { mPendingCommands = new ArrayMap<>(); mRequestedCommandSeqNumbers = new ArraySet<>(); + boolean connectRequested; if (token.getType() == TYPE_SESSION) { - connectToSession(); + mServiceConnection = null; + connectRequested = requestConnectToSession(); } else { - // TODO: Handle connect to session service. + mServiceConnection = new SessionServiceConnection(); + connectRequested = requestConnectToService(); + } + if (!connectRequested) { + close(); } } @Override public void close() { synchronized (mLock) { + if (mServiceConnection != null) { + mContext.unbindService(mServiceConnection); + } if (mSessionBinder != null) { try { mSessionBinder.disconnect(mControllerStub, getNextSeqNumber()); @@ -146,6 +162,18 @@ public class MediaController2 implements AutoCloseable { } /** + * Returns whether the session's playback is active. + * + * @return {@code true} if playback active. {@code false} otherwise. + * @see ControllerCallback#onPlaybackActiveChanged(MediaController2, boolean) + */ + public boolean isPlaybackActive() { + synchronized (mLock) { + return mPlaybackActive; + } + } + + /** * Sends a session command to the session * <p> * @param command the session command @@ -207,89 +235,82 @@ public class MediaController2 implements AutoCloseable { // Called by Controller2Link.onConnected void onConnected(int seq, Bundle connectionResult) { - final long token = Binder.clearCallingIdentity(); - try { - Session2Link sessionBinder = connectionResult.getParcelable(KEY_SESSION2LINK); - Session2CommandGroup allowedCommands = - connectionResult.getParcelable(KEY_ALLOWED_COMMANDS); - if (DEBUG) { - Log.d(TAG, "notifyConnected sessionBinder=" + sessionBinder - + ", allowedCommands=" + allowedCommands); - } - if (sessionBinder == null || allowedCommands == null) { - // Connection rejected. - close(); - return; - } - synchronized (mLock) { - mSessionBinder = sessionBinder; - mAllowedCommands = allowedCommands; - // Implementation for the local binder is no-op, - // so can be used without worrying about deadlock. - sessionBinder.linkToDeath(mDeathRecipient, 0); - mConnectedToken = new Session2Token(mSessionToken.getUid(), TYPE_SESSION, - mSessionToken.getPackageName(), sessionBinder); - } - mCallbackExecutor.execute(() -> { - mCallback.onConnected(MediaController2.this, allowedCommands); - }); - } finally { - Binder.restoreCallingIdentity(token); + Session2Link sessionBinder = connectionResult.getParcelable(KEY_SESSION2LINK); + Session2CommandGroup allowedCommands = + connectionResult.getParcelable(KEY_ALLOWED_COMMANDS); + boolean playbackActive = connectionResult.getBoolean(KEY_PLAYBACK_ACTIVE); + if (DEBUG) { + Log.d(TAG, "notifyConnected sessionBinder=" + sessionBinder + + ", allowedCommands=" + allowedCommands); } + if (sessionBinder == null || allowedCommands == null) { + // Connection rejected. + close(); + return; + } + synchronized (mLock) { + mSessionBinder = sessionBinder; + mAllowedCommands = allowedCommands; + mPlaybackActive = playbackActive; + + // Implementation for the local binder is no-op, + // so can be used without worrying about deadlock. + sessionBinder.linkToDeath(mDeathRecipient, 0); + mConnectedToken = new Session2Token(mSessionToken.getUid(), TYPE_SESSION, + mSessionToken.getPackageName(), sessionBinder); + } + mCallbackExecutor.execute(() -> { + mCallback.onConnected(MediaController2.this, allowedCommands); + }); } // Called by Controller2Link.onDisconnected void onDisconnected(int seq) { - final long token = Binder.clearCallingIdentity(); - try { - // close() will call mCallback.onDisconnected - close(); - } finally { - Binder.restoreCallingIdentity(token); + // close() will call mCallback.onDisconnected + close(); + } + + // Called by Controller2Link.onPlaybackActiveChanged + void onPlaybackActiveChanged(int seq, boolean playbackActive) { + synchronized (mLock) { + mPlaybackActive = playbackActive; } + mCallbackExecutor.execute(() -> { + mCallback.onPlaybackActiveChanged(MediaController2.this, playbackActive); + }); } // Called by Controller2Link.onSessionCommand void onSessionCommand(int seq, Session2Command command, Bundle args, @Nullable ResultReceiver resultReceiver) { - final long token = Binder.clearCallingIdentity(); - try { + synchronized (mLock) { + mRequestedCommandSeqNumbers.add(seq); + } + mCallbackExecutor.execute(() -> { + boolean isCanceled; synchronized (mLock) { - mRequestedCommandSeqNumbers.add(seq); + isCanceled = !mRequestedCommandSeqNumbers.remove(seq); } - mCallbackExecutor.execute(() -> { - boolean isCanceled; - synchronized (mLock) { - isCanceled = !mRequestedCommandSeqNumbers.remove(seq); - } - if (isCanceled) { - resultReceiver.send(RESULT_INFO_SKIPPED, null); - return; - } - Session2Command.Result result = mCallback.onSessionCommand( - MediaController2.this, command, args); - if (resultReceiver != null) { - if (result == null) { - throw new RuntimeException("onSessionCommand shouldn't return null"); - } else { - resultReceiver.send(result.getResultCode(), result.getResultData()); - } + if (isCanceled) { + resultReceiver.send(RESULT_INFO_SKIPPED, null); + return; + } + Session2Command.Result result = mCallback.onSessionCommand( + MediaController2.this, command, args); + if (resultReceiver != null) { + if (result == null) { + throw new RuntimeException("onSessionCommand shouldn't return null"); + } else { + resultReceiver.send(result.getResultCode(), result.getResultData()); } - }); - } finally { - Binder.restoreCallingIdentity(token); - } + } + }); } // Called by Controller2Link.onSessionCommand void onCancelCommand(int seq) { - final long token = Binder.clearCallingIdentity(); - try { - synchronized (mLock) { - mRequestedCommandSeqNumbers.remove(seq); - } - } finally { - Binder.restoreCallingIdentity(token); + synchronized (mLock) { + mRequestedCommandSeqNumbers.remove(seq); } } @@ -299,18 +320,55 @@ public class MediaController2 implements AutoCloseable { } } - private void connectToSession() { - Session2Link sessionBinder = mSessionToken.getSessionLink(); + private Bundle createConnectionRequest() { Bundle connectionRequest = new Bundle(); connectionRequest.putString(KEY_PACKAGE_NAME, mContext.getPackageName()); connectionRequest.putInt(KEY_PID, Process.myPid()); + return connectionRequest; + } + private boolean requestConnectToSession() { + Session2Link sessionBinder = mSessionToken.getSessionLink(); + Bundle connectionRequest = createConnectionRequest(); try { sessionBinder.connect(mControllerStub, getNextSeqNumber(), connectionRequest); } catch (RuntimeException e) { - Log.w(TAG, "Failed to call connection request. Framework will retry" - + " automatically"); + Log.w(TAG, "Failed to call connection request", e); + return false; + } + return true; + } + + private boolean requestConnectToService() { + // Service. Needs to get fresh binder whenever connection is needed. + final Intent intent = new Intent(MediaSession2Service.SERVICE_INTERFACE); + intent.setClassName(mSessionToken.getPackageName(), mSessionToken.getServiceName()); + + // Use bindService() instead of startForegroundService() to start session service for three + // reasons. + // 1. Prevent session service owner's stopSelf() from destroying service. + // With the startForegroundService(), service's call of stopSelf() will trigger immediate + // onDestroy() calls on the main thread even when onConnect() is running in another + // thread. + // 2. Minimize APIs for developers to take care about. + // With bindService(), developers only need to take care about Service.onBind() + // but Service.onStartCommand() should be also taken care about with the + // startForegroundService(). + // 3. Future support for UI-less playback + // If a service wants to keep running, it should be either foreground service or + // bound service. But there had been request for the feature for system apps + // and using bindService() will be better fit with it. + synchronized (mLock) { + boolean result = mContext.bindService( + intent, mServiceConnection, Context.BIND_AUTO_CREATE); + if (!result) { + Log.w(TAG, "bind to " + mSessionToken + " failed"); + return false; + } else if (DEBUG) { + Log.d(TAG, "bind to " + mSessionToken + " succeeded"); + } } + return true; } /** @@ -342,6 +400,17 @@ public class MediaController2 implements AutoCloseable { public void onDisconnected(@NonNull MediaController2 controller) {} /** + * Called when the playback of the session's playback activeness is changed. + * + * @param controller the controller for this event + * @param playbackActive {@code true} if the session's playback is active. + * {@code false} otherwise. + * @see MediaController2#isPlaybackActive() + */ + public void onPlaybackActiveChanged(@NonNull MediaController2 controller, + boolean playbackActive) {} + + /** * Called when the connected session sent a session command. * * @param controller the controller for this event @@ -367,4 +436,59 @@ public class MediaController2 implements AutoCloseable { public void onCommandResult(@NonNull MediaController2 controller, @NonNull Object token, @NonNull Session2Command command, @NonNull Session2Command.Result result) {} } + + // This will be called on the main thread. + private class SessionServiceConnection implements ServiceConnection { + SessionServiceConnection() { + } + + @Override + public void onServiceConnected(ComponentName name, IBinder service) { + // Note that it's always main-thread. + boolean connectRequested = false; + try { + if (DEBUG) { + Log.d(TAG, "onServiceConnected " + name + " " + this); + } + // Sanity check + if (!mSessionToken.getPackageName().equals(name.getPackageName())) { + Log.wtf(TAG, "Expected connection to " + mSessionToken.getPackageName() + + " but is connected to " + name); + return; + } + IMediaSession2Service iService = IMediaSession2Service.Stub.asInterface(service); + if (iService == null) { + Log.wtf(TAG, "Service interface is missing."); + return; + } + Bundle connectionRequest = createConnectionRequest(); + iService.connect(mControllerStub, getNextSeqNumber(), connectionRequest); + connectRequested = true; + } catch (RemoteException e) { + Log.w(TAG, "Service " + name + " has died prematurely", e); + } finally { + if (!connectRequested) { + close(); + } + } + } + + @Override + public void onServiceDisconnected(ComponentName name) { + // Temporal lose of the binding because of the service crash. System will automatically + // rebind, so just no-op. + if (DEBUG) { + Log.w(TAG, "Session service " + name + " is disconnected."); + } + close(); + } + + @Override + public void onBindingDied(ComponentName name) { + // Permanent lose of the binding because of the service package update or removed. + // This SessionServiceRecord will be removed accordingly, but forget session binder here + // for sure. + close(); + } + } } diff --git a/media/java/android/media/MediaDrm.java b/media/java/android/media/MediaDrm.java index 75b391534dd4..bfc10da5d431 100644 --- a/media/java/android/media/MediaDrm.java +++ b/media/java/android/media/MediaDrm.java @@ -1285,7 +1285,7 @@ public final class MediaDrm implements AutoCloseable { @Retention(RetentionPolicy.SOURCE) @IntDef({HDCP_LEVEL_UNKNOWN, HDCP_NONE, HDCP_V1, HDCP_V2, - HDCP_V2_1, HDCP_V2_2, HDCP_NO_DIGITAL_OUTPUT}) + HDCP_V2_1, HDCP_V2_2, HDCP_V2_3, HDCP_NO_DIGITAL_OUTPUT}) public @interface HdcpLevel {} @@ -1321,6 +1321,11 @@ public final class MediaDrm implements AutoCloseable { public static final int HDCP_V2_2 = 5; /** + * HDCP version 2.3 Type 1. + */ + public static final int HDCP_V2_3 = 6; + + /** * No digital output, implicitly secure */ public static final int HDCP_NO_DIGITAL_OUTPUT = Integer.MAX_VALUE; diff --git a/media/java/android/media/MediaFormat.java b/media/java/android/media/MediaFormat.java index 594a22457cc3..c82b5f6f12a1 100644 --- a/media/java/android/media/MediaFormat.java +++ b/media/java/android/media/MediaFormat.java @@ -124,6 +124,7 @@ import java.util.stream.Collectors; public final class MediaFormat { public static final String MIMETYPE_VIDEO_VP8 = "video/x-vnd.on2.vp8"; public static final String MIMETYPE_VIDEO_VP9 = "video/x-vnd.on2.vp9"; + public static final String MIMETYPE_VIDEO_AV1 = "video/av01"; public static final String MIMETYPE_VIDEO_AVC = "video/avc"; public static final String MIMETYPE_VIDEO_HEVC = "video/hevc"; public static final String MIMETYPE_VIDEO_MPEG4 = "video/mp4v-es"; diff --git a/media/java/android/media/MediaRecorder.java b/media/java/android/media/MediaRecorder.java index 25b1df26fd40..1304afe3654e 100644 --- a/media/java/android/media/MediaRecorder.java +++ b/media/java/android/media/MediaRecorder.java @@ -302,6 +302,34 @@ public class MediaRecorder implements AudioRouting, * {@link #DEFAULT} otherwise. */ public static final int UNPROCESSED = 9; + + /** + * Source for capturing audio meant to be processed in real time and played back for live + * performance (e.g karaoke). + * <p> + * The capture path will minimize latency and coupling with + * playback path. + * </p> + */ + public static final int VOICE_PERFORMANCE = 10; + + /** + * Source for an echo canceller to capture the reference signal to be cancelled. + * <p> + * The echo reference signal will be captured as close as possible to the DAC in order + * to include all post processing applied to the playback path. + * </p><p> + * Capturing the echo reference requires the + * {@link android.Manifest.permission#CAPTURE_AUDIO_OUTPUT} permission. + * This permission is reserved for use by system components and is not available to + * third-party applications. + * </p> + * @hide + */ + @SystemApi + @RequiresPermission(android.Manifest.permission.CAPTURE_AUDIO_OUTPUT) + public static final int ECHO_REFERENCE = 1997; + /** * Audio source for capturing broadcast radio tuner output. * @hide @@ -343,6 +371,7 @@ public class MediaRecorder implements AudioRouting, case AudioSource.VOICE_COMMUNICATION: //case REMOTE_SUBMIX: considered "system" as it requires system permissions case AudioSource.UNPROCESSED: + case AudioSource.VOICE_PERFORMANCE: return false; default: return true; @@ -372,6 +401,10 @@ public class MediaRecorder implements AudioRouting, return "REMOTE_SUBMIX"; case AudioSource.UNPROCESSED: return "UNPROCESSED"; + case AudioSource.ECHO_REFERENCE: + return "ECHO_REFERENCE"; + case AudioSource.VOICE_PERFORMANCE: + return "VOICE_PERFORMANCE"; case AudioSource.RADIO_TUNER: return "RADIO_TUNER"; case AudioSource.HOTWORD: @@ -524,7 +557,7 @@ public class MediaRecorder implements AudioRouting, * @see android.media.MediaRecorder.AudioSource */ public static final int getAudioSourceMax() { - return AudioSource.UNPROCESSED; + return AudioSource.VOICE_PERFORMANCE; } /** diff --git a/media/java/android/media/MediaSession2.java b/media/java/android/media/MediaSession2.java index e008adf120ab..3adac7295fff 100644 --- a/media/java/android/media/MediaSession2.java +++ b/media/java/android/media/MediaSession2.java @@ -19,6 +19,7 @@ package android.media; import static android.media.MediaConstants.KEY_ALLOWED_COMMANDS; import static android.media.MediaConstants.KEY_PACKAGE_NAME; import static android.media.MediaConstants.KEY_PID; +import static android.media.MediaConstants.KEY_PLAYBACK_ACTIVE; import static android.media.MediaConstants.KEY_SESSION2LINK; import static android.media.Session2Command.RESULT_ERROR_UNKNOWN_ERROR; import static android.media.Session2Command.RESULT_INFO_SKIPPED; @@ -31,7 +32,6 @@ import android.content.Context; import android.content.Intent; import android.media.session.MediaSessionManager; import android.media.session.MediaSessionManager.RemoteUserInfo; -import android.os.Binder; import android.os.Bundle; import android.os.Handler; import android.os.Process; @@ -41,7 +41,6 @@ import android.util.ArraySet; import android.util.Log; import java.util.ArrayList; -import java.util.Collection; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -89,6 +88,8 @@ public class MediaSession2 implements AutoCloseable { //@GuardedBy("mLock") private boolean mClosed; + //@GuardedBy("mLock") + private boolean mPlaybackActive; MediaSession2(@NonNull Context context, @NonNull String id, PendingIntent sessionActivity, @NonNull Executor callbackExecutor, @NonNull SessionCallback callback) { @@ -117,14 +118,18 @@ public class MediaSession2 implements AutoCloseable { @Override public void close() { try { - synchronized (MediaSession2.class) { - SESSION_ID_LIST.remove(mSessionId); - } - Collection<ControllerInfo> controllerInfos; + List<ControllerInfo> controllerInfos; synchronized (mLock) { - controllerInfos = mConnectedControllers.values(); - mConnectedControllers.clear(); + if (mClosed) { + return; + } mClosed = true; + controllerInfos = getConnectedControllers(); + mConnectedControllers.clear(); + mCallback.onSessionClosed(this); + } + synchronized (MediaSession2.class) { + SESSION_ID_LIST.remove(mSessionId); } for (ControllerInfo info : controllerInfos) { info.notifyDisconnected(); @@ -160,10 +165,7 @@ public class MediaSession2 implements AutoCloseable { if (command == null) { throw new IllegalArgumentException("command shouldn't be null"); } - Collection<ControllerInfo> controllerInfos; - synchronized (mLock) { - controllerInfos = mConnectedControllers.values(); - } + List<ControllerInfo> controllerInfos = getConnectedControllers(); for (ControllerInfo controller : controllerInfos) { controller.sendSessionCommand(command, args, null); } @@ -216,29 +218,61 @@ public class MediaSession2 implements AutoCloseable { controller.cancelSessionCommand(token); } + /** + * Sets whether the playback is active (i.e. playing something) + * + * @param playbackActive {@code true} if the playback active, {@code false} otherwise. + **/ + public void setPlaybackActive(boolean playbackActive) { + synchronized (mLock) { + if (mPlaybackActive == playbackActive) { + return; + } + mPlaybackActive = playbackActive; + } + List<ControllerInfo> controllerInfos = getConnectedControllers(); + for (ControllerInfo controller : controllerInfos) { + controller.notifyPlaybackActiveChanged(playbackActive); + } + } + + /** + * Returns whehther the playback is active (i.e. playing something) + * + * @return {@code true} if the playback active, {@code false} otherwise. + */ + public boolean isPlaybackActive() { + synchronized (mLock) { + return mPlaybackActive; + } + } + boolean isClosed() { synchronized (mLock) { return mClosed; } } - // Called by Session2Link.onConnect - void onConnect(final Controller2Link controller, int seq, Bundle connectionRequest) { - if (controller == null || connectionRequest == null) { - return; - } - final int uid = Binder.getCallingUid(); - final int callingPid = Binder.getCallingPid(); - final long token = Binder.clearCallingIdentity(); - // Binder.getCallingPid() can be 0 for an oneway call from the remote process. - // If it's the case, use PID from the ConnectionRequest. - final int pid = (callingPid != 0) ? callingPid : connectionRequest.getInt(KEY_PID); - final String pkg = connectionRequest.getString(KEY_PACKAGE_NAME); - try { - RemoteUserInfo remoteUserInfo = new RemoteUserInfo(pkg, pid, uid); - final ControllerInfo controllerInfo = new ControllerInfo(remoteUserInfo, - mSessionManager.isTrustedForMediaControl(remoteUserInfo), controller); - mCallbackExecutor.execute(() -> { + SessionCallback getCallback() { + return mCallback; + } + + // Called by Session2Link.onConnect and MediaSession2Service.MediaSession2ServiceStub.connect + void onConnect(final Controller2Link controller, int callingPid, int callingUid, int seq, + Bundle connectionRequest) { + if (callingPid == 0) { + // The pid here is from Binder.getCallingPid(), which can be 0 for an oneway call from + // the remote process. If it's the case, use PID from the connectionRequest. + callingPid = connectionRequest.getInt(KEY_PID); + } + String callingPkg = connectionRequest.getString(KEY_PACKAGE_NAME); + + RemoteUserInfo remoteUserInfo = new RemoteUserInfo(callingPkg, callingPid, callingUid); + final ControllerInfo controllerInfo = new ControllerInfo(remoteUserInfo, + mSessionManager.isTrustedForMediaControl(remoteUserInfo), controller); + mCallbackExecutor.execute(() -> { + boolean connected = false; + try { if (isClosed()) { return; } @@ -247,77 +281,72 @@ public class MediaSession2 implements AutoCloseable { // Don't reject connection for the request from trusted app. // Otherwise server will fail to retrieve session's information to dispatch // media keys to. - boolean accept = - controllerInfo.mAllowedCommands != null || controllerInfo.isTrusted(); - if (accept) { - if (controllerInfo.mAllowedCommands == null) { - // For trusted apps, send non-null allowed commands to keep - // connection. - controllerInfo.mAllowedCommands = - new Session2CommandGroup.Builder().build(); + if (controllerInfo.mAllowedCommands == null && !controllerInfo.isTrusted()) { + return; + } + if (controllerInfo.mAllowedCommands == null) { + // For trusted apps, send non-null allowed commands to keep + // connection. + controllerInfo.mAllowedCommands = + new Session2CommandGroup.Builder().build(); + } + if (DEBUG) { + Log.d(TAG, "Accepting connection: " + controllerInfo); + } + synchronized (mLock) { + if (mConnectedControllers.containsKey(controller)) { + Log.w(TAG, "Controller " + controllerInfo + " has sent connection" + + " request multiple times"); } + mConnectedControllers.put(controller, controllerInfo); + } + // If connection is accepted, notify the current state to the controller. + // It's needed because we cannot call synchronous calls between + // session/controller. + Bundle connectionResult = new Bundle(); + connectionResult.putParcelable(KEY_SESSION2LINK, mSessionStub); + connectionResult.putParcelable(KEY_ALLOWED_COMMANDS, + controllerInfo.mAllowedCommands); + connectionResult.putBoolean(KEY_PLAYBACK_ACTIVE, isPlaybackActive()); + + // Double check if session is still there, because close() can be called in + // another thread. + if (isClosed()) { + return; + } + controllerInfo.notifyConnected(connectionResult); + connected = true; + } finally { + if (!connected) { if (DEBUG) { - Log.d(TAG, "Accepting connection: " + controllerInfo); + Log.d(TAG, "Rejecting connection or notifying that session is closed" + + ", controllerInfo=" + controllerInfo); } synchronized (mLock) { - if (mConnectedControllers.containsKey(controller)) { - Log.w(TAG, "Controller " + controllerInfo + " has sent connection" - + " request multiple times"); - } - mConnectedControllers.put(controller, controllerInfo); - } - // If connection is accepted, notify the current state to the controller. - // It's needed because we cannot call synchronous calls between - // session/controller. - Bundle connectionResult = new Bundle(); - connectionResult.putParcelable(KEY_SESSION2LINK, mSessionStub); - connectionResult.putParcelable(KEY_ALLOWED_COMMANDS, - controllerInfo.mAllowedCommands); - - // Double check if session is still there, because close() can be called in - // another thread. - if (isClosed()) { - return; - } - controllerInfo.notifyConnected(connectionResult); - } else { - if (DEBUG) { - Log.d(TAG, "Rejecting connection, controllerInfo=" + controllerInfo); + mConnectedControllers.remove(controller); } controllerInfo.notifyDisconnected(); } - }); - } finally { - Binder.restoreCallingIdentity(token); - } + } + }); } // Called by Session2Link.onDisconnect - void onDisconnect(final Controller2Link controller, int seq) { - if (controller == null) { - return; - } + void onDisconnect(@NonNull final Controller2Link controller, int seq) { final ControllerInfo controllerInfo; synchronized (mLock) { - controllerInfo = mConnectedControllers.get(controller); + controllerInfo = mConnectedControllers.remove(controller); } if (controllerInfo == null) { return; } - - final long token = Binder.clearCallingIdentity(); - try { - mCallbackExecutor.execute(() -> { - mCallback.onDisconnected(MediaSession2.this, controllerInfo); - }); - mConnectedControllers.remove(controller); - } finally { - Binder.restoreCallingIdentity(token); - } + mCallbackExecutor.execute(() -> { + mCallback.onDisconnected(MediaSession2.this, controllerInfo); + }); } // Called by Session2Link.onSessionCommand - void onSessionCommand(final Controller2Link controller, final int seq, + void onSessionCommand(@NonNull final Controller2Link controller, final int seq, final Session2Command command, final Bundle args, @Nullable ResultReceiver resultReceiver) { if (controller == null) { @@ -332,34 +361,28 @@ public class MediaSession2 implements AutoCloseable { } // TODO: check allowed commands. - final long token = Binder.clearCallingIdentity(); - try { - synchronized (mLock) { - controllerInfo.addRequestedCommandSeqNumber(seq); + synchronized (mLock) { + controllerInfo.addRequestedCommandSeqNumber(seq); + } + mCallbackExecutor.execute(() -> { + if (!controllerInfo.removeRequestedCommandSeqNumber(seq)) { + resultReceiver.send(RESULT_INFO_SKIPPED, null); + return; } - - mCallbackExecutor.execute(() -> { - if (!controllerInfo.removeRequestedCommandSeqNumber(seq)) { - resultReceiver.send(RESULT_INFO_SKIPPED, null); - return; - } - Session2Command.Result result = mCallback.onSessionCommand( - MediaSession2.this, controllerInfo, command, args); - if (resultReceiver != null) { - if (result == null) { - throw new RuntimeException("onSessionCommand shouldn't return null"); - } else { - resultReceiver.send(result.getResultCode(), result.getResultData()); - } + Session2Command.Result result = mCallback.onSessionCommand( + MediaSession2.this, controllerInfo, command, args); + if (resultReceiver != null) { + if (result == null) { + throw new RuntimeException("onSessionCommand shouldn't return null"); + } else { + resultReceiver.send(result.getResultCode(), result.getResultData()); } - }); - } finally { - Binder.restoreCallingIdentity(token); - } + } + }); } // Called by Session2Link.onCancelCommand - void onCancelCommand(final Controller2Link controller, final int seq) { + void onCancelCommand(@NonNull final Controller2Link controller, final int seq) { final ControllerInfo controllerInfo; synchronized (mLock) { controllerInfo = mConnectedControllers.get(controller); @@ -367,13 +390,15 @@ public class MediaSession2 implements AutoCloseable { if (controllerInfo == null) { return; } + controllerInfo.removeRequestedCommandSeqNumber(seq); + } - final long token = Binder.clearCallingIdentity(); - try { - controllerInfo.removeRequestedCommandSeqNumber(seq); - } finally { - Binder.restoreCallingIdentity(token); + private List<ControllerInfo> getConnectedControllers() { + List<ControllerInfo> controllers = new ArrayList<>(); + synchronized (mLock) { + controllers.addAll(mConnectedControllers.values()); } + return controllers; } /** @@ -599,6 +624,16 @@ public class MediaSession2 implements AutoCloseable { } } + void notifyPlaybackActiveChanged(boolean playbackActive) { + if (mControllerBinder == null) return; + + try { + mControllerBinder.notifyPlaybackActiveChanged(getNextSeqNumber(), playbackActive); + } catch (RuntimeException e) { + // Controller may be died prematurely. + } + } + void sendSessionCommand(Session2Command command, Bundle args, ResultReceiver resultReceiver) { if (mControllerBinder == null) return; @@ -660,6 +695,8 @@ public class MediaSession2 implements AutoCloseable { * This API is not generally intended for third party application developers. */ public abstract static class SessionCallback { + ForegroundServiceEventCallback mForegroundServiceEventCallback; + /** * Called when a controller is created for this session. Return allowed commands for * controller. By default it returns {@code null}. @@ -716,5 +753,19 @@ public class MediaSession2 implements AutoCloseable { public void onCommandResult(@NonNull MediaSession2 session, @NonNull ControllerInfo controller, @NonNull Object token, @NonNull Session2Command command, @NonNull Session2Command.Result result) {} + + final void onSessionClosed(MediaSession2 session) { + if (mForegroundServiceEventCallback != null) { + mForegroundServiceEventCallback.onSessionClosed(session); + } + } + + void setForegroundServiceEventCallback(ForegroundServiceEventCallback callback) { + mForegroundServiceEventCallback = callback; + } + + abstract static class ForegroundServiceEventCallback { + public void onSessionClosed(MediaSession2 session) {} + } } } diff --git a/media/java/android/media/MediaSession2Service.java b/media/java/android/media/MediaSession2Service.java new file mode 100644 index 000000000000..8fb00fe487e8 --- /dev/null +++ b/media/java/android/media/MediaSession2Service.java @@ -0,0 +1,288 @@ +/* + * Copyright 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.media; + +import android.annotation.CallSuper; +import android.annotation.NonNull; +import android.annotation.Nullable; +import android.app.Service; +import android.content.Intent; +import android.os.Binder; +import android.os.Bundle; +import android.os.Handler; +import android.os.IBinder; +import android.util.ArrayMap; +import android.util.Log; + +import com.android.internal.annotations.GuardedBy; + +import java.lang.ref.WeakReference; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +/** + * Service containing {@link MediaSession2}. + * <p> + * This API is not generally intended for third party application developers. + * Use the <a href="{@docRoot}jetpack/androidx.html">AndroidX</a> + * <a href="{@docRoot}reference/androidx/media2/package-summary.html">Media2 Library</a> + * for consistent behavior across all devices. + * @hide + */ +// TODO: Unhide +// TODO: Add onUpdateNotification(), and calls it to get Notification for startForegroundService() +// when a session's player state becomes playing. +public abstract class MediaSession2Service extends Service { + /** + * The {@link Intent} that must be declared as handled by the service. + */ + public static final String SERVICE_INTERFACE = "android.media.MediaSession2Service"; + + private static final String TAG = "MediaSession2Service"; + private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG); + + private final Object mLock = new Object(); + @GuardedBy("mLock") + private Map<String, MediaSession2> mSessions = new ArrayMap<>(); + + private MediaSession2ServiceStub mStub; + + /** + * Called by the system when the service is first created. Do not call this method directly. + * <p> + * Override this method if you need your own initialization. Derived classes MUST call through + * to the super class's implementation of this method. + */ + @CallSuper + @Override + public void onCreate() { + super.onCreate(); + mStub = new MediaSession2ServiceStub(this); + } + + @CallSuper + @Override + @Nullable + public IBinder onBind(@NonNull Intent intent) { + if (SERVICE_INTERFACE.equals(intent.getAction())) { + return mStub; + } + return null; + } + + @CallSuper + @Override + public int onStartCommand(Intent intent, int flags, int startId) { + // TODO: Dispatch media key events to the primary session. + return START_STICKY; + } + + /** + * Called by the system to notify that it is no longer used and is being removed. Do not call + * this method directly. + * <p> + * Override this method if you need your own clean up. Derived classes MUST call through + * to the super class's implementation of this method. + */ + @CallSuper + @Override + public void onDestroy() { + super.onDestroy(); + synchronized (mLock) { + for (MediaSession2 session : mSessions.values()) { + session.getCallback().setForegroundServiceEventCallback(null); + } + mSessions.clear(); + } + mStub.close(); + } + + /** + * Called when a {@link MediaController2} is created with the this service's + * {@link Session2Token}. Return the primary session for telling the controller which session to + * connect. + * <p> + * Primary session is the highest priority session that this service manages. Here are some + * recommendations of the primary session. + * <ol> + * <li>When there's no {@link MediaSession2}, create and return a new session. Resume the + * playback that the app has the lastly played with the new session. The behavior is what + * framework expects when the framework sends key events to the service.</li> + * <li>When there's multiple {@link MediaSession2}s, pick the session that has the lastly + * started the playback. This is the same way as the framework prioritize sessions to receive + * media key events.</li> + * </ol> + * <p> + * Session returned here will be added to this service automatically. You don't need to call + * {@link #addSession(MediaSession2)} for that. + * <p> + * Session service will accept or reject the connection with the + * {@link MediaSession2.SessionCallback} in the session returned here. + * <p> + * This method is always called on the main thread. + * + * @return a new session + * @see MediaSession2.Builder + * @see #getSessions() + */ + @NonNull + public abstract MediaSession2 onGetPrimarySession(); + + /** + * Adds a session to this service. + * <p> + * Added session will be removed automatically when it's closed, or removed when + * {@link #removeSession} is called. + * + * @param session a session to be added. + * @see #removeSession(MediaSession2) + */ + public final void addSession(@NonNull MediaSession2 session) { + if (session == null) { + throw new IllegalArgumentException("session shouldn't be null"); + } + if (session.isClosed()) { + throw new IllegalArgumentException("session is already closed"); + } + synchronized (mLock) { + MediaSession2 previousSession = mSessions.get(session.getSessionId()); + if (previousSession != session) { + if (previousSession != null) { + Log.w(TAG, "Session ID should be unique, ID=" + session.getSessionId() + + ", previous=" + previousSession + ", session=" + session); + } + return; + } + mSessions.put(session.getSessionId(), session); + session.getCallback().setForegroundServiceEventCallback( + new MediaSession2.SessionCallback.ForegroundServiceEventCallback() { + @Override + public void onSessionClosed(MediaSession2 session) { + removeSession(session); + } + }); + } + } + + /** + * Removes a session from this service. + * + * @param session a session to be removed. + * @see #addSession(MediaSession2) + */ + public final void removeSession(@NonNull MediaSession2 session) { + if (session == null) { + throw new IllegalArgumentException("session shouldn't be null"); + } + synchronized (mLock) { + mSessions.remove(session.getSessionId()); + } + } + + /** + * Gets the list of {@link MediaSession2}s that you've added to this service. + * + * @return sessions + */ + public final @NonNull List<MediaSession2> getSessions() { + List<MediaSession2> list = new ArrayList<>(); + synchronized (mLock) { + list.addAll(mSessions.values()); + } + return list; + } + + private static final class MediaSession2ServiceStub extends IMediaSession2Service.Stub + implements AutoCloseable { + final WeakReference<MediaSession2Service> mService; + final Handler mHandler; + + MediaSession2ServiceStub(MediaSession2Service service) { + mService = new WeakReference<>(service); + mHandler = new Handler(service.getMainLooper()); + } + + @Override + public void connect(Controller2Link caller, int seq, Bundle connectionRequest) { + if (mService.get() == null) { + if (DEBUG) { + Log.d(TAG, "Service is already destroyed"); + } + return; + } + if (caller == null || connectionRequest == null) { + if (DEBUG) { + Log.d(TAG, "Ignoring calls with illegal arguments, caller=" + caller + + ", connectionRequest=" + connectionRequest); + } + return; + } + final int pid = Binder.getCallingPid(); + final int uid = Binder.getCallingUid(); + final long token = Binder.clearCallingIdentity(); + try { + mHandler.post(() -> { + boolean shouldNotifyDisconnected = true; + try { + final MediaSession2Service service = mService.get(); + if (service == null) { + if (DEBUG) { + Log.d(TAG, "Service isn't available"); + } + return; + } + if (DEBUG) { + Log.d(TAG, "Handling incoming connection request from the" + + " controller, controller=" + caller + ", uid=" + uid); + } + final MediaSession2 session; + session = service.onGetPrimarySession(); + service.addSession(session); + shouldNotifyDisconnected = false; + session.onConnect(caller, pid, uid, seq, connectionRequest); + } catch (Exception e) { + // Don't propagate exception in service to the controller. + Log.w(TAG, "Failed to add a session to session service", e); + } finally { + // Trick to call onDisconnected() in one place. + if (shouldNotifyDisconnected) { + if (DEBUG) { + Log.d(TAG, "Service has destroyed prematurely." + + " Rejecting connection"); + } + try { + caller.notifyDisconnected(0); + } catch (RuntimeException e) { + // Controller may be died prematurely. + // Not an issue because we'll ignore it anyway. + } + } + } + }); + } finally { + Binder.restoreCallingIdentity(token); + } + } + + @Override + public void close() { + mHandler.removeCallbacksAndMessages(null); + mService.clear(); + } + } +} diff --git a/media/java/android/media/MicrophoneDirection.java b/media/java/android/media/MicrophoneDirection.java new file mode 100644 index 000000000000..99201c0279bf --- /dev/null +++ b/media/java/android/media/MicrophoneDirection.java @@ -0,0 +1,62 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.media; + +/** + * @hide + */ +public interface MicrophoneDirection { + /** + * @hide + */ + int MIC_DIRECTION_UNSPECIFIED = 0; + + /** + * @hide + */ + int MIC_DIRECTION_FRONT = 1; + + /** + * @hide + */ + int MIC_DIRECTION_BACK = 2; + + /** + * @hide + */ + int MIC_DIRECTION_EXTERNAL = 3; + + /** + * Specifies the logical microphone (for processing). + * + * @param direction Direction constant (MicrophoneDirection.MIC_DIRECTION_*) + * @return retval OK if the call is successful, an error code otherwise. + * @hide + */ + int setMicrophoneDirection(int direction); + + /** + * Specifies the zoom factor (i.e. the field dimension) for the selected microphone + * (for processing). The selected microphone is determined by the use-case for the stream. + * + * @param zoom the desired field dimension of microphone capture. Range is from -1 (wide angle), + * though 0 (no zoom) to 1 (maximum zoom). + * @return retval OK if the call is successful, an error code otherwise. + * @hide + */ + int setMicrophoneFieldDimension(float zoom); +} diff --git a/media/java/android/media/Session2Link.java b/media/java/android/media/Session2Link.java index 5fe558da12f5..08664aa3b38f 100644 --- a/media/java/android/media/Session2Link.java +++ b/media/java/android/media/Session2Link.java @@ -17,6 +17,7 @@ package android.media; import android.annotation.NonNull; +import android.os.Binder; import android.os.Bundle; import android.os.IBinder; import android.os.Parcel; @@ -145,8 +146,9 @@ public final class Session2Link implements Parcelable { } /** Stub implementation for IMediaSession2.connect */ - public void onConnect(final Controller2Link caller, int seq, Bundle connectionRequest) { - mSession.onConnect(caller, seq, connectionRequest); + public void onConnect(final Controller2Link caller, int pid, int uid, int seq, + Bundle connectionRequest) { + mSession.onConnect(caller, pid, uid, seq, connectionRequest); } /** Stub implementation for IMediaSession2.disconnect */ @@ -168,23 +170,57 @@ public final class Session2Link implements Parcelable { private class Session2Stub extends IMediaSession2.Stub { @Override public void connect(final Controller2Link caller, int seq, Bundle connectionRequest) { - Session2Link.this.onConnect(caller, seq, connectionRequest); + if (caller == null || connectionRequest == null) { + return; + } + final int pid = Binder.getCallingPid(); + final int uid = Binder.getCallingUid(); + final long token = Binder.clearCallingIdentity(); + try { + Session2Link.this.onConnect(caller, pid, uid, seq, connectionRequest); + } finally { + Binder.restoreCallingIdentity(token); + } } @Override public void disconnect(final Controller2Link caller, int seq) { - Session2Link.this.onDisconnect(caller, seq); + if (caller == null) { + return; + } + final long token = Binder.clearCallingIdentity(); + try { + Session2Link.this.onDisconnect(caller, seq); + } finally { + Binder.restoreCallingIdentity(token); + } } @Override public void sendSessionCommand(final Controller2Link caller, final int seq, final Session2Command command, final Bundle args, ResultReceiver resultReceiver) { - Session2Link.this.onSessionCommand(caller, seq, command, args, resultReceiver); + if (caller == null) { + return; + } + final long token = Binder.clearCallingIdentity(); + try { + Session2Link.this.onSessionCommand(caller, seq, command, args, resultReceiver); + } finally { + Binder.restoreCallingIdentity(token); + } } @Override public void cancelSessionCommand(final Controller2Link caller, final int seq) { - Session2Link.this.onCancelCommand(caller, seq); + if (caller == null) { + return; + } + final long token = Binder.clearCallingIdentity(); + try { + Session2Link.this.onCancelCommand(caller, seq); + } finally { + Binder.restoreCallingIdentity(token); + } } } } diff --git a/media/java/android/media/Session2Token.java b/media/java/android/media/Session2Token.java index 95ee4c039f4b..c7b891151201 100644 --- a/media/java/android/media/Session2Token.java +++ b/media/java/android/media/Session2Token.java @@ -152,9 +152,7 @@ public final class Session2Token implements Parcelable { mType = in.readInt(); mPackageName = in.readString(); mServiceName = in.readString(); - // TODO: Uncomment below and stop hardcode mSessionLink - mSessionLink = null; - //mSessionLink = ISession.Stub.asInterface(in.readStrongBinder()); + mSessionLink = Session2Link.CREATOR.createFromParcel(in); mComponentName = ComponentName.unflattenFromString(in.readString()); } @@ -164,8 +162,7 @@ public final class Session2Token implements Parcelable { dest.writeInt(mType); dest.writeString(mPackageName); dest.writeString(mServiceName); - // TODO: Uncomment below - //dest.writeStrongBinder(mSessionLink.getBinder()); + mSessionLink.writeToParcel(dest, flags); dest.writeString(mComponentName == null ? "" : mComponentName.flattenToString()); } diff --git a/media/java/android/media/session/MediaSessionProviderService.java b/media/java/android/media/session/MediaSessionProviderService.java new file mode 100644 index 000000000000..9a346ff4a12e --- /dev/null +++ b/media/java/android/media/session/MediaSessionProviderService.java @@ -0,0 +1,35 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.media.session; + +import android.app.Service; +import android.content.Intent; +import android.os.IBinder; + +/** + * Abstract class for mainline module services. + * + * @hide // TODO: Make it as a @SystemApi + */ +public abstract class MediaSessionProviderService extends Service { + + @Override + public IBinder onBind(Intent intent) { + // TODO: Return IMediaSessionProviderService.Stub() + return null; + } +} diff --git a/media/jni/android_media_MediaCodec.cpp b/media/jni/android_media_MediaCodec.cpp index 7b07bea3cf1a..406f9dd94bb4 100644 --- a/media/jni/android_media_MediaCodec.cpp +++ b/media/jni/android_media_MediaCodec.cpp @@ -648,7 +648,6 @@ static jobject getCodecCapabilitiesObject( capabilities->getSupportedColorFormats(&colorFormats); capabilities->getSupportedProfileLevels(&profileLevels); - uint32_t flags = capabilities->getFlags(); sp<AMessage> details = capabilities->getDetails(); jobject defaultFormatObj = NULL; @@ -687,7 +686,7 @@ static jobject getCodecCapabilitiesObject( return env->NewObject( gCodecInfo.capsClazz, gCodecInfo.capsCtorId, - profileLevelArray.get(), colorFormatsArray.get(), isEncoder, flags, + profileLevelArray.get(), colorFormatsArray.get(), isEncoder, defaultFormatRef.get(), detailsRef.get()); } @@ -700,23 +699,28 @@ status_t JMediaCodec::getCodecInfo(JNIEnv *env, jobject *codecInfoObject) const return err; } + // TODO: get alias ScopedLocalRef<jstring> nameObject(env, env->NewStringUTF(codecInfo->getCodecName())); + ScopedLocalRef<jstring> canonicalNameObject(env, + env->NewStringUTF(codecInfo->getCodecName())); + + MediaCodecInfo::Attributes attributes = codecInfo->getAttributes(); bool isEncoder = codecInfo->isEncoder(); - Vector<AString> mimes; - codecInfo->getSupportedMimes(&mimes); + Vector<AString> mediaTypes; + codecInfo->getSupportedMediaTypes(&mediaTypes); ScopedLocalRef<jobjectArray> capsArrayObj(env, - env->NewObjectArray(mimes.size(), gCodecInfo.capsClazz, NULL)); + env->NewObjectArray(mediaTypes.size(), gCodecInfo.capsClazz, NULL)); - for (size_t i = 0; i < mimes.size(); i++) { + for (size_t i = 0; i < mediaTypes.size(); i++) { const sp<MediaCodecInfo::Capabilities> caps = - codecInfo->getCapabilitiesFor(mimes[i].c_str()); + codecInfo->getCapabilitiesFor(mediaTypes[i].c_str()); ScopedLocalRef<jobject> capsObj(env, getCodecCapabilitiesObject( - env, mimes[i].c_str(), isEncoder, caps)); + env, mediaTypes[i].c_str(), isEncoder, caps)); env->SetObjectArrayElement(capsArrayObj.get(), i, capsObj.get()); } @@ -726,10 +730,10 @@ status_t JMediaCodec::getCodecInfo(JNIEnv *env, jobject *codecInfoObject) const CHECK(codecInfoClazz.get() != NULL); jmethodID codecInfoCtorID = env->GetMethodID(codecInfoClazz.get(), "<init>", - "(Ljava/lang/String;Z[Landroid/media/MediaCodecInfo$CodecCapabilities;)V"); + "(Ljava/lang/String;Ljava/lang/String;I[Landroid/media/MediaCodecInfo$CodecCapabilities;)V"); *codecInfoObject = env->NewObject(codecInfoClazz.get(), codecInfoCtorID, - nameObject.get(), isEncoder, capsArrayObj.get()); + nameObject.get(), canonicalNameObject.get(), attributes, capsArrayObj.get()); return OK; } @@ -2079,7 +2083,7 @@ static void android_media_MediaCodec_native_init(JNIEnv *env) { gCodecInfo.capsClazz = (jclass)env->NewGlobalRef(clazz.get()); method = env->GetMethodID(clazz.get(), "<init>", - "([Landroid/media/MediaCodecInfo$CodecProfileLevel;[IZI" + "([Landroid/media/MediaCodecInfo$CodecProfileLevel;[IZ" "Ljava/util/Map;Ljava/util/Map;)V"); CHECK(method != NULL); gCodecInfo.capsCtorId = method; @@ -2217,7 +2221,7 @@ static const JNINativeMethod gMethods[] = { { "getImage", "(ZI)Landroid/media/Image;", (void *)android_media_MediaCodec_getImage }, - { "getName", "()Ljava/lang/String;", + { "getCanonicalName", "()Ljava/lang/String;", (void *)android_media_MediaCodec_getName }, { "getOwnCodecInfo", "()Landroid/media/MediaCodecInfo;", diff --git a/media/jni/android_media_MediaCodecList.cpp b/media/jni/android_media_MediaCodecList.cpp index 8de11caf7d7a..cf1494296756 100644 --- a/media/jni/android_media_MediaCodecList.cpp +++ b/media/jni/android_media_MediaCodecList.cpp @@ -41,6 +41,21 @@ static sp<IMediaCodecList> getCodecList(JNIEnv *env) { return mcl; } +static sp<MediaCodecInfo> getCodecInfo(JNIEnv *env, jint index) { + sp<IMediaCodecList> mcl = getCodecList(env); + if (mcl == NULL) { + // Runtime exception already pending. + return NULL; + } + + sp<MediaCodecInfo> info = mcl->getCodecInfo(index); + if (info == NULL) { + jniThrowException(env, "java/lang/IllegalArgumentException", NULL); + } + + return info; +} + static jint android_media_MediaCodecList_getCodecCount( JNIEnv *env, jobject /* thiz */) { sp<IMediaCodecList> mcl = getCodecList(env); @@ -53,15 +68,22 @@ static jint android_media_MediaCodecList_getCodecCount( static jstring android_media_MediaCodecList_getCodecName( JNIEnv *env, jobject /* thiz */, jint index) { - sp<IMediaCodecList> mcl = getCodecList(env); - if (mcl == NULL) { + sp<MediaCodecInfo> info = getCodecInfo(env, index); + if (info == NULL) { // Runtime exception already pending. return NULL; } - const sp<MediaCodecInfo> &info = mcl->getCodecInfo(index); + // TODO: support aliases + const char *name = info->getCodecName(); + return env->NewStringUTF(name); +} + +static jstring android_media_MediaCodecList_getCanonicalName( + JNIEnv *env, jobject /* thiz */, jint index) { + sp<MediaCodecInfo> info = getCodecInfo(env, index); if (info == NULL) { - jniThrowException(env, "java/lang/IllegalArgumentException", NULL); + // Runtime exception already pending. return NULL; } @@ -94,39 +116,27 @@ static jint android_media_MediaCodecList_findCodecByName( return ret; } -static jboolean android_media_MediaCodecList_isEncoder( +static jboolean android_media_MediaCodecList_getAttributes( JNIEnv *env, jobject /* thiz */, jint index) { - sp<IMediaCodecList> mcl = getCodecList(env); - if (mcl == NULL) { - // Runtime exception already pending. - return false; - } - - const sp<MediaCodecInfo> &info = mcl->getCodecInfo(index); + sp<MediaCodecInfo> info = getCodecInfo(env, index); if (info == NULL) { - jniThrowException(env, "java/lang/IllegalArgumentException", NULL); - return false; + // Runtime exception already pending. + return 0; } - return info->isEncoder(); + return info->getAttributes(); } static jarray android_media_MediaCodecList_getSupportedTypes( JNIEnv *env, jobject /* thiz */, jint index) { - sp<IMediaCodecList> mcl = getCodecList(env); - if (mcl == NULL) { - // Runtime exception already pending. - return NULL; - } - - const sp<MediaCodecInfo> &info = mcl->getCodecInfo(index); + sp<MediaCodecInfo> info = getCodecInfo(env, index); if (info == NULL) { - jniThrowException(env, "java/lang/IllegalArgumentException", NULL); + // Runtime exception already pending. return NULL; } Vector<AString> types; - info->getSupportedMimes(&types); + info->getSupportedMediaTypes(&types); jclass clazz = env->FindClass("java/lang/String"); CHECK(clazz != NULL); @@ -150,17 +160,12 @@ static jobject android_media_MediaCodecList_getCodecCapabilities( return NULL; } - sp<IMediaCodecList> mcl = getCodecList(env); - if (mcl == NULL) { + sp<MediaCodecInfo> info = getCodecInfo(env, index); + if (info == NULL) { // Runtime exception already pending. return NULL; } - const sp<MediaCodecInfo> &info = mcl->getCodecInfo(index); - if (info == NULL) { - jniThrowException(env, "java/lang/IllegalArgumentException", NULL); - return NULL; - } const char *typeStr = env->GetStringUTFChars(type, NULL); if (typeStr == NULL) { @@ -186,7 +191,6 @@ static jobject android_media_MediaCodecList_getCodecCapabilities( capabilities->getSupportedColorFormats(&colorFormats); capabilities->getSupportedProfileLevels(&profileLevels); - uint32_t flags = capabilities->getFlags(); sp<AMessage> details = capabilities->getDetails(); bool isEncoder = info->isEncoder(); @@ -240,11 +244,11 @@ static jobject android_media_MediaCodecList_getCodecCapabilities( } jmethodID capsConstructID = env->GetMethodID(capsClazz, "<init>", - "([Landroid/media/MediaCodecInfo$CodecProfileLevel;[IZI" + "([Landroid/media/MediaCodecInfo$CodecProfileLevel;[IZ" "Ljava/util/Map;Ljava/util/Map;)V"); jobject caps = env->NewObject(capsClazz, capsConstructID, - profileLevelArray, colorFormatsArray, isEncoder, flags, + profileLevelArray, colorFormatsArray, isEncoder, defaultFormatObj, infoObj); env->DeleteLocalRef(profileLevelArray); @@ -288,9 +292,15 @@ static void android_media_MediaCodecList_native_init(JNIEnv* /* env */) { static const JNINativeMethod gMethods[] = { { "native_getCodecCount", "()I", (void *)android_media_MediaCodecList_getCodecCount }, + + { "getCanonicalName", "(I)Ljava/lang/String;", + (void *)android_media_MediaCodecList_getCanonicalName }, + { "getCodecName", "(I)Ljava/lang/String;", (void *)android_media_MediaCodecList_getCodecName }, - { "isEncoder", "(I)Z", (void *)android_media_MediaCodecList_isEncoder }, + + { "getAttributes", "(I)I", (void *)android_media_MediaCodecList_getAttributes }, + { "getSupportedTypes", "(I)[Ljava/lang/String;", (void *)android_media_MediaCodecList_getSupportedTypes }, diff --git a/media/jni/android_media_MediaDrm.cpp b/media/jni/android_media_MediaDrm.cpp index 83364590039d..42c5b052d4aa 100644 --- a/media/jni/android_media_MediaDrm.cpp +++ b/media/jni/android_media_MediaDrm.cpp @@ -159,6 +159,7 @@ struct HDCPLevels { jint kHdcpV2; jint kHdcpV2_1; jint kHdcpV2_2; + jint kHdcpV2_3; jint kHdcpNoOutput; } gHdcpLevels; @@ -774,6 +775,8 @@ static void android_media_MediaDrm_native_init(JNIEnv *env) { gHdcpLevels.kHdcpV2_1 = env->GetStaticIntField(clazz, field); GET_STATIC_FIELD_ID(field, clazz, "HDCP_V2_2", "I"); gHdcpLevels.kHdcpV2_2 = env->GetStaticIntField(clazz, field); + GET_STATIC_FIELD_ID(field, clazz, "HDCP_V2_3", "I"); + gHdcpLevels.kHdcpV2_3 = env->GetStaticIntField(clazz, field); GET_STATIC_FIELD_ID(field, clazz, "HDCP_NO_DIGITAL_OUTPUT", "I"); gHdcpLevels.kHdcpNoOutput = env->GetStaticIntField(clazz, field); @@ -1390,6 +1393,8 @@ static jint HdcpLevelTojint(DrmPlugin::HdcpLevel level) { return gHdcpLevels.kHdcpV2_1; case DrmPlugin::kHdcpV2_2: return gHdcpLevels.kHdcpV2_2; + case DrmPlugin::kHdcpV2_3: + return gHdcpLevels.kHdcpV2_3; case DrmPlugin::kHdcpNoOutput: return gHdcpLevels.kHdcpNoOutput; } diff --git a/media/jni/android_mtp_MtpDatabase.cpp b/media/jni/android_mtp_MtpDatabase.cpp index 56b85b5167f5..06a7182e4b1d 100644 --- a/media/jni/android_mtp_MtpDatabase.cpp +++ b/media/jni/android_mtp_MtpDatabase.cpp @@ -708,6 +708,24 @@ MtpResponseCode MtpDatabase::getObjectPropertyList(MtpObjectHandle handle, int type = dataTypes[i]; packet.putUInt16(type); + if (type == MTP_TYPE_STR) { + jstring value = (jstring)env->GetObjectArrayElement(stringValuesArray, i); + const char *valueStr = (value ? env->GetStringUTFChars(value, NULL) : NULL); + if (valueStr) { + packet.putString(valueStr); + env->ReleaseStringUTFChars(value, valueStr); + } else { + packet.putEmptyString(); + } + env->DeleteLocalRef(value); + continue; + } + + if (!longValues) { + ALOGE("bad longValuesArray value in MyMtpDatabase::getObjectPropertyList"); + continue; + } + switch (type) { case MTP_TYPE_INT8: packet.putInt8(longValues[i]); @@ -739,18 +757,6 @@ MtpResponseCode MtpDatabase::getObjectPropertyList(MtpObjectHandle handle, case MTP_TYPE_UINT128: packet.putUInt128(longValues[i]); break; - case MTP_TYPE_STR: { - jstring value = (jstring)env->GetObjectArrayElement(stringValuesArray, i); - const char *valueStr = (value ? env->GetStringUTFChars(value, NULL) : NULL); - if (valueStr) { - packet.putString(valueStr); - env->ReleaseStringUTFChars(value, valueStr); - } else { - packet.putEmptyString(); - } - env->DeleteLocalRef(value); - break; - } default: ALOGE("bad or unsupported data type in MtpDatabase::getObjectPropertyList"); break; diff --git a/media/packages/MediaCore/Android.bp b/media/packages/MediaCore/Android.bp new file mode 100644 index 000000000000..c7fd58bf933a --- /dev/null +++ b/media/packages/MediaCore/Android.bp @@ -0,0 +1,21 @@ +android_app { + name: "MediaCore", + + srcs: [ + "src/**/*.java", + ], + + static_libs: [ + // TODO: Temporarily statically linked. Should go into "libs" + "media1", + ], + + // System app + platform_apis: true, + + // Privileged app + privileged: true, + + // Make sure that the implementation only relies on SDK or system APIs. + sdk_version: "system_current", +} diff --git a/media/packages/MediaCore/AndroidManifest.xml b/media/packages/MediaCore/AndroidManifest.xml new file mode 100644 index 000000000000..4e2b274511e8 --- /dev/null +++ b/media/packages/MediaCore/AndroidManifest.xml @@ -0,0 +1,32 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* //device/apps/common/AndroidManifest.xml +** +** Copyright 2019, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ +--> +<manifest xmlns:android="http://schemas.android.com/apk/res/android" + package="com.android.media" coreApp="true" android:sharedUserId="android.uid.system" + android:sharedUserLabel="@string/android_system_label"> + <application android:process="system" + android:persistent="true" + android:directBootAware="true"> + <service android:name="AmlMediaSessionProviderService" android:singleUser="true"> + <intent-filter> + <action android:name="android.media.session.MediaSessionProviderService"/> + </intent-filter> + </service> + </application> +</manifest> diff --git a/media/packages/MediaCore/res/values/strings.xml b/media/packages/MediaCore/res/values/strings.xml new file mode 100644 index 000000000000..59fd635b905f --- /dev/null +++ b/media/packages/MediaCore/res/values/strings.xml @@ -0,0 +1,21 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright 2019 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> + +<resources> + <!-- Label for the Android system components when they are shown to the user. --> + <string name="android_system_label" translatable="false">Android System</string> +</resources> + diff --git a/media/packages/MediaCore/src/com/android/media/AmlMediaSessionProviderService.java b/media/packages/MediaCore/src/com/android/media/AmlMediaSessionProviderService.java new file mode 100644 index 000000000000..43b95ab7ebdb --- /dev/null +++ b/media/packages/MediaCore/src/com/android/media/AmlMediaSessionProviderService.java @@ -0,0 +1,37 @@ +/* + * Copyright 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.media; + +import android.content.Context; +import android.media.session.MediaSessionProviderService; +import android.os.PowerManager; +import android.util.Log; + +/** + * System implementation of MediaSessionProviderService + */ +public class AmlMediaSessionProviderService extends MediaSessionProviderService { + private static final String TAG = "AmlMediaSessionProviderS"; + static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG); + + private Context mContext; + + public AmlMediaSessionProviderService(Context context) { + mContext = context; + PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE); + } +} diff --git a/media/tests/players/Android.mk b/media/tests/players/Android.mk index 35aba4dfa25e..ee9d85099104 100644 --- a/media/tests/players/Android.mk +++ b/media/tests/players/Android.mk @@ -25,7 +25,7 @@ LOCAL_SHARED_LIBRARIES:= \ liblog LOCAL_MODULE:= invoke_mock_media_player -LOCAL_MODULE_TAGS := tests eng +LOCAL_MODULE_TAGS := tests LOCAL_CFLAGS += -Wall -Werror -Wunused -Wunreachable-code diff --git a/native/android/sensor.cpp b/native/android/sensor.cpp index 8e5821024cee..c3b2e2526ea8 100644 --- a/native/android/sensor.cpp +++ b/native/android/sensor.cpp @@ -342,3 +342,8 @@ int ASensor_getHighestDirectReportRateLevel(ASensor const *sensor) { RETURN_IF_SENSOR_IS_NULL(ASENSOR_DIRECT_RATE_STOP); return static_cast<Sensor const *>(sensor)->getHighestDirectReportRateLevel(); } + +int ASensor_getHandle(ASensor const* sensor) { + RETURN_IF_SENSOR_IS_NULL(ASENSOR_INVALID); + return static_cast<Sensor const*>(sensor)->getHandle(); +} diff --git a/packages/SettingsLib/EntityHeaderWidgets/res/layout/app_view.xml b/packages/SettingsLib/EntityHeaderWidgets/res/layout/app_view.xml index fcafa3140955..96045120fec4 100644 --- a/packages/SettingsLib/EntityHeaderWidgets/res/layout/app_view.xml +++ b/packages/SettingsLib/EntityHeaderWidgets/res/layout/app_view.xml @@ -22,6 +22,8 @@ android:layout_weight="1" android:layout_marginEnd="16dp" android:gravity="center" + android:clickable="true" + android:background="?android:attr/selectableItemBackground" android:orientation="vertical"> <ImageView diff --git a/packages/SettingsLib/EntityHeaderWidgets/src/com/android/settingslib/widget/AppEntitiesHeaderController.java b/packages/SettingsLib/EntityHeaderWidgets/src/com/android/settingslib/widget/AppEntitiesHeaderController.java index 8ccf89fc38b0..73cb8db136b5 100644 --- a/packages/SettingsLib/EntityHeaderWidgets/src/com/android/settingslib/widget/AppEntitiesHeaderController.java +++ b/packages/SettingsLib/EntityHeaderWidgets/src/com/android/settingslib/widget/AppEntitiesHeaderController.java @@ -18,7 +18,6 @@ package com.android.settingslib.widget; import android.content.Context; import android.content.res.Resources; -import android.graphics.drawable.Drawable; import android.text.TextUtils; import android.util.Log; import android.view.View; @@ -32,23 +31,9 @@ import androidx.annotation.StringRes; import androidx.annotation.VisibleForTesting; /** - * This is used to initialize view which was inflated + * This class is used to initialize view which was inflated * from {@link R.xml.app_entities_header.xml}. * - * <p>The view looks like below. - * - * <pre> - * -------------------------------------------------------------- - * | Header title | - * -------------------------------------------------------------- - * | App1 icon | App2 icon | App3 icon | - * | App1 title | App2 title | App3 title | - * | App1 summary | App2 summary | App3 summary | - * |------------------------------------------------------------- - * | Header details | - * -------------------------------------------------------------- - * </pre> - * * <p>How to use AppEntitiesHeaderController? * * <p>1. Add a {@link LayoutPreference} in layout XML file. @@ -66,13 +51,20 @@ import androidx.annotation.VisibleForTesting; * View headerView = ((LayoutPreference) screen.findPreference("app_entities_header")) * .findViewById(R.id.app_entities_header); * + * final AppEntityInfo appEntityInfo = new AppEntityInfo.Builder() + * .setIcon(icon) + * .setTitle(title) + * .setSummary(summary) + * .setOnClickListener(view -> doSomething()) + * .build(); + * * AppEntitiesHeaderController.newInstance(context, headerView) * .setHeaderTitleRes(R.string.xxxxx) * .setHeaderDetailsRes(R.string.xxxxx) * .setHeaderDetailsClickListener(onClickListener) - * .setAppEntity(0, icon, "app title", "app summary") - * .setAppEntity(1, icon, "app title", "app summary") - * .setAppEntity(2, icon, "app title", "app summary") + * .setAppEntity(0, appEntityInfo) + * .setAppEntity(1, appEntityInfo) + * .setAppEntity(2, appEntityInfo) * .apply(); * </pre> */ @@ -81,13 +73,13 @@ public class AppEntitiesHeaderController { private static final String TAG = "AppEntitiesHeaderCtl"; @VisibleForTesting - static final int MAXIMUM_APPS = 3; + public static final int MAXIMUM_APPS = 3; private final Context mContext; private final TextView mHeaderTitleView; private final Button mHeaderDetailsView; - private final AppEntity[] mAppEntities; + private final AppEntityInfo[] mAppEntityInfos; private final View[] mAppEntityViews; private final ImageView[] mAppIconViews; private final TextView[] mAppTitleViews; @@ -100,7 +92,7 @@ public class AppEntitiesHeaderController { /** * Creates a new instance of the controller. * - * @param context the Context the view is running in + * @param context the Context the view is running in * @param appEntitiesHeaderView view was inflated from <code>app_entities_header</code> */ public static AppEntitiesHeaderController newInstance(@NonNull Context context, @@ -113,7 +105,7 @@ public class AppEntitiesHeaderController { mHeaderTitleView = appEntitiesHeaderView.findViewById(R.id.header_title); mHeaderDetailsView = appEntitiesHeaderView.findViewById(R.id.header_details); - mAppEntities = new AppEntity[MAXIMUM_APPS]; + mAppEntityInfos = new AppEntityInfo[MAXIMUM_APPS]; mAppIconViews = new ImageView[MAXIMUM_APPS]; mAppTitleViews = new TextView[MAXIMUM_APPS]; mAppSummaryViews = new TextView[MAXIMUM_APPS]; @@ -162,16 +154,13 @@ public class AppEntitiesHeaderController { /** * Set an app entity at a specified position view. * - * @param index the index at which the specified view is to be inserted - * @param icon the icon of app entity - * @param titleRes the title of app entity - * @param summaryRes the summary of app entity + * @param index the index at which the specified view is to be inserted + * @param appEntityInfo the information of an app entity * @return this {@code AppEntitiesHeaderController} object */ - public AppEntitiesHeaderController setAppEntity(int index, @NonNull Drawable icon, - @Nullable CharSequence titleRes, @Nullable CharSequence summaryRes) { - final AppEntity appEntity = new AppEntity(icon, titleRes, summaryRes); - mAppEntities[index] = appEntity; + public AppEntitiesHeaderController setAppEntity(int index, + @NonNull AppEntityInfo appEntityInfo) { + mAppEntityInfos[index] = appEntityInfo; return this; } @@ -182,7 +171,7 @@ public class AppEntitiesHeaderController { * @return this {@code AppEntitiesHeaderController} object */ public AppEntitiesHeaderController removeAppEntity(int index) { - mAppEntities[index] = null; + mAppEntityInfos[index] = null; return this; } @@ -237,31 +226,23 @@ public class AppEntitiesHeaderController { } private void bindAppEntityView(int index) { - final AppEntity appEntity = mAppEntities[index]; - mAppEntityViews[index].setVisibility(appEntity != null ? View.VISIBLE : View.GONE); + final AppEntityInfo appEntityInfo = mAppEntityInfos[index]; + mAppEntityViews[index].setVisibility(appEntityInfo != null ? View.VISIBLE : View.GONE); - if (appEntity != null) { - mAppIconViews[index].setImageDrawable(appEntity.icon); + if (appEntityInfo != null) { + mAppEntityViews[index].setOnClickListener(appEntityInfo.getClickListener()); + mAppIconViews[index].setImageDrawable(appEntityInfo.getIcon()); + + final CharSequence title = appEntityInfo.getTitle(); mAppTitleViews[index].setVisibility( - TextUtils.isEmpty(appEntity.title) ? View.INVISIBLE : View.VISIBLE); - mAppTitleViews[index].setText(appEntity.title); + TextUtils.isEmpty(title) ? View.INVISIBLE : View.VISIBLE); + mAppTitleViews[index].setText(title); + final CharSequence summary = appEntityInfo.getSummary(); mAppSummaryViews[index].setVisibility( - TextUtils.isEmpty(appEntity.summary) ? View.INVISIBLE : View.VISIBLE); - mAppSummaryViews[index].setText(appEntity.summary); - } - } - - private static class AppEntity { - public final Drawable icon; - public final CharSequence title; - public final CharSequence summary; - - AppEntity(Drawable appIcon, CharSequence appTitle, CharSequence appSummary) { - icon = appIcon; - title = appTitle; - summary = appSummary; + TextUtils.isEmpty(summary) ? View.INVISIBLE : View.VISIBLE); + mAppSummaryViews[index].setText(summary); } } } diff --git a/packages/SettingsLib/EntityHeaderWidgets/src/com/android/settingslib/widget/AppEntityInfo.java b/packages/SettingsLib/EntityHeaderWidgets/src/com/android/settingslib/widget/AppEntityInfo.java new file mode 100644 index 000000000000..1e55f2e99bfc --- /dev/null +++ b/packages/SettingsLib/EntityHeaderWidgets/src/com/android/settingslib/widget/AppEntityInfo.java @@ -0,0 +1,129 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.settingslib.widget; + +import android.graphics.drawable.Drawable; +import android.view.View; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + +/** + * AppEntityInfo is responsible for storing app information shown in {@link R.xml.app_view.xml}. + */ +public class AppEntityInfo { + + private final Drawable mIcon; + private final CharSequence mTitle; + private final CharSequence mSummary; + private final View.OnClickListener mClickListener; + + /** + * Gets the drawable for the icon of app entity. + * + * @return the drawable for the icon of app entity. + */ + public Drawable getIcon() { + return mIcon; + } + + /** + * Gets the text for the title of app enitity. + * + * @return the text for the title of app enitity. + */ + public CharSequence getTitle() { + return mTitle; + } + + /** + * Gets the text for the summary of app enitity. + * + * @return the text for the summary of app enitity. + */ + public CharSequence getSummary() { + return mSummary; + } + + /** + * Gets the click listener for the app entity view. + * + * @return click listener for the app entity view. + */ + public View.OnClickListener getClickListener() { + return mClickListener; + } + + private AppEntityInfo(Builder builder) { + mIcon = builder.mIcon; + mTitle = builder.mTitle; + mSummary = builder.mSummary; + mClickListener = builder.mClickListener; + } + + /** + * Builder class for {@link AppEntityInfo} + */ + public static class Builder { + + private Drawable mIcon; + private CharSequence mTitle; + private CharSequence mSummary; + private View.OnClickListener mClickListener; + + /** + * Creates an instance of a {@link AppEntityInfo} based on the current builder settings. + * + * @return The {@link AppEntityInfo}. + */ + public AppEntityInfo build() { + return new AppEntityInfo(this); + } + + /** + * Sets the drawable for the icon. + */ + public Builder setIcon(@NonNull Drawable icon) { + mIcon = icon; + return this; + } + + /** + * Sets the text for the title. + */ + public Builder setTitle(@Nullable CharSequence title) { + mTitle = title; + return this; + } + + /** + * Sets the text for the summary. + */ + public Builder setSummary(@Nullable CharSequence summary) { + mSummary = summary; + return this; + } + + /** + * Sets the click listener for app entity view. + */ + public Builder setOnClickListener(@Nullable View.OnClickListener clickListener) { + mClickListener = clickListener; + return this; + } + } +} diff --git a/packages/SettingsLib/SearchWidget/res/values-fa/strings.xml b/packages/SettingsLib/SearchWidget/res/values-fa/strings.xml index 3787005ecfbb..237d62ea159c 100644 --- a/packages/SettingsLib/SearchWidget/res/values-fa/strings.xml +++ b/packages/SettingsLib/SearchWidget/res/values-fa/strings.xml @@ -17,5 +17,5 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="search_menu" msgid="1604061903696928905">"تنظیمات جستجو"</string> + <string name="search_menu" msgid="1604061903696928905">"جستجوی تنظیمات"</string> </resources> diff --git a/packages/SettingsLib/res/values-af/strings.xml b/packages/SettingsLib/res/values-af/strings.xml index ac34a99e0255..080fcc2ce3c0 100644 --- a/packages/SettingsLib/res/values-af/strings.xml +++ b/packages/SettingsLib/res/values-af/strings.xml @@ -38,13 +38,87 @@ <string name="connected_via_network_scorer" msgid="5713793306870815341">"Outomaties deur %1$s gekoppel"</string> <string name="connected_via_network_scorer_default" msgid="7867260222020343104">"Outomaties deur netwerkgraderingverskaffer gekoppel"</string> <string name="connected_via_passpoint" msgid="2826205693803088747">"Gekoppel via %1$s"</string> + <!-- no translation found for ssid_by_passpoint_provider (7898171424140673315) --> + <skip /> <string name="available_via_passpoint" msgid="1617440946846329613">"Beskikbaar via %1$s"</string> + <!-- no translation found for tap_to_set_up (2468970825530423314) --> + <skip /> <string name="wifi_connected_no_internet" msgid="8202906332837777829">"Gekoppel, geen internet nie"</string> <string name="wifi_status_no_internet" msgid="5784710974669608361">"Geen internet nie"</string> <string name="wifi_status_sign_in_required" msgid="123517180404752756">"Aanmelding word vereis"</string> <string name="wifi_ap_unable_to_handle_new_sta" msgid="5348824313514404541">"Toegangspunt is tydelik vol"</string> <string name="connected_via_carrier" msgid="7583780074526041912">"Gekoppel via %1$s"</string> <string name="available_via_carrier" msgid="1469036129740799053">"Beskikbaar via %1$s"</string> + <!-- no translation found for osu_failure_ap_connection (598977488344424542) --> + <skip /> + <!-- no translation found for osu_failure_server_url_invalid (2237477219243136714) --> + <skip /> + <!-- no translation found for osu_failure_server_connection (8192988165059982174) --> + <skip /> + <!-- no translation found for osu_failure_server_validation (4631649978129606823) --> + <skip /> + <!-- no translation found for osu_failure_service_provider_verification (4854091521439785597) --> + <skip /> + <!-- no translation found for osu_failure_provisioning_aborted (424627208135320329) --> + <skip /> + <!-- no translation found for osu_failure_provisioning_not_available (3021783729256985432) --> + <skip /> + <!-- no translation found for osu_failure_invalid_server_url (8548886196179435758) --> + <skip /> + <!-- no translation found for osu_failure_unexpected_command_type (8245921319866603904) --> + <skip /> + <!-- no translation found for osu_failure_unexpected_soap_message_type (2255897608510053065) --> + <skip /> + <!-- no translation found for osu_failure_soap_message_exchange (4357358438685987192) --> + <skip /> + <!-- no translation found for osu_failure_start_redirect_listener (4292769407279548482) --> + <skip /> + <!-- no translation found for osu_failure_timed_out_redirect_listener (3168657820278807508) --> + <skip /> + <!-- no translation found for osu_failure_no_osu_activity_found (4593038891437878675) --> + <skip /> + <!-- no translation found for osu_failure_unexpected_soap_message_status (6568467710235256675) --> + <skip /> + <!-- no translation found for osu_failure_no_pps_mo (850567403039076835) --> + <skip /> + <!-- no translation found for osu_failure_no_aaa_server_trust_root_node (8961455873459838456) --> + <skip /> + <!-- no translation found for osu_failure_no_remediation_server_trust_root_node (5041179688081545244) --> + <skip /> + <!-- no translation found for osu_failure_no_policy_server_trust_root_node (6617290380940513539) --> + <skip /> + <!-- no translation found for osu_failure_retrieve_trust_root_certificates (1499136256195528265) --> + <skip /> + <!-- no translation found for osu_failure_no_aaa_trust_root_certificate (1904322497042226984) --> + <skip /> + <!-- no translation found for osu_failure_add_passpoint_configuration (2173557755811446047) --> + <skip /> + <!-- no translation found for osu_failure_osu_provider_not_found (6616172862116673082) --> + <skip /> + <!-- no translation found for osu_status_ap_connecting (5296821043003441437) --> + <skip /> + <!-- no translation found for osu_status_ap_connected (3777289375683170728) --> + <skip /> + <!-- no translation found for osu_status_server_connecting (8499785407540355867) --> + <skip /> + <!-- no translation found for osu_status_server_validated (3158727184762596355) --> + <skip /> + <!-- no translation found for osu_status_server_connected (8382024481520158168) --> + <skip /> + <!-- no translation found for osu_status_init_soap_exchange (8628063888912101981) --> + <skip /> + <!-- no translation found for osu_status_waiting_for_redirect_response (2343016207837053197) --> + <skip /> + <!-- no translation found for osu_status_redirect_response_received (5323368411922609405) --> + <skip /> + <!-- no translation found for osu_status_second_soap_exchange (7115332266758483909) --> + <skip /> + <!-- no translation found for osu_status_third_soap_exchange (8460901783597440766) --> + <skip /> + <!-- no translation found for osu_status_retrieving_trust_root_certs (1563445892926269689) --> + <skip /> + <!-- no translation found for osu_provisioning_complete (5120178802493970149) --> + <skip /> <string name="speed_label_very_slow" msgid="1867055264243608530">"Baie stadig"</string> <string name="speed_label_slow" msgid="813109590815810235">"Stadig"</string> <string name="speed_label_okay" msgid="2331665440671174858">"OK"</string> diff --git a/packages/SettingsLib/res/values-am/strings.xml b/packages/SettingsLib/res/values-am/strings.xml index 9405b7da588f..53d1c4d5d393 100644 --- a/packages/SettingsLib/res/values-am/strings.xml +++ b/packages/SettingsLib/res/values-am/strings.xml @@ -38,13 +38,87 @@ <string name="connected_via_network_scorer" msgid="5713793306870815341">"በ%1$s በኩል በራስ-ሰር ተገናኝቷል"</string> <string name="connected_via_network_scorer_default" msgid="7867260222020343104">"በአውታረ መረብ ደረጃ ሰጪ አቅራቢ በኩል በራስ-ሰር ተገናኝቷል"</string> <string name="connected_via_passpoint" msgid="2826205693803088747">"በ%1$s በኩል መገናኘት"</string> + <!-- no translation found for ssid_by_passpoint_provider (7898171424140673315) --> + <skip /> <string name="available_via_passpoint" msgid="1617440946846329613">"በ%1$s በኩል የሚገኝ"</string> + <!-- no translation found for tap_to_set_up (2468970825530423314) --> + <skip /> <string name="wifi_connected_no_internet" msgid="8202906332837777829">"ተገናኝቷል፣ ምንም በይነመረብ የለም"</string> <string name="wifi_status_no_internet" msgid="5784710974669608361">"ምንም በይነመረብ የለም"</string> <string name="wifi_status_sign_in_required" msgid="123517180404752756">"ወደ መለያ መግባት ያስፈልጋል"</string> <string name="wifi_ap_unable_to_handle_new_sta" msgid="5348824313514404541">"የመዳረሻ ነጥብ ለጊዜው ሞልቷል"</string> <string name="connected_via_carrier" msgid="7583780074526041912">"በ%1$s በኩል ተገናኝቷል"</string> <string name="available_via_carrier" msgid="1469036129740799053">"በ%1$s በኩል የሚገኝ"</string> + <!-- no translation found for osu_failure_ap_connection (598977488344424542) --> + <skip /> + <!-- no translation found for osu_failure_server_url_invalid (2237477219243136714) --> + <skip /> + <!-- no translation found for osu_failure_server_connection (8192988165059982174) --> + <skip /> + <!-- no translation found for osu_failure_server_validation (4631649978129606823) --> + <skip /> + <!-- no translation found for osu_failure_service_provider_verification (4854091521439785597) --> + <skip /> + <!-- no translation found for osu_failure_provisioning_aborted (424627208135320329) --> + <skip /> + <!-- no translation found for osu_failure_provisioning_not_available (3021783729256985432) --> + <skip /> + <!-- no translation found for osu_failure_invalid_server_url (8548886196179435758) --> + <skip /> + <!-- no translation found for osu_failure_unexpected_command_type (8245921319866603904) --> + <skip /> + <!-- no translation found for osu_failure_unexpected_soap_message_type (2255897608510053065) --> + <skip /> + <!-- no translation found for osu_failure_soap_message_exchange (4357358438685987192) --> + <skip /> + <!-- no translation found for osu_failure_start_redirect_listener (4292769407279548482) --> + <skip /> + <!-- no translation found for osu_failure_timed_out_redirect_listener (3168657820278807508) --> + <skip /> + <!-- no translation found for osu_failure_no_osu_activity_found (4593038891437878675) --> + <skip /> + <!-- no translation found for osu_failure_unexpected_soap_message_status (6568467710235256675) --> + <skip /> + <!-- no translation found for osu_failure_no_pps_mo (850567403039076835) --> + <skip /> + <!-- no translation found for osu_failure_no_aaa_server_trust_root_node (8961455873459838456) --> + <skip /> + <!-- no translation found for osu_failure_no_remediation_server_trust_root_node (5041179688081545244) --> + <skip /> + <!-- no translation found for osu_failure_no_policy_server_trust_root_node (6617290380940513539) --> + <skip /> + <!-- no translation found for osu_failure_retrieve_trust_root_certificates (1499136256195528265) --> + <skip /> + <!-- no translation found for osu_failure_no_aaa_trust_root_certificate (1904322497042226984) --> + <skip /> + <!-- no translation found for osu_failure_add_passpoint_configuration (2173557755811446047) --> + <skip /> + <!-- no translation found for osu_failure_osu_provider_not_found (6616172862116673082) --> + <skip /> + <!-- no translation found for osu_status_ap_connecting (5296821043003441437) --> + <skip /> + <!-- no translation found for osu_status_ap_connected (3777289375683170728) --> + <skip /> + <!-- no translation found for osu_status_server_connecting (8499785407540355867) --> + <skip /> + <!-- no translation found for osu_status_server_validated (3158727184762596355) --> + <skip /> + <!-- no translation found for osu_status_server_connected (8382024481520158168) --> + <skip /> + <!-- no translation found for osu_status_init_soap_exchange (8628063888912101981) --> + <skip /> + <!-- no translation found for osu_status_waiting_for_redirect_response (2343016207837053197) --> + <skip /> + <!-- no translation found for osu_status_redirect_response_received (5323368411922609405) --> + <skip /> + <!-- no translation found for osu_status_second_soap_exchange (7115332266758483909) --> + <skip /> + <!-- no translation found for osu_status_third_soap_exchange (8460901783597440766) --> + <skip /> + <!-- no translation found for osu_status_retrieving_trust_root_certs (1563445892926269689) --> + <skip /> + <!-- no translation found for osu_provisioning_complete (5120178802493970149) --> + <skip /> <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> diff --git a/packages/SettingsLib/res/values-ar/strings.xml b/packages/SettingsLib/res/values-ar/strings.xml index 8ffd7a9ab41a..81755a78f1e2 100644 --- a/packages/SettingsLib/res/values-ar/strings.xml +++ b/packages/SettingsLib/res/values-ar/strings.xml @@ -38,13 +38,87 @@ <string name="connected_via_network_scorer" msgid="5713793306870815341">"تم الاتصال تلقائيًا عبر %1$s"</string> <string name="connected_via_network_scorer_default" msgid="7867260222020343104">"تم الاتصال تلقائيًا عبر مقدم خدمة تقييم الشبكة"</string> <string name="connected_via_passpoint" msgid="2826205693803088747">"تم الاتصال عبر %1$s"</string> + <!-- no translation found for ssid_by_passpoint_provider (7898171424140673315) --> + <skip /> <string name="available_via_passpoint" msgid="1617440946846329613">"متوفرة عبر %1$s"</string> + <!-- no translation found for tap_to_set_up (2468970825530423314) --> + <skip /> <string name="wifi_connected_no_internet" msgid="8202906332837777829">"متصلة ولكن بلا إنترنت"</string> <string name="wifi_status_no_internet" msgid="5784710974669608361">"لا يتوفر اتصال إنترنت."</string> <string name="wifi_status_sign_in_required" msgid="123517180404752756">"يلزم تسجيل الدخول"</string> <string name="wifi_ap_unable_to_handle_new_sta" msgid="5348824313514404541">"نقطة الدخول ممتلئة مؤقتًا"</string> <string name="connected_via_carrier" msgid="7583780074526041912">"تم الاتصال عبر %1$s"</string> <string name="available_via_carrier" msgid="1469036129740799053">"متوفرة عبر %1$s"</string> + <!-- no translation found for osu_failure_ap_connection (598977488344424542) --> + <skip /> + <!-- no translation found for osu_failure_server_url_invalid (2237477219243136714) --> + <skip /> + <!-- no translation found for osu_failure_server_connection (8192988165059982174) --> + <skip /> + <!-- no translation found for osu_failure_server_validation (4631649978129606823) --> + <skip /> + <!-- no translation found for osu_failure_service_provider_verification (4854091521439785597) --> + <skip /> + <!-- no translation found for osu_failure_provisioning_aborted (424627208135320329) --> + <skip /> + <!-- no translation found for osu_failure_provisioning_not_available (3021783729256985432) --> + <skip /> + <!-- no translation found for osu_failure_invalid_server_url (8548886196179435758) --> + <skip /> + <!-- no translation found for osu_failure_unexpected_command_type (8245921319866603904) --> + <skip /> + <!-- no translation found for osu_failure_unexpected_soap_message_type (2255897608510053065) --> + <skip /> + <!-- no translation found for osu_failure_soap_message_exchange (4357358438685987192) --> + <skip /> + <!-- no translation found for osu_failure_start_redirect_listener (4292769407279548482) --> + <skip /> + <!-- no translation found for osu_failure_timed_out_redirect_listener (3168657820278807508) --> + <skip /> + <!-- no translation found for osu_failure_no_osu_activity_found (4593038891437878675) --> + <skip /> + <!-- no translation found for osu_failure_unexpected_soap_message_status (6568467710235256675) --> + <skip /> + <!-- no translation found for osu_failure_no_pps_mo (850567403039076835) --> + <skip /> + <!-- no translation found for osu_failure_no_aaa_server_trust_root_node (8961455873459838456) --> + <skip /> + <!-- no translation found for osu_failure_no_remediation_server_trust_root_node (5041179688081545244) --> + <skip /> + <!-- no translation found for osu_failure_no_policy_server_trust_root_node (6617290380940513539) --> + <skip /> + <!-- no translation found for osu_failure_retrieve_trust_root_certificates (1499136256195528265) --> + <skip /> + <!-- no translation found for osu_failure_no_aaa_trust_root_certificate (1904322497042226984) --> + <skip /> + <!-- no translation found for osu_failure_add_passpoint_configuration (2173557755811446047) --> + <skip /> + <!-- no translation found for osu_failure_osu_provider_not_found (6616172862116673082) --> + <skip /> + <!-- no translation found for osu_status_ap_connecting (5296821043003441437) --> + <skip /> + <!-- no translation found for osu_status_ap_connected (3777289375683170728) --> + <skip /> + <!-- no translation found for osu_status_server_connecting (8499785407540355867) --> + <skip /> + <!-- no translation found for osu_status_server_validated (3158727184762596355) --> + <skip /> + <!-- no translation found for osu_status_server_connected (8382024481520158168) --> + <skip /> + <!-- no translation found for osu_status_init_soap_exchange (8628063888912101981) --> + <skip /> + <!-- no translation found for osu_status_waiting_for_redirect_response (2343016207837053197) --> + <skip /> + <!-- no translation found for osu_status_redirect_response_received (5323368411922609405) --> + <skip /> + <!-- no translation found for osu_status_second_soap_exchange (7115332266758483909) --> + <skip /> + <!-- no translation found for osu_status_third_soap_exchange (8460901783597440766) --> + <skip /> + <!-- no translation found for osu_status_retrieving_trust_root_certs (1563445892926269689) --> + <skip /> + <!-- no translation found for osu_provisioning_complete (5120178802493970149) --> + <skip /> <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> diff --git a/packages/SettingsLib/res/values-as/strings.xml b/packages/SettingsLib/res/values-as/strings.xml index 3ad13bd8a0bb..6cb0c3e7bfc8 100644 --- a/packages/SettingsLib/res/values-as/strings.xml +++ b/packages/SettingsLib/res/values-as/strings.xml @@ -38,13 +38,87 @@ <string name="connected_via_network_scorer" msgid="5713793306870815341">"%1$s মাধ্যমেদি স্বয়ংক্ৰিয়ভাৱে সংযোগ কৰা হৈছে"</string> <string name="connected_via_network_scorer_default" msgid="7867260222020343104">"নেটৱৰ্ক ৰেটিং প্ৰদানকাৰীৰ জৰিয়তে স্বয়ং সংয়োগ কৰা হ’ল"</string> <string name="connected_via_passpoint" msgid="2826205693803088747">"%1$s-ৰ মাধ্যমেদি সংযোগ কৰা হৈছে"</string> + <!-- no translation found for ssid_by_passpoint_provider (7898171424140673315) --> + <skip /> <string name="available_via_passpoint" msgid="1617440946846329613">"%1$sৰ মাধ্যমেৰে উপলব্ধ"</string> + <!-- no translation found for tap_to_set_up (2468970825530423314) --> + <skip /> <string name="wifi_connected_no_internet" msgid="8202906332837777829">"সংযোজিত, ইণ্টাৰনেট নাই"</string> <string name="wifi_status_no_internet" msgid="5784710974669608361">"ইণ্টাৰনেট সংযোগ নাই"</string> <string name="wifi_status_sign_in_required" msgid="123517180404752756">"ছাইন ইন কৰা দৰকাৰী"</string> <string name="wifi_ap_unable_to_handle_new_sta" msgid="5348824313514404541">"একচেছ পইণ্ট কিছু সময়ৰ বাবে পূৰ্ণ হৈ আছে"</string> <string name="connected_via_carrier" msgid="7583780074526041912">"%1$sৰ যোগেৰে সংযোজিত"</string> <string name="available_via_carrier" msgid="1469036129740799053">"%1$sৰ মাধ্যমেৰে উপলব্ধ"</string> + <!-- no translation found for osu_failure_ap_connection (598977488344424542) --> + <skip /> + <!-- no translation found for osu_failure_server_url_invalid (2237477219243136714) --> + <skip /> + <!-- no translation found for osu_failure_server_connection (8192988165059982174) --> + <skip /> + <!-- no translation found for osu_failure_server_validation (4631649978129606823) --> + <skip /> + <!-- no translation found for osu_failure_service_provider_verification (4854091521439785597) --> + <skip /> + <!-- no translation found for osu_failure_provisioning_aborted (424627208135320329) --> + <skip /> + <!-- no translation found for osu_failure_provisioning_not_available (3021783729256985432) --> + <skip /> + <!-- no translation found for osu_failure_invalid_server_url (8548886196179435758) --> + <skip /> + <!-- no translation found for osu_failure_unexpected_command_type (8245921319866603904) --> + <skip /> + <!-- no translation found for osu_failure_unexpected_soap_message_type (2255897608510053065) --> + <skip /> + <!-- no translation found for osu_failure_soap_message_exchange (4357358438685987192) --> + <skip /> + <!-- no translation found for osu_failure_start_redirect_listener (4292769407279548482) --> + <skip /> + <!-- no translation found for osu_failure_timed_out_redirect_listener (3168657820278807508) --> + <skip /> + <!-- no translation found for osu_failure_no_osu_activity_found (4593038891437878675) --> + <skip /> + <!-- no translation found for osu_failure_unexpected_soap_message_status (6568467710235256675) --> + <skip /> + <!-- no translation found for osu_failure_no_pps_mo (850567403039076835) --> + <skip /> + <!-- no translation found for osu_failure_no_aaa_server_trust_root_node (8961455873459838456) --> + <skip /> + <!-- no translation found for osu_failure_no_remediation_server_trust_root_node (5041179688081545244) --> + <skip /> + <!-- no translation found for osu_failure_no_policy_server_trust_root_node (6617290380940513539) --> + <skip /> + <!-- no translation found for osu_failure_retrieve_trust_root_certificates (1499136256195528265) --> + <skip /> + <!-- no translation found for osu_failure_no_aaa_trust_root_certificate (1904322497042226984) --> + <skip /> + <!-- no translation found for osu_failure_add_passpoint_configuration (2173557755811446047) --> + <skip /> + <!-- no translation found for osu_failure_osu_provider_not_found (6616172862116673082) --> + <skip /> + <!-- no translation found for osu_status_ap_connecting (5296821043003441437) --> + <skip /> + <!-- no translation found for osu_status_ap_connected (3777289375683170728) --> + <skip /> + <!-- no translation found for osu_status_server_connecting (8499785407540355867) --> + <skip /> + <!-- no translation found for osu_status_server_validated (3158727184762596355) --> + <skip /> + <!-- no translation found for osu_status_server_connected (8382024481520158168) --> + <skip /> + <!-- no translation found for osu_status_init_soap_exchange (8628063888912101981) --> + <skip /> + <!-- no translation found for osu_status_waiting_for_redirect_response (2343016207837053197) --> + <skip /> + <!-- no translation found for osu_status_redirect_response_received (5323368411922609405) --> + <skip /> + <!-- no translation found for osu_status_second_soap_exchange (7115332266758483909) --> + <skip /> + <!-- no translation found for osu_status_third_soap_exchange (8460901783597440766) --> + <skip /> + <!-- no translation found for osu_status_retrieving_trust_root_certs (1563445892926269689) --> + <skip /> + <!-- no translation found for osu_provisioning_complete (5120178802493970149) --> + <skip /> <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> diff --git a/packages/SettingsLib/res/values-az/strings.xml b/packages/SettingsLib/res/values-az/strings.xml index daa9c8f72ac8..d30834f23fb1 100644 --- a/packages/SettingsLib/res/values-az/strings.xml +++ b/packages/SettingsLib/res/values-az/strings.xml @@ -38,13 +38,87 @@ <string name="connected_via_network_scorer" msgid="5713793306870815341">"%1$s üzərindən avtomatik qoşuldu"</string> <string name="connected_via_network_scorer_default" msgid="7867260222020343104">"Avtomatik olaraq şəbəkə reytinq provayderi ilə qoşuludur"</string> <string name="connected_via_passpoint" msgid="2826205693803088747">"%1$s vasitəsilə qoşuludur"</string> + <!-- no translation found for ssid_by_passpoint_provider (7898171424140673315) --> + <skip /> <string name="available_via_passpoint" msgid="1617440946846329613">"%1$s vasitəsilə əlçatandır"</string> + <!-- no translation found for tap_to_set_up (2468970825530423314) --> + <skip /> <string name="wifi_connected_no_internet" msgid="8202906332837777829">"Qoşuludur, internet yoxdur"</string> <string name="wifi_status_no_internet" msgid="5784710974669608361">"İnternet yoxdur"</string> <string name="wifi_status_sign_in_required" msgid="123517180404752756">"Giriş tələb olunur"</string> <string name="wifi_ap_unable_to_handle_new_sta" msgid="5348824313514404541">"Giriş nöqtəsi müvəqqəti olaraq doludur"</string> <string name="connected_via_carrier" msgid="7583780074526041912">"%1$s ilə qoşuludur"</string> <string name="available_via_carrier" msgid="1469036129740799053">"%1$s vasitəsilə əlçatandır"</string> + <!-- no translation found for osu_failure_ap_connection (598977488344424542) --> + <skip /> + <!-- no translation found for osu_failure_server_url_invalid (2237477219243136714) --> + <skip /> + <!-- no translation found for osu_failure_server_connection (8192988165059982174) --> + <skip /> + <!-- no translation found for osu_failure_server_validation (4631649978129606823) --> + <skip /> + <!-- no translation found for osu_failure_service_provider_verification (4854091521439785597) --> + <skip /> + <!-- no translation found for osu_failure_provisioning_aborted (424627208135320329) --> + <skip /> + <!-- no translation found for osu_failure_provisioning_not_available (3021783729256985432) --> + <skip /> + <!-- no translation found for osu_failure_invalid_server_url (8548886196179435758) --> + <skip /> + <!-- no translation found for osu_failure_unexpected_command_type (8245921319866603904) --> + <skip /> + <!-- no translation found for osu_failure_unexpected_soap_message_type (2255897608510053065) --> + <skip /> + <!-- no translation found for osu_failure_soap_message_exchange (4357358438685987192) --> + <skip /> + <!-- no translation found for osu_failure_start_redirect_listener (4292769407279548482) --> + <skip /> + <!-- no translation found for osu_failure_timed_out_redirect_listener (3168657820278807508) --> + <skip /> + <!-- no translation found for osu_failure_no_osu_activity_found (4593038891437878675) --> + <skip /> + <!-- no translation found for osu_failure_unexpected_soap_message_status (6568467710235256675) --> + <skip /> + <!-- no translation found for osu_failure_no_pps_mo (850567403039076835) --> + <skip /> + <!-- no translation found for osu_failure_no_aaa_server_trust_root_node (8961455873459838456) --> + <skip /> + <!-- no translation found for osu_failure_no_remediation_server_trust_root_node (5041179688081545244) --> + <skip /> + <!-- no translation found for osu_failure_no_policy_server_trust_root_node (6617290380940513539) --> + <skip /> + <!-- no translation found for osu_failure_retrieve_trust_root_certificates (1499136256195528265) --> + <skip /> + <!-- no translation found for osu_failure_no_aaa_trust_root_certificate (1904322497042226984) --> + <skip /> + <!-- no translation found for osu_failure_add_passpoint_configuration (2173557755811446047) --> + <skip /> + <!-- no translation found for osu_failure_osu_provider_not_found (6616172862116673082) --> + <skip /> + <!-- no translation found for osu_status_ap_connecting (5296821043003441437) --> + <skip /> + <!-- no translation found for osu_status_ap_connected (3777289375683170728) --> + <skip /> + <!-- no translation found for osu_status_server_connecting (8499785407540355867) --> + <skip /> + <!-- no translation found for osu_status_server_validated (3158727184762596355) --> + <skip /> + <!-- no translation found for osu_status_server_connected (8382024481520158168) --> + <skip /> + <!-- no translation found for osu_status_init_soap_exchange (8628063888912101981) --> + <skip /> + <!-- no translation found for osu_status_waiting_for_redirect_response (2343016207837053197) --> + <skip /> + <!-- no translation found for osu_status_redirect_response_received (5323368411922609405) --> + <skip /> + <!-- no translation found for osu_status_second_soap_exchange (7115332266758483909) --> + <skip /> + <!-- no translation found for osu_status_third_soap_exchange (8460901783597440766) --> + <skip /> + <!-- no translation found for osu_status_retrieving_trust_root_certs (1563445892926269689) --> + <skip /> + <!-- no translation found for osu_provisioning_complete (5120178802493970149) --> + <skip /> <string name="speed_label_very_slow" msgid="1867055264243608530">"Çox Yavaş"</string> <string name="speed_label_slow" msgid="813109590815810235">"Yavaş"</string> <string name="speed_label_okay" msgid="2331665440671174858">"OK"</string> diff --git a/packages/SettingsLib/res/values-b+sr+Latn/strings.xml b/packages/SettingsLib/res/values-b+sr+Latn/strings.xml index 44f14df92435..427daab2fed6 100644 --- a/packages/SettingsLib/res/values-b+sr+Latn/strings.xml +++ b/packages/SettingsLib/res/values-b+sr+Latn/strings.xml @@ -38,13 +38,87 @@ <string name="connected_via_network_scorer" msgid="5713793306870815341">"Automatski povezano preko %1$s"</string> <string name="connected_via_network_scorer_default" msgid="7867260222020343104">"Automatski povezano preko dobavljača ocene mreže"</string> <string name="connected_via_passpoint" msgid="2826205693803088747">"Veza je uspostavljena preko pristupne tačke %1$s"</string> + <!-- no translation found for ssid_by_passpoint_provider (7898171424140673315) --> + <skip /> <string name="available_via_passpoint" msgid="1617440946846329613">"Dostupna je preko pristupne tačke %1$s"</string> + <!-- no translation found for tap_to_set_up (2468970825530423314) --> + <skip /> <string name="wifi_connected_no_internet" msgid="8202906332837777829">"Veza je uspostavljena, nema interneta"</string> <string name="wifi_status_no_internet" msgid="5784710974669608361">"Nema interneta"</string> <string name="wifi_status_sign_in_required" msgid="123517180404752756">"Treba da se prijavite"</string> <string name="wifi_ap_unable_to_handle_new_sta" msgid="5348824313514404541">"Pristupna tačka je privremeno zauzeta"</string> <string name="connected_via_carrier" msgid="7583780074526041912">"Povezano preko %1$s"</string> <string name="available_via_carrier" msgid="1469036129740799053">"Dostupno preko %1$s"</string> + <!-- no translation found for osu_failure_ap_connection (598977488344424542) --> + <skip /> + <!-- no translation found for osu_failure_server_url_invalid (2237477219243136714) --> + <skip /> + <!-- no translation found for osu_failure_server_connection (8192988165059982174) --> + <skip /> + <!-- no translation found for osu_failure_server_validation (4631649978129606823) --> + <skip /> + <!-- no translation found for osu_failure_service_provider_verification (4854091521439785597) --> + <skip /> + <!-- no translation found for osu_failure_provisioning_aborted (424627208135320329) --> + <skip /> + <!-- no translation found for osu_failure_provisioning_not_available (3021783729256985432) --> + <skip /> + <!-- no translation found for osu_failure_invalid_server_url (8548886196179435758) --> + <skip /> + <!-- no translation found for osu_failure_unexpected_command_type (8245921319866603904) --> + <skip /> + <!-- no translation found for osu_failure_unexpected_soap_message_type (2255897608510053065) --> + <skip /> + <!-- no translation found for osu_failure_soap_message_exchange (4357358438685987192) --> + <skip /> + <!-- no translation found for osu_failure_start_redirect_listener (4292769407279548482) --> + <skip /> + <!-- no translation found for osu_failure_timed_out_redirect_listener (3168657820278807508) --> + <skip /> + <!-- no translation found for osu_failure_no_osu_activity_found (4593038891437878675) --> + <skip /> + <!-- no translation found for osu_failure_unexpected_soap_message_status (6568467710235256675) --> + <skip /> + <!-- no translation found for osu_failure_no_pps_mo (850567403039076835) --> + <skip /> + <!-- no translation found for osu_failure_no_aaa_server_trust_root_node (8961455873459838456) --> + <skip /> + <!-- no translation found for osu_failure_no_remediation_server_trust_root_node (5041179688081545244) --> + <skip /> + <!-- no translation found for osu_failure_no_policy_server_trust_root_node (6617290380940513539) --> + <skip /> + <!-- no translation found for osu_failure_retrieve_trust_root_certificates (1499136256195528265) --> + <skip /> + <!-- no translation found for osu_failure_no_aaa_trust_root_certificate (1904322497042226984) --> + <skip /> + <!-- no translation found for osu_failure_add_passpoint_configuration (2173557755811446047) --> + <skip /> + <!-- no translation found for osu_failure_osu_provider_not_found (6616172862116673082) --> + <skip /> + <!-- no translation found for osu_status_ap_connecting (5296821043003441437) --> + <skip /> + <!-- no translation found for osu_status_ap_connected (3777289375683170728) --> + <skip /> + <!-- no translation found for osu_status_server_connecting (8499785407540355867) --> + <skip /> + <!-- no translation found for osu_status_server_validated (3158727184762596355) --> + <skip /> + <!-- no translation found for osu_status_server_connected (8382024481520158168) --> + <skip /> + <!-- no translation found for osu_status_init_soap_exchange (8628063888912101981) --> + <skip /> + <!-- no translation found for osu_status_waiting_for_redirect_response (2343016207837053197) --> + <skip /> + <!-- no translation found for osu_status_redirect_response_received (5323368411922609405) --> + <skip /> + <!-- no translation found for osu_status_second_soap_exchange (7115332266758483909) --> + <skip /> + <!-- no translation found for osu_status_third_soap_exchange (8460901783597440766) --> + <skip /> + <!-- no translation found for osu_status_retrieving_trust_root_certs (1563445892926269689) --> + <skip /> + <!-- no translation found for osu_provisioning_complete (5120178802493970149) --> + <skip /> <string name="speed_label_very_slow" msgid="1867055264243608530">"Veoma spora"</string> <string name="speed_label_slow" msgid="813109590815810235">"Spora"</string> <string name="speed_label_okay" msgid="2331665440671174858">"Potvrdi"</string> diff --git a/packages/SettingsLib/res/values-be/strings.xml b/packages/SettingsLib/res/values-be/strings.xml index 2dcdd372f03b..a156caf06040 100644 --- a/packages/SettingsLib/res/values-be/strings.xml +++ b/packages/SettingsLib/res/values-be/strings.xml @@ -38,13 +38,87 @@ <string name="connected_via_network_scorer" msgid="5713793306870815341">"Аўтаматычна падключана праз %1$s"</string> <string name="connected_via_network_scorer_default" msgid="7867260222020343104">"Аўтаматычна падключана праз пастаўшчыка паслугі ацэнкі сеткі"</string> <string name="connected_via_passpoint" msgid="2826205693803088747">"Падлучана праз %1$s"</string> + <!-- no translation found for ssid_by_passpoint_provider (7898171424140673315) --> + <skip /> <string name="available_via_passpoint" msgid="1617440946846329613">"Даступна праз %1$s"</string> + <!-- no translation found for tap_to_set_up (2468970825530423314) --> + <skip /> <string name="wifi_connected_no_internet" msgid="8202906332837777829">"Падключана, без доступу да інтэрнэту"</string> <string name="wifi_status_no_internet" msgid="5784710974669608361">"Не падключана да інтэрнэту"</string> <string name="wifi_status_sign_in_required" msgid="123517180404752756">"Трэба выканаць уваход"</string> <string name="wifi_ap_unable_to_handle_new_sta" msgid="5348824313514404541">"Пункт доступу часова заняты"</string> <string name="connected_via_carrier" msgid="7583780074526041912">"Падлучана праз %1$s"</string> <string name="available_via_carrier" msgid="1469036129740799053">"Даступна праз %1$s"</string> + <!-- no translation found for osu_failure_ap_connection (598977488344424542) --> + <skip /> + <!-- no translation found for osu_failure_server_url_invalid (2237477219243136714) --> + <skip /> + <!-- no translation found for osu_failure_server_connection (8192988165059982174) --> + <skip /> + <!-- no translation found for osu_failure_server_validation (4631649978129606823) --> + <skip /> + <!-- no translation found for osu_failure_service_provider_verification (4854091521439785597) --> + <skip /> + <!-- no translation found for osu_failure_provisioning_aborted (424627208135320329) --> + <skip /> + <!-- no translation found for osu_failure_provisioning_not_available (3021783729256985432) --> + <skip /> + <!-- no translation found for osu_failure_invalid_server_url (8548886196179435758) --> + <skip /> + <!-- no translation found for osu_failure_unexpected_command_type (8245921319866603904) --> + <skip /> + <!-- no translation found for osu_failure_unexpected_soap_message_type (2255897608510053065) --> + <skip /> + <!-- no translation found for osu_failure_soap_message_exchange (4357358438685987192) --> + <skip /> + <!-- no translation found for osu_failure_start_redirect_listener (4292769407279548482) --> + <skip /> + <!-- no translation found for osu_failure_timed_out_redirect_listener (3168657820278807508) --> + <skip /> + <!-- no translation found for osu_failure_no_osu_activity_found (4593038891437878675) --> + <skip /> + <!-- no translation found for osu_failure_unexpected_soap_message_status (6568467710235256675) --> + <skip /> + <!-- no translation found for osu_failure_no_pps_mo (850567403039076835) --> + <skip /> + <!-- no translation found for osu_failure_no_aaa_server_trust_root_node (8961455873459838456) --> + <skip /> + <!-- no translation found for osu_failure_no_remediation_server_trust_root_node (5041179688081545244) --> + <skip /> + <!-- no translation found for osu_failure_no_policy_server_trust_root_node (6617290380940513539) --> + <skip /> + <!-- no translation found for osu_failure_retrieve_trust_root_certificates (1499136256195528265) --> + <skip /> + <!-- no translation found for osu_failure_no_aaa_trust_root_certificate (1904322497042226984) --> + <skip /> + <!-- no translation found for osu_failure_add_passpoint_configuration (2173557755811446047) --> + <skip /> + <!-- no translation found for osu_failure_osu_provider_not_found (6616172862116673082) --> + <skip /> + <!-- no translation found for osu_status_ap_connecting (5296821043003441437) --> + <skip /> + <!-- no translation found for osu_status_ap_connected (3777289375683170728) --> + <skip /> + <!-- no translation found for osu_status_server_connecting (8499785407540355867) --> + <skip /> + <!-- no translation found for osu_status_server_validated (3158727184762596355) --> + <skip /> + <!-- no translation found for osu_status_server_connected (8382024481520158168) --> + <skip /> + <!-- no translation found for osu_status_init_soap_exchange (8628063888912101981) --> + <skip /> + <!-- no translation found for osu_status_waiting_for_redirect_response (2343016207837053197) --> + <skip /> + <!-- no translation found for osu_status_redirect_response_received (5323368411922609405) --> + <skip /> + <!-- no translation found for osu_status_second_soap_exchange (7115332266758483909) --> + <skip /> + <!-- no translation found for osu_status_third_soap_exchange (8460901783597440766) --> + <skip /> + <!-- no translation found for osu_status_retrieving_trust_root_certs (1563445892926269689) --> + <skip /> + <!-- no translation found for osu_provisioning_complete (5120178802493970149) --> + <skip /> <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> diff --git a/packages/SettingsLib/res/values-bg/strings.xml b/packages/SettingsLib/res/values-bg/strings.xml index 1e2f0f43a8a9..83336460d542 100644 --- a/packages/SettingsLib/res/values-bg/strings.xml +++ b/packages/SettingsLib/res/values-bg/strings.xml @@ -38,13 +38,87 @@ <string name="connected_via_network_scorer" msgid="5713793306870815341">"Автоматично е установена връзка чрез %1$s"</string> <string name="connected_via_network_scorer_default" msgid="7867260222020343104">"Автоматично е установена връзка чрез доставчик на услуги за оценяване на мрежите"</string> <string name="connected_via_passpoint" msgid="2826205693803088747">"Установена е връзка през „%1$s“"</string> + <!-- no translation found for ssid_by_passpoint_provider (7898171424140673315) --> + <skip /> <string name="available_via_passpoint" msgid="1617440946846329613">"Мрежата е достъпна през „%1$s“"</string> + <!-- no translation found for tap_to_set_up (2468970825530423314) --> + <skip /> <string name="wifi_connected_no_internet" msgid="8202906332837777829">"Установена е връзка – няма достъп до интернет"</string> <string name="wifi_status_no_internet" msgid="5784710974669608361">"Няма връзка с интернет"</string> <string name="wifi_status_sign_in_required" msgid="123517180404752756">"Изисква се вход в профила"</string> <string name="wifi_ap_unable_to_handle_new_sta" msgid="5348824313514404541">"Точката за достъп временно е пълна"</string> <string name="connected_via_carrier" msgid="7583780074526041912">"Установена е връзка през %1$s"</string> <string name="available_via_carrier" msgid="1469036129740799053">"Мрежата е достъпна през %1$s"</string> + <!-- no translation found for osu_failure_ap_connection (598977488344424542) --> + <skip /> + <!-- no translation found for osu_failure_server_url_invalid (2237477219243136714) --> + <skip /> + <!-- no translation found for osu_failure_server_connection (8192988165059982174) --> + <skip /> + <!-- no translation found for osu_failure_server_validation (4631649978129606823) --> + <skip /> + <!-- no translation found for osu_failure_service_provider_verification (4854091521439785597) --> + <skip /> + <!-- no translation found for osu_failure_provisioning_aborted (424627208135320329) --> + <skip /> + <!-- no translation found for osu_failure_provisioning_not_available (3021783729256985432) --> + <skip /> + <!-- no translation found for osu_failure_invalid_server_url (8548886196179435758) --> + <skip /> + <!-- no translation found for osu_failure_unexpected_command_type (8245921319866603904) --> + <skip /> + <!-- no translation found for osu_failure_unexpected_soap_message_type (2255897608510053065) --> + <skip /> + <!-- no translation found for osu_failure_soap_message_exchange (4357358438685987192) --> + <skip /> + <!-- no translation found for osu_failure_start_redirect_listener (4292769407279548482) --> + <skip /> + <!-- no translation found for osu_failure_timed_out_redirect_listener (3168657820278807508) --> + <skip /> + <!-- no translation found for osu_failure_no_osu_activity_found (4593038891437878675) --> + <skip /> + <!-- no translation found for osu_failure_unexpected_soap_message_status (6568467710235256675) --> + <skip /> + <!-- no translation found for osu_failure_no_pps_mo (850567403039076835) --> + <skip /> + <!-- no translation found for osu_failure_no_aaa_server_trust_root_node (8961455873459838456) --> + <skip /> + <!-- no translation found for osu_failure_no_remediation_server_trust_root_node (5041179688081545244) --> + <skip /> + <!-- no translation found for osu_failure_no_policy_server_trust_root_node (6617290380940513539) --> + <skip /> + <!-- no translation found for osu_failure_retrieve_trust_root_certificates (1499136256195528265) --> + <skip /> + <!-- no translation found for osu_failure_no_aaa_trust_root_certificate (1904322497042226984) --> + <skip /> + <!-- no translation found for osu_failure_add_passpoint_configuration (2173557755811446047) --> + <skip /> + <!-- no translation found for osu_failure_osu_provider_not_found (6616172862116673082) --> + <skip /> + <!-- no translation found for osu_status_ap_connecting (5296821043003441437) --> + <skip /> + <!-- no translation found for osu_status_ap_connected (3777289375683170728) --> + <skip /> + <!-- no translation found for osu_status_server_connecting (8499785407540355867) --> + <skip /> + <!-- no translation found for osu_status_server_validated (3158727184762596355) --> + <skip /> + <!-- no translation found for osu_status_server_connected (8382024481520158168) --> + <skip /> + <!-- no translation found for osu_status_init_soap_exchange (8628063888912101981) --> + <skip /> + <!-- no translation found for osu_status_waiting_for_redirect_response (2343016207837053197) --> + <skip /> + <!-- no translation found for osu_status_redirect_response_received (5323368411922609405) --> + <skip /> + <!-- no translation found for osu_status_second_soap_exchange (7115332266758483909) --> + <skip /> + <!-- no translation found for osu_status_third_soap_exchange (8460901783597440766) --> + <skip /> + <!-- no translation found for osu_status_retrieving_trust_root_certs (1563445892926269689) --> + <skip /> + <!-- no translation found for osu_provisioning_complete (5120178802493970149) --> + <skip /> <string name="speed_label_very_slow" msgid="1867055264243608530">"Много бавна"</string> <string name="speed_label_slow" msgid="813109590815810235">"Бавна"</string> <string name="speed_label_okay" msgid="2331665440671174858">"ОK"</string> diff --git a/packages/SettingsLib/res/values-bn/strings.xml b/packages/SettingsLib/res/values-bn/strings.xml index 4ec893b0e60b..c7b3afea80d4 100644 --- a/packages/SettingsLib/res/values-bn/strings.xml +++ b/packages/SettingsLib/res/values-bn/strings.xml @@ -38,13 +38,87 @@ <string name="connected_via_network_scorer" msgid="5713793306870815341">"স্বয়ংক্রিয়ভাবে %1$s এর মাধ্যমে কানেক্ট হয়েছে"</string> <string name="connected_via_network_scorer_default" msgid="7867260222020343104">"নেটওয়ার্কের রেটিং প্রদানকারীর মাধ্যমে অটোমেটিক কানেক্ট"</string> <string name="connected_via_passpoint" msgid="2826205693803088747">"%1$s মাধ্যমে কানেক্ট হয়েছে"</string> + <!-- no translation found for ssid_by_passpoint_provider (7898171424140673315) --> + <skip /> <string name="available_via_passpoint" msgid="1617440946846329613">"%1$s এর মাধ্যমে উপলব্ধ"</string> + <!-- no translation found for tap_to_set_up (2468970825530423314) --> + <skip /> <string name="wifi_connected_no_internet" msgid="8202906332837777829">"কানেক্ট, ইন্টারনেট নেই"</string> <string name="wifi_status_no_internet" msgid="5784710974669608361">"ইন্টারনেট কানেকশন নেই"</string> <string name="wifi_status_sign_in_required" msgid="123517180404752756">"সাইন-ইন করা দরকার"</string> <string name="wifi_ap_unable_to_handle_new_sta" msgid="5348824313514404541">"এই মুহূর্তে অ্যাক্সেস পয়েন্টের কোনও কানেকশন ফাঁকা নেই"</string> <string name="connected_via_carrier" msgid="7583780074526041912">"%1$s এর মাধ্যমে কানেক্ট হয়েছে"</string> <string name="available_via_carrier" msgid="1469036129740799053">"%1$s এর মাধ্যমে পাওয়া যাচ্ছে"</string> + <!-- no translation found for osu_failure_ap_connection (598977488344424542) --> + <skip /> + <!-- no translation found for osu_failure_server_url_invalid (2237477219243136714) --> + <skip /> + <!-- no translation found for osu_failure_server_connection (8192988165059982174) --> + <skip /> + <!-- no translation found for osu_failure_server_validation (4631649978129606823) --> + <skip /> + <!-- no translation found for osu_failure_service_provider_verification (4854091521439785597) --> + <skip /> + <!-- no translation found for osu_failure_provisioning_aborted (424627208135320329) --> + <skip /> + <!-- no translation found for osu_failure_provisioning_not_available (3021783729256985432) --> + <skip /> + <!-- no translation found for osu_failure_invalid_server_url (8548886196179435758) --> + <skip /> + <!-- no translation found for osu_failure_unexpected_command_type (8245921319866603904) --> + <skip /> + <!-- no translation found for osu_failure_unexpected_soap_message_type (2255897608510053065) --> + <skip /> + <!-- no translation found for osu_failure_soap_message_exchange (4357358438685987192) --> + <skip /> + <!-- no translation found for osu_failure_start_redirect_listener (4292769407279548482) --> + <skip /> + <!-- no translation found for osu_failure_timed_out_redirect_listener (3168657820278807508) --> + <skip /> + <!-- no translation found for osu_failure_no_osu_activity_found (4593038891437878675) --> + <skip /> + <!-- no translation found for osu_failure_unexpected_soap_message_status (6568467710235256675) --> + <skip /> + <!-- no translation found for osu_failure_no_pps_mo (850567403039076835) --> + <skip /> + <!-- no translation found for osu_failure_no_aaa_server_trust_root_node (8961455873459838456) --> + <skip /> + <!-- no translation found for osu_failure_no_remediation_server_trust_root_node (5041179688081545244) --> + <skip /> + <!-- no translation found for osu_failure_no_policy_server_trust_root_node (6617290380940513539) --> + <skip /> + <!-- no translation found for osu_failure_retrieve_trust_root_certificates (1499136256195528265) --> + <skip /> + <!-- no translation found for osu_failure_no_aaa_trust_root_certificate (1904322497042226984) --> + <skip /> + <!-- no translation found for osu_failure_add_passpoint_configuration (2173557755811446047) --> + <skip /> + <!-- no translation found for osu_failure_osu_provider_not_found (6616172862116673082) --> + <skip /> + <!-- no translation found for osu_status_ap_connecting (5296821043003441437) --> + <skip /> + <!-- no translation found for osu_status_ap_connected (3777289375683170728) --> + <skip /> + <!-- no translation found for osu_status_server_connecting (8499785407540355867) --> + <skip /> + <!-- no translation found for osu_status_server_validated (3158727184762596355) --> + <skip /> + <!-- no translation found for osu_status_server_connected (8382024481520158168) --> + <skip /> + <!-- no translation found for osu_status_init_soap_exchange (8628063888912101981) --> + <skip /> + <!-- no translation found for osu_status_waiting_for_redirect_response (2343016207837053197) --> + <skip /> + <!-- no translation found for osu_status_redirect_response_received (5323368411922609405) --> + <skip /> + <!-- no translation found for osu_status_second_soap_exchange (7115332266758483909) --> + <skip /> + <!-- no translation found for osu_status_third_soap_exchange (8460901783597440766) --> + <skip /> + <!-- no translation found for osu_status_retrieving_trust_root_certs (1563445892926269689) --> + <skip /> + <!-- no translation found for osu_provisioning_complete (5120178802493970149) --> + <skip /> <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> diff --git a/packages/SettingsLib/res/values-bs/strings.xml b/packages/SettingsLib/res/values-bs/strings.xml index a0a0e2afdb38..715a8a5a85c4 100644 --- a/packages/SettingsLib/res/values-bs/strings.xml +++ b/packages/SettingsLib/res/values-bs/strings.xml @@ -27,7 +27,7 @@ <string name="wifi_disabled_network_failure" msgid="2364951338436007124">"Greška u konfiguraciji IP-a"</string> <string name="wifi_disabled_by_recommendation_provider" msgid="5168315140978066096">"Niste povezani zbog slabog kvaliteta mreže"</string> <string name="wifi_disabled_wifi_failure" msgid="3081668066612876581">"Greška pri povezivanju na WiFi"</string> - <string name="wifi_disabled_password_failure" msgid="8659805351763133575">"Problem pri provjeri vjerodostojnosti."</string> + <string name="wifi_disabled_password_failure" msgid="8659805351763133575">"Problem pri autentifikaciji."</string> <string name="wifi_cant_connect" msgid="5410016875644565884">"Nije se moguće povezati"</string> <string name="wifi_cant_connect_to_ap" msgid="1222553274052685331">"Nije se moguće povezati na aplikaciju \'<xliff:g id="AP_NAME">%1$s</xliff:g>\'"</string> <string name="wifi_check_password_try_again" msgid="516958988102584767">"Provjerite lozinku i pokušajte ponovo"</string> @@ -38,13 +38,87 @@ <string name="connected_via_network_scorer" msgid="5713793306870815341">"Automatski povezano koristeći %1$s"</string> <string name="connected_via_network_scorer_default" msgid="7867260222020343104">"Automatski povezano putem ocjenjivača mreže"</string> <string name="connected_via_passpoint" msgid="2826205693803088747">"Povezani preko %1$s"</string> + <!-- no translation found for ssid_by_passpoint_provider (7898171424140673315) --> + <skip /> <string name="available_via_passpoint" msgid="1617440946846329613">"Dostupan preko %1$s"</string> + <!-- no translation found for tap_to_set_up (2468970825530423314) --> + <skip /> <string name="wifi_connected_no_internet" msgid="8202906332837777829">"Povezano, nema interneta"</string> <string name="wifi_status_no_internet" msgid="5784710974669608361">"Nema internetske veze"</string> <string name="wifi_status_sign_in_required" msgid="123517180404752756">"Potrebna je prijava"</string> <string name="wifi_ap_unable_to_handle_new_sta" msgid="5348824313514404541">"Pristupna tačka je privremeno puna"</string> <string name="connected_via_carrier" msgid="7583780074526041912">"Povezano koristeći %1$s"</string> <string name="available_via_carrier" msgid="1469036129740799053">"Dostupna koristeći %1$s"</string> + <!-- no translation found for osu_failure_ap_connection (598977488344424542) --> + <skip /> + <!-- no translation found for osu_failure_server_url_invalid (2237477219243136714) --> + <skip /> + <!-- no translation found for osu_failure_server_connection (8192988165059982174) --> + <skip /> + <!-- no translation found for osu_failure_server_validation (4631649978129606823) --> + <skip /> + <!-- no translation found for osu_failure_service_provider_verification (4854091521439785597) --> + <skip /> + <!-- no translation found for osu_failure_provisioning_aborted (424627208135320329) --> + <skip /> + <!-- no translation found for osu_failure_provisioning_not_available (3021783729256985432) --> + <skip /> + <!-- no translation found for osu_failure_invalid_server_url (8548886196179435758) --> + <skip /> + <!-- no translation found for osu_failure_unexpected_command_type (8245921319866603904) --> + <skip /> + <!-- no translation found for osu_failure_unexpected_soap_message_type (2255897608510053065) --> + <skip /> + <!-- no translation found for osu_failure_soap_message_exchange (4357358438685987192) --> + <skip /> + <!-- no translation found for osu_failure_start_redirect_listener (4292769407279548482) --> + <skip /> + <!-- no translation found for osu_failure_timed_out_redirect_listener (3168657820278807508) --> + <skip /> + <!-- no translation found for osu_failure_no_osu_activity_found (4593038891437878675) --> + <skip /> + <!-- no translation found for osu_failure_unexpected_soap_message_status (6568467710235256675) --> + <skip /> + <!-- no translation found for osu_failure_no_pps_mo (850567403039076835) --> + <skip /> + <!-- no translation found for osu_failure_no_aaa_server_trust_root_node (8961455873459838456) --> + <skip /> + <!-- no translation found for osu_failure_no_remediation_server_trust_root_node (5041179688081545244) --> + <skip /> + <!-- no translation found for osu_failure_no_policy_server_trust_root_node (6617290380940513539) --> + <skip /> + <!-- no translation found for osu_failure_retrieve_trust_root_certificates (1499136256195528265) --> + <skip /> + <!-- no translation found for osu_failure_no_aaa_trust_root_certificate (1904322497042226984) --> + <skip /> + <!-- no translation found for osu_failure_add_passpoint_configuration (2173557755811446047) --> + <skip /> + <!-- no translation found for osu_failure_osu_provider_not_found (6616172862116673082) --> + <skip /> + <!-- no translation found for osu_status_ap_connecting (5296821043003441437) --> + <skip /> + <!-- no translation found for osu_status_ap_connected (3777289375683170728) --> + <skip /> + <!-- no translation found for osu_status_server_connecting (8499785407540355867) --> + <skip /> + <!-- no translation found for osu_status_server_validated (3158727184762596355) --> + <skip /> + <!-- no translation found for osu_status_server_connected (8382024481520158168) --> + <skip /> + <!-- no translation found for osu_status_init_soap_exchange (8628063888912101981) --> + <skip /> + <!-- no translation found for osu_status_waiting_for_redirect_response (2343016207837053197) --> + <skip /> + <!-- no translation found for osu_status_redirect_response_received (5323368411922609405) --> + <skip /> + <!-- no translation found for osu_status_second_soap_exchange (7115332266758483909) --> + <skip /> + <!-- no translation found for osu_status_third_soap_exchange (8460901783597440766) --> + <skip /> + <!-- no translation found for osu_status_retrieving_trust_root_certs (1563445892926269689) --> + <skip /> + <!-- no translation found for osu_provisioning_complete (5120178802493970149) --> + <skip /> <string name="speed_label_very_slow" msgid="1867055264243608530">"Veoma sporo"</string> <string name="speed_label_slow" msgid="813109590815810235">"Sporo"</string> <string name="speed_label_okay" msgid="2331665440671174858">"UREDU"</string> diff --git a/packages/SettingsLib/res/values-ca/strings.xml b/packages/SettingsLib/res/values-ca/strings.xml index 0bd6a1bd4b26..56f55dd1bcbc 100644 --- a/packages/SettingsLib/res/values-ca/strings.xml +++ b/packages/SettingsLib/res/values-ca/strings.xml @@ -38,13 +38,87 @@ <string name="connected_via_network_scorer" msgid="5713793306870815341">"Connectada automàticament a través de: %1$s"</string> <string name="connected_via_network_scorer_default" msgid="7867260222020343104">"Connectada automàticament a través d\'un proveïdor de valoració de xarxes"</string> <string name="connected_via_passpoint" msgid="2826205693803088747">"Connectada mitjançant %1$s"</string> + <!-- no translation found for ssid_by_passpoint_provider (7898171424140673315) --> + <skip /> <string name="available_via_passpoint" msgid="1617440946846329613">"Disponible mitjançant %1$s"</string> + <!-- no translation found for tap_to_set_up (2468970825530423314) --> + <skip /> <string name="wifi_connected_no_internet" msgid="8202906332837777829">"Connectada, sense Internet"</string> <string name="wifi_status_no_internet" msgid="5784710974669608361">"Sense connexió a Internet"</string> <string name="wifi_status_sign_in_required" msgid="123517180404752756">"Cal iniciar la sessió"</string> <string name="wifi_ap_unable_to_handle_new_sta" msgid="5348824313514404541">"El punt d\'accés està temporalment ple"</string> <string name="connected_via_carrier" msgid="7583780074526041912">"Connectat mitjançant %1$s"</string> <string name="available_via_carrier" msgid="1469036129740799053">"Disponible mitjançant %1$s"</string> + <!-- no translation found for osu_failure_ap_connection (598977488344424542) --> + <skip /> + <!-- no translation found for osu_failure_server_url_invalid (2237477219243136714) --> + <skip /> + <!-- no translation found for osu_failure_server_connection (8192988165059982174) --> + <skip /> + <!-- no translation found for osu_failure_server_validation (4631649978129606823) --> + <skip /> + <!-- no translation found for osu_failure_service_provider_verification (4854091521439785597) --> + <skip /> + <!-- no translation found for osu_failure_provisioning_aborted (424627208135320329) --> + <skip /> + <!-- no translation found for osu_failure_provisioning_not_available (3021783729256985432) --> + <skip /> + <!-- no translation found for osu_failure_invalid_server_url (8548886196179435758) --> + <skip /> + <!-- no translation found for osu_failure_unexpected_command_type (8245921319866603904) --> + <skip /> + <!-- no translation found for osu_failure_unexpected_soap_message_type (2255897608510053065) --> + <skip /> + <!-- no translation found for osu_failure_soap_message_exchange (4357358438685987192) --> + <skip /> + <!-- no translation found for osu_failure_start_redirect_listener (4292769407279548482) --> + <skip /> + <!-- no translation found for osu_failure_timed_out_redirect_listener (3168657820278807508) --> + <skip /> + <!-- no translation found for osu_failure_no_osu_activity_found (4593038891437878675) --> + <skip /> + <!-- no translation found for osu_failure_unexpected_soap_message_status (6568467710235256675) --> + <skip /> + <!-- no translation found for osu_failure_no_pps_mo (850567403039076835) --> + <skip /> + <!-- no translation found for osu_failure_no_aaa_server_trust_root_node (8961455873459838456) --> + <skip /> + <!-- no translation found for osu_failure_no_remediation_server_trust_root_node (5041179688081545244) --> + <skip /> + <!-- no translation found for osu_failure_no_policy_server_trust_root_node (6617290380940513539) --> + <skip /> + <!-- no translation found for osu_failure_retrieve_trust_root_certificates (1499136256195528265) --> + <skip /> + <!-- no translation found for osu_failure_no_aaa_trust_root_certificate (1904322497042226984) --> + <skip /> + <!-- no translation found for osu_failure_add_passpoint_configuration (2173557755811446047) --> + <skip /> + <!-- no translation found for osu_failure_osu_provider_not_found (6616172862116673082) --> + <skip /> + <!-- no translation found for osu_status_ap_connecting (5296821043003441437) --> + <skip /> + <!-- no translation found for osu_status_ap_connected (3777289375683170728) --> + <skip /> + <!-- no translation found for osu_status_server_connecting (8499785407540355867) --> + <skip /> + <!-- no translation found for osu_status_server_validated (3158727184762596355) --> + <skip /> + <!-- no translation found for osu_status_server_connected (8382024481520158168) --> + <skip /> + <!-- no translation found for osu_status_init_soap_exchange (8628063888912101981) --> + <skip /> + <!-- no translation found for osu_status_waiting_for_redirect_response (2343016207837053197) --> + <skip /> + <!-- no translation found for osu_status_redirect_response_received (5323368411922609405) --> + <skip /> + <!-- no translation found for osu_status_second_soap_exchange (7115332266758483909) --> + <skip /> + <!-- no translation found for osu_status_third_soap_exchange (8460901783597440766) --> + <skip /> + <!-- no translation found for osu_status_retrieving_trust_root_certs (1563445892926269689) --> + <skip /> + <!-- no translation found for osu_provisioning_complete (5120178802493970149) --> + <skip /> <string name="speed_label_very_slow" msgid="1867055264243608530">"Molt lenta"</string> <string name="speed_label_slow" msgid="813109590815810235">"Lenta"</string> <string name="speed_label_okay" msgid="2331665440671174858">"Correcta"</string> diff --git a/packages/SettingsLib/res/values-cs/strings.xml b/packages/SettingsLib/res/values-cs/strings.xml index 69c22ec0faa8..edbb3581403b 100644 --- a/packages/SettingsLib/res/values-cs/strings.xml +++ b/packages/SettingsLib/res/values-cs/strings.xml @@ -38,13 +38,87 @@ <string name="connected_via_network_scorer" msgid="5713793306870815341">"Automaticky připojeno přes poskytovatele %1$s"</string> <string name="connected_via_network_scorer_default" msgid="7867260222020343104">"Automaticky připojeno přes poskytovatele hodnocení sítí"</string> <string name="connected_via_passpoint" msgid="2826205693803088747">"Připojeno prostřednictvím %1$s"</string> + <!-- no translation found for ssid_by_passpoint_provider (7898171424140673315) --> + <skip /> <string name="available_via_passpoint" msgid="1617440946846329613">"Dostupné prostřednictvím %1$s"</string> + <!-- no translation found for tap_to_set_up (2468970825530423314) --> + <skip /> <string name="wifi_connected_no_internet" msgid="8202906332837777829">"Připojeno, není k dispozici internet"</string> <string name="wifi_status_no_internet" msgid="5784710974669608361">"Nejste připojeni k internetu"</string> <string name="wifi_status_sign_in_required" msgid="123517180404752756">"Je vyžadováno přihlášení"</string> <string name="wifi_ap_unable_to_handle_new_sta" msgid="5348824313514404541">"Přístupový bod je dočasně zaplněn"</string> <string name="connected_via_carrier" msgid="7583780074526041912">"Připojeno prostřednictvím %1$s"</string> <string name="available_via_carrier" msgid="1469036129740799053">"Dostupné prostřednictvím %1$s"</string> + <!-- no translation found for osu_failure_ap_connection (598977488344424542) --> + <skip /> + <!-- no translation found for osu_failure_server_url_invalid (2237477219243136714) --> + <skip /> + <!-- no translation found for osu_failure_server_connection (8192988165059982174) --> + <skip /> + <!-- no translation found for osu_failure_server_validation (4631649978129606823) --> + <skip /> + <!-- no translation found for osu_failure_service_provider_verification (4854091521439785597) --> + <skip /> + <!-- no translation found for osu_failure_provisioning_aborted (424627208135320329) --> + <skip /> + <!-- no translation found for osu_failure_provisioning_not_available (3021783729256985432) --> + <skip /> + <!-- no translation found for osu_failure_invalid_server_url (8548886196179435758) --> + <skip /> + <!-- no translation found for osu_failure_unexpected_command_type (8245921319866603904) --> + <skip /> + <!-- no translation found for osu_failure_unexpected_soap_message_type (2255897608510053065) --> + <skip /> + <!-- no translation found for osu_failure_soap_message_exchange (4357358438685987192) --> + <skip /> + <!-- no translation found for osu_failure_start_redirect_listener (4292769407279548482) --> + <skip /> + <!-- no translation found for osu_failure_timed_out_redirect_listener (3168657820278807508) --> + <skip /> + <!-- no translation found for osu_failure_no_osu_activity_found (4593038891437878675) --> + <skip /> + <!-- no translation found for osu_failure_unexpected_soap_message_status (6568467710235256675) --> + <skip /> + <!-- no translation found for osu_failure_no_pps_mo (850567403039076835) --> + <skip /> + <!-- no translation found for osu_failure_no_aaa_server_trust_root_node (8961455873459838456) --> + <skip /> + <!-- no translation found for osu_failure_no_remediation_server_trust_root_node (5041179688081545244) --> + <skip /> + <!-- no translation found for osu_failure_no_policy_server_trust_root_node (6617290380940513539) --> + <skip /> + <!-- no translation found for osu_failure_retrieve_trust_root_certificates (1499136256195528265) --> + <skip /> + <!-- no translation found for osu_failure_no_aaa_trust_root_certificate (1904322497042226984) --> + <skip /> + <!-- no translation found for osu_failure_add_passpoint_configuration (2173557755811446047) --> + <skip /> + <!-- no translation found for osu_failure_osu_provider_not_found (6616172862116673082) --> + <skip /> + <!-- no translation found for osu_status_ap_connecting (5296821043003441437) --> + <skip /> + <!-- no translation found for osu_status_ap_connected (3777289375683170728) --> + <skip /> + <!-- no translation found for osu_status_server_connecting (8499785407540355867) --> + <skip /> + <!-- no translation found for osu_status_server_validated (3158727184762596355) --> + <skip /> + <!-- no translation found for osu_status_server_connected (8382024481520158168) --> + <skip /> + <!-- no translation found for osu_status_init_soap_exchange (8628063888912101981) --> + <skip /> + <!-- no translation found for osu_status_waiting_for_redirect_response (2343016207837053197) --> + <skip /> + <!-- no translation found for osu_status_redirect_response_received (5323368411922609405) --> + <skip /> + <!-- no translation found for osu_status_second_soap_exchange (7115332266758483909) --> + <skip /> + <!-- no translation found for osu_status_third_soap_exchange (8460901783597440766) --> + <skip /> + <!-- no translation found for osu_status_retrieving_trust_root_certs (1563445892926269689) --> + <skip /> + <!-- no translation found for osu_provisioning_complete (5120178802493970149) --> + <skip /> <string name="speed_label_very_slow" msgid="1867055264243608530">"Velmi pomalá"</string> <string name="speed_label_slow" msgid="813109590815810235">"Pomalá"</string> <string name="speed_label_okay" msgid="2331665440671174858">"OK"</string> diff --git a/packages/SettingsLib/res/values-da/strings.xml b/packages/SettingsLib/res/values-da/strings.xml index 077258a387f9..1d3457978d81 100644 --- a/packages/SettingsLib/res/values-da/strings.xml +++ b/packages/SettingsLib/res/values-da/strings.xml @@ -38,13 +38,87 @@ <string name="connected_via_network_scorer" msgid="5713793306870815341">"Automatisk tilsluttet via %1$s"</string> <string name="connected_via_network_scorer_default" msgid="7867260222020343104">"Automatisk forbundet via udbyder af netværksvurdering"</string> <string name="connected_via_passpoint" msgid="2826205693803088747">"Tilsluttet via %1$s"</string> + <!-- no translation found for ssid_by_passpoint_provider (7898171424140673315) --> + <skip /> <string name="available_via_passpoint" msgid="1617440946846329613">"Tilgængelig via %1$s"</string> + <!-- no translation found for tap_to_set_up (2468970825530423314) --> + <skip /> <string name="wifi_connected_no_internet" msgid="8202906332837777829">"Tilsluttet – intet internet"</string> <string name="wifi_status_no_internet" msgid="5784710974669608361">"Intet internet"</string> <string name="wifi_status_sign_in_required" msgid="123517180404752756">"Login er påkrævet"</string> <string name="wifi_ap_unable_to_handle_new_sta" msgid="5348824313514404541">"Adgangspunktet er midlertidigt fuldt"</string> <string name="connected_via_carrier" msgid="7583780074526041912">"Tilsluttet via %1$s"</string> <string name="available_via_carrier" msgid="1469036129740799053">"Tilgængelig via %1$s"</string> + <!-- no translation found for osu_failure_ap_connection (598977488344424542) --> + <skip /> + <!-- no translation found for osu_failure_server_url_invalid (2237477219243136714) --> + <skip /> + <!-- no translation found for osu_failure_server_connection (8192988165059982174) --> + <skip /> + <!-- no translation found for osu_failure_server_validation (4631649978129606823) --> + <skip /> + <!-- no translation found for osu_failure_service_provider_verification (4854091521439785597) --> + <skip /> + <!-- no translation found for osu_failure_provisioning_aborted (424627208135320329) --> + <skip /> + <!-- no translation found for osu_failure_provisioning_not_available (3021783729256985432) --> + <skip /> + <!-- no translation found for osu_failure_invalid_server_url (8548886196179435758) --> + <skip /> + <!-- no translation found for osu_failure_unexpected_command_type (8245921319866603904) --> + <skip /> + <!-- no translation found for osu_failure_unexpected_soap_message_type (2255897608510053065) --> + <skip /> + <!-- no translation found for osu_failure_soap_message_exchange (4357358438685987192) --> + <skip /> + <!-- no translation found for osu_failure_start_redirect_listener (4292769407279548482) --> + <skip /> + <!-- no translation found for osu_failure_timed_out_redirect_listener (3168657820278807508) --> + <skip /> + <!-- no translation found for osu_failure_no_osu_activity_found (4593038891437878675) --> + <skip /> + <!-- no translation found for osu_failure_unexpected_soap_message_status (6568467710235256675) --> + <skip /> + <!-- no translation found for osu_failure_no_pps_mo (850567403039076835) --> + <skip /> + <!-- no translation found for osu_failure_no_aaa_server_trust_root_node (8961455873459838456) --> + <skip /> + <!-- no translation found for osu_failure_no_remediation_server_trust_root_node (5041179688081545244) --> + <skip /> + <!-- no translation found for osu_failure_no_policy_server_trust_root_node (6617290380940513539) --> + <skip /> + <!-- no translation found for osu_failure_retrieve_trust_root_certificates (1499136256195528265) --> + <skip /> + <!-- no translation found for osu_failure_no_aaa_trust_root_certificate (1904322497042226984) --> + <skip /> + <!-- no translation found for osu_failure_add_passpoint_configuration (2173557755811446047) --> + <skip /> + <!-- no translation found for osu_failure_osu_provider_not_found (6616172862116673082) --> + <skip /> + <!-- no translation found for osu_status_ap_connecting (5296821043003441437) --> + <skip /> + <!-- no translation found for osu_status_ap_connected (3777289375683170728) --> + <skip /> + <!-- no translation found for osu_status_server_connecting (8499785407540355867) --> + <skip /> + <!-- no translation found for osu_status_server_validated (3158727184762596355) --> + <skip /> + <!-- no translation found for osu_status_server_connected (8382024481520158168) --> + <skip /> + <!-- no translation found for osu_status_init_soap_exchange (8628063888912101981) --> + <skip /> + <!-- no translation found for osu_status_waiting_for_redirect_response (2343016207837053197) --> + <skip /> + <!-- no translation found for osu_status_redirect_response_received (5323368411922609405) --> + <skip /> + <!-- no translation found for osu_status_second_soap_exchange (7115332266758483909) --> + <skip /> + <!-- no translation found for osu_status_third_soap_exchange (8460901783597440766) --> + <skip /> + <!-- no translation found for osu_status_retrieving_trust_root_certs (1563445892926269689) --> + <skip /> + <!-- no translation found for osu_provisioning_complete (5120178802493970149) --> + <skip /> <string name="speed_label_very_slow" msgid="1867055264243608530">"Meget langsom"</string> <string name="speed_label_slow" msgid="813109590815810235">"Langsom"</string> <string name="speed_label_okay" msgid="2331665440671174858">"OK"</string> diff --git a/packages/SettingsLib/res/values-de/strings.xml b/packages/SettingsLib/res/values-de/strings.xml index c4e03ad81ea6..1abc35913ac1 100644 --- a/packages/SettingsLib/res/values-de/strings.xml +++ b/packages/SettingsLib/res/values-de/strings.xml @@ -38,13 +38,87 @@ <string name="connected_via_network_scorer" msgid="5713793306870815341">"Automatisch über %1$s verbunden"</string> <string name="connected_via_network_scorer_default" msgid="7867260222020343104">"Automatisch über Anbieter von Netzwerkbewertungen verbunden"</string> <string name="connected_via_passpoint" msgid="2826205693803088747">"Über %1$s verbunden"</string> + <!-- no translation found for ssid_by_passpoint_provider (7898171424140673315) --> + <skip /> <string name="available_via_passpoint" msgid="1617440946846329613">"Verfügbar über %1$s"</string> + <!-- no translation found for tap_to_set_up (2468970825530423314) --> + <skip /> <string name="wifi_connected_no_internet" msgid="8202906332837777829">"Verbunden, kein Internet"</string> <string name="wifi_status_no_internet" msgid="5784710974669608361">"Kein Internet"</string> <string name="wifi_status_sign_in_required" msgid="123517180404752756">"Anmeldung erforderlich"</string> <string name="wifi_ap_unable_to_handle_new_sta" msgid="5348824313514404541">"Zugangspunkt vorübergehend voll belegt"</string> <string name="connected_via_carrier" msgid="7583780074526041912">"Über %1$s verbunden"</string> <string name="available_via_carrier" msgid="1469036129740799053">"Verfügbar über %1$s"</string> + <!-- no translation found for osu_failure_ap_connection (598977488344424542) --> + <skip /> + <!-- no translation found for osu_failure_server_url_invalid (2237477219243136714) --> + <skip /> + <!-- no translation found for osu_failure_server_connection (8192988165059982174) --> + <skip /> + <!-- no translation found for osu_failure_server_validation (4631649978129606823) --> + <skip /> + <!-- no translation found for osu_failure_service_provider_verification (4854091521439785597) --> + <skip /> + <!-- no translation found for osu_failure_provisioning_aborted (424627208135320329) --> + <skip /> + <!-- no translation found for osu_failure_provisioning_not_available (3021783729256985432) --> + <skip /> + <!-- no translation found for osu_failure_invalid_server_url (8548886196179435758) --> + <skip /> + <!-- no translation found for osu_failure_unexpected_command_type (8245921319866603904) --> + <skip /> + <!-- no translation found for osu_failure_unexpected_soap_message_type (2255897608510053065) --> + <skip /> + <!-- no translation found for osu_failure_soap_message_exchange (4357358438685987192) --> + <skip /> + <!-- no translation found for osu_failure_start_redirect_listener (4292769407279548482) --> + <skip /> + <!-- no translation found for osu_failure_timed_out_redirect_listener (3168657820278807508) --> + <skip /> + <!-- no translation found for osu_failure_no_osu_activity_found (4593038891437878675) --> + <skip /> + <!-- no translation found for osu_failure_unexpected_soap_message_status (6568467710235256675) --> + <skip /> + <!-- no translation found for osu_failure_no_pps_mo (850567403039076835) --> + <skip /> + <!-- no translation found for osu_failure_no_aaa_server_trust_root_node (8961455873459838456) --> + <skip /> + <!-- no translation found for osu_failure_no_remediation_server_trust_root_node (5041179688081545244) --> + <skip /> + <!-- no translation found for osu_failure_no_policy_server_trust_root_node (6617290380940513539) --> + <skip /> + <!-- no translation found for osu_failure_retrieve_trust_root_certificates (1499136256195528265) --> + <skip /> + <!-- no translation found for osu_failure_no_aaa_trust_root_certificate (1904322497042226984) --> + <skip /> + <!-- no translation found for osu_failure_add_passpoint_configuration (2173557755811446047) --> + <skip /> + <!-- no translation found for osu_failure_osu_provider_not_found (6616172862116673082) --> + <skip /> + <!-- no translation found for osu_status_ap_connecting (5296821043003441437) --> + <skip /> + <!-- no translation found for osu_status_ap_connected (3777289375683170728) --> + <skip /> + <!-- no translation found for osu_status_server_connecting (8499785407540355867) --> + <skip /> + <!-- no translation found for osu_status_server_validated (3158727184762596355) --> + <skip /> + <!-- no translation found for osu_status_server_connected (8382024481520158168) --> + <skip /> + <!-- no translation found for osu_status_init_soap_exchange (8628063888912101981) --> + <skip /> + <!-- no translation found for osu_status_waiting_for_redirect_response (2343016207837053197) --> + <skip /> + <!-- no translation found for osu_status_redirect_response_received (5323368411922609405) --> + <skip /> + <!-- no translation found for osu_status_second_soap_exchange (7115332266758483909) --> + <skip /> + <!-- no translation found for osu_status_third_soap_exchange (8460901783597440766) --> + <skip /> + <!-- no translation found for osu_status_retrieving_trust_root_certs (1563445892926269689) --> + <skip /> + <!-- no translation found for osu_provisioning_complete (5120178802493970149) --> + <skip /> <string name="speed_label_very_slow" msgid="1867055264243608530">"Sehr langsam"</string> <string name="speed_label_slow" msgid="813109590815810235">"Langsam"</string> <string name="speed_label_okay" msgid="2331665440671174858">"OK"</string> diff --git a/packages/SettingsLib/res/values-el/strings.xml b/packages/SettingsLib/res/values-el/strings.xml index 642e86226090..eb575584cdc2 100644 --- a/packages/SettingsLib/res/values-el/strings.xml +++ b/packages/SettingsLib/res/values-el/strings.xml @@ -38,13 +38,87 @@ <string name="connected_via_network_scorer" msgid="5713793306870815341">"Συνδέθηκε αυτόματα μέσω %1$s"</string> <string name="connected_via_network_scorer_default" msgid="7867260222020343104">"Συνδέθηκε αυτόματα μέσω παρόχου αξιολόγησης δικτύου"</string> <string name="connected_via_passpoint" msgid="2826205693803088747">"Συνδέθηκε μέσω %1$s"</string> + <!-- no translation found for ssid_by_passpoint_provider (7898171424140673315) --> + <skip /> <string name="available_via_passpoint" msgid="1617440946846329613">"Διαθέσιμο μέσω %1$s"</string> + <!-- no translation found for tap_to_set_up (2468970825530423314) --> + <skip /> <string name="wifi_connected_no_internet" msgid="8202906332837777829">"Συνδέθηκε, χωρίς σύνδεση στο διαδίκτυο"</string> <string name="wifi_status_no_internet" msgid="5784710974669608361">"Δεν υπάρχει σύνδεση στο διαδίκτυο"</string> <string name="wifi_status_sign_in_required" msgid="123517180404752756">"Απαιτείται σύνδεση"</string> <string name="wifi_ap_unable_to_handle_new_sta" msgid="5348824313514404541">"Το σημείο πρόσβασης είναι προσωρινά πλήρες"</string> <string name="connected_via_carrier" msgid="7583780074526041912">"Συνδέθηκε μέσω %1$s"</string> <string name="available_via_carrier" msgid="1469036129740799053">"Διαθέσιμο μέσω %1$s"</string> + <!-- no translation found for osu_failure_ap_connection (598977488344424542) --> + <skip /> + <!-- no translation found for osu_failure_server_url_invalid (2237477219243136714) --> + <skip /> + <!-- no translation found for osu_failure_server_connection (8192988165059982174) --> + <skip /> + <!-- no translation found for osu_failure_server_validation (4631649978129606823) --> + <skip /> + <!-- no translation found for osu_failure_service_provider_verification (4854091521439785597) --> + <skip /> + <!-- no translation found for osu_failure_provisioning_aborted (424627208135320329) --> + <skip /> + <!-- no translation found for osu_failure_provisioning_not_available (3021783729256985432) --> + <skip /> + <!-- no translation found for osu_failure_invalid_server_url (8548886196179435758) --> + <skip /> + <!-- no translation found for osu_failure_unexpected_command_type (8245921319866603904) --> + <skip /> + <!-- no translation found for osu_failure_unexpected_soap_message_type (2255897608510053065) --> + <skip /> + <!-- no translation found for osu_failure_soap_message_exchange (4357358438685987192) --> + <skip /> + <!-- no translation found for osu_failure_start_redirect_listener (4292769407279548482) --> + <skip /> + <!-- no translation found for osu_failure_timed_out_redirect_listener (3168657820278807508) --> + <skip /> + <!-- no translation found for osu_failure_no_osu_activity_found (4593038891437878675) --> + <skip /> + <!-- no translation found for osu_failure_unexpected_soap_message_status (6568467710235256675) --> + <skip /> + <!-- no translation found for osu_failure_no_pps_mo (850567403039076835) --> + <skip /> + <!-- no translation found for osu_failure_no_aaa_server_trust_root_node (8961455873459838456) --> + <skip /> + <!-- no translation found for osu_failure_no_remediation_server_trust_root_node (5041179688081545244) --> + <skip /> + <!-- no translation found for osu_failure_no_policy_server_trust_root_node (6617290380940513539) --> + <skip /> + <!-- no translation found for osu_failure_retrieve_trust_root_certificates (1499136256195528265) --> + <skip /> + <!-- no translation found for osu_failure_no_aaa_trust_root_certificate (1904322497042226984) --> + <skip /> + <!-- no translation found for osu_failure_add_passpoint_configuration (2173557755811446047) --> + <skip /> + <!-- no translation found for osu_failure_osu_provider_not_found (6616172862116673082) --> + <skip /> + <!-- no translation found for osu_status_ap_connecting (5296821043003441437) --> + <skip /> + <!-- no translation found for osu_status_ap_connected (3777289375683170728) --> + <skip /> + <!-- no translation found for osu_status_server_connecting (8499785407540355867) --> + <skip /> + <!-- no translation found for osu_status_server_validated (3158727184762596355) --> + <skip /> + <!-- no translation found for osu_status_server_connected (8382024481520158168) --> + <skip /> + <!-- no translation found for osu_status_init_soap_exchange (8628063888912101981) --> + <skip /> + <!-- no translation found for osu_status_waiting_for_redirect_response (2343016207837053197) --> + <skip /> + <!-- no translation found for osu_status_redirect_response_received (5323368411922609405) --> + <skip /> + <!-- no translation found for osu_status_second_soap_exchange (7115332266758483909) --> + <skip /> + <!-- no translation found for osu_status_third_soap_exchange (8460901783597440766) --> + <skip /> + <!-- no translation found for osu_status_retrieving_trust_root_certs (1563445892926269689) --> + <skip /> + <!-- no translation found for osu_provisioning_complete (5120178802493970149) --> + <skip /> <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> diff --git a/packages/SettingsLib/res/values-en-rAU/strings.xml b/packages/SettingsLib/res/values-en-rAU/strings.xml index 0cdfaf25514a..1f74d9b1029a 100644 --- a/packages/SettingsLib/res/values-en-rAU/strings.xml +++ b/packages/SettingsLib/res/values-en-rAU/strings.xml @@ -38,13 +38,87 @@ <string name="connected_via_network_scorer" msgid="5713793306870815341">"Automatically connected via %1$s"</string> <string name="connected_via_network_scorer_default" msgid="7867260222020343104">"Automatically connected via network rating provider"</string> <string name="connected_via_passpoint" msgid="2826205693803088747">"Connected via %1$s"</string> + <!-- no translation found for ssid_by_passpoint_provider (7898171424140673315) --> + <skip /> <string name="available_via_passpoint" msgid="1617440946846329613">"Available via %1$s"</string> + <!-- no translation found for tap_to_set_up (2468970825530423314) --> + <skip /> <string name="wifi_connected_no_internet" msgid="8202906332837777829">"Connected, no Internet"</string> <string name="wifi_status_no_internet" msgid="5784710974669608361">"No Internet"</string> <string name="wifi_status_sign_in_required" msgid="123517180404752756">"Sign-in required"</string> <string name="wifi_ap_unable_to_handle_new_sta" msgid="5348824313514404541">"Access point temporarily full"</string> <string name="connected_via_carrier" msgid="7583780074526041912">"Connected via %1$s"</string> <string name="available_via_carrier" msgid="1469036129740799053">"Available via %1$s"</string> + <!-- no translation found for osu_failure_ap_connection (598977488344424542) --> + <skip /> + <!-- no translation found for osu_failure_server_url_invalid (2237477219243136714) --> + <skip /> + <!-- no translation found for osu_failure_server_connection (8192988165059982174) --> + <skip /> + <!-- no translation found for osu_failure_server_validation (4631649978129606823) --> + <skip /> + <!-- no translation found for osu_failure_service_provider_verification (4854091521439785597) --> + <skip /> + <!-- no translation found for osu_failure_provisioning_aborted (424627208135320329) --> + <skip /> + <!-- no translation found for osu_failure_provisioning_not_available (3021783729256985432) --> + <skip /> + <!-- no translation found for osu_failure_invalid_server_url (8548886196179435758) --> + <skip /> + <!-- no translation found for osu_failure_unexpected_command_type (8245921319866603904) --> + <skip /> + <!-- no translation found for osu_failure_unexpected_soap_message_type (2255897608510053065) --> + <skip /> + <!-- no translation found for osu_failure_soap_message_exchange (4357358438685987192) --> + <skip /> + <!-- no translation found for osu_failure_start_redirect_listener (4292769407279548482) --> + <skip /> + <!-- no translation found for osu_failure_timed_out_redirect_listener (3168657820278807508) --> + <skip /> + <!-- no translation found for osu_failure_no_osu_activity_found (4593038891437878675) --> + <skip /> + <!-- no translation found for osu_failure_unexpected_soap_message_status (6568467710235256675) --> + <skip /> + <!-- no translation found for osu_failure_no_pps_mo (850567403039076835) --> + <skip /> + <!-- no translation found for osu_failure_no_aaa_server_trust_root_node (8961455873459838456) --> + <skip /> + <!-- no translation found for osu_failure_no_remediation_server_trust_root_node (5041179688081545244) --> + <skip /> + <!-- no translation found for osu_failure_no_policy_server_trust_root_node (6617290380940513539) --> + <skip /> + <!-- no translation found for osu_failure_retrieve_trust_root_certificates (1499136256195528265) --> + <skip /> + <!-- no translation found for osu_failure_no_aaa_trust_root_certificate (1904322497042226984) --> + <skip /> + <!-- no translation found for osu_failure_add_passpoint_configuration (2173557755811446047) --> + <skip /> + <!-- no translation found for osu_failure_osu_provider_not_found (6616172862116673082) --> + <skip /> + <!-- no translation found for osu_status_ap_connecting (5296821043003441437) --> + <skip /> + <!-- no translation found for osu_status_ap_connected (3777289375683170728) --> + <skip /> + <!-- no translation found for osu_status_server_connecting (8499785407540355867) --> + <skip /> + <!-- no translation found for osu_status_server_validated (3158727184762596355) --> + <skip /> + <!-- no translation found for osu_status_server_connected (8382024481520158168) --> + <skip /> + <!-- no translation found for osu_status_init_soap_exchange (8628063888912101981) --> + <skip /> + <!-- no translation found for osu_status_waiting_for_redirect_response (2343016207837053197) --> + <skip /> + <!-- no translation found for osu_status_redirect_response_received (5323368411922609405) --> + <skip /> + <!-- no translation found for osu_status_second_soap_exchange (7115332266758483909) --> + <skip /> + <!-- no translation found for osu_status_third_soap_exchange (8460901783597440766) --> + <skip /> + <!-- no translation found for osu_status_retrieving_trust_root_certs (1563445892926269689) --> + <skip /> + <!-- no translation found for osu_provisioning_complete (5120178802493970149) --> + <skip /> <string name="speed_label_very_slow" msgid="1867055264243608530">"Very slow"</string> <string name="speed_label_slow" msgid="813109590815810235">"Slow"</string> <string name="speed_label_okay" msgid="2331665440671174858">"OK"</string> diff --git a/packages/SettingsLib/res/values-en-rCA/strings.xml b/packages/SettingsLib/res/values-en-rCA/strings.xml index 0cdfaf25514a..1f74d9b1029a 100644 --- a/packages/SettingsLib/res/values-en-rCA/strings.xml +++ b/packages/SettingsLib/res/values-en-rCA/strings.xml @@ -38,13 +38,87 @@ <string name="connected_via_network_scorer" msgid="5713793306870815341">"Automatically connected via %1$s"</string> <string name="connected_via_network_scorer_default" msgid="7867260222020343104">"Automatically connected via network rating provider"</string> <string name="connected_via_passpoint" msgid="2826205693803088747">"Connected via %1$s"</string> + <!-- no translation found for ssid_by_passpoint_provider (7898171424140673315) --> + <skip /> <string name="available_via_passpoint" msgid="1617440946846329613">"Available via %1$s"</string> + <!-- no translation found for tap_to_set_up (2468970825530423314) --> + <skip /> <string name="wifi_connected_no_internet" msgid="8202906332837777829">"Connected, no Internet"</string> <string name="wifi_status_no_internet" msgid="5784710974669608361">"No Internet"</string> <string name="wifi_status_sign_in_required" msgid="123517180404752756">"Sign-in required"</string> <string name="wifi_ap_unable_to_handle_new_sta" msgid="5348824313514404541">"Access point temporarily full"</string> <string name="connected_via_carrier" msgid="7583780074526041912">"Connected via %1$s"</string> <string name="available_via_carrier" msgid="1469036129740799053">"Available via %1$s"</string> + <!-- no translation found for osu_failure_ap_connection (598977488344424542) --> + <skip /> + <!-- no translation found for osu_failure_server_url_invalid (2237477219243136714) --> + <skip /> + <!-- no translation found for osu_failure_server_connection (8192988165059982174) --> + <skip /> + <!-- no translation found for osu_failure_server_validation (4631649978129606823) --> + <skip /> + <!-- no translation found for osu_failure_service_provider_verification (4854091521439785597) --> + <skip /> + <!-- no translation found for osu_failure_provisioning_aborted (424627208135320329) --> + <skip /> + <!-- no translation found for osu_failure_provisioning_not_available (3021783729256985432) --> + <skip /> + <!-- no translation found for osu_failure_invalid_server_url (8548886196179435758) --> + <skip /> + <!-- no translation found for osu_failure_unexpected_command_type (8245921319866603904) --> + <skip /> + <!-- no translation found for osu_failure_unexpected_soap_message_type (2255897608510053065) --> + <skip /> + <!-- no translation found for osu_failure_soap_message_exchange (4357358438685987192) --> + <skip /> + <!-- no translation found for osu_failure_start_redirect_listener (4292769407279548482) --> + <skip /> + <!-- no translation found for osu_failure_timed_out_redirect_listener (3168657820278807508) --> + <skip /> + <!-- no translation found for osu_failure_no_osu_activity_found (4593038891437878675) --> + <skip /> + <!-- no translation found for osu_failure_unexpected_soap_message_status (6568467710235256675) --> + <skip /> + <!-- no translation found for osu_failure_no_pps_mo (850567403039076835) --> + <skip /> + <!-- no translation found for osu_failure_no_aaa_server_trust_root_node (8961455873459838456) --> + <skip /> + <!-- no translation found for osu_failure_no_remediation_server_trust_root_node (5041179688081545244) --> + <skip /> + <!-- no translation found for osu_failure_no_policy_server_trust_root_node (6617290380940513539) --> + <skip /> + <!-- no translation found for osu_failure_retrieve_trust_root_certificates (1499136256195528265) --> + <skip /> + <!-- no translation found for osu_failure_no_aaa_trust_root_certificate (1904322497042226984) --> + <skip /> + <!-- no translation found for osu_failure_add_passpoint_configuration (2173557755811446047) --> + <skip /> + <!-- no translation found for osu_failure_osu_provider_not_found (6616172862116673082) --> + <skip /> + <!-- no translation found for osu_status_ap_connecting (5296821043003441437) --> + <skip /> + <!-- no translation found for osu_status_ap_connected (3777289375683170728) --> + <skip /> + <!-- no translation found for osu_status_server_connecting (8499785407540355867) --> + <skip /> + <!-- no translation found for osu_status_server_validated (3158727184762596355) --> + <skip /> + <!-- no translation found for osu_status_server_connected (8382024481520158168) --> + <skip /> + <!-- no translation found for osu_status_init_soap_exchange (8628063888912101981) --> + <skip /> + <!-- no translation found for osu_status_waiting_for_redirect_response (2343016207837053197) --> + <skip /> + <!-- no translation found for osu_status_redirect_response_received (5323368411922609405) --> + <skip /> + <!-- no translation found for osu_status_second_soap_exchange (7115332266758483909) --> + <skip /> + <!-- no translation found for osu_status_third_soap_exchange (8460901783597440766) --> + <skip /> + <!-- no translation found for osu_status_retrieving_trust_root_certs (1563445892926269689) --> + <skip /> + <!-- no translation found for osu_provisioning_complete (5120178802493970149) --> + <skip /> <string name="speed_label_very_slow" msgid="1867055264243608530">"Very slow"</string> <string name="speed_label_slow" msgid="813109590815810235">"Slow"</string> <string name="speed_label_okay" msgid="2331665440671174858">"OK"</string> diff --git a/packages/SettingsLib/res/values-en-rGB/strings.xml b/packages/SettingsLib/res/values-en-rGB/strings.xml index 0cdfaf25514a..1f74d9b1029a 100644 --- a/packages/SettingsLib/res/values-en-rGB/strings.xml +++ b/packages/SettingsLib/res/values-en-rGB/strings.xml @@ -38,13 +38,87 @@ <string name="connected_via_network_scorer" msgid="5713793306870815341">"Automatically connected via %1$s"</string> <string name="connected_via_network_scorer_default" msgid="7867260222020343104">"Automatically connected via network rating provider"</string> <string name="connected_via_passpoint" msgid="2826205693803088747">"Connected via %1$s"</string> + <!-- no translation found for ssid_by_passpoint_provider (7898171424140673315) --> + <skip /> <string name="available_via_passpoint" msgid="1617440946846329613">"Available via %1$s"</string> + <!-- no translation found for tap_to_set_up (2468970825530423314) --> + <skip /> <string name="wifi_connected_no_internet" msgid="8202906332837777829">"Connected, no Internet"</string> <string name="wifi_status_no_internet" msgid="5784710974669608361">"No Internet"</string> <string name="wifi_status_sign_in_required" msgid="123517180404752756">"Sign-in required"</string> <string name="wifi_ap_unable_to_handle_new_sta" msgid="5348824313514404541">"Access point temporarily full"</string> <string name="connected_via_carrier" msgid="7583780074526041912">"Connected via %1$s"</string> <string name="available_via_carrier" msgid="1469036129740799053">"Available via %1$s"</string> + <!-- no translation found for osu_failure_ap_connection (598977488344424542) --> + <skip /> + <!-- no translation found for osu_failure_server_url_invalid (2237477219243136714) --> + <skip /> + <!-- no translation found for osu_failure_server_connection (8192988165059982174) --> + <skip /> + <!-- no translation found for osu_failure_server_validation (4631649978129606823) --> + <skip /> + <!-- no translation found for osu_failure_service_provider_verification (4854091521439785597) --> + <skip /> + <!-- no translation found for osu_failure_provisioning_aborted (424627208135320329) --> + <skip /> + <!-- no translation found for osu_failure_provisioning_not_available (3021783729256985432) --> + <skip /> + <!-- no translation found for osu_failure_invalid_server_url (8548886196179435758) --> + <skip /> + <!-- no translation found for osu_failure_unexpected_command_type (8245921319866603904) --> + <skip /> + <!-- no translation found for osu_failure_unexpected_soap_message_type (2255897608510053065) --> + <skip /> + <!-- no translation found for osu_failure_soap_message_exchange (4357358438685987192) --> + <skip /> + <!-- no translation found for osu_failure_start_redirect_listener (4292769407279548482) --> + <skip /> + <!-- no translation found for osu_failure_timed_out_redirect_listener (3168657820278807508) --> + <skip /> + <!-- no translation found for osu_failure_no_osu_activity_found (4593038891437878675) --> + <skip /> + <!-- no translation found for osu_failure_unexpected_soap_message_status (6568467710235256675) --> + <skip /> + <!-- no translation found for osu_failure_no_pps_mo (850567403039076835) --> + <skip /> + <!-- no translation found for osu_failure_no_aaa_server_trust_root_node (8961455873459838456) --> + <skip /> + <!-- no translation found for osu_failure_no_remediation_server_trust_root_node (5041179688081545244) --> + <skip /> + <!-- no translation found for osu_failure_no_policy_server_trust_root_node (6617290380940513539) --> + <skip /> + <!-- no translation found for osu_failure_retrieve_trust_root_certificates (1499136256195528265) --> + <skip /> + <!-- no translation found for osu_failure_no_aaa_trust_root_certificate (1904322497042226984) --> + <skip /> + <!-- no translation found for osu_failure_add_passpoint_configuration (2173557755811446047) --> + <skip /> + <!-- no translation found for osu_failure_osu_provider_not_found (6616172862116673082) --> + <skip /> + <!-- no translation found for osu_status_ap_connecting (5296821043003441437) --> + <skip /> + <!-- no translation found for osu_status_ap_connected (3777289375683170728) --> + <skip /> + <!-- no translation found for osu_status_server_connecting (8499785407540355867) --> + <skip /> + <!-- no translation found for osu_status_server_validated (3158727184762596355) --> + <skip /> + <!-- no translation found for osu_status_server_connected (8382024481520158168) --> + <skip /> + <!-- no translation found for osu_status_init_soap_exchange (8628063888912101981) --> + <skip /> + <!-- no translation found for osu_status_waiting_for_redirect_response (2343016207837053197) --> + <skip /> + <!-- no translation found for osu_status_redirect_response_received (5323368411922609405) --> + <skip /> + <!-- no translation found for osu_status_second_soap_exchange (7115332266758483909) --> + <skip /> + <!-- no translation found for osu_status_third_soap_exchange (8460901783597440766) --> + <skip /> + <!-- no translation found for osu_status_retrieving_trust_root_certs (1563445892926269689) --> + <skip /> + <!-- no translation found for osu_provisioning_complete (5120178802493970149) --> + <skip /> <string name="speed_label_very_slow" msgid="1867055264243608530">"Very slow"</string> <string name="speed_label_slow" msgid="813109590815810235">"Slow"</string> <string name="speed_label_okay" msgid="2331665440671174858">"OK"</string> diff --git a/packages/SettingsLib/res/values-en-rIN/strings.xml b/packages/SettingsLib/res/values-en-rIN/strings.xml index 0cdfaf25514a..1f74d9b1029a 100644 --- a/packages/SettingsLib/res/values-en-rIN/strings.xml +++ b/packages/SettingsLib/res/values-en-rIN/strings.xml @@ -38,13 +38,87 @@ <string name="connected_via_network_scorer" msgid="5713793306870815341">"Automatically connected via %1$s"</string> <string name="connected_via_network_scorer_default" msgid="7867260222020343104">"Automatically connected via network rating provider"</string> <string name="connected_via_passpoint" msgid="2826205693803088747">"Connected via %1$s"</string> + <!-- no translation found for ssid_by_passpoint_provider (7898171424140673315) --> + <skip /> <string name="available_via_passpoint" msgid="1617440946846329613">"Available via %1$s"</string> + <!-- no translation found for tap_to_set_up (2468970825530423314) --> + <skip /> <string name="wifi_connected_no_internet" msgid="8202906332837777829">"Connected, no Internet"</string> <string name="wifi_status_no_internet" msgid="5784710974669608361">"No Internet"</string> <string name="wifi_status_sign_in_required" msgid="123517180404752756">"Sign-in required"</string> <string name="wifi_ap_unable_to_handle_new_sta" msgid="5348824313514404541">"Access point temporarily full"</string> <string name="connected_via_carrier" msgid="7583780074526041912">"Connected via %1$s"</string> <string name="available_via_carrier" msgid="1469036129740799053">"Available via %1$s"</string> + <!-- no translation found for osu_failure_ap_connection (598977488344424542) --> + <skip /> + <!-- no translation found for osu_failure_server_url_invalid (2237477219243136714) --> + <skip /> + <!-- no translation found for osu_failure_server_connection (8192988165059982174) --> + <skip /> + <!-- no translation found for osu_failure_server_validation (4631649978129606823) --> + <skip /> + <!-- no translation found for osu_failure_service_provider_verification (4854091521439785597) --> + <skip /> + <!-- no translation found for osu_failure_provisioning_aborted (424627208135320329) --> + <skip /> + <!-- no translation found for osu_failure_provisioning_not_available (3021783729256985432) --> + <skip /> + <!-- no translation found for osu_failure_invalid_server_url (8548886196179435758) --> + <skip /> + <!-- no translation found for osu_failure_unexpected_command_type (8245921319866603904) --> + <skip /> + <!-- no translation found for osu_failure_unexpected_soap_message_type (2255897608510053065) --> + <skip /> + <!-- no translation found for osu_failure_soap_message_exchange (4357358438685987192) --> + <skip /> + <!-- no translation found for osu_failure_start_redirect_listener (4292769407279548482) --> + <skip /> + <!-- no translation found for osu_failure_timed_out_redirect_listener (3168657820278807508) --> + <skip /> + <!-- no translation found for osu_failure_no_osu_activity_found (4593038891437878675) --> + <skip /> + <!-- no translation found for osu_failure_unexpected_soap_message_status (6568467710235256675) --> + <skip /> + <!-- no translation found for osu_failure_no_pps_mo (850567403039076835) --> + <skip /> + <!-- no translation found for osu_failure_no_aaa_server_trust_root_node (8961455873459838456) --> + <skip /> + <!-- no translation found for osu_failure_no_remediation_server_trust_root_node (5041179688081545244) --> + <skip /> + <!-- no translation found for osu_failure_no_policy_server_trust_root_node (6617290380940513539) --> + <skip /> + <!-- no translation found for osu_failure_retrieve_trust_root_certificates (1499136256195528265) --> + <skip /> + <!-- no translation found for osu_failure_no_aaa_trust_root_certificate (1904322497042226984) --> + <skip /> + <!-- no translation found for osu_failure_add_passpoint_configuration (2173557755811446047) --> + <skip /> + <!-- no translation found for osu_failure_osu_provider_not_found (6616172862116673082) --> + <skip /> + <!-- no translation found for osu_status_ap_connecting (5296821043003441437) --> + <skip /> + <!-- no translation found for osu_status_ap_connected (3777289375683170728) --> + <skip /> + <!-- no translation found for osu_status_server_connecting (8499785407540355867) --> + <skip /> + <!-- no translation found for osu_status_server_validated (3158727184762596355) --> + <skip /> + <!-- no translation found for osu_status_server_connected (8382024481520158168) --> + <skip /> + <!-- no translation found for osu_status_init_soap_exchange (8628063888912101981) --> + <skip /> + <!-- no translation found for osu_status_waiting_for_redirect_response (2343016207837053197) --> + <skip /> + <!-- no translation found for osu_status_redirect_response_received (5323368411922609405) --> + <skip /> + <!-- no translation found for osu_status_second_soap_exchange (7115332266758483909) --> + <skip /> + <!-- no translation found for osu_status_third_soap_exchange (8460901783597440766) --> + <skip /> + <!-- no translation found for osu_status_retrieving_trust_root_certs (1563445892926269689) --> + <skip /> + <!-- no translation found for osu_provisioning_complete (5120178802493970149) --> + <skip /> <string name="speed_label_very_slow" msgid="1867055264243608530">"Very slow"</string> <string name="speed_label_slow" msgid="813109590815810235">"Slow"</string> <string name="speed_label_okay" msgid="2331665440671174858">"OK"</string> diff --git a/packages/SettingsLib/res/values-en-rXC/strings.xml b/packages/SettingsLib/res/values-en-rXC/strings.xml index eda4d1bb938e..082a33107a6c 100644 --- a/packages/SettingsLib/res/values-en-rXC/strings.xml +++ b/packages/SettingsLib/res/values-en-rXC/strings.xml @@ -38,13 +38,50 @@ <string name="connected_via_network_scorer" msgid="5713793306870815341">"Automatically connected via %1$s"</string> <string name="connected_via_network_scorer_default" msgid="7867260222020343104">"Automatically connected via network rating provider"</string> <string name="connected_via_passpoint" msgid="2826205693803088747">"Connected via %1$s"</string> + <string name="ssid_by_passpoint_provider" msgid="7898171424140673315">"<xliff:g id="SSID">%1$s</xliff:g> by <xliff:g id="PASSPOINTPROVIDER">%2$s</xliff:g>"</string> <string name="available_via_passpoint" msgid="1617440946846329613">"Available via %1$s"</string> + <string name="tap_to_set_up" msgid="2468970825530423314">"Tap to set up"</string> <string name="wifi_connected_no_internet" msgid="8202906332837777829">"Connected, no internet"</string> <string name="wifi_status_no_internet" msgid="5784710974669608361">"No internet"</string> <string name="wifi_status_sign_in_required" msgid="123517180404752756">"Sign in required"</string> <string name="wifi_ap_unable_to_handle_new_sta" msgid="5348824313514404541">"Access point temporarily full"</string> <string name="connected_via_carrier" msgid="7583780074526041912">"Connected via %1$s"</string> <string name="available_via_carrier" msgid="1469036129740799053">"Available via %1$s"</string> + <string name="osu_failure_ap_connection" msgid="598977488344424542">"Connection failed"</string> + <string name="osu_failure_server_url_invalid" msgid="2237477219243136714">"Invalid OSU server URL"</string> + <string name="osu_failure_server_connection" msgid="8192988165059982174">"OSU server connection failed"</string> + <string name="osu_failure_server_validation" msgid="4631649978129606823">"OSU server validation failed"</string> + <string name="osu_failure_service_provider_verification" msgid="4854091521439785597">"Invalid OSU server certificate"</string> + <string name="osu_failure_provisioning_aborted" msgid="424627208135320329">"Provisioning aborted"</string> + <string name="osu_failure_provisioning_not_available" msgid="3021783729256985432">"Provisioning not available"</string> + <string name="osu_failure_invalid_server_url" msgid="8548886196179435758">"Invalid OSU server URL"</string> + <string name="osu_failure_unexpected_command_type" msgid="8245921319866603904">"Unexpected command type"</string> + <string name="osu_failure_unexpected_soap_message_type" msgid="2255897608510053065">"Unexpected SOAP message type"</string> + <string name="osu_failure_soap_message_exchange" msgid="4357358438685987192">"SOAP message exchange failed"</string> + <string name="osu_failure_start_redirect_listener" msgid="4292769407279548482">"Redirect listener failed to start"</string> + <string name="osu_failure_timed_out_redirect_listener" msgid="3168657820278807508">"Timed out waiting for redirect"</string> + <string name="osu_failure_no_osu_activity_found" msgid="4593038891437878675">"No OSU activity found"</string> + <string name="osu_failure_unexpected_soap_message_status" msgid="6568467710235256675">"Unexpected SOAP message status"</string> + <string name="osu_failure_no_pps_mo" msgid="850567403039076835">"Failed to find PPS-MO"</string> + <string name="osu_failure_no_aaa_server_trust_root_node" msgid="8961455873459838456">"Failed to find trust root node for AAA server"</string> + <string name="osu_failure_no_remediation_server_trust_root_node" msgid="5041179688081545244">"Failed to find trust root node for remediation server"</string> + <string name="osu_failure_no_policy_server_trust_root_node" msgid="6617290380940513539">"Failed to find trust root node for policy server"</string> + <string name="osu_failure_retrieve_trust_root_certificates" msgid="1499136256195528265">"Failed to retrieve trust root certificates"</string> + <string name="osu_failure_no_aaa_trust_root_certificate" msgid="1904322497042226984">"Failed to find trust root certificate for AAA server"</string> + <string name="osu_failure_add_passpoint_configuration" msgid="2173557755811446047">"Failed to add PassPoint configuration"</string> + <string name="osu_failure_osu_provider_not_found" msgid="6616172862116673082">"Failed to find an OSU provider"</string> + <string name="osu_status_ap_connecting" msgid="5296821043003441437">"Connecting"</string> + <string name="osu_status_ap_connected" msgid="3777289375683170728">"Connected"</string> + <string name="osu_status_server_connecting" msgid="8499785407540355867">"Connecting to OSU server"</string> + <string name="osu_status_server_validated" msgid="3158727184762596355">"OSU server validated"</string> + <string name="osu_status_server_connected" msgid="8382024481520158168">"Connected to OSU server"</string> + <string name="osu_status_init_soap_exchange" msgid="8628063888912101981">"Initial SOAP exchange"</string> + <string name="osu_status_waiting_for_redirect_response" msgid="2343016207837053197">"Waiting for redirect response"</string> + <string name="osu_status_redirect_response_received" msgid="5323368411922609405">"Received redirect response"</string> + <string name="osu_status_second_soap_exchange" msgid="7115332266758483909">"Second SOAP exchange"</string> + <string name="osu_status_third_soap_exchange" msgid="8460901783597440766">"Third SOAP exchange"</string> + <string name="osu_status_retrieving_trust_root_certs" msgid="1563445892926269689">"Retrieving trust root certificates"</string> + <string name="osu_provisioning_complete" msgid="5120178802493970149">"Provisioning complete"</string> <string name="speed_label_very_slow" msgid="1867055264243608530">"Very Slow"</string> <string name="speed_label_slow" msgid="813109590815810235">"Slow"</string> <string name="speed_label_okay" msgid="2331665440671174858">"OK"</string> diff --git a/packages/SettingsLib/res/values-es-rUS/strings.xml b/packages/SettingsLib/res/values-es-rUS/strings.xml index bd3d1b763c17..795ad9c8d655 100644 --- a/packages/SettingsLib/res/values-es-rUS/strings.xml +++ b/packages/SettingsLib/res/values-es-rUS/strings.xml @@ -38,13 +38,87 @@ <string name="connected_via_network_scorer" msgid="5713793306870815341">"Conexión automática mediante %1$s"</string> <string name="connected_via_network_scorer_default" msgid="7867260222020343104">"Conectado automáticamente mediante proveedor de calificación de red"</string> <string name="connected_via_passpoint" msgid="2826205693803088747">"Conexión a través de %1$s"</string> + <!-- no translation found for ssid_by_passpoint_provider (7898171424140673315) --> + <skip /> <string name="available_via_passpoint" msgid="1617440946846329613">"Disponible a través de %1$s"</string> + <!-- no translation found for tap_to_set_up (2468970825530423314) --> + <skip /> <string name="wifi_connected_no_internet" msgid="8202906332837777829">"Conectado pero sin conexión a Internet"</string> <string name="wifi_status_no_internet" msgid="5784710974669608361">"Sin Internet"</string> <string name="wifi_status_sign_in_required" msgid="123517180404752756">"Acceso obligatorio"</string> <string name="wifi_ap_unable_to_handle_new_sta" msgid="5348824313514404541">"El punto de acceso está completo temporalmente"</string> <string name="connected_via_carrier" msgid="7583780074526041912">"Conexión a través de %1$s"</string> <string name="available_via_carrier" msgid="1469036129740799053">"Disponible a través de %1$s"</string> + <!-- no translation found for osu_failure_ap_connection (598977488344424542) --> + <skip /> + <!-- no translation found for osu_failure_server_url_invalid (2237477219243136714) --> + <skip /> + <!-- no translation found for osu_failure_server_connection (8192988165059982174) --> + <skip /> + <!-- no translation found for osu_failure_server_validation (4631649978129606823) --> + <skip /> + <!-- no translation found for osu_failure_service_provider_verification (4854091521439785597) --> + <skip /> + <!-- no translation found for osu_failure_provisioning_aborted (424627208135320329) --> + <skip /> + <!-- no translation found for osu_failure_provisioning_not_available (3021783729256985432) --> + <skip /> + <!-- no translation found for osu_failure_invalid_server_url (8548886196179435758) --> + <skip /> + <!-- no translation found for osu_failure_unexpected_command_type (8245921319866603904) --> + <skip /> + <!-- no translation found for osu_failure_unexpected_soap_message_type (2255897608510053065) --> + <skip /> + <!-- no translation found for osu_failure_soap_message_exchange (4357358438685987192) --> + <skip /> + <!-- no translation found for osu_failure_start_redirect_listener (4292769407279548482) --> + <skip /> + <!-- no translation found for osu_failure_timed_out_redirect_listener (3168657820278807508) --> + <skip /> + <!-- no translation found for osu_failure_no_osu_activity_found (4593038891437878675) --> + <skip /> + <!-- no translation found for osu_failure_unexpected_soap_message_status (6568467710235256675) --> + <skip /> + <!-- no translation found for osu_failure_no_pps_mo (850567403039076835) --> + <skip /> + <!-- no translation found for osu_failure_no_aaa_server_trust_root_node (8961455873459838456) --> + <skip /> + <!-- no translation found for osu_failure_no_remediation_server_trust_root_node (5041179688081545244) --> + <skip /> + <!-- no translation found for osu_failure_no_policy_server_trust_root_node (6617290380940513539) --> + <skip /> + <!-- no translation found for osu_failure_retrieve_trust_root_certificates (1499136256195528265) --> + <skip /> + <!-- no translation found for osu_failure_no_aaa_trust_root_certificate (1904322497042226984) --> + <skip /> + <!-- no translation found for osu_failure_add_passpoint_configuration (2173557755811446047) --> + <skip /> + <!-- no translation found for osu_failure_osu_provider_not_found (6616172862116673082) --> + <skip /> + <!-- no translation found for osu_status_ap_connecting (5296821043003441437) --> + <skip /> + <!-- no translation found for osu_status_ap_connected (3777289375683170728) --> + <skip /> + <!-- no translation found for osu_status_server_connecting (8499785407540355867) --> + <skip /> + <!-- no translation found for osu_status_server_validated (3158727184762596355) --> + <skip /> + <!-- no translation found for osu_status_server_connected (8382024481520158168) --> + <skip /> + <!-- no translation found for osu_status_init_soap_exchange (8628063888912101981) --> + <skip /> + <!-- no translation found for osu_status_waiting_for_redirect_response (2343016207837053197) --> + <skip /> + <!-- no translation found for osu_status_redirect_response_received (5323368411922609405) --> + <skip /> + <!-- no translation found for osu_status_second_soap_exchange (7115332266758483909) --> + <skip /> + <!-- no translation found for osu_status_third_soap_exchange (8460901783597440766) --> + <skip /> + <!-- no translation found for osu_status_retrieving_trust_root_certs (1563445892926269689) --> + <skip /> + <!-- no translation found for osu_provisioning_complete (5120178802493970149) --> + <skip /> <string name="speed_label_very_slow" msgid="1867055264243608530">"Muy lenta"</string> <string name="speed_label_slow" msgid="813109590815810235">"Lenta"</string> <string name="speed_label_okay" msgid="2331665440671174858">"Aceptar"</string> @@ -144,7 +218,7 @@ <string name="tts_settings_title" msgid="1237820681016639683">"Salida de texto a voz"</string> <string name="tts_default_rate_title" msgid="6030550998379310088">"Velocidad de voz"</string> <string name="tts_default_rate_summary" msgid="4061815292287182801">"Velocidad en la que se habla el texto"</string> - <string name="tts_default_pitch_title" msgid="6135942113172488671">"Sonido"</string> + <string name="tts_default_pitch_title" msgid="6135942113172488671">"Tono"</string> <string name="tts_default_pitch_summary" msgid="1944885882882650009">"Afecta el tono de la voz sintetizada"</string> <string name="tts_default_lang_title" msgid="8018087612299820556">"Idioma"</string> <string name="tts_lang_use_system" msgid="2679252467416513208">"Usar el idioma del sistema"</string> diff --git a/packages/SettingsLib/res/values-es/strings.xml b/packages/SettingsLib/res/values-es/strings.xml index 94f88eb52dd6..669871f85488 100644 --- a/packages/SettingsLib/res/values-es/strings.xml +++ b/packages/SettingsLib/res/values-es/strings.xml @@ -38,13 +38,87 @@ <string name="connected_via_network_scorer" msgid="5713793306870815341">"Conectada automáticamente a través de %1$s"</string> <string name="connected_via_network_scorer_default" msgid="7867260222020343104">"Conectado automáticamente a través de un proveedor de valoración de redes"</string> <string name="connected_via_passpoint" msgid="2826205693803088747">"Conectado a través de %1$s"</string> + <!-- no translation found for ssid_by_passpoint_provider (7898171424140673315) --> + <skip /> <string name="available_via_passpoint" msgid="1617440946846329613">"Disponible a través de %1$s"</string> + <!-- no translation found for tap_to_set_up (2468970825530423314) --> + <skip /> <string name="wifi_connected_no_internet" msgid="8202906332837777829">"Conexión sin Internet"</string> <string name="wifi_status_no_internet" msgid="5784710974669608361">"Sin Internet"</string> <string name="wifi_status_sign_in_required" msgid="123517180404752756">"Debes iniciar sesión"</string> <string name="wifi_ap_unable_to_handle_new_sta" msgid="5348824313514404541">"Punto de acceso temporalmente lleno"</string> <string name="connected_via_carrier" msgid="7583780074526041912">"Conectado a través de %1$s"</string> <string name="available_via_carrier" msgid="1469036129740799053">"Disponible a través de %1$s"</string> + <!-- no translation found for osu_failure_ap_connection (598977488344424542) --> + <skip /> + <!-- no translation found for osu_failure_server_url_invalid (2237477219243136714) --> + <skip /> + <!-- no translation found for osu_failure_server_connection (8192988165059982174) --> + <skip /> + <!-- no translation found for osu_failure_server_validation (4631649978129606823) --> + <skip /> + <!-- no translation found for osu_failure_service_provider_verification (4854091521439785597) --> + <skip /> + <!-- no translation found for osu_failure_provisioning_aborted (424627208135320329) --> + <skip /> + <!-- no translation found for osu_failure_provisioning_not_available (3021783729256985432) --> + <skip /> + <!-- no translation found for osu_failure_invalid_server_url (8548886196179435758) --> + <skip /> + <!-- no translation found for osu_failure_unexpected_command_type (8245921319866603904) --> + <skip /> + <!-- no translation found for osu_failure_unexpected_soap_message_type (2255897608510053065) --> + <skip /> + <!-- no translation found for osu_failure_soap_message_exchange (4357358438685987192) --> + <skip /> + <!-- no translation found for osu_failure_start_redirect_listener (4292769407279548482) --> + <skip /> + <!-- no translation found for osu_failure_timed_out_redirect_listener (3168657820278807508) --> + <skip /> + <!-- no translation found for osu_failure_no_osu_activity_found (4593038891437878675) --> + <skip /> + <!-- no translation found for osu_failure_unexpected_soap_message_status (6568467710235256675) --> + <skip /> + <!-- no translation found for osu_failure_no_pps_mo (850567403039076835) --> + <skip /> + <!-- no translation found for osu_failure_no_aaa_server_trust_root_node (8961455873459838456) --> + <skip /> + <!-- no translation found for osu_failure_no_remediation_server_trust_root_node (5041179688081545244) --> + <skip /> + <!-- no translation found for osu_failure_no_policy_server_trust_root_node (6617290380940513539) --> + <skip /> + <!-- no translation found for osu_failure_retrieve_trust_root_certificates (1499136256195528265) --> + <skip /> + <!-- no translation found for osu_failure_no_aaa_trust_root_certificate (1904322497042226984) --> + <skip /> + <!-- no translation found for osu_failure_add_passpoint_configuration (2173557755811446047) --> + <skip /> + <!-- no translation found for osu_failure_osu_provider_not_found (6616172862116673082) --> + <skip /> + <!-- no translation found for osu_status_ap_connecting (5296821043003441437) --> + <skip /> + <!-- no translation found for osu_status_ap_connected (3777289375683170728) --> + <skip /> + <!-- no translation found for osu_status_server_connecting (8499785407540355867) --> + <skip /> + <!-- no translation found for osu_status_server_validated (3158727184762596355) --> + <skip /> + <!-- no translation found for osu_status_server_connected (8382024481520158168) --> + <skip /> + <!-- no translation found for osu_status_init_soap_exchange (8628063888912101981) --> + <skip /> + <!-- no translation found for osu_status_waiting_for_redirect_response (2343016207837053197) --> + <skip /> + <!-- no translation found for osu_status_redirect_response_received (5323368411922609405) --> + <skip /> + <!-- no translation found for osu_status_second_soap_exchange (7115332266758483909) --> + <skip /> + <!-- no translation found for osu_status_third_soap_exchange (8460901783597440766) --> + <skip /> + <!-- no translation found for osu_status_retrieving_trust_root_certs (1563445892926269689) --> + <skip /> + <!-- no translation found for osu_provisioning_complete (5120178802493970149) --> + <skip /> <string name="speed_label_very_slow" msgid="1867055264243608530">"Muy lenta"</string> <string name="speed_label_slow" msgid="813109590815810235">"Lenta"</string> <string name="speed_label_okay" msgid="2331665440671174858">"Aceptable"</string> diff --git a/packages/SettingsLib/res/values-et/strings.xml b/packages/SettingsLib/res/values-et/strings.xml index 31527dcfcf2a..0c9d28ea65a5 100644 --- a/packages/SettingsLib/res/values-et/strings.xml +++ b/packages/SettingsLib/res/values-et/strings.xml @@ -38,13 +38,87 @@ <string name="connected_via_network_scorer" msgid="5713793306870815341">"Ühendus loodi automaatselt teenusega %1$s"</string> <string name="connected_via_network_scorer_default" msgid="7867260222020343104">"Ühendus loodi automaatselt võrgukvaliteedi hinnangute pakkuja kaudu"</string> <string name="connected_via_passpoint" msgid="2826205693803088747">"Ühendatud üksuse %1$s kaudu"</string> + <!-- no translation found for ssid_by_passpoint_provider (7898171424140673315) --> + <skip /> <string name="available_via_passpoint" msgid="1617440946846329613">"Saadaval üksuse %1$s kaudu"</string> + <!-- no translation found for tap_to_set_up (2468970825530423314) --> + <skip /> <string name="wifi_connected_no_internet" msgid="8202906332837777829">"Ühendatud, Interneti-ühendus puudub"</string> <string name="wifi_status_no_internet" msgid="5784710974669608361">"Interneti-ühendus puudub"</string> <string name="wifi_status_sign_in_required" msgid="123517180404752756">"Nõutav on sisselogimine"</string> <string name="wifi_ap_unable_to_handle_new_sta" msgid="5348824313514404541">"Pääsupunkt on ajutiselt täis"</string> <string name="connected_via_carrier" msgid="7583780074526041912">"Ühendatud operaatori %1$s kaudu"</string> <string name="available_via_carrier" msgid="1469036129740799053">"Saadaval operaatori %1$s kaudu"</string> + <!-- no translation found for osu_failure_ap_connection (598977488344424542) --> + <skip /> + <!-- no translation found for osu_failure_server_url_invalid (2237477219243136714) --> + <skip /> + <!-- no translation found for osu_failure_server_connection (8192988165059982174) --> + <skip /> + <!-- no translation found for osu_failure_server_validation (4631649978129606823) --> + <skip /> + <!-- no translation found for osu_failure_service_provider_verification (4854091521439785597) --> + <skip /> + <!-- no translation found for osu_failure_provisioning_aborted (424627208135320329) --> + <skip /> + <!-- no translation found for osu_failure_provisioning_not_available (3021783729256985432) --> + <skip /> + <!-- no translation found for osu_failure_invalid_server_url (8548886196179435758) --> + <skip /> + <!-- no translation found for osu_failure_unexpected_command_type (8245921319866603904) --> + <skip /> + <!-- no translation found for osu_failure_unexpected_soap_message_type (2255897608510053065) --> + <skip /> + <!-- no translation found for osu_failure_soap_message_exchange (4357358438685987192) --> + <skip /> + <!-- no translation found for osu_failure_start_redirect_listener (4292769407279548482) --> + <skip /> + <!-- no translation found for osu_failure_timed_out_redirect_listener (3168657820278807508) --> + <skip /> + <!-- no translation found for osu_failure_no_osu_activity_found (4593038891437878675) --> + <skip /> + <!-- no translation found for osu_failure_unexpected_soap_message_status (6568467710235256675) --> + <skip /> + <!-- no translation found for osu_failure_no_pps_mo (850567403039076835) --> + <skip /> + <!-- no translation found for osu_failure_no_aaa_server_trust_root_node (8961455873459838456) --> + <skip /> + <!-- no translation found for osu_failure_no_remediation_server_trust_root_node (5041179688081545244) --> + <skip /> + <!-- no translation found for osu_failure_no_policy_server_trust_root_node (6617290380940513539) --> + <skip /> + <!-- no translation found for osu_failure_retrieve_trust_root_certificates (1499136256195528265) --> + <skip /> + <!-- no translation found for osu_failure_no_aaa_trust_root_certificate (1904322497042226984) --> + <skip /> + <!-- no translation found for osu_failure_add_passpoint_configuration (2173557755811446047) --> + <skip /> + <!-- no translation found for osu_failure_osu_provider_not_found (6616172862116673082) --> + <skip /> + <!-- no translation found for osu_status_ap_connecting (5296821043003441437) --> + <skip /> + <!-- no translation found for osu_status_ap_connected (3777289375683170728) --> + <skip /> + <!-- no translation found for osu_status_server_connecting (8499785407540355867) --> + <skip /> + <!-- no translation found for osu_status_server_validated (3158727184762596355) --> + <skip /> + <!-- no translation found for osu_status_server_connected (8382024481520158168) --> + <skip /> + <!-- no translation found for osu_status_init_soap_exchange (8628063888912101981) --> + <skip /> + <!-- no translation found for osu_status_waiting_for_redirect_response (2343016207837053197) --> + <skip /> + <!-- no translation found for osu_status_redirect_response_received (5323368411922609405) --> + <skip /> + <!-- no translation found for osu_status_second_soap_exchange (7115332266758483909) --> + <skip /> + <!-- no translation found for osu_status_third_soap_exchange (8460901783597440766) --> + <skip /> + <!-- no translation found for osu_status_retrieving_trust_root_certs (1563445892926269689) --> + <skip /> + <!-- no translation found for osu_provisioning_complete (5120178802493970149) --> + <skip /> <string name="speed_label_very_slow" msgid="1867055264243608530">"Väga aeglane"</string> <string name="speed_label_slow" msgid="813109590815810235">"Aeglane"</string> <string name="speed_label_okay" msgid="2331665440671174858">"Hea"</string> diff --git a/packages/SettingsLib/res/values-eu/strings.xml b/packages/SettingsLib/res/values-eu/strings.xml index dd7728431e84..2687d1d7d210 100644 --- a/packages/SettingsLib/res/values-eu/strings.xml +++ b/packages/SettingsLib/res/values-eu/strings.xml @@ -38,13 +38,87 @@ <string name="connected_via_network_scorer" msgid="5713793306870815341">"%1$s bidez automatikoki konektatuta"</string> <string name="connected_via_network_scorer_default" msgid="7867260222020343104">"Automatikoki konektatuta sareen balorazioen hornitzailearen bidez"</string> <string name="connected_via_passpoint" msgid="2826205693803088747">"%1$s bidez konektatuta"</string> + <!-- no translation found for ssid_by_passpoint_provider (7898171424140673315) --> + <skip /> <string name="available_via_passpoint" msgid="1617440946846329613">"%1$s bidez erabilgarri"</string> + <!-- no translation found for tap_to_set_up (2468970825530423314) --> + <skip /> <string name="wifi_connected_no_internet" msgid="8202906332837777829">"Konektatuta; ezin da atzitu Internet"</string> <string name="wifi_status_no_internet" msgid="5784710974669608361">"Ez dago Interneteko konexiorik"</string> <string name="wifi_status_sign_in_required" msgid="123517180404752756">"Saioa hasi behar da"</string> <string name="wifi_ap_unable_to_handle_new_sta" msgid="5348824313514404541">"Sarbide-puntua beteta dago aldi baterako"</string> <string name="connected_via_carrier" msgid="7583780074526041912">"%1$s bidez konektatuta"</string> <string name="available_via_carrier" msgid="1469036129740799053">"%1$s bidez erabilgarri"</string> + <!-- no translation found for osu_failure_ap_connection (598977488344424542) --> + <skip /> + <!-- no translation found for osu_failure_server_url_invalid (2237477219243136714) --> + <skip /> + <!-- no translation found for osu_failure_server_connection (8192988165059982174) --> + <skip /> + <!-- no translation found for osu_failure_server_validation (4631649978129606823) --> + <skip /> + <!-- no translation found for osu_failure_service_provider_verification (4854091521439785597) --> + <skip /> + <!-- no translation found for osu_failure_provisioning_aborted (424627208135320329) --> + <skip /> + <!-- no translation found for osu_failure_provisioning_not_available (3021783729256985432) --> + <skip /> + <!-- no translation found for osu_failure_invalid_server_url (8548886196179435758) --> + <skip /> + <!-- no translation found for osu_failure_unexpected_command_type (8245921319866603904) --> + <skip /> + <!-- no translation found for osu_failure_unexpected_soap_message_type (2255897608510053065) --> + <skip /> + <!-- no translation found for osu_failure_soap_message_exchange (4357358438685987192) --> + <skip /> + <!-- no translation found for osu_failure_start_redirect_listener (4292769407279548482) --> + <skip /> + <!-- no translation found for osu_failure_timed_out_redirect_listener (3168657820278807508) --> + <skip /> + <!-- no translation found for osu_failure_no_osu_activity_found (4593038891437878675) --> + <skip /> + <!-- no translation found for osu_failure_unexpected_soap_message_status (6568467710235256675) --> + <skip /> + <!-- no translation found for osu_failure_no_pps_mo (850567403039076835) --> + <skip /> + <!-- no translation found for osu_failure_no_aaa_server_trust_root_node (8961455873459838456) --> + <skip /> + <!-- no translation found for osu_failure_no_remediation_server_trust_root_node (5041179688081545244) --> + <skip /> + <!-- no translation found for osu_failure_no_policy_server_trust_root_node (6617290380940513539) --> + <skip /> + <!-- no translation found for osu_failure_retrieve_trust_root_certificates (1499136256195528265) --> + <skip /> + <!-- no translation found for osu_failure_no_aaa_trust_root_certificate (1904322497042226984) --> + <skip /> + <!-- no translation found for osu_failure_add_passpoint_configuration (2173557755811446047) --> + <skip /> + <!-- no translation found for osu_failure_osu_provider_not_found (6616172862116673082) --> + <skip /> + <!-- no translation found for osu_status_ap_connecting (5296821043003441437) --> + <skip /> + <!-- no translation found for osu_status_ap_connected (3777289375683170728) --> + <skip /> + <!-- no translation found for osu_status_server_connecting (8499785407540355867) --> + <skip /> + <!-- no translation found for osu_status_server_validated (3158727184762596355) --> + <skip /> + <!-- no translation found for osu_status_server_connected (8382024481520158168) --> + <skip /> + <!-- no translation found for osu_status_init_soap_exchange (8628063888912101981) --> + <skip /> + <!-- no translation found for osu_status_waiting_for_redirect_response (2343016207837053197) --> + <skip /> + <!-- no translation found for osu_status_redirect_response_received (5323368411922609405) --> + <skip /> + <!-- no translation found for osu_status_second_soap_exchange (7115332266758483909) --> + <skip /> + <!-- no translation found for osu_status_third_soap_exchange (8460901783597440766) --> + <skip /> + <!-- no translation found for osu_status_retrieving_trust_root_certs (1563445892926269689) --> + <skip /> + <!-- no translation found for osu_provisioning_complete (5120178802493970149) --> + <skip /> <string name="speed_label_very_slow" msgid="1867055264243608530">"Oso motela"</string> <string name="speed_label_slow" msgid="813109590815810235">"Motela"</string> <string name="speed_label_okay" msgid="2331665440671174858">"Ados"</string> diff --git a/packages/SettingsLib/res/values-fa/strings.xml b/packages/SettingsLib/res/values-fa/strings.xml index 57f8960b04d8..ec6200febb7e 100644 --- a/packages/SettingsLib/res/values-fa/strings.xml +++ b/packages/SettingsLib/res/values-fa/strings.xml @@ -38,13 +38,87 @@ <string name="connected_via_network_scorer" msgid="5713793306870815341">"اتصال خودکار ازطریق %1$s"</string> <string name="connected_via_network_scorer_default" msgid="7867260222020343104">"اتصال خودکار ازطریق ارائهدهنده رتبهبندی شبکه"</string> <string name="connected_via_passpoint" msgid="2826205693803088747">"متصل از طریق %1$s"</string> + <!-- no translation found for ssid_by_passpoint_provider (7898171424140673315) --> + <skip /> <string name="available_via_passpoint" msgid="1617440946846329613">"در دسترس از طریق %1$s"</string> + <!-- no translation found for tap_to_set_up (2468970825530423314) --> + <skip /> <string name="wifi_connected_no_internet" msgid="8202906332837777829">"متصل، بدون اینترنت"</string> <string name="wifi_status_no_internet" msgid="5784710974669608361">"عدم دسترسی به اینترنت"</string> <string name="wifi_status_sign_in_required" msgid="123517180404752756">"ورود به سیستم لازم است"</string> <string name="wifi_ap_unable_to_handle_new_sta" msgid="5348824313514404541">"ظرفیت نقطه دسترسی موقتاً تکمیل شده است"</string> <string name="connected_via_carrier" msgid="7583780074526041912">"متصل ازطریق %1$s"</string> <string name="available_via_carrier" msgid="1469036129740799053">"در دسترس ازطریق %1$s"</string> + <!-- no translation found for osu_failure_ap_connection (598977488344424542) --> + <skip /> + <!-- no translation found for osu_failure_server_url_invalid (2237477219243136714) --> + <skip /> + <!-- no translation found for osu_failure_server_connection (8192988165059982174) --> + <skip /> + <!-- no translation found for osu_failure_server_validation (4631649978129606823) --> + <skip /> + <!-- no translation found for osu_failure_service_provider_verification (4854091521439785597) --> + <skip /> + <!-- no translation found for osu_failure_provisioning_aborted (424627208135320329) --> + <skip /> + <!-- no translation found for osu_failure_provisioning_not_available (3021783729256985432) --> + <skip /> + <!-- no translation found for osu_failure_invalid_server_url (8548886196179435758) --> + <skip /> + <!-- no translation found for osu_failure_unexpected_command_type (8245921319866603904) --> + <skip /> + <!-- no translation found for osu_failure_unexpected_soap_message_type (2255897608510053065) --> + <skip /> + <!-- no translation found for osu_failure_soap_message_exchange (4357358438685987192) --> + <skip /> + <!-- no translation found for osu_failure_start_redirect_listener (4292769407279548482) --> + <skip /> + <!-- no translation found for osu_failure_timed_out_redirect_listener (3168657820278807508) --> + <skip /> + <!-- no translation found for osu_failure_no_osu_activity_found (4593038891437878675) --> + <skip /> + <!-- no translation found for osu_failure_unexpected_soap_message_status (6568467710235256675) --> + <skip /> + <!-- no translation found for osu_failure_no_pps_mo (850567403039076835) --> + <skip /> + <!-- no translation found for osu_failure_no_aaa_server_trust_root_node (8961455873459838456) --> + <skip /> + <!-- no translation found for osu_failure_no_remediation_server_trust_root_node (5041179688081545244) --> + <skip /> + <!-- no translation found for osu_failure_no_policy_server_trust_root_node (6617290380940513539) --> + <skip /> + <!-- no translation found for osu_failure_retrieve_trust_root_certificates (1499136256195528265) --> + <skip /> + <!-- no translation found for osu_failure_no_aaa_trust_root_certificate (1904322497042226984) --> + <skip /> + <!-- no translation found for osu_failure_add_passpoint_configuration (2173557755811446047) --> + <skip /> + <!-- no translation found for osu_failure_osu_provider_not_found (6616172862116673082) --> + <skip /> + <!-- no translation found for osu_status_ap_connecting (5296821043003441437) --> + <skip /> + <!-- no translation found for osu_status_ap_connected (3777289375683170728) --> + <skip /> + <!-- no translation found for osu_status_server_connecting (8499785407540355867) --> + <skip /> + <!-- no translation found for osu_status_server_validated (3158727184762596355) --> + <skip /> + <!-- no translation found for osu_status_server_connected (8382024481520158168) --> + <skip /> + <!-- no translation found for osu_status_init_soap_exchange (8628063888912101981) --> + <skip /> + <!-- no translation found for osu_status_waiting_for_redirect_response (2343016207837053197) --> + <skip /> + <!-- no translation found for osu_status_redirect_response_received (5323368411922609405) --> + <skip /> + <!-- no translation found for osu_status_second_soap_exchange (7115332266758483909) --> + <skip /> + <!-- no translation found for osu_status_third_soap_exchange (8460901783597440766) --> + <skip /> + <!-- no translation found for osu_status_retrieving_trust_root_certs (1563445892926269689) --> + <skip /> + <!-- no translation found for osu_provisioning_complete (5120178802493970149) --> + <skip /> <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> diff --git a/packages/SettingsLib/res/values-fi/strings.xml b/packages/SettingsLib/res/values-fi/strings.xml index 922d8d320f9d..174caef15881 100644 --- a/packages/SettingsLib/res/values-fi/strings.xml +++ b/packages/SettingsLib/res/values-fi/strings.xml @@ -38,13 +38,87 @@ <string name="connected_via_network_scorer" msgid="5713793306870815341">"Automaattinen yhteys muodostettu palvelun %1$s kautta"</string> <string name="connected_via_network_scorer_default" msgid="7867260222020343104">"Yhdistetty automaattisesti verkon arviointipalvelun kautta"</string> <string name="connected_via_passpoint" msgid="2826205693803088747">"Yhdistetty seuraavan kautta: %1$s"</string> + <!-- no translation found for ssid_by_passpoint_provider (7898171424140673315) --> + <skip /> <string name="available_via_passpoint" msgid="1617440946846329613">"Käytettävissä seuraavan kautta: %1$s"</string> + <!-- no translation found for tap_to_set_up (2468970825530423314) --> + <skip /> <string name="wifi_connected_no_internet" msgid="8202906332837777829">"Yhdistetty, ei internetyhteyttä"</string> <string name="wifi_status_no_internet" msgid="5784710974669608361">"Ei internetyhteyttä"</string> <string name="wifi_status_sign_in_required" msgid="123517180404752756">"Sisäänkirjautuminen vaaditaan"</string> <string name="wifi_ap_unable_to_handle_new_sta" msgid="5348824313514404541">"Yhteyspiste tilapäisesti täynnä"</string> <string name="connected_via_carrier" msgid="7583780074526041912">"Yhdistetty, verkko: %1$s"</string> <string name="available_via_carrier" msgid="1469036129740799053">"Käytettävissä, verkko: %1$s"</string> + <!-- no translation found for osu_failure_ap_connection (598977488344424542) --> + <skip /> + <!-- no translation found for osu_failure_server_url_invalid (2237477219243136714) --> + <skip /> + <!-- no translation found for osu_failure_server_connection (8192988165059982174) --> + <skip /> + <!-- no translation found for osu_failure_server_validation (4631649978129606823) --> + <skip /> + <!-- no translation found for osu_failure_service_provider_verification (4854091521439785597) --> + <skip /> + <!-- no translation found for osu_failure_provisioning_aborted (424627208135320329) --> + <skip /> + <!-- no translation found for osu_failure_provisioning_not_available (3021783729256985432) --> + <skip /> + <!-- no translation found for osu_failure_invalid_server_url (8548886196179435758) --> + <skip /> + <!-- no translation found for osu_failure_unexpected_command_type (8245921319866603904) --> + <skip /> + <!-- no translation found for osu_failure_unexpected_soap_message_type (2255897608510053065) --> + <skip /> + <!-- no translation found for osu_failure_soap_message_exchange (4357358438685987192) --> + <skip /> + <!-- no translation found for osu_failure_start_redirect_listener (4292769407279548482) --> + <skip /> + <!-- no translation found for osu_failure_timed_out_redirect_listener (3168657820278807508) --> + <skip /> + <!-- no translation found for osu_failure_no_osu_activity_found (4593038891437878675) --> + <skip /> + <!-- no translation found for osu_failure_unexpected_soap_message_status (6568467710235256675) --> + <skip /> + <!-- no translation found for osu_failure_no_pps_mo (850567403039076835) --> + <skip /> + <!-- no translation found for osu_failure_no_aaa_server_trust_root_node (8961455873459838456) --> + <skip /> + <!-- no translation found for osu_failure_no_remediation_server_trust_root_node (5041179688081545244) --> + <skip /> + <!-- no translation found for osu_failure_no_policy_server_trust_root_node (6617290380940513539) --> + <skip /> + <!-- no translation found for osu_failure_retrieve_trust_root_certificates (1499136256195528265) --> + <skip /> + <!-- no translation found for osu_failure_no_aaa_trust_root_certificate (1904322497042226984) --> + <skip /> + <!-- no translation found for osu_failure_add_passpoint_configuration (2173557755811446047) --> + <skip /> + <!-- no translation found for osu_failure_osu_provider_not_found (6616172862116673082) --> + <skip /> + <!-- no translation found for osu_status_ap_connecting (5296821043003441437) --> + <skip /> + <!-- no translation found for osu_status_ap_connected (3777289375683170728) --> + <skip /> + <!-- no translation found for osu_status_server_connecting (8499785407540355867) --> + <skip /> + <!-- no translation found for osu_status_server_validated (3158727184762596355) --> + <skip /> + <!-- no translation found for osu_status_server_connected (8382024481520158168) --> + <skip /> + <!-- no translation found for osu_status_init_soap_exchange (8628063888912101981) --> + <skip /> + <!-- no translation found for osu_status_waiting_for_redirect_response (2343016207837053197) --> + <skip /> + <!-- no translation found for osu_status_redirect_response_received (5323368411922609405) --> + <skip /> + <!-- no translation found for osu_status_second_soap_exchange (7115332266758483909) --> + <skip /> + <!-- no translation found for osu_status_third_soap_exchange (8460901783597440766) --> + <skip /> + <!-- no translation found for osu_status_retrieving_trust_root_certs (1563445892926269689) --> + <skip /> + <!-- no translation found for osu_provisioning_complete (5120178802493970149) --> + <skip /> <string name="speed_label_very_slow" msgid="1867055264243608530">"Hyvin hidas"</string> <string name="speed_label_slow" msgid="813109590815810235">"Hidas"</string> <string name="speed_label_okay" msgid="2331665440671174858">"OK"</string> diff --git a/packages/SettingsLib/res/values-fr-rCA/strings.xml b/packages/SettingsLib/res/values-fr-rCA/strings.xml index 765a80f77b3c..f189d7700278 100644 --- a/packages/SettingsLib/res/values-fr-rCA/strings.xml +++ b/packages/SettingsLib/res/values-fr-rCA/strings.xml @@ -38,13 +38,87 @@ <string name="connected_via_network_scorer" msgid="5713793306870815341">"Automatiquement connecté par %1$s"</string> <string name="connected_via_network_scorer_default" msgid="7867260222020343104">"Connecté automatiquement par le fournisseur d\'avis sur le réseau"</string> <string name="connected_via_passpoint" msgid="2826205693803088747">"Connecté par %1$s"</string> + <!-- no translation found for ssid_by_passpoint_provider (7898171424140673315) --> + <skip /> <string name="available_via_passpoint" msgid="1617440946846329613">"Accessible par %1$s"</string> + <!-- no translation found for tap_to_set_up (2468970825530423314) --> + <skip /> <string name="wifi_connected_no_internet" msgid="8202906332837777829">"Connecté, aucun accès à Internet"</string> <string name="wifi_status_no_internet" msgid="5784710974669608361">"Aucune connexion Internet"</string> <string name="wifi_status_sign_in_required" msgid="123517180404752756">"Connexion requise"</string> <string name="wifi_ap_unable_to_handle_new_sta" msgid="5348824313514404541">"Le point d\'accès est temporairement plein"</string> <string name="connected_via_carrier" msgid="7583780074526041912">"Connecté par %1$s"</string> <string name="available_via_carrier" msgid="1469036129740799053">"Accessible par %1$s"</string> + <!-- no translation found for osu_failure_ap_connection (598977488344424542) --> + <skip /> + <!-- no translation found for osu_failure_server_url_invalid (2237477219243136714) --> + <skip /> + <!-- no translation found for osu_failure_server_connection (8192988165059982174) --> + <skip /> + <!-- no translation found for osu_failure_server_validation (4631649978129606823) --> + <skip /> + <!-- no translation found for osu_failure_service_provider_verification (4854091521439785597) --> + <skip /> + <!-- no translation found for osu_failure_provisioning_aborted (424627208135320329) --> + <skip /> + <!-- no translation found for osu_failure_provisioning_not_available (3021783729256985432) --> + <skip /> + <!-- no translation found for osu_failure_invalid_server_url (8548886196179435758) --> + <skip /> + <!-- no translation found for osu_failure_unexpected_command_type (8245921319866603904) --> + <skip /> + <!-- no translation found for osu_failure_unexpected_soap_message_type (2255897608510053065) --> + <skip /> + <!-- no translation found for osu_failure_soap_message_exchange (4357358438685987192) --> + <skip /> + <!-- no translation found for osu_failure_start_redirect_listener (4292769407279548482) --> + <skip /> + <!-- no translation found for osu_failure_timed_out_redirect_listener (3168657820278807508) --> + <skip /> + <!-- no translation found for osu_failure_no_osu_activity_found (4593038891437878675) --> + <skip /> + <!-- no translation found for osu_failure_unexpected_soap_message_status (6568467710235256675) --> + <skip /> + <!-- no translation found for osu_failure_no_pps_mo (850567403039076835) --> + <skip /> + <!-- no translation found for osu_failure_no_aaa_server_trust_root_node (8961455873459838456) --> + <skip /> + <!-- no translation found for osu_failure_no_remediation_server_trust_root_node (5041179688081545244) --> + <skip /> + <!-- no translation found for osu_failure_no_policy_server_trust_root_node (6617290380940513539) --> + <skip /> + <!-- no translation found for osu_failure_retrieve_trust_root_certificates (1499136256195528265) --> + <skip /> + <!-- no translation found for osu_failure_no_aaa_trust_root_certificate (1904322497042226984) --> + <skip /> + <!-- no translation found for osu_failure_add_passpoint_configuration (2173557755811446047) --> + <skip /> + <!-- no translation found for osu_failure_osu_provider_not_found (6616172862116673082) --> + <skip /> + <!-- no translation found for osu_status_ap_connecting (5296821043003441437) --> + <skip /> + <!-- no translation found for osu_status_ap_connected (3777289375683170728) --> + <skip /> + <!-- no translation found for osu_status_server_connecting (8499785407540355867) --> + <skip /> + <!-- no translation found for osu_status_server_validated (3158727184762596355) --> + <skip /> + <!-- no translation found for osu_status_server_connected (8382024481520158168) --> + <skip /> + <!-- no translation found for osu_status_init_soap_exchange (8628063888912101981) --> + <skip /> + <!-- no translation found for osu_status_waiting_for_redirect_response (2343016207837053197) --> + <skip /> + <!-- no translation found for osu_status_redirect_response_received (5323368411922609405) --> + <skip /> + <!-- no translation found for osu_status_second_soap_exchange (7115332266758483909) --> + <skip /> + <!-- no translation found for osu_status_third_soap_exchange (8460901783597440766) --> + <skip /> + <!-- no translation found for osu_status_retrieving_trust_root_certs (1563445892926269689) --> + <skip /> + <!-- no translation found for osu_provisioning_complete (5120178802493970149) --> + <skip /> <string name="speed_label_very_slow" msgid="1867055264243608530">"Très lente"</string> <string name="speed_label_slow" msgid="813109590815810235">"Lente"</string> <string name="speed_label_okay" msgid="2331665440671174858">"OK"</string> diff --git a/packages/SettingsLib/res/values-fr/strings.xml b/packages/SettingsLib/res/values-fr/strings.xml index 198b92278072..97cc5aa02258 100644 --- a/packages/SettingsLib/res/values-fr/strings.xml +++ b/packages/SettingsLib/res/values-fr/strings.xml @@ -38,13 +38,87 @@ <string name="connected_via_network_scorer" msgid="5713793306870815341">"Connecté automatiquement via %1$s"</string> <string name="connected_via_network_scorer_default" msgid="7867260222020343104">"Connecté automatiquement via un fournisseur d\'évaluation de l\'état du réseau"</string> <string name="connected_via_passpoint" msgid="2826205693803088747">"Connecté via %1$s"</string> + <!-- no translation found for ssid_by_passpoint_provider (7898171424140673315) --> + <skip /> <string name="available_via_passpoint" msgid="1617440946846329613">"Disponible via %1$s"</string> + <!-- no translation found for tap_to_set_up (2468970825530423314) --> + <skip /> <string name="wifi_connected_no_internet" msgid="8202906332837777829">"Connecté, aucun accès à Internet"</string> <string name="wifi_status_no_internet" msgid="5784710974669608361">"Aucun accès à Internet"</string> <string name="wifi_status_sign_in_required" msgid="123517180404752756">"Connexion requise"</string> <string name="wifi_ap_unable_to_handle_new_sta" msgid="5348824313514404541">"Point d\'accès temporairement plein"</string> <string name="connected_via_carrier" msgid="7583780074526041912">"Connecté via %1$s"</string> <string name="available_via_carrier" msgid="1469036129740799053">"Disponible via %1$s"</string> + <!-- no translation found for osu_failure_ap_connection (598977488344424542) --> + <skip /> + <!-- no translation found for osu_failure_server_url_invalid (2237477219243136714) --> + <skip /> + <!-- no translation found for osu_failure_server_connection (8192988165059982174) --> + <skip /> + <!-- no translation found for osu_failure_server_validation (4631649978129606823) --> + <skip /> + <!-- no translation found for osu_failure_service_provider_verification (4854091521439785597) --> + <skip /> + <!-- no translation found for osu_failure_provisioning_aborted (424627208135320329) --> + <skip /> + <!-- no translation found for osu_failure_provisioning_not_available (3021783729256985432) --> + <skip /> + <!-- no translation found for osu_failure_invalid_server_url (8548886196179435758) --> + <skip /> + <!-- no translation found for osu_failure_unexpected_command_type (8245921319866603904) --> + <skip /> + <!-- no translation found for osu_failure_unexpected_soap_message_type (2255897608510053065) --> + <skip /> + <!-- no translation found for osu_failure_soap_message_exchange (4357358438685987192) --> + <skip /> + <!-- no translation found for osu_failure_start_redirect_listener (4292769407279548482) --> + <skip /> + <!-- no translation found for osu_failure_timed_out_redirect_listener (3168657820278807508) --> + <skip /> + <!-- no translation found for osu_failure_no_osu_activity_found (4593038891437878675) --> + <skip /> + <!-- no translation found for osu_failure_unexpected_soap_message_status (6568467710235256675) --> + <skip /> + <!-- no translation found for osu_failure_no_pps_mo (850567403039076835) --> + <skip /> + <!-- no translation found for osu_failure_no_aaa_server_trust_root_node (8961455873459838456) --> + <skip /> + <!-- no translation found for osu_failure_no_remediation_server_trust_root_node (5041179688081545244) --> + <skip /> + <!-- no translation found for osu_failure_no_policy_server_trust_root_node (6617290380940513539) --> + <skip /> + <!-- no translation found for osu_failure_retrieve_trust_root_certificates (1499136256195528265) --> + <skip /> + <!-- no translation found for osu_failure_no_aaa_trust_root_certificate (1904322497042226984) --> + <skip /> + <!-- no translation found for osu_failure_add_passpoint_configuration (2173557755811446047) --> + <skip /> + <!-- no translation found for osu_failure_osu_provider_not_found (6616172862116673082) --> + <skip /> + <!-- no translation found for osu_status_ap_connecting (5296821043003441437) --> + <skip /> + <!-- no translation found for osu_status_ap_connected (3777289375683170728) --> + <skip /> + <!-- no translation found for osu_status_server_connecting (8499785407540355867) --> + <skip /> + <!-- no translation found for osu_status_server_validated (3158727184762596355) --> + <skip /> + <!-- no translation found for osu_status_server_connected (8382024481520158168) --> + <skip /> + <!-- no translation found for osu_status_init_soap_exchange (8628063888912101981) --> + <skip /> + <!-- no translation found for osu_status_waiting_for_redirect_response (2343016207837053197) --> + <skip /> + <!-- no translation found for osu_status_redirect_response_received (5323368411922609405) --> + <skip /> + <!-- no translation found for osu_status_second_soap_exchange (7115332266758483909) --> + <skip /> + <!-- no translation found for osu_status_third_soap_exchange (8460901783597440766) --> + <skip /> + <!-- no translation found for osu_status_retrieving_trust_root_certs (1563445892926269689) --> + <skip /> + <!-- no translation found for osu_provisioning_complete (5120178802493970149) --> + <skip /> <string name="speed_label_very_slow" msgid="1867055264243608530">"Très lente"</string> <string name="speed_label_slow" msgid="813109590815810235">"Lente"</string> <string name="speed_label_okay" msgid="2331665440671174858">"Correct"</string> @@ -372,10 +446,10 @@ <string name="power_remaining_duration_only_enhanced" msgid="4189311599812296592">"Temps restant en fonction de votre utilisation : environ <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string> <string name="power_discharging_duration_enhanced" msgid="1992003260664804080">"Temps restant en fonction de votre utilisation (<xliff:g id="LEVEL">%2$s</xliff:g>) : environ <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string> <string name="power_remaining_duration_only_short" msgid="3463575350656389957">"Temps restant : <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string> - <string name="power_discharge_by_enhanced" msgid="2095821536747992464">"Temps restant estimé en fonction de votre utilisation : <xliff:g id="TIME">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string> - <string name="power_discharge_by_only_enhanced" msgid="2175151772952365149">"Temps restant estimé en fonction de votre utilisation : <xliff:g id="TIME">%1$s</xliff:g>"</string> - <string name="power_discharge_by" msgid="6453537733650125582">"Temps restant estimé : <xliff:g id="TIME">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string> - <string name="power_discharge_by_only" msgid="107616694963545745">"Temps restant estimé : <xliff:g id="TIME">%1$s</xliff:g>"</string> + <string name="power_discharge_by_enhanced" msgid="2095821536747992464">"Devrait durer jusqu\'à environ <xliff:g id="TIME">%1$s</xliff:g> en fonction de votre utilisation (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string> + <string name="power_discharge_by_only_enhanced" msgid="2175151772952365149">"Devrait durer jusqu\'à environ <xliff:g id="TIME">%1$s</xliff:g> en fonction de votre utilisation"</string> + <string name="power_discharge_by" msgid="6453537733650125582">"Devrait durer jusqu\'à environ <xliff:g id="TIME">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string> + <string name="power_discharge_by_only" msgid="107616694963545745">"Devrait durer jusqu\'à environ <xliff:g id="TIME">%1$s</xliff:g>"</string> <string name="power_discharge_by_only_short" msgid="1372817269546888804">"Jusqu\'à <xliff:g id="TIME">%1$s</xliff:g>"</string> <string name="power_remaining_less_than_duration_only" msgid="5996752448813295329">"Il reste moins de <xliff:g id="THRESHOLD">%1$s</xliff:g>"</string> <string name="power_remaining_less_than_duration" msgid="5751885147712659423">"Il reste moins de <xliff:g id="THRESHOLD">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string> diff --git a/packages/SettingsLib/res/values-gl/strings.xml b/packages/SettingsLib/res/values-gl/strings.xml index de5e7e415059..fb63a9d39c37 100644 --- a/packages/SettingsLib/res/values-gl/strings.xml +++ b/packages/SettingsLib/res/values-gl/strings.xml @@ -38,13 +38,87 @@ <string name="connected_via_network_scorer" msgid="5713793306870815341">"Conectouse automaticamente a través de %1$s"</string> <string name="connected_via_network_scorer_default" msgid="7867260222020343104">"Conectada automaticamente a través dun provedor de valoración de rede"</string> <string name="connected_via_passpoint" msgid="2826205693803088747">"Conectado a través de %1$s"</string> + <!-- no translation found for ssid_by_passpoint_provider (7898171424140673315) --> + <skip /> <string name="available_via_passpoint" msgid="1617440946846329613">"Dispoñible a través de %1$s"</string> + <!-- no translation found for tap_to_set_up (2468970825530423314) --> + <skip /> <string name="wifi_connected_no_internet" msgid="8202906332837777829">"Conexión sen Internet"</string> <string name="wifi_status_no_internet" msgid="5784710974669608361">"Non hai conexión a Internet"</string> <string name="wifi_status_sign_in_required" msgid="123517180404752756">"É obrigatorio iniciar sesión"</string> <string name="wifi_ap_unable_to_handle_new_sta" msgid="5348824313514404541">"O punto de acceso está temporalmente cheo"</string> <string name="connected_via_carrier" msgid="7583780074526041912">"Conectado a través de %1$s"</string> <string name="available_via_carrier" msgid="1469036129740799053">"Dispoñible a través de %1$s"</string> + <!-- no translation found for osu_failure_ap_connection (598977488344424542) --> + <skip /> + <!-- no translation found for osu_failure_server_url_invalid (2237477219243136714) --> + <skip /> + <!-- no translation found for osu_failure_server_connection (8192988165059982174) --> + <skip /> + <!-- no translation found for osu_failure_server_validation (4631649978129606823) --> + <skip /> + <!-- no translation found for osu_failure_service_provider_verification (4854091521439785597) --> + <skip /> + <!-- no translation found for osu_failure_provisioning_aborted (424627208135320329) --> + <skip /> + <!-- no translation found for osu_failure_provisioning_not_available (3021783729256985432) --> + <skip /> + <!-- no translation found for osu_failure_invalid_server_url (8548886196179435758) --> + <skip /> + <!-- no translation found for osu_failure_unexpected_command_type (8245921319866603904) --> + <skip /> + <!-- no translation found for osu_failure_unexpected_soap_message_type (2255897608510053065) --> + <skip /> + <!-- no translation found for osu_failure_soap_message_exchange (4357358438685987192) --> + <skip /> + <!-- no translation found for osu_failure_start_redirect_listener (4292769407279548482) --> + <skip /> + <!-- no translation found for osu_failure_timed_out_redirect_listener (3168657820278807508) --> + <skip /> + <!-- no translation found for osu_failure_no_osu_activity_found (4593038891437878675) --> + <skip /> + <!-- no translation found for osu_failure_unexpected_soap_message_status (6568467710235256675) --> + <skip /> + <!-- no translation found for osu_failure_no_pps_mo (850567403039076835) --> + <skip /> + <!-- no translation found for osu_failure_no_aaa_server_trust_root_node (8961455873459838456) --> + <skip /> + <!-- no translation found for osu_failure_no_remediation_server_trust_root_node (5041179688081545244) --> + <skip /> + <!-- no translation found for osu_failure_no_policy_server_trust_root_node (6617290380940513539) --> + <skip /> + <!-- no translation found for osu_failure_retrieve_trust_root_certificates (1499136256195528265) --> + <skip /> + <!-- no translation found for osu_failure_no_aaa_trust_root_certificate (1904322497042226984) --> + <skip /> + <!-- no translation found for osu_failure_add_passpoint_configuration (2173557755811446047) --> + <skip /> + <!-- no translation found for osu_failure_osu_provider_not_found (6616172862116673082) --> + <skip /> + <!-- no translation found for osu_status_ap_connecting (5296821043003441437) --> + <skip /> + <!-- no translation found for osu_status_ap_connected (3777289375683170728) --> + <skip /> + <!-- no translation found for osu_status_server_connecting (8499785407540355867) --> + <skip /> + <!-- no translation found for osu_status_server_validated (3158727184762596355) --> + <skip /> + <!-- no translation found for osu_status_server_connected (8382024481520158168) --> + <skip /> + <!-- no translation found for osu_status_init_soap_exchange (8628063888912101981) --> + <skip /> + <!-- no translation found for osu_status_waiting_for_redirect_response (2343016207837053197) --> + <skip /> + <!-- no translation found for osu_status_redirect_response_received (5323368411922609405) --> + <skip /> + <!-- no translation found for osu_status_second_soap_exchange (7115332266758483909) --> + <skip /> + <!-- no translation found for osu_status_third_soap_exchange (8460901783597440766) --> + <skip /> + <!-- no translation found for osu_status_retrieving_trust_root_certs (1563445892926269689) --> + <skip /> + <!-- no translation found for osu_provisioning_complete (5120178802493970149) --> + <skip /> <string name="speed_label_very_slow" msgid="1867055264243608530">"Moi lenta"</string> <string name="speed_label_slow" msgid="813109590815810235">"Lenta"</string> <string name="speed_label_okay" msgid="2331665440671174858">"Aceptar"</string> diff --git a/packages/SettingsLib/res/values-gu/strings.xml b/packages/SettingsLib/res/values-gu/strings.xml index 993eed1bef32..54fa7d1aad04 100644 --- a/packages/SettingsLib/res/values-gu/strings.xml +++ b/packages/SettingsLib/res/values-gu/strings.xml @@ -38,13 +38,87 @@ <string name="connected_via_network_scorer" msgid="5713793306870815341">"%1$s દ્વારા સ્વત: કનેક્ટ થયેલ"</string> <string name="connected_via_network_scorer_default" msgid="7867260222020343104">"નેટવર્ક રેટિંગ પ્રદાતા દ્વારા આપમેળે કનેક્ટ થયું"</string> <string name="connected_via_passpoint" msgid="2826205693803088747">"%1$s દ્વારા કનેક્ટ થયેલ"</string> + <!-- no translation found for ssid_by_passpoint_provider (7898171424140673315) --> + <skip /> <string name="available_via_passpoint" msgid="1617440946846329613">"%1$s દ્વારા ઉપલબ્ધ"</string> + <!-- no translation found for tap_to_set_up (2468970825530423314) --> + <skip /> <string name="wifi_connected_no_internet" msgid="8202906332837777829">"કનેક્ટ કર્યું, કોઈ ઇન્ટરનેટ નથી"</string> <string name="wifi_status_no_internet" msgid="5784710974669608361">"ઇન્ટરનેટ ઍક્સેસ નથી"</string> <string name="wifi_status_sign_in_required" msgid="123517180404752756">"સાઇન ઇન આવશ્યક"</string> <string name="wifi_ap_unable_to_handle_new_sta" msgid="5348824313514404541">"ઍક્સેસ પૉઇન્ટ અસ્થાયીરૂપે ભરાયેલ છે"</string> <string name="connected_via_carrier" msgid="7583780074526041912">"%1$s દ્વારા કનેક્ટ થયેલ"</string> <string name="available_via_carrier" msgid="1469036129740799053">"%1$s દ્વારા ઉપલબ્ધ"</string> + <!-- no translation found for osu_failure_ap_connection (598977488344424542) --> + <skip /> + <!-- no translation found for osu_failure_server_url_invalid (2237477219243136714) --> + <skip /> + <!-- no translation found for osu_failure_server_connection (8192988165059982174) --> + <skip /> + <!-- no translation found for osu_failure_server_validation (4631649978129606823) --> + <skip /> + <!-- no translation found for osu_failure_service_provider_verification (4854091521439785597) --> + <skip /> + <!-- no translation found for osu_failure_provisioning_aborted (424627208135320329) --> + <skip /> + <!-- no translation found for osu_failure_provisioning_not_available (3021783729256985432) --> + <skip /> + <!-- no translation found for osu_failure_invalid_server_url (8548886196179435758) --> + <skip /> + <!-- no translation found for osu_failure_unexpected_command_type (8245921319866603904) --> + <skip /> + <!-- no translation found for osu_failure_unexpected_soap_message_type (2255897608510053065) --> + <skip /> + <!-- no translation found for osu_failure_soap_message_exchange (4357358438685987192) --> + <skip /> + <!-- no translation found for osu_failure_start_redirect_listener (4292769407279548482) --> + <skip /> + <!-- no translation found for osu_failure_timed_out_redirect_listener (3168657820278807508) --> + <skip /> + <!-- no translation found for osu_failure_no_osu_activity_found (4593038891437878675) --> + <skip /> + <!-- no translation found for osu_failure_unexpected_soap_message_status (6568467710235256675) --> + <skip /> + <!-- no translation found for osu_failure_no_pps_mo (850567403039076835) --> + <skip /> + <!-- no translation found for osu_failure_no_aaa_server_trust_root_node (8961455873459838456) --> + <skip /> + <!-- no translation found for osu_failure_no_remediation_server_trust_root_node (5041179688081545244) --> + <skip /> + <!-- no translation found for osu_failure_no_policy_server_trust_root_node (6617290380940513539) --> + <skip /> + <!-- no translation found for osu_failure_retrieve_trust_root_certificates (1499136256195528265) --> + <skip /> + <!-- no translation found for osu_failure_no_aaa_trust_root_certificate (1904322497042226984) --> + <skip /> + <!-- no translation found for osu_failure_add_passpoint_configuration (2173557755811446047) --> + <skip /> + <!-- no translation found for osu_failure_osu_provider_not_found (6616172862116673082) --> + <skip /> + <!-- no translation found for osu_status_ap_connecting (5296821043003441437) --> + <skip /> + <!-- no translation found for osu_status_ap_connected (3777289375683170728) --> + <skip /> + <!-- no translation found for osu_status_server_connecting (8499785407540355867) --> + <skip /> + <!-- no translation found for osu_status_server_validated (3158727184762596355) --> + <skip /> + <!-- no translation found for osu_status_server_connected (8382024481520158168) --> + <skip /> + <!-- no translation found for osu_status_init_soap_exchange (8628063888912101981) --> + <skip /> + <!-- no translation found for osu_status_waiting_for_redirect_response (2343016207837053197) --> + <skip /> + <!-- no translation found for osu_status_redirect_response_received (5323368411922609405) --> + <skip /> + <!-- no translation found for osu_status_second_soap_exchange (7115332266758483909) --> + <skip /> + <!-- no translation found for osu_status_third_soap_exchange (8460901783597440766) --> + <skip /> + <!-- no translation found for osu_status_retrieving_trust_root_certs (1563445892926269689) --> + <skip /> + <!-- no translation found for osu_provisioning_complete (5120178802493970149) --> + <skip /> <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> diff --git a/packages/SettingsLib/res/values-hi/strings.xml b/packages/SettingsLib/res/values-hi/strings.xml index faf551eedca7..0aba3f6a3b9e 100644 --- a/packages/SettingsLib/res/values-hi/strings.xml +++ b/packages/SettingsLib/res/values-hi/strings.xml @@ -38,13 +38,87 @@ <string name="connected_via_network_scorer" msgid="5713793306870815341">"%1$s के ज़रिए ऑटोमैटिक रूप से कनेक्ट है"</string> <string name="connected_via_network_scorer_default" msgid="7867260222020343104">"नेटवर्क रेटिंग प्रदाता के ज़रिए अपने आप कनेक्ट है"</string> <string name="connected_via_passpoint" msgid="2826205693803088747">"%1$s के द्वारा उपलब्ध"</string> + <!-- no translation found for ssid_by_passpoint_provider (7898171424140673315) --> + <skip /> <string name="available_via_passpoint" msgid="1617440946846329613">"%1$s के द्वारा उपलब्ध"</string> + <!-- no translation found for tap_to_set_up (2468970825530423314) --> + <skip /> <string name="wifi_connected_no_internet" msgid="8202906332837777829">"कनेक्ट हो गया है, लेकिन इंटरनेट नहीं है"</string> <string name="wifi_status_no_internet" msgid="5784710974669608361">"इंटरनेट कनेक्शन नहीं है"</string> <string name="wifi_status_sign_in_required" msgid="123517180404752756">"साइन इन करना ज़रूरी है"</string> <string name="wifi_ap_unable_to_handle_new_sta" msgid="5348824313514404541">"एक्सेस प्वाइंट फ़िलहाल भरा हुआ है"</string> <string name="connected_via_carrier" msgid="7583780074526041912">"%1$s के ज़रिए कनेक्ट"</string> <string name="available_via_carrier" msgid="1469036129740799053">"%1$s के ज़रिए उपलब्ध"</string> + <!-- no translation found for osu_failure_ap_connection (598977488344424542) --> + <skip /> + <!-- no translation found for osu_failure_server_url_invalid (2237477219243136714) --> + <skip /> + <!-- no translation found for osu_failure_server_connection (8192988165059982174) --> + <skip /> + <!-- no translation found for osu_failure_server_validation (4631649978129606823) --> + <skip /> + <!-- no translation found for osu_failure_service_provider_verification (4854091521439785597) --> + <skip /> + <!-- no translation found for osu_failure_provisioning_aborted (424627208135320329) --> + <skip /> + <!-- no translation found for osu_failure_provisioning_not_available (3021783729256985432) --> + <skip /> + <!-- no translation found for osu_failure_invalid_server_url (8548886196179435758) --> + <skip /> + <!-- no translation found for osu_failure_unexpected_command_type (8245921319866603904) --> + <skip /> + <!-- no translation found for osu_failure_unexpected_soap_message_type (2255897608510053065) --> + <skip /> + <!-- no translation found for osu_failure_soap_message_exchange (4357358438685987192) --> + <skip /> + <!-- no translation found for osu_failure_start_redirect_listener (4292769407279548482) --> + <skip /> + <!-- no translation found for osu_failure_timed_out_redirect_listener (3168657820278807508) --> + <skip /> + <!-- no translation found for osu_failure_no_osu_activity_found (4593038891437878675) --> + <skip /> + <!-- no translation found for osu_failure_unexpected_soap_message_status (6568467710235256675) --> + <skip /> + <!-- no translation found for osu_failure_no_pps_mo (850567403039076835) --> + <skip /> + <!-- no translation found for osu_failure_no_aaa_server_trust_root_node (8961455873459838456) --> + <skip /> + <!-- no translation found for osu_failure_no_remediation_server_trust_root_node (5041179688081545244) --> + <skip /> + <!-- no translation found for osu_failure_no_policy_server_trust_root_node (6617290380940513539) --> + <skip /> + <!-- no translation found for osu_failure_retrieve_trust_root_certificates (1499136256195528265) --> + <skip /> + <!-- no translation found for osu_failure_no_aaa_trust_root_certificate (1904322497042226984) --> + <skip /> + <!-- no translation found for osu_failure_add_passpoint_configuration (2173557755811446047) --> + <skip /> + <!-- no translation found for osu_failure_osu_provider_not_found (6616172862116673082) --> + <skip /> + <!-- no translation found for osu_status_ap_connecting (5296821043003441437) --> + <skip /> + <!-- no translation found for osu_status_ap_connected (3777289375683170728) --> + <skip /> + <!-- no translation found for osu_status_server_connecting (8499785407540355867) --> + <skip /> + <!-- no translation found for osu_status_server_validated (3158727184762596355) --> + <skip /> + <!-- no translation found for osu_status_server_connected (8382024481520158168) --> + <skip /> + <!-- no translation found for osu_status_init_soap_exchange (8628063888912101981) --> + <skip /> + <!-- no translation found for osu_status_waiting_for_redirect_response (2343016207837053197) --> + <skip /> + <!-- no translation found for osu_status_redirect_response_received (5323368411922609405) --> + <skip /> + <!-- no translation found for osu_status_second_soap_exchange (7115332266758483909) --> + <skip /> + <!-- no translation found for osu_status_third_soap_exchange (8460901783597440766) --> + <skip /> + <!-- no translation found for osu_status_retrieving_trust_root_certs (1563445892926269689) --> + <skip /> + <!-- no translation found for osu_provisioning_complete (5120178802493970149) --> + <skip /> <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> diff --git a/packages/SettingsLib/res/values-hr/strings.xml b/packages/SettingsLib/res/values-hr/strings.xml index 5f04b656f625..5a48ffd2c74a 100644 --- a/packages/SettingsLib/res/values-hr/strings.xml +++ b/packages/SettingsLib/res/values-hr/strings.xml @@ -38,13 +38,87 @@ <string name="connected_via_network_scorer" msgid="5713793306870815341">"Automatski povezan putem %1$s"</string> <string name="connected_via_network_scorer_default" msgid="7867260222020343104">"Automatski povezan putem ocjenjivača mreže"</string> <string name="connected_via_passpoint" msgid="2826205693803088747">"Povezano putem %1$s"</string> + <!-- no translation found for ssid_by_passpoint_provider (7898171424140673315) --> + <skip /> <string name="available_via_passpoint" msgid="1617440946846329613">"Dostupno putem %1$s"</string> + <!-- no translation found for tap_to_set_up (2468970825530423314) --> + <skip /> <string name="wifi_connected_no_internet" msgid="8202906332837777829">"Povezano, bez interneta"</string> <string name="wifi_status_no_internet" msgid="5784710974669608361">"Nema interneta"</string> <string name="wifi_status_sign_in_required" msgid="123517180404752756">"Obavezna prijava"</string> <string name="wifi_ap_unable_to_handle_new_sta" msgid="5348824313514404541">"Pristupna je točka privremeno puna"</string> <string name="connected_via_carrier" msgid="7583780074526041912">"Povezano putem mreže %1$s"</string> <string name="available_via_carrier" msgid="1469036129740799053">"Dostupno putem mreže %1$s"</string> + <!-- no translation found for osu_failure_ap_connection (598977488344424542) --> + <skip /> + <!-- no translation found for osu_failure_server_url_invalid (2237477219243136714) --> + <skip /> + <!-- no translation found for osu_failure_server_connection (8192988165059982174) --> + <skip /> + <!-- no translation found for osu_failure_server_validation (4631649978129606823) --> + <skip /> + <!-- no translation found for osu_failure_service_provider_verification (4854091521439785597) --> + <skip /> + <!-- no translation found for osu_failure_provisioning_aborted (424627208135320329) --> + <skip /> + <!-- no translation found for osu_failure_provisioning_not_available (3021783729256985432) --> + <skip /> + <!-- no translation found for osu_failure_invalid_server_url (8548886196179435758) --> + <skip /> + <!-- no translation found for osu_failure_unexpected_command_type (8245921319866603904) --> + <skip /> + <!-- no translation found for osu_failure_unexpected_soap_message_type (2255897608510053065) --> + <skip /> + <!-- no translation found for osu_failure_soap_message_exchange (4357358438685987192) --> + <skip /> + <!-- no translation found for osu_failure_start_redirect_listener (4292769407279548482) --> + <skip /> + <!-- no translation found for osu_failure_timed_out_redirect_listener (3168657820278807508) --> + <skip /> + <!-- no translation found for osu_failure_no_osu_activity_found (4593038891437878675) --> + <skip /> + <!-- no translation found for osu_failure_unexpected_soap_message_status (6568467710235256675) --> + <skip /> + <!-- no translation found for osu_failure_no_pps_mo (850567403039076835) --> + <skip /> + <!-- no translation found for osu_failure_no_aaa_server_trust_root_node (8961455873459838456) --> + <skip /> + <!-- no translation found for osu_failure_no_remediation_server_trust_root_node (5041179688081545244) --> + <skip /> + <!-- no translation found for osu_failure_no_policy_server_trust_root_node (6617290380940513539) --> + <skip /> + <!-- no translation found for osu_failure_retrieve_trust_root_certificates (1499136256195528265) --> + <skip /> + <!-- no translation found for osu_failure_no_aaa_trust_root_certificate (1904322497042226984) --> + <skip /> + <!-- no translation found for osu_failure_add_passpoint_configuration (2173557755811446047) --> + <skip /> + <!-- no translation found for osu_failure_osu_provider_not_found (6616172862116673082) --> + <skip /> + <!-- no translation found for osu_status_ap_connecting (5296821043003441437) --> + <skip /> + <!-- no translation found for osu_status_ap_connected (3777289375683170728) --> + <skip /> + <!-- no translation found for osu_status_server_connecting (8499785407540355867) --> + <skip /> + <!-- no translation found for osu_status_server_validated (3158727184762596355) --> + <skip /> + <!-- no translation found for osu_status_server_connected (8382024481520158168) --> + <skip /> + <!-- no translation found for osu_status_init_soap_exchange (8628063888912101981) --> + <skip /> + <!-- no translation found for osu_status_waiting_for_redirect_response (2343016207837053197) --> + <skip /> + <!-- no translation found for osu_status_redirect_response_received (5323368411922609405) --> + <skip /> + <!-- no translation found for osu_status_second_soap_exchange (7115332266758483909) --> + <skip /> + <!-- no translation found for osu_status_third_soap_exchange (8460901783597440766) --> + <skip /> + <!-- no translation found for osu_status_retrieving_trust_root_certs (1563445892926269689) --> + <skip /> + <!-- no translation found for osu_provisioning_complete (5120178802493970149) --> + <skip /> <string name="speed_label_very_slow" msgid="1867055264243608530">"Vrlo sporo"</string> <string name="speed_label_slow" msgid="813109590815810235">"Sporo"</string> <string name="speed_label_okay" msgid="2331665440671174858">"U redu"</string> diff --git a/packages/SettingsLib/res/values-hu/strings.xml b/packages/SettingsLib/res/values-hu/strings.xml index 7469c1a86080..1fa7f6a7f56c 100644 --- a/packages/SettingsLib/res/values-hu/strings.xml +++ b/packages/SettingsLib/res/values-hu/strings.xml @@ -38,13 +38,87 @@ <string name="connected_via_network_scorer" msgid="5713793306870815341">"Automatikusan csatlakozott a következőn keresztül: %1$s"</string> <string name="connected_via_network_scorer_default" msgid="7867260222020343104">"Automatikusan csatlakozott a hálózatértékelés szolgáltatóján keresztül"</string> <string name="connected_via_passpoint" msgid="2826205693803088747">"Csatlakozva a következőn keresztül: %1$s"</string> + <!-- no translation found for ssid_by_passpoint_provider (7898171424140673315) --> + <skip /> <string name="available_via_passpoint" msgid="1617440946846329613">"Elérhető a következőn keresztül: %1$s"</string> + <!-- no translation found for tap_to_set_up (2468970825530423314) --> + <skip /> <string name="wifi_connected_no_internet" msgid="8202906332837777829">"Csatlakozva, nincs internet-hozzáférés"</string> <string name="wifi_status_no_internet" msgid="5784710974669608361">"Nincs internetkapcsolat"</string> <string name="wifi_status_sign_in_required" msgid="123517180404752756">"Bejelentkezést igényel"</string> <string name="wifi_ap_unable_to_handle_new_sta" msgid="5348824313514404541">"A hozzáférési pont átmenetileg megtelt"</string> <string name="connected_via_carrier" msgid="7583780074526041912">"Csatlakozva a következőn keresztül: %1$s"</string> <string name="available_via_carrier" msgid="1469036129740799053">"Elérhető a következőn keresztül: %1$s"</string> + <!-- no translation found for osu_failure_ap_connection (598977488344424542) --> + <skip /> + <!-- no translation found for osu_failure_server_url_invalid (2237477219243136714) --> + <skip /> + <!-- no translation found for osu_failure_server_connection (8192988165059982174) --> + <skip /> + <!-- no translation found for osu_failure_server_validation (4631649978129606823) --> + <skip /> + <!-- no translation found for osu_failure_service_provider_verification (4854091521439785597) --> + <skip /> + <!-- no translation found for osu_failure_provisioning_aborted (424627208135320329) --> + <skip /> + <!-- no translation found for osu_failure_provisioning_not_available (3021783729256985432) --> + <skip /> + <!-- no translation found for osu_failure_invalid_server_url (8548886196179435758) --> + <skip /> + <!-- no translation found for osu_failure_unexpected_command_type (8245921319866603904) --> + <skip /> + <!-- no translation found for osu_failure_unexpected_soap_message_type (2255897608510053065) --> + <skip /> + <!-- no translation found for osu_failure_soap_message_exchange (4357358438685987192) --> + <skip /> + <!-- no translation found for osu_failure_start_redirect_listener (4292769407279548482) --> + <skip /> + <!-- no translation found for osu_failure_timed_out_redirect_listener (3168657820278807508) --> + <skip /> + <!-- no translation found for osu_failure_no_osu_activity_found (4593038891437878675) --> + <skip /> + <!-- no translation found for osu_failure_unexpected_soap_message_status (6568467710235256675) --> + <skip /> + <!-- no translation found for osu_failure_no_pps_mo (850567403039076835) --> + <skip /> + <!-- no translation found for osu_failure_no_aaa_server_trust_root_node (8961455873459838456) --> + <skip /> + <!-- no translation found for osu_failure_no_remediation_server_trust_root_node (5041179688081545244) --> + <skip /> + <!-- no translation found for osu_failure_no_policy_server_trust_root_node (6617290380940513539) --> + <skip /> + <!-- no translation found for osu_failure_retrieve_trust_root_certificates (1499136256195528265) --> + <skip /> + <!-- no translation found for osu_failure_no_aaa_trust_root_certificate (1904322497042226984) --> + <skip /> + <!-- no translation found for osu_failure_add_passpoint_configuration (2173557755811446047) --> + <skip /> + <!-- no translation found for osu_failure_osu_provider_not_found (6616172862116673082) --> + <skip /> + <!-- no translation found for osu_status_ap_connecting (5296821043003441437) --> + <skip /> + <!-- no translation found for osu_status_ap_connected (3777289375683170728) --> + <skip /> + <!-- no translation found for osu_status_server_connecting (8499785407540355867) --> + <skip /> + <!-- no translation found for osu_status_server_validated (3158727184762596355) --> + <skip /> + <!-- no translation found for osu_status_server_connected (8382024481520158168) --> + <skip /> + <!-- no translation found for osu_status_init_soap_exchange (8628063888912101981) --> + <skip /> + <!-- no translation found for osu_status_waiting_for_redirect_response (2343016207837053197) --> + <skip /> + <!-- no translation found for osu_status_redirect_response_received (5323368411922609405) --> + <skip /> + <!-- no translation found for osu_status_second_soap_exchange (7115332266758483909) --> + <skip /> + <!-- no translation found for osu_status_third_soap_exchange (8460901783597440766) --> + <skip /> + <!-- no translation found for osu_status_retrieving_trust_root_certs (1563445892926269689) --> + <skip /> + <!-- no translation found for osu_provisioning_complete (5120178802493970149) --> + <skip /> <string name="speed_label_very_slow" msgid="1867055264243608530">"Nagyon lassú"</string> <string name="speed_label_slow" msgid="813109590815810235">"Lassú"</string> <string name="speed_label_okay" msgid="2331665440671174858">"Rendben"</string> diff --git a/packages/SettingsLib/res/values-hy/strings.xml b/packages/SettingsLib/res/values-hy/strings.xml index b27bb7e4d693..02a24fe18b42 100644 --- a/packages/SettingsLib/res/values-hy/strings.xml +++ b/packages/SettingsLib/res/values-hy/strings.xml @@ -38,13 +38,87 @@ <string name="connected_via_network_scorer" msgid="5713793306870815341">"Ավտոմատ կերպով կապակցվել է %1$s-ի միջոցով"</string> <string name="connected_via_network_scorer_default" msgid="7867260222020343104">"Ավտոմատ կերպով միացել է ցանցի վարկանիշի ծառայության մատակարարի միջոցով"</string> <string name="connected_via_passpoint" msgid="2826205693803088747">"Կապակցված է %1$s-ի միջոցով"</string> + <!-- no translation found for ssid_by_passpoint_provider (7898171424140673315) --> + <skip /> <string name="available_via_passpoint" msgid="1617440946846329613">"Հասանելի է %1$s-ի միջոցով"</string> + <!-- no translation found for tap_to_set_up (2468970825530423314) --> + <skip /> <string name="wifi_connected_no_internet" msgid="8202906332837777829">"Միացված է, սակայն ինտերնետ կապ չկա"</string> <string name="wifi_status_no_internet" msgid="5784710974669608361">"Ինտերնետ կապ չկա"</string> <string name="wifi_status_sign_in_required" msgid="123517180404752756">"Անհրաժեշտ է մուտք գործել"</string> <string name="wifi_ap_unable_to_handle_new_sta" msgid="5348824313514404541">"Հասանելիության կետը ժամանակավորապես լիքն է"</string> <string name="connected_via_carrier" msgid="7583780074526041912">"Միացված է %1$s-ի միջոցով"</string> <string name="available_via_carrier" msgid="1469036129740799053">"Հասանելի է %1$s-ի միջոցով"</string> + <!-- no translation found for osu_failure_ap_connection (598977488344424542) --> + <skip /> + <!-- no translation found for osu_failure_server_url_invalid (2237477219243136714) --> + <skip /> + <!-- no translation found for osu_failure_server_connection (8192988165059982174) --> + <skip /> + <!-- no translation found for osu_failure_server_validation (4631649978129606823) --> + <skip /> + <!-- no translation found for osu_failure_service_provider_verification (4854091521439785597) --> + <skip /> + <!-- no translation found for osu_failure_provisioning_aborted (424627208135320329) --> + <skip /> + <!-- no translation found for osu_failure_provisioning_not_available (3021783729256985432) --> + <skip /> + <!-- no translation found for osu_failure_invalid_server_url (8548886196179435758) --> + <skip /> + <!-- no translation found for osu_failure_unexpected_command_type (8245921319866603904) --> + <skip /> + <!-- no translation found for osu_failure_unexpected_soap_message_type (2255897608510053065) --> + <skip /> + <!-- no translation found for osu_failure_soap_message_exchange (4357358438685987192) --> + <skip /> + <!-- no translation found for osu_failure_start_redirect_listener (4292769407279548482) --> + <skip /> + <!-- no translation found for osu_failure_timed_out_redirect_listener (3168657820278807508) --> + <skip /> + <!-- no translation found for osu_failure_no_osu_activity_found (4593038891437878675) --> + <skip /> + <!-- no translation found for osu_failure_unexpected_soap_message_status (6568467710235256675) --> + <skip /> + <!-- no translation found for osu_failure_no_pps_mo (850567403039076835) --> + <skip /> + <!-- no translation found for osu_failure_no_aaa_server_trust_root_node (8961455873459838456) --> + <skip /> + <!-- no translation found for osu_failure_no_remediation_server_trust_root_node (5041179688081545244) --> + <skip /> + <!-- no translation found for osu_failure_no_policy_server_trust_root_node (6617290380940513539) --> + <skip /> + <!-- no translation found for osu_failure_retrieve_trust_root_certificates (1499136256195528265) --> + <skip /> + <!-- no translation found for osu_failure_no_aaa_trust_root_certificate (1904322497042226984) --> + <skip /> + <!-- no translation found for osu_failure_add_passpoint_configuration (2173557755811446047) --> + <skip /> + <!-- no translation found for osu_failure_osu_provider_not_found (6616172862116673082) --> + <skip /> + <!-- no translation found for osu_status_ap_connecting (5296821043003441437) --> + <skip /> + <!-- no translation found for osu_status_ap_connected (3777289375683170728) --> + <skip /> + <!-- no translation found for osu_status_server_connecting (8499785407540355867) --> + <skip /> + <!-- no translation found for osu_status_server_validated (3158727184762596355) --> + <skip /> + <!-- no translation found for osu_status_server_connected (8382024481520158168) --> + <skip /> + <!-- no translation found for osu_status_init_soap_exchange (8628063888912101981) --> + <skip /> + <!-- no translation found for osu_status_waiting_for_redirect_response (2343016207837053197) --> + <skip /> + <!-- no translation found for osu_status_redirect_response_received (5323368411922609405) --> + <skip /> + <!-- no translation found for osu_status_second_soap_exchange (7115332266758483909) --> + <skip /> + <!-- no translation found for osu_status_third_soap_exchange (8460901783597440766) --> + <skip /> + <!-- no translation found for osu_status_retrieving_trust_root_certs (1563445892926269689) --> + <skip /> + <!-- no translation found for osu_provisioning_complete (5120178802493970149) --> + <skip /> <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> diff --git a/packages/SettingsLib/res/values-in/strings.xml b/packages/SettingsLib/res/values-in/strings.xml index 342a50521750..6b901ffa621b 100644 --- a/packages/SettingsLib/res/values-in/strings.xml +++ b/packages/SettingsLib/res/values-in/strings.xml @@ -38,13 +38,87 @@ <string name="connected_via_network_scorer" msgid="5713793306870815341">"Tersambung otomatis melalui %1$s"</string> <string name="connected_via_network_scorer_default" msgid="7867260222020343104">"Otomatis tersambung melalui penyedia rating jaringan"</string> <string name="connected_via_passpoint" msgid="2826205693803088747">"Terhubung melalui %1$s"</string> + <!-- no translation found for ssid_by_passpoint_provider (7898171424140673315) --> + <skip /> <string name="available_via_passpoint" msgid="1617440946846329613">"Tersedia melalui %1$s"</string> + <!-- no translation found for tap_to_set_up (2468970825530423314) --> + <skip /> <string name="wifi_connected_no_internet" msgid="8202906332837777829">"Tersambung, tidak ada internet"</string> <string name="wifi_status_no_internet" msgid="5784710974669608361">"Tidak ada internet"</string> <string name="wifi_status_sign_in_required" msgid="123517180404752756">"Perlu login"</string> <string name="wifi_ap_unable_to_handle_new_sta" msgid="5348824313514404541">"Titik akses penuh untuk sementara"</string> <string name="connected_via_carrier" msgid="7583780074526041912">"Tersambung melalui %1$s"</string> <string name="available_via_carrier" msgid="1469036129740799053">"Tersedia melalui %1$s"</string> + <!-- no translation found for osu_failure_ap_connection (598977488344424542) --> + <skip /> + <!-- no translation found for osu_failure_server_url_invalid (2237477219243136714) --> + <skip /> + <!-- no translation found for osu_failure_server_connection (8192988165059982174) --> + <skip /> + <!-- no translation found for osu_failure_server_validation (4631649978129606823) --> + <skip /> + <!-- no translation found for osu_failure_service_provider_verification (4854091521439785597) --> + <skip /> + <!-- no translation found for osu_failure_provisioning_aborted (424627208135320329) --> + <skip /> + <!-- no translation found for osu_failure_provisioning_not_available (3021783729256985432) --> + <skip /> + <!-- no translation found for osu_failure_invalid_server_url (8548886196179435758) --> + <skip /> + <!-- no translation found for osu_failure_unexpected_command_type (8245921319866603904) --> + <skip /> + <!-- no translation found for osu_failure_unexpected_soap_message_type (2255897608510053065) --> + <skip /> + <!-- no translation found for osu_failure_soap_message_exchange (4357358438685987192) --> + <skip /> + <!-- no translation found for osu_failure_start_redirect_listener (4292769407279548482) --> + <skip /> + <!-- no translation found for osu_failure_timed_out_redirect_listener (3168657820278807508) --> + <skip /> + <!-- no translation found for osu_failure_no_osu_activity_found (4593038891437878675) --> + <skip /> + <!-- no translation found for osu_failure_unexpected_soap_message_status (6568467710235256675) --> + <skip /> + <!-- no translation found for osu_failure_no_pps_mo (850567403039076835) --> + <skip /> + <!-- no translation found for osu_failure_no_aaa_server_trust_root_node (8961455873459838456) --> + <skip /> + <!-- no translation found for osu_failure_no_remediation_server_trust_root_node (5041179688081545244) --> + <skip /> + <!-- no translation found for osu_failure_no_policy_server_trust_root_node (6617290380940513539) --> + <skip /> + <!-- no translation found for osu_failure_retrieve_trust_root_certificates (1499136256195528265) --> + <skip /> + <!-- no translation found for osu_failure_no_aaa_trust_root_certificate (1904322497042226984) --> + <skip /> + <!-- no translation found for osu_failure_add_passpoint_configuration (2173557755811446047) --> + <skip /> + <!-- no translation found for osu_failure_osu_provider_not_found (6616172862116673082) --> + <skip /> + <!-- no translation found for osu_status_ap_connecting (5296821043003441437) --> + <skip /> + <!-- no translation found for osu_status_ap_connected (3777289375683170728) --> + <skip /> + <!-- no translation found for osu_status_server_connecting (8499785407540355867) --> + <skip /> + <!-- no translation found for osu_status_server_validated (3158727184762596355) --> + <skip /> + <!-- no translation found for osu_status_server_connected (8382024481520158168) --> + <skip /> + <!-- no translation found for osu_status_init_soap_exchange (8628063888912101981) --> + <skip /> + <!-- no translation found for osu_status_waiting_for_redirect_response (2343016207837053197) --> + <skip /> + <!-- no translation found for osu_status_redirect_response_received (5323368411922609405) --> + <skip /> + <!-- no translation found for osu_status_second_soap_exchange (7115332266758483909) --> + <skip /> + <!-- no translation found for osu_status_third_soap_exchange (8460901783597440766) --> + <skip /> + <!-- no translation found for osu_status_retrieving_trust_root_certs (1563445892926269689) --> + <skip /> + <!-- no translation found for osu_provisioning_complete (5120178802493970149) --> + <skip /> <string name="speed_label_very_slow" msgid="1867055264243608530">"Sangat Lambat"</string> <string name="speed_label_slow" msgid="813109590815810235">"Lambat"</string> <string name="speed_label_okay" msgid="2331665440671174858">"Oke"</string> diff --git a/packages/SettingsLib/res/values-is/strings.xml b/packages/SettingsLib/res/values-is/strings.xml index 8f1b9a1abdcf..ae31d6ba384c 100644 --- a/packages/SettingsLib/res/values-is/strings.xml +++ b/packages/SettingsLib/res/values-is/strings.xml @@ -38,13 +38,87 @@ <string name="connected_via_network_scorer" msgid="5713793306870815341">"Sjálfkrafa tengt um %1$s"</string> <string name="connected_via_network_scorer_default" msgid="7867260222020343104">"Sjálfkrafa tengt um netgæðaveitu"</string> <string name="connected_via_passpoint" msgid="2826205693803088747">"Tengt í gegnum %1$s"</string> + <!-- no translation found for ssid_by_passpoint_provider (7898171424140673315) --> + <skip /> <string name="available_via_passpoint" msgid="1617440946846329613">"Í boði í gegnum %1$s"</string> + <!-- no translation found for tap_to_set_up (2468970825530423314) --> + <skip /> <string name="wifi_connected_no_internet" msgid="8202906332837777829">"Tengt, enginn netaðgangur"</string> <string name="wifi_status_no_internet" msgid="5784710974669608361">"Engin nettenging"</string> <string name="wifi_status_sign_in_required" msgid="123517180404752756">"Innskráningar krafist"</string> <string name="wifi_ap_unable_to_handle_new_sta" msgid="5348824313514404541">"Aðgangsstaður tímabundið fullur"</string> <string name="connected_via_carrier" msgid="7583780074526041912">"Tengt í gegnum %1$s"</string> <string name="available_via_carrier" msgid="1469036129740799053">"Í boði í gegnum %1$s"</string> + <!-- no translation found for osu_failure_ap_connection (598977488344424542) --> + <skip /> + <!-- no translation found for osu_failure_server_url_invalid (2237477219243136714) --> + <skip /> + <!-- no translation found for osu_failure_server_connection (8192988165059982174) --> + <skip /> + <!-- no translation found for osu_failure_server_validation (4631649978129606823) --> + <skip /> + <!-- no translation found for osu_failure_service_provider_verification (4854091521439785597) --> + <skip /> + <!-- no translation found for osu_failure_provisioning_aborted (424627208135320329) --> + <skip /> + <!-- no translation found for osu_failure_provisioning_not_available (3021783729256985432) --> + <skip /> + <!-- no translation found for osu_failure_invalid_server_url (8548886196179435758) --> + <skip /> + <!-- no translation found for osu_failure_unexpected_command_type (8245921319866603904) --> + <skip /> + <!-- no translation found for osu_failure_unexpected_soap_message_type (2255897608510053065) --> + <skip /> + <!-- no translation found for osu_failure_soap_message_exchange (4357358438685987192) --> + <skip /> + <!-- no translation found for osu_failure_start_redirect_listener (4292769407279548482) --> + <skip /> + <!-- no translation found for osu_failure_timed_out_redirect_listener (3168657820278807508) --> + <skip /> + <!-- no translation found for osu_failure_no_osu_activity_found (4593038891437878675) --> + <skip /> + <!-- no translation found for osu_failure_unexpected_soap_message_status (6568467710235256675) --> + <skip /> + <!-- no translation found for osu_failure_no_pps_mo (850567403039076835) --> + <skip /> + <!-- no translation found for osu_failure_no_aaa_server_trust_root_node (8961455873459838456) --> + <skip /> + <!-- no translation found for osu_failure_no_remediation_server_trust_root_node (5041179688081545244) --> + <skip /> + <!-- no translation found for osu_failure_no_policy_server_trust_root_node (6617290380940513539) --> + <skip /> + <!-- no translation found for osu_failure_retrieve_trust_root_certificates (1499136256195528265) --> + <skip /> + <!-- no translation found for osu_failure_no_aaa_trust_root_certificate (1904322497042226984) --> + <skip /> + <!-- no translation found for osu_failure_add_passpoint_configuration (2173557755811446047) --> + <skip /> + <!-- no translation found for osu_failure_osu_provider_not_found (6616172862116673082) --> + <skip /> + <!-- no translation found for osu_status_ap_connecting (5296821043003441437) --> + <skip /> + <!-- no translation found for osu_status_ap_connected (3777289375683170728) --> + <skip /> + <!-- no translation found for osu_status_server_connecting (8499785407540355867) --> + <skip /> + <!-- no translation found for osu_status_server_validated (3158727184762596355) --> + <skip /> + <!-- no translation found for osu_status_server_connected (8382024481520158168) --> + <skip /> + <!-- no translation found for osu_status_init_soap_exchange (8628063888912101981) --> + <skip /> + <!-- no translation found for osu_status_waiting_for_redirect_response (2343016207837053197) --> + <skip /> + <!-- no translation found for osu_status_redirect_response_received (5323368411922609405) --> + <skip /> + <!-- no translation found for osu_status_second_soap_exchange (7115332266758483909) --> + <skip /> + <!-- no translation found for osu_status_third_soap_exchange (8460901783597440766) --> + <skip /> + <!-- no translation found for osu_status_retrieving_trust_root_certs (1563445892926269689) --> + <skip /> + <!-- no translation found for osu_provisioning_complete (5120178802493970149) --> + <skip /> <string name="speed_label_very_slow" msgid="1867055264243608530">"Mjög hægt"</string> <string name="speed_label_slow" msgid="813109590815810235">"Hægt"</string> <string name="speed_label_okay" msgid="2331665440671174858">"Í lagi"</string> diff --git a/packages/SettingsLib/res/values-it/strings.xml b/packages/SettingsLib/res/values-it/strings.xml index 6600ca26e7c5..44acbcb12dd8 100644 --- a/packages/SettingsLib/res/values-it/strings.xml +++ b/packages/SettingsLib/res/values-it/strings.xml @@ -38,13 +38,87 @@ <string name="connected_via_network_scorer" msgid="5713793306870815341">"Collegato automaticamente tramite %1$s"</string> <string name="connected_via_network_scorer_default" msgid="7867260222020343104">"Collegato automaticamente tramite fornitore di servizi di valutazione rete"</string> <string name="connected_via_passpoint" msgid="2826205693803088747">"Collegato tramite %1$s"</string> + <!-- no translation found for ssid_by_passpoint_provider (7898171424140673315) --> + <skip /> <string name="available_via_passpoint" msgid="1617440946846329613">"Disponibile tramite %1$s"</string> + <!-- no translation found for tap_to_set_up (2468970825530423314) --> + <skip /> <string name="wifi_connected_no_internet" msgid="8202906332837777829">"Connesso, senza Internet"</string> <string name="wifi_status_no_internet" msgid="5784710974669608361">"Nessuna connessione a Internet"</string> <string name="wifi_status_sign_in_required" msgid="123517180404752756">"Accesso richiesto"</string> <string name="wifi_ap_unable_to_handle_new_sta" msgid="5348824313514404541">"Punto di accesso momentaneamente al completo"</string> <string name="connected_via_carrier" msgid="7583780074526041912">"Connesso tramite %1$s"</string> <string name="available_via_carrier" msgid="1469036129740799053">"Disponibile tramite %1$s"</string> + <!-- no translation found for osu_failure_ap_connection (598977488344424542) --> + <skip /> + <!-- no translation found for osu_failure_server_url_invalid (2237477219243136714) --> + <skip /> + <!-- no translation found for osu_failure_server_connection (8192988165059982174) --> + <skip /> + <!-- no translation found for osu_failure_server_validation (4631649978129606823) --> + <skip /> + <!-- no translation found for osu_failure_service_provider_verification (4854091521439785597) --> + <skip /> + <!-- no translation found for osu_failure_provisioning_aborted (424627208135320329) --> + <skip /> + <!-- no translation found for osu_failure_provisioning_not_available (3021783729256985432) --> + <skip /> + <!-- no translation found for osu_failure_invalid_server_url (8548886196179435758) --> + <skip /> + <!-- no translation found for osu_failure_unexpected_command_type (8245921319866603904) --> + <skip /> + <!-- no translation found for osu_failure_unexpected_soap_message_type (2255897608510053065) --> + <skip /> + <!-- no translation found for osu_failure_soap_message_exchange (4357358438685987192) --> + <skip /> + <!-- no translation found for osu_failure_start_redirect_listener (4292769407279548482) --> + <skip /> + <!-- no translation found for osu_failure_timed_out_redirect_listener (3168657820278807508) --> + <skip /> + <!-- no translation found for osu_failure_no_osu_activity_found (4593038891437878675) --> + <skip /> + <!-- no translation found for osu_failure_unexpected_soap_message_status (6568467710235256675) --> + <skip /> + <!-- no translation found for osu_failure_no_pps_mo (850567403039076835) --> + <skip /> + <!-- no translation found for osu_failure_no_aaa_server_trust_root_node (8961455873459838456) --> + <skip /> + <!-- no translation found for osu_failure_no_remediation_server_trust_root_node (5041179688081545244) --> + <skip /> + <!-- no translation found for osu_failure_no_policy_server_trust_root_node (6617290380940513539) --> + <skip /> + <!-- no translation found for osu_failure_retrieve_trust_root_certificates (1499136256195528265) --> + <skip /> + <!-- no translation found for osu_failure_no_aaa_trust_root_certificate (1904322497042226984) --> + <skip /> + <!-- no translation found for osu_failure_add_passpoint_configuration (2173557755811446047) --> + <skip /> + <!-- no translation found for osu_failure_osu_provider_not_found (6616172862116673082) --> + <skip /> + <!-- no translation found for osu_status_ap_connecting (5296821043003441437) --> + <skip /> + <!-- no translation found for osu_status_ap_connected (3777289375683170728) --> + <skip /> + <!-- no translation found for osu_status_server_connecting (8499785407540355867) --> + <skip /> + <!-- no translation found for osu_status_server_validated (3158727184762596355) --> + <skip /> + <!-- no translation found for osu_status_server_connected (8382024481520158168) --> + <skip /> + <!-- no translation found for osu_status_init_soap_exchange (8628063888912101981) --> + <skip /> + <!-- no translation found for osu_status_waiting_for_redirect_response (2343016207837053197) --> + <skip /> + <!-- no translation found for osu_status_redirect_response_received (5323368411922609405) --> + <skip /> + <!-- no translation found for osu_status_second_soap_exchange (7115332266758483909) --> + <skip /> + <!-- no translation found for osu_status_third_soap_exchange (8460901783597440766) --> + <skip /> + <!-- no translation found for osu_status_retrieving_trust_root_certs (1563445892926269689) --> + <skip /> + <!-- no translation found for osu_provisioning_complete (5120178802493970149) --> + <skip /> <string name="speed_label_very_slow" msgid="1867055264243608530">"Molto lenta"</string> <string name="speed_label_slow" msgid="813109590815810235">"Lenta"</string> <string name="speed_label_okay" msgid="2331665440671174858">"OK"</string> diff --git a/packages/SettingsLib/res/values-iw/strings.xml b/packages/SettingsLib/res/values-iw/strings.xml index a8da0b1bb6ad..5ae1321679fd 100644 --- a/packages/SettingsLib/res/values-iw/strings.xml +++ b/packages/SettingsLib/res/values-iw/strings.xml @@ -38,13 +38,87 @@ <string name="connected_via_network_scorer" msgid="5713793306870815341">"מחובר אוטומטית דרך %1$s"</string> <string name="connected_via_network_scorer_default" msgid="7867260222020343104">"מחובר אוטומטית דרך ספק של דירוג רשת"</string> <string name="connected_via_passpoint" msgid="2826205693803088747">"מחובר דרך %1$s"</string> + <!-- no translation found for ssid_by_passpoint_provider (7898171424140673315) --> + <skip /> <string name="available_via_passpoint" msgid="1617440946846329613">"זמינה דרך %1$s"</string> + <!-- no translation found for tap_to_set_up (2468970825530423314) --> + <skip /> <string name="wifi_connected_no_internet" msgid="8202906332837777829">"מחובר. אין אינטרנט"</string> <string name="wifi_status_no_internet" msgid="5784710974669608361">"אין אינטרנט"</string> <string name="wifi_status_sign_in_required" msgid="123517180404752756">"נדרשת כניסה"</string> <string name="wifi_ap_unable_to_handle_new_sta" msgid="5348824313514404541">"נקודת הגישה מלאה באופן זמני"</string> <string name="connected_via_carrier" msgid="7583780074526041912">"מחובר לרשת של %1$s"</string> <string name="available_via_carrier" msgid="1469036129740799053">"זמינה דרך %1$s"</string> + <!-- no translation found for osu_failure_ap_connection (598977488344424542) --> + <skip /> + <!-- no translation found for osu_failure_server_url_invalid (2237477219243136714) --> + <skip /> + <!-- no translation found for osu_failure_server_connection (8192988165059982174) --> + <skip /> + <!-- no translation found for osu_failure_server_validation (4631649978129606823) --> + <skip /> + <!-- no translation found for osu_failure_service_provider_verification (4854091521439785597) --> + <skip /> + <!-- no translation found for osu_failure_provisioning_aborted (424627208135320329) --> + <skip /> + <!-- no translation found for osu_failure_provisioning_not_available (3021783729256985432) --> + <skip /> + <!-- no translation found for osu_failure_invalid_server_url (8548886196179435758) --> + <skip /> + <!-- no translation found for osu_failure_unexpected_command_type (8245921319866603904) --> + <skip /> + <!-- no translation found for osu_failure_unexpected_soap_message_type (2255897608510053065) --> + <skip /> + <!-- no translation found for osu_failure_soap_message_exchange (4357358438685987192) --> + <skip /> + <!-- no translation found for osu_failure_start_redirect_listener (4292769407279548482) --> + <skip /> + <!-- no translation found for osu_failure_timed_out_redirect_listener (3168657820278807508) --> + <skip /> + <!-- no translation found for osu_failure_no_osu_activity_found (4593038891437878675) --> + <skip /> + <!-- no translation found for osu_failure_unexpected_soap_message_status (6568467710235256675) --> + <skip /> + <!-- no translation found for osu_failure_no_pps_mo (850567403039076835) --> + <skip /> + <!-- no translation found for osu_failure_no_aaa_server_trust_root_node (8961455873459838456) --> + <skip /> + <!-- no translation found for osu_failure_no_remediation_server_trust_root_node (5041179688081545244) --> + <skip /> + <!-- no translation found for osu_failure_no_policy_server_trust_root_node (6617290380940513539) --> + <skip /> + <!-- no translation found for osu_failure_retrieve_trust_root_certificates (1499136256195528265) --> + <skip /> + <!-- no translation found for osu_failure_no_aaa_trust_root_certificate (1904322497042226984) --> + <skip /> + <!-- no translation found for osu_failure_add_passpoint_configuration (2173557755811446047) --> + <skip /> + <!-- no translation found for osu_failure_osu_provider_not_found (6616172862116673082) --> + <skip /> + <!-- no translation found for osu_status_ap_connecting (5296821043003441437) --> + <skip /> + <!-- no translation found for osu_status_ap_connected (3777289375683170728) --> + <skip /> + <!-- no translation found for osu_status_server_connecting (8499785407540355867) --> + <skip /> + <!-- no translation found for osu_status_server_validated (3158727184762596355) --> + <skip /> + <!-- no translation found for osu_status_server_connected (8382024481520158168) --> + <skip /> + <!-- no translation found for osu_status_init_soap_exchange (8628063888912101981) --> + <skip /> + <!-- no translation found for osu_status_waiting_for_redirect_response (2343016207837053197) --> + <skip /> + <!-- no translation found for osu_status_redirect_response_received (5323368411922609405) --> + <skip /> + <!-- no translation found for osu_status_second_soap_exchange (7115332266758483909) --> + <skip /> + <!-- no translation found for osu_status_third_soap_exchange (8460901783597440766) --> + <skip /> + <!-- no translation found for osu_status_retrieving_trust_root_certs (1563445892926269689) --> + <skip /> + <!-- no translation found for osu_provisioning_complete (5120178802493970149) --> + <skip /> <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> diff --git a/packages/SettingsLib/res/values-ja/strings.xml b/packages/SettingsLib/res/values-ja/strings.xml index ea62637fa27f..25308cfe940b 100644 --- a/packages/SettingsLib/res/values-ja/strings.xml +++ b/packages/SettingsLib/res/values-ja/strings.xml @@ -38,13 +38,87 @@ <string name="connected_via_network_scorer" msgid="5713793306870815341">"%1$s 経由で自動的に接続しています"</string> <string name="connected_via_network_scorer_default" msgid="7867260222020343104">"ネットワーク評価プロバイダ経由で自動的に接続しています"</string> <string name="connected_via_passpoint" msgid="2826205693803088747">"%1$s経由で接続"</string> + <!-- no translation found for ssid_by_passpoint_provider (7898171424140673315) --> + <skip /> <string name="available_via_passpoint" msgid="1617440946846329613">"%1$s経由で使用可能"</string> + <!-- no translation found for tap_to_set_up (2468970825530423314) --> + <skip /> <string name="wifi_connected_no_internet" msgid="8202906332837777829">"接続済み、インターネット接続なし"</string> <string name="wifi_status_no_internet" msgid="5784710974669608361">"インターネット未接続"</string> <string name="wifi_status_sign_in_required" msgid="123517180404752756">"ログインが必要"</string> <string name="wifi_ap_unable_to_handle_new_sta" msgid="5348824313514404541">"アクセス ポイントが一時的にいっぱいです"</string> <string name="connected_via_carrier" msgid="7583780074526041912">"%1$s 経由で接続済み"</string> <string name="available_via_carrier" msgid="1469036129740799053">"%1$s 経由で使用可能"</string> + <!-- no translation found for osu_failure_ap_connection (598977488344424542) --> + <skip /> + <!-- no translation found for osu_failure_server_url_invalid (2237477219243136714) --> + <skip /> + <!-- no translation found for osu_failure_server_connection (8192988165059982174) --> + <skip /> + <!-- no translation found for osu_failure_server_validation (4631649978129606823) --> + <skip /> + <!-- no translation found for osu_failure_service_provider_verification (4854091521439785597) --> + <skip /> + <!-- no translation found for osu_failure_provisioning_aborted (424627208135320329) --> + <skip /> + <!-- no translation found for osu_failure_provisioning_not_available (3021783729256985432) --> + <skip /> + <!-- no translation found for osu_failure_invalid_server_url (8548886196179435758) --> + <skip /> + <!-- no translation found for osu_failure_unexpected_command_type (8245921319866603904) --> + <skip /> + <!-- no translation found for osu_failure_unexpected_soap_message_type (2255897608510053065) --> + <skip /> + <!-- no translation found for osu_failure_soap_message_exchange (4357358438685987192) --> + <skip /> + <!-- no translation found for osu_failure_start_redirect_listener (4292769407279548482) --> + <skip /> + <!-- no translation found for osu_failure_timed_out_redirect_listener (3168657820278807508) --> + <skip /> + <!-- no translation found for osu_failure_no_osu_activity_found (4593038891437878675) --> + <skip /> + <!-- no translation found for osu_failure_unexpected_soap_message_status (6568467710235256675) --> + <skip /> + <!-- no translation found for osu_failure_no_pps_mo (850567403039076835) --> + <skip /> + <!-- no translation found for osu_failure_no_aaa_server_trust_root_node (8961455873459838456) --> + <skip /> + <!-- no translation found for osu_failure_no_remediation_server_trust_root_node (5041179688081545244) --> + <skip /> + <!-- no translation found for osu_failure_no_policy_server_trust_root_node (6617290380940513539) --> + <skip /> + <!-- no translation found for osu_failure_retrieve_trust_root_certificates (1499136256195528265) --> + <skip /> + <!-- no translation found for osu_failure_no_aaa_trust_root_certificate (1904322497042226984) --> + <skip /> + <!-- no translation found for osu_failure_add_passpoint_configuration (2173557755811446047) --> + <skip /> + <!-- no translation found for osu_failure_osu_provider_not_found (6616172862116673082) --> + <skip /> + <!-- no translation found for osu_status_ap_connecting (5296821043003441437) --> + <skip /> + <!-- no translation found for osu_status_ap_connected (3777289375683170728) --> + <skip /> + <!-- no translation found for osu_status_server_connecting (8499785407540355867) --> + <skip /> + <!-- no translation found for osu_status_server_validated (3158727184762596355) --> + <skip /> + <!-- no translation found for osu_status_server_connected (8382024481520158168) --> + <skip /> + <!-- no translation found for osu_status_init_soap_exchange (8628063888912101981) --> + <skip /> + <!-- no translation found for osu_status_waiting_for_redirect_response (2343016207837053197) --> + <skip /> + <!-- no translation found for osu_status_redirect_response_received (5323368411922609405) --> + <skip /> + <!-- no translation found for osu_status_second_soap_exchange (7115332266758483909) --> + <skip /> + <!-- no translation found for osu_status_third_soap_exchange (8460901783597440766) --> + <skip /> + <!-- no translation found for osu_status_retrieving_trust_root_certs (1563445892926269689) --> + <skip /> + <!-- no translation found for osu_provisioning_complete (5120178802493970149) --> + <skip /> <string name="speed_label_very_slow" msgid="1867055264243608530">"とても遅い"</string> <string name="speed_label_slow" msgid="813109590815810235">"遅い"</string> <string name="speed_label_okay" msgid="2331665440671174858">"OK"</string> diff --git a/packages/SettingsLib/res/values-ka/strings.xml b/packages/SettingsLib/res/values-ka/strings.xml index bd88435f419f..b38dcc61a91a 100644 --- a/packages/SettingsLib/res/values-ka/strings.xml +++ b/packages/SettingsLib/res/values-ka/strings.xml @@ -38,13 +38,87 @@ <string name="connected_via_network_scorer" msgid="5713793306870815341">"ავტომატურად დაკავშირდა %1$s-ის მეშვეობით"</string> <string name="connected_via_network_scorer_default" msgid="7867260222020343104">"ავტომატურად დაკავშირდა ქსელის ხარისხის შეფასების პროვაიდერის მეშვეობით"</string> <string name="connected_via_passpoint" msgid="2826205693803088747">"%1$s-ით დაკავშირებული"</string> + <!-- no translation found for ssid_by_passpoint_provider (7898171424140673315) --> + <skip /> <string name="available_via_passpoint" msgid="1617440946846329613">"ხელმისაწვდომია %1$s-ით"</string> + <!-- no translation found for tap_to_set_up (2468970825530423314) --> + <skip /> <string name="wifi_connected_no_internet" msgid="8202906332837777829">"დაკავშირებულია, ინტერნეტის გარეშე"</string> <string name="wifi_status_no_internet" msgid="5784710974669608361">"ინტერნეტ-კავშირი არ არის"</string> <string name="wifi_status_sign_in_required" msgid="123517180404752756">"აუცილებელია სისტემაში შესვლა"</string> <string name="wifi_ap_unable_to_handle_new_sta" msgid="5348824313514404541">"წვდომის წერტილი დროებით გადატვირთულია"</string> <string name="connected_via_carrier" msgid="7583780074526041912">"%1$s-ით დაკავშირებული"</string> <string name="available_via_carrier" msgid="1469036129740799053">"ხელმისაწვდომია %1$s-ით"</string> + <!-- no translation found for osu_failure_ap_connection (598977488344424542) --> + <skip /> + <!-- no translation found for osu_failure_server_url_invalid (2237477219243136714) --> + <skip /> + <!-- no translation found for osu_failure_server_connection (8192988165059982174) --> + <skip /> + <!-- no translation found for osu_failure_server_validation (4631649978129606823) --> + <skip /> + <!-- no translation found for osu_failure_service_provider_verification (4854091521439785597) --> + <skip /> + <!-- no translation found for osu_failure_provisioning_aborted (424627208135320329) --> + <skip /> + <!-- no translation found for osu_failure_provisioning_not_available (3021783729256985432) --> + <skip /> + <!-- no translation found for osu_failure_invalid_server_url (8548886196179435758) --> + <skip /> + <!-- no translation found for osu_failure_unexpected_command_type (8245921319866603904) --> + <skip /> + <!-- no translation found for osu_failure_unexpected_soap_message_type (2255897608510053065) --> + <skip /> + <!-- no translation found for osu_failure_soap_message_exchange (4357358438685987192) --> + <skip /> + <!-- no translation found for osu_failure_start_redirect_listener (4292769407279548482) --> + <skip /> + <!-- no translation found for osu_failure_timed_out_redirect_listener (3168657820278807508) --> + <skip /> + <!-- no translation found for osu_failure_no_osu_activity_found (4593038891437878675) --> + <skip /> + <!-- no translation found for osu_failure_unexpected_soap_message_status (6568467710235256675) --> + <skip /> + <!-- no translation found for osu_failure_no_pps_mo (850567403039076835) --> + <skip /> + <!-- no translation found for osu_failure_no_aaa_server_trust_root_node (8961455873459838456) --> + <skip /> + <!-- no translation found for osu_failure_no_remediation_server_trust_root_node (5041179688081545244) --> + <skip /> + <!-- no translation found for osu_failure_no_policy_server_trust_root_node (6617290380940513539) --> + <skip /> + <!-- no translation found for osu_failure_retrieve_trust_root_certificates (1499136256195528265) --> + <skip /> + <!-- no translation found for osu_failure_no_aaa_trust_root_certificate (1904322497042226984) --> + <skip /> + <!-- no translation found for osu_failure_add_passpoint_configuration (2173557755811446047) --> + <skip /> + <!-- no translation found for osu_failure_osu_provider_not_found (6616172862116673082) --> + <skip /> + <!-- no translation found for osu_status_ap_connecting (5296821043003441437) --> + <skip /> + <!-- no translation found for osu_status_ap_connected (3777289375683170728) --> + <skip /> + <!-- no translation found for osu_status_server_connecting (8499785407540355867) --> + <skip /> + <!-- no translation found for osu_status_server_validated (3158727184762596355) --> + <skip /> + <!-- no translation found for osu_status_server_connected (8382024481520158168) --> + <skip /> + <!-- no translation found for osu_status_init_soap_exchange (8628063888912101981) --> + <skip /> + <!-- no translation found for osu_status_waiting_for_redirect_response (2343016207837053197) --> + <skip /> + <!-- no translation found for osu_status_redirect_response_received (5323368411922609405) --> + <skip /> + <!-- no translation found for osu_status_second_soap_exchange (7115332266758483909) --> + <skip /> + <!-- no translation found for osu_status_third_soap_exchange (8460901783597440766) --> + <skip /> + <!-- no translation found for osu_status_retrieving_trust_root_certs (1563445892926269689) --> + <skip /> + <!-- no translation found for osu_provisioning_complete (5120178802493970149) --> + <skip /> <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> diff --git a/packages/SettingsLib/res/values-kk/strings.xml b/packages/SettingsLib/res/values-kk/strings.xml index d22b13951ed1..54087a0b6a42 100644 --- a/packages/SettingsLib/res/values-kk/strings.xml +++ b/packages/SettingsLib/res/values-kk/strings.xml @@ -38,13 +38,87 @@ <string name="connected_via_network_scorer" msgid="5713793306870815341">"%1$s арқылы автоматты қосылды"</string> <string name="connected_via_network_scorer_default" msgid="7867260222020343104">"Желі рейтингі провайдері арқылы автоматты түрде қосылған"</string> <string name="connected_via_passpoint" msgid="2826205693803088747">"%1$s арқылы қосылған"</string> + <!-- no translation found for ssid_by_passpoint_provider (7898171424140673315) --> + <skip /> <string name="available_via_passpoint" msgid="1617440946846329613">"%1$s арқылы қолжетімді"</string> + <!-- no translation found for tap_to_set_up (2468970825530423314) --> + <skip /> <string name="wifi_connected_no_internet" msgid="8202906332837777829">"Қосылған, интернет жоқ"</string> <string name="wifi_status_no_internet" msgid="5784710974669608361">"Интернетпен байланыс жоқ"</string> <string name="wifi_status_sign_in_required" msgid="123517180404752756">"Есептік жазбаға кіру керек"</string> <string name="wifi_ap_unable_to_handle_new_sta" msgid="5348824313514404541">"Кіру нүктесі уақытша бос емес"</string> <string name="connected_via_carrier" msgid="7583780074526041912">"%1$s арқылы қосылды"</string> <string name="available_via_carrier" msgid="1469036129740799053">"%1$s арқылы қолжетімді"</string> + <!-- no translation found for osu_failure_ap_connection (598977488344424542) --> + <skip /> + <!-- no translation found for osu_failure_server_url_invalid (2237477219243136714) --> + <skip /> + <!-- no translation found for osu_failure_server_connection (8192988165059982174) --> + <skip /> + <!-- no translation found for osu_failure_server_validation (4631649978129606823) --> + <skip /> + <!-- no translation found for osu_failure_service_provider_verification (4854091521439785597) --> + <skip /> + <!-- no translation found for osu_failure_provisioning_aborted (424627208135320329) --> + <skip /> + <!-- no translation found for osu_failure_provisioning_not_available (3021783729256985432) --> + <skip /> + <!-- no translation found for osu_failure_invalid_server_url (8548886196179435758) --> + <skip /> + <!-- no translation found for osu_failure_unexpected_command_type (8245921319866603904) --> + <skip /> + <!-- no translation found for osu_failure_unexpected_soap_message_type (2255897608510053065) --> + <skip /> + <!-- no translation found for osu_failure_soap_message_exchange (4357358438685987192) --> + <skip /> + <!-- no translation found for osu_failure_start_redirect_listener (4292769407279548482) --> + <skip /> + <!-- no translation found for osu_failure_timed_out_redirect_listener (3168657820278807508) --> + <skip /> + <!-- no translation found for osu_failure_no_osu_activity_found (4593038891437878675) --> + <skip /> + <!-- no translation found for osu_failure_unexpected_soap_message_status (6568467710235256675) --> + <skip /> + <!-- no translation found for osu_failure_no_pps_mo (850567403039076835) --> + <skip /> + <!-- no translation found for osu_failure_no_aaa_server_trust_root_node (8961455873459838456) --> + <skip /> + <!-- no translation found for osu_failure_no_remediation_server_trust_root_node (5041179688081545244) --> + <skip /> + <!-- no translation found for osu_failure_no_policy_server_trust_root_node (6617290380940513539) --> + <skip /> + <!-- no translation found for osu_failure_retrieve_trust_root_certificates (1499136256195528265) --> + <skip /> + <!-- no translation found for osu_failure_no_aaa_trust_root_certificate (1904322497042226984) --> + <skip /> + <!-- no translation found for osu_failure_add_passpoint_configuration (2173557755811446047) --> + <skip /> + <!-- no translation found for osu_failure_osu_provider_not_found (6616172862116673082) --> + <skip /> + <!-- no translation found for osu_status_ap_connecting (5296821043003441437) --> + <skip /> + <!-- no translation found for osu_status_ap_connected (3777289375683170728) --> + <skip /> + <!-- no translation found for osu_status_server_connecting (8499785407540355867) --> + <skip /> + <!-- no translation found for osu_status_server_validated (3158727184762596355) --> + <skip /> + <!-- no translation found for osu_status_server_connected (8382024481520158168) --> + <skip /> + <!-- no translation found for osu_status_init_soap_exchange (8628063888912101981) --> + <skip /> + <!-- no translation found for osu_status_waiting_for_redirect_response (2343016207837053197) --> + <skip /> + <!-- no translation found for osu_status_redirect_response_received (5323368411922609405) --> + <skip /> + <!-- no translation found for osu_status_second_soap_exchange (7115332266758483909) --> + <skip /> + <!-- no translation found for osu_status_third_soap_exchange (8460901783597440766) --> + <skip /> + <!-- no translation found for osu_status_retrieving_trust_root_certs (1563445892926269689) --> + <skip /> + <!-- no translation found for osu_provisioning_complete (5120178802493970149) --> + <skip /> <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> diff --git a/packages/SettingsLib/res/values-km/strings.xml b/packages/SettingsLib/res/values-km/strings.xml index d516db9f1a8c..3fc609f3c4e9 100644 --- a/packages/SettingsLib/res/values-km/strings.xml +++ b/packages/SettingsLib/res/values-km/strings.xml @@ -38,13 +38,87 @@ <string name="connected_via_network_scorer" msgid="5713793306870815341">"បានភ្ជាប់ដោយស្វ័យប្រវត្តិតាមរយៈ %1$s"</string> <string name="connected_via_network_scorer_default" msgid="7867260222020343104">"បានភ្ជាប់ដោយស្វ័យប្រវត្តិតាមរយៈក្រុមហ៊ុនផ្តល់ការវាយតម្លៃលើបណ្តាញ"</string> <string name="connected_via_passpoint" msgid="2826205693803088747">"បានភ្ជាប់តាមរយៈ %1$s"</string> + <!-- no translation found for ssid_by_passpoint_provider (7898171424140673315) --> + <skip /> <string name="available_via_passpoint" msgid="1617440946846329613">"មានតាមរយៈ %1$s"</string> + <!-- no translation found for tap_to_set_up (2468970825530423314) --> + <skip /> <string name="wifi_connected_no_internet" msgid="8202906332837777829">"បានភ្ជាប់ ប៉ុន្តែគ្មានអ៊ីនធឺណិតទេ"</string> <string name="wifi_status_no_internet" msgid="5784710974669608361">"គ្មានអ៊ីនធឺណិតទេ"</string> <string name="wifi_status_sign_in_required" msgid="123517180404752756">"តម្រូវឱ្យចូលគណនី"</string> <string name="wifi_ap_unable_to_handle_new_sta" msgid="5348824313514404541">"ចំណុចចូលប្រើពេញជាបណ្តោះអាសន្ន"</string> <string name="connected_via_carrier" msgid="7583780074526041912">"បានភ្ជាប់តាមរយៈ %1$s"</string> <string name="available_via_carrier" msgid="1469036129740799053">"មានតាមរយៈ %1$s"</string> + <!-- no translation found for osu_failure_ap_connection (598977488344424542) --> + <skip /> + <!-- no translation found for osu_failure_server_url_invalid (2237477219243136714) --> + <skip /> + <!-- no translation found for osu_failure_server_connection (8192988165059982174) --> + <skip /> + <!-- no translation found for osu_failure_server_validation (4631649978129606823) --> + <skip /> + <!-- no translation found for osu_failure_service_provider_verification (4854091521439785597) --> + <skip /> + <!-- no translation found for osu_failure_provisioning_aborted (424627208135320329) --> + <skip /> + <!-- no translation found for osu_failure_provisioning_not_available (3021783729256985432) --> + <skip /> + <!-- no translation found for osu_failure_invalid_server_url (8548886196179435758) --> + <skip /> + <!-- no translation found for osu_failure_unexpected_command_type (8245921319866603904) --> + <skip /> + <!-- no translation found for osu_failure_unexpected_soap_message_type (2255897608510053065) --> + <skip /> + <!-- no translation found for osu_failure_soap_message_exchange (4357358438685987192) --> + <skip /> + <!-- no translation found for osu_failure_start_redirect_listener (4292769407279548482) --> + <skip /> + <!-- no translation found for osu_failure_timed_out_redirect_listener (3168657820278807508) --> + <skip /> + <!-- no translation found for osu_failure_no_osu_activity_found (4593038891437878675) --> + <skip /> + <!-- no translation found for osu_failure_unexpected_soap_message_status (6568467710235256675) --> + <skip /> + <!-- no translation found for osu_failure_no_pps_mo (850567403039076835) --> + <skip /> + <!-- no translation found for osu_failure_no_aaa_server_trust_root_node (8961455873459838456) --> + <skip /> + <!-- no translation found for osu_failure_no_remediation_server_trust_root_node (5041179688081545244) --> + <skip /> + <!-- no translation found for osu_failure_no_policy_server_trust_root_node (6617290380940513539) --> + <skip /> + <!-- no translation found for osu_failure_retrieve_trust_root_certificates (1499136256195528265) --> + <skip /> + <!-- no translation found for osu_failure_no_aaa_trust_root_certificate (1904322497042226984) --> + <skip /> + <!-- no translation found for osu_failure_add_passpoint_configuration (2173557755811446047) --> + <skip /> + <!-- no translation found for osu_failure_osu_provider_not_found (6616172862116673082) --> + <skip /> + <!-- no translation found for osu_status_ap_connecting (5296821043003441437) --> + <skip /> + <!-- no translation found for osu_status_ap_connected (3777289375683170728) --> + <skip /> + <!-- no translation found for osu_status_server_connecting (8499785407540355867) --> + <skip /> + <!-- no translation found for osu_status_server_validated (3158727184762596355) --> + <skip /> + <!-- no translation found for osu_status_server_connected (8382024481520158168) --> + <skip /> + <!-- no translation found for osu_status_init_soap_exchange (8628063888912101981) --> + <skip /> + <!-- no translation found for osu_status_waiting_for_redirect_response (2343016207837053197) --> + <skip /> + <!-- no translation found for osu_status_redirect_response_received (5323368411922609405) --> + <skip /> + <!-- no translation found for osu_status_second_soap_exchange (7115332266758483909) --> + <skip /> + <!-- no translation found for osu_status_third_soap_exchange (8460901783597440766) --> + <skip /> + <!-- no translation found for osu_status_retrieving_trust_root_certs (1563445892926269689) --> + <skip /> + <!-- no translation found for osu_provisioning_complete (5120178802493970149) --> + <skip /> <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> diff --git a/packages/SettingsLib/res/values-kn/strings.xml b/packages/SettingsLib/res/values-kn/strings.xml index 94a711cf57ee..bc1150d42aeb 100644 --- a/packages/SettingsLib/res/values-kn/strings.xml +++ b/packages/SettingsLib/res/values-kn/strings.xml @@ -38,13 +38,87 @@ <string name="connected_via_network_scorer" msgid="5713793306870815341">"%1$s ಮೂಲಕ ಸ್ವಯಂಚಾಲಿತವಾಗಿ ಸಂಪರ್ಕಿಸಲಾಗಿದೆ"</string> <string name="connected_via_network_scorer_default" msgid="7867260222020343104">"ನೆಟ್ವರ್ಕ್ ರೇಟಿಂಗ್ ಒದಗಿಸುವವರ ಮೂಲಕ ಸ್ವಯಂಚಾಲಿತವಾಗಿ ಸಂಪರ್ಕಿಸಲಾಗಿದೆ"</string> <string name="connected_via_passpoint" msgid="2826205693803088747">"%1$s ಮೂಲಕ ಸಂಪರ್ಕಗೊಂಡಿದೆ"</string> + <!-- no translation found for ssid_by_passpoint_provider (7898171424140673315) --> + <skip /> <string name="available_via_passpoint" msgid="1617440946846329613">"%1$s ಮೂಲಕ ಲಭ್ಯವಿದೆ"</string> + <!-- no translation found for tap_to_set_up (2468970825530423314) --> + <skip /> <string name="wifi_connected_no_internet" msgid="8202906332837777829">"ಸಂಪರ್ಕಪಡಿಸಲಾಗಿದೆ, ಇಂಟರ್ನೆಟ್ ಇಲ್ಲ"</string> <string name="wifi_status_no_internet" msgid="5784710974669608361">"ಇಂಟರ್ನೆಟ್ ಇಲ್ಲ"</string> <string name="wifi_status_sign_in_required" msgid="123517180404752756">"ಸೈನ್ ಇನ್ ಮಾಡುವ ಅಗತ್ಯವಿದೆ"</string> <string name="wifi_ap_unable_to_handle_new_sta" msgid="5348824313514404541">"ಪ್ರವೇಶ ಕೇಂದ್ರ ತಾತ್ಕಾಲಿಕವಾಗಿ ಭರ್ತಿಯಾಗಿದೆ"</string> <string name="connected_via_carrier" msgid="7583780074526041912">"%1$s ಮೂಲಕ ಸಂಪರ್ಕಗೊಂಡಿದೆ"</string> <string name="available_via_carrier" msgid="1469036129740799053">"%1$s ಮೂಲಕ ಲಭ್ಯವಿದೆ"</string> + <!-- no translation found for osu_failure_ap_connection (598977488344424542) --> + <skip /> + <!-- no translation found for osu_failure_server_url_invalid (2237477219243136714) --> + <skip /> + <!-- no translation found for osu_failure_server_connection (8192988165059982174) --> + <skip /> + <!-- no translation found for osu_failure_server_validation (4631649978129606823) --> + <skip /> + <!-- no translation found for osu_failure_service_provider_verification (4854091521439785597) --> + <skip /> + <!-- no translation found for osu_failure_provisioning_aborted (424627208135320329) --> + <skip /> + <!-- no translation found for osu_failure_provisioning_not_available (3021783729256985432) --> + <skip /> + <!-- no translation found for osu_failure_invalid_server_url (8548886196179435758) --> + <skip /> + <!-- no translation found for osu_failure_unexpected_command_type (8245921319866603904) --> + <skip /> + <!-- no translation found for osu_failure_unexpected_soap_message_type (2255897608510053065) --> + <skip /> + <!-- no translation found for osu_failure_soap_message_exchange (4357358438685987192) --> + <skip /> + <!-- no translation found for osu_failure_start_redirect_listener (4292769407279548482) --> + <skip /> + <!-- no translation found for osu_failure_timed_out_redirect_listener (3168657820278807508) --> + <skip /> + <!-- no translation found for osu_failure_no_osu_activity_found (4593038891437878675) --> + <skip /> + <!-- no translation found for osu_failure_unexpected_soap_message_status (6568467710235256675) --> + <skip /> + <!-- no translation found for osu_failure_no_pps_mo (850567403039076835) --> + <skip /> + <!-- no translation found for osu_failure_no_aaa_server_trust_root_node (8961455873459838456) --> + <skip /> + <!-- no translation found for osu_failure_no_remediation_server_trust_root_node (5041179688081545244) --> + <skip /> + <!-- no translation found for osu_failure_no_policy_server_trust_root_node (6617290380940513539) --> + <skip /> + <!-- no translation found for osu_failure_retrieve_trust_root_certificates (1499136256195528265) --> + <skip /> + <!-- no translation found for osu_failure_no_aaa_trust_root_certificate (1904322497042226984) --> + <skip /> + <!-- no translation found for osu_failure_add_passpoint_configuration (2173557755811446047) --> + <skip /> + <!-- no translation found for osu_failure_osu_provider_not_found (6616172862116673082) --> + <skip /> + <!-- no translation found for osu_status_ap_connecting (5296821043003441437) --> + <skip /> + <!-- no translation found for osu_status_ap_connected (3777289375683170728) --> + <skip /> + <!-- no translation found for osu_status_server_connecting (8499785407540355867) --> + <skip /> + <!-- no translation found for osu_status_server_validated (3158727184762596355) --> + <skip /> + <!-- no translation found for osu_status_server_connected (8382024481520158168) --> + <skip /> + <!-- no translation found for osu_status_init_soap_exchange (8628063888912101981) --> + <skip /> + <!-- no translation found for osu_status_waiting_for_redirect_response (2343016207837053197) --> + <skip /> + <!-- no translation found for osu_status_redirect_response_received (5323368411922609405) --> + <skip /> + <!-- no translation found for osu_status_second_soap_exchange (7115332266758483909) --> + <skip /> + <!-- no translation found for osu_status_third_soap_exchange (8460901783597440766) --> + <skip /> + <!-- no translation found for osu_status_retrieving_trust_root_certs (1563445892926269689) --> + <skip /> + <!-- no translation found for osu_provisioning_complete (5120178802493970149) --> + <skip /> <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> diff --git a/packages/SettingsLib/res/values-ko/strings.xml b/packages/SettingsLib/res/values-ko/strings.xml index 0b4125fa41cb..035c24b6195d 100644 --- a/packages/SettingsLib/res/values-ko/strings.xml +++ b/packages/SettingsLib/res/values-ko/strings.xml @@ -38,13 +38,87 @@ <string name="connected_via_network_scorer" msgid="5713793306870815341">"%1$s을(를) 통해 자동으로 연결됨"</string> <string name="connected_via_network_scorer_default" msgid="7867260222020343104">"네트워크 평가 제공업체를 통해 자동으로 연결됨"</string> <string name="connected_via_passpoint" msgid="2826205693803088747">"%1$s을(를) 통해 연결됨"</string> + <!-- no translation found for ssid_by_passpoint_provider (7898171424140673315) --> + <skip /> <string name="available_via_passpoint" msgid="1617440946846329613">"%1$s을(를) 통해 사용 가능"</string> + <!-- no translation found for tap_to_set_up (2468970825530423314) --> + <skip /> <string name="wifi_connected_no_internet" msgid="8202906332837777829">"연결됨, 인터넷 사용 불가"</string> <string name="wifi_status_no_internet" msgid="5784710974669608361">"인터넷 연결 없음"</string> <string name="wifi_status_sign_in_required" msgid="123517180404752756">"로그인 필요"</string> <string name="wifi_ap_unable_to_handle_new_sta" msgid="5348824313514404541">"액세스 포인트가 일시적으로 가득 참"</string> <string name="connected_via_carrier" msgid="7583780074526041912">"%1$s을(를) 통해 연결됨"</string> <string name="available_via_carrier" msgid="1469036129740799053">"%1$s을(를) 통해 사용 가능"</string> + <!-- no translation found for osu_failure_ap_connection (598977488344424542) --> + <skip /> + <!-- no translation found for osu_failure_server_url_invalid (2237477219243136714) --> + <skip /> + <!-- no translation found for osu_failure_server_connection (8192988165059982174) --> + <skip /> + <!-- no translation found for osu_failure_server_validation (4631649978129606823) --> + <skip /> + <!-- no translation found for osu_failure_service_provider_verification (4854091521439785597) --> + <skip /> + <!-- no translation found for osu_failure_provisioning_aborted (424627208135320329) --> + <skip /> + <!-- no translation found for osu_failure_provisioning_not_available (3021783729256985432) --> + <skip /> + <!-- no translation found for osu_failure_invalid_server_url (8548886196179435758) --> + <skip /> + <!-- no translation found for osu_failure_unexpected_command_type (8245921319866603904) --> + <skip /> + <!-- no translation found for osu_failure_unexpected_soap_message_type (2255897608510053065) --> + <skip /> + <!-- no translation found for osu_failure_soap_message_exchange (4357358438685987192) --> + <skip /> + <!-- no translation found for osu_failure_start_redirect_listener (4292769407279548482) --> + <skip /> + <!-- no translation found for osu_failure_timed_out_redirect_listener (3168657820278807508) --> + <skip /> + <!-- no translation found for osu_failure_no_osu_activity_found (4593038891437878675) --> + <skip /> + <!-- no translation found for osu_failure_unexpected_soap_message_status (6568467710235256675) --> + <skip /> + <!-- no translation found for osu_failure_no_pps_mo (850567403039076835) --> + <skip /> + <!-- no translation found for osu_failure_no_aaa_server_trust_root_node (8961455873459838456) --> + <skip /> + <!-- no translation found for osu_failure_no_remediation_server_trust_root_node (5041179688081545244) --> + <skip /> + <!-- no translation found for osu_failure_no_policy_server_trust_root_node (6617290380940513539) --> + <skip /> + <!-- no translation found for osu_failure_retrieve_trust_root_certificates (1499136256195528265) --> + <skip /> + <!-- no translation found for osu_failure_no_aaa_trust_root_certificate (1904322497042226984) --> + <skip /> + <!-- no translation found for osu_failure_add_passpoint_configuration (2173557755811446047) --> + <skip /> + <!-- no translation found for osu_failure_osu_provider_not_found (6616172862116673082) --> + <skip /> + <!-- no translation found for osu_status_ap_connecting (5296821043003441437) --> + <skip /> + <!-- no translation found for osu_status_ap_connected (3777289375683170728) --> + <skip /> + <!-- no translation found for osu_status_server_connecting (8499785407540355867) --> + <skip /> + <!-- no translation found for osu_status_server_validated (3158727184762596355) --> + <skip /> + <!-- no translation found for osu_status_server_connected (8382024481520158168) --> + <skip /> + <!-- no translation found for osu_status_init_soap_exchange (8628063888912101981) --> + <skip /> + <!-- no translation found for osu_status_waiting_for_redirect_response (2343016207837053197) --> + <skip /> + <!-- no translation found for osu_status_redirect_response_received (5323368411922609405) --> + <skip /> + <!-- no translation found for osu_status_second_soap_exchange (7115332266758483909) --> + <skip /> + <!-- no translation found for osu_status_third_soap_exchange (8460901783597440766) --> + <skip /> + <!-- no translation found for osu_status_retrieving_trust_root_certs (1563445892926269689) --> + <skip /> + <!-- no translation found for osu_provisioning_complete (5120178802493970149) --> + <skip /> <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> diff --git a/packages/SettingsLib/res/values-ky/strings.xml b/packages/SettingsLib/res/values-ky/strings.xml index 42dc97e187c5..8a68c785c701 100644 --- a/packages/SettingsLib/res/values-ky/strings.xml +++ b/packages/SettingsLib/res/values-ky/strings.xml @@ -38,13 +38,87 @@ <string name="connected_via_network_scorer" msgid="5713793306870815341">"%1$s аркылуу автоматтык түрдө туташты"</string> <string name="connected_via_network_scorer_default" msgid="7867260222020343104">"Тармактар рейтингинин автору аркылуу автоматтык түрдө туташты"</string> <string name="connected_via_passpoint" msgid="2826205693803088747">"%1$s аркылуу жеткиликтүү"</string> + <!-- no translation found for ssid_by_passpoint_provider (7898171424140673315) --> + <skip /> <string name="available_via_passpoint" msgid="1617440946846329613">"%1$s аркылуу жеткиликтүү"</string> + <!-- no translation found for tap_to_set_up (2468970825530423314) --> + <skip /> <string name="wifi_connected_no_internet" msgid="8202906332837777829">"Туташып турат, Интернет жок"</string> <string name="wifi_status_no_internet" msgid="5784710974669608361">"Интернет жок"</string> <string name="wifi_status_sign_in_required" msgid="123517180404752756">"Аккаунтка кирүү талап кылынат"</string> <string name="wifi_ap_unable_to_handle_new_sta" msgid="5348824313514404541">"Байланыш түйүнүнө өтө көп түзмөк туташып турат"</string> <string name="connected_via_carrier" msgid="7583780074526041912">"%1$s аркылуу туташты"</string> <string name="available_via_carrier" msgid="1469036129740799053">"%1$s аркылуу иштейт"</string> + <!-- no translation found for osu_failure_ap_connection (598977488344424542) --> + <skip /> + <!-- no translation found for osu_failure_server_url_invalid (2237477219243136714) --> + <skip /> + <!-- no translation found for osu_failure_server_connection (8192988165059982174) --> + <skip /> + <!-- no translation found for osu_failure_server_validation (4631649978129606823) --> + <skip /> + <!-- no translation found for osu_failure_service_provider_verification (4854091521439785597) --> + <skip /> + <!-- no translation found for osu_failure_provisioning_aborted (424627208135320329) --> + <skip /> + <!-- no translation found for osu_failure_provisioning_not_available (3021783729256985432) --> + <skip /> + <!-- no translation found for osu_failure_invalid_server_url (8548886196179435758) --> + <skip /> + <!-- no translation found for osu_failure_unexpected_command_type (8245921319866603904) --> + <skip /> + <!-- no translation found for osu_failure_unexpected_soap_message_type (2255897608510053065) --> + <skip /> + <!-- no translation found for osu_failure_soap_message_exchange (4357358438685987192) --> + <skip /> + <!-- no translation found for osu_failure_start_redirect_listener (4292769407279548482) --> + <skip /> + <!-- no translation found for osu_failure_timed_out_redirect_listener (3168657820278807508) --> + <skip /> + <!-- no translation found for osu_failure_no_osu_activity_found (4593038891437878675) --> + <skip /> + <!-- no translation found for osu_failure_unexpected_soap_message_status (6568467710235256675) --> + <skip /> + <!-- no translation found for osu_failure_no_pps_mo (850567403039076835) --> + <skip /> + <!-- no translation found for osu_failure_no_aaa_server_trust_root_node (8961455873459838456) --> + <skip /> + <!-- no translation found for osu_failure_no_remediation_server_trust_root_node (5041179688081545244) --> + <skip /> + <!-- no translation found for osu_failure_no_policy_server_trust_root_node (6617290380940513539) --> + <skip /> + <!-- no translation found for osu_failure_retrieve_trust_root_certificates (1499136256195528265) --> + <skip /> + <!-- no translation found for osu_failure_no_aaa_trust_root_certificate (1904322497042226984) --> + <skip /> + <!-- no translation found for osu_failure_add_passpoint_configuration (2173557755811446047) --> + <skip /> + <!-- no translation found for osu_failure_osu_provider_not_found (6616172862116673082) --> + <skip /> + <!-- no translation found for osu_status_ap_connecting (5296821043003441437) --> + <skip /> + <!-- no translation found for osu_status_ap_connected (3777289375683170728) --> + <skip /> + <!-- no translation found for osu_status_server_connecting (8499785407540355867) --> + <skip /> + <!-- no translation found for osu_status_server_validated (3158727184762596355) --> + <skip /> + <!-- no translation found for osu_status_server_connected (8382024481520158168) --> + <skip /> + <!-- no translation found for osu_status_init_soap_exchange (8628063888912101981) --> + <skip /> + <!-- no translation found for osu_status_waiting_for_redirect_response (2343016207837053197) --> + <skip /> + <!-- no translation found for osu_status_redirect_response_received (5323368411922609405) --> + <skip /> + <!-- no translation found for osu_status_second_soap_exchange (7115332266758483909) --> + <skip /> + <!-- no translation found for osu_status_third_soap_exchange (8460901783597440766) --> + <skip /> + <!-- no translation found for osu_status_retrieving_trust_root_certs (1563445892926269689) --> + <skip /> + <!-- no translation found for osu_provisioning_complete (5120178802493970149) --> + <skip /> <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> diff --git a/packages/SettingsLib/res/values-lo/strings.xml b/packages/SettingsLib/res/values-lo/strings.xml index 0505a5d68f5a..009f44f55259 100644 --- a/packages/SettingsLib/res/values-lo/strings.xml +++ b/packages/SettingsLib/res/values-lo/strings.xml @@ -38,13 +38,87 @@ <string name="connected_via_network_scorer" msgid="5713793306870815341">"ເຊື່ອມຕໍ່ຜ່ານທາງ %1$s ໂດຍອັດຕະໂນມັດ"</string> <string name="connected_via_network_scorer_default" msgid="7867260222020343104">"ເຊື່ອມຕໍ່ກັບອັດຕະໂນມັດແລ້ວຜ່ານຜູ້ໃຫ້ບໍລິການຄະແນນເຄືອຂ່າຍ"</string> <string name="connected_via_passpoint" msgid="2826205693803088747">"ເຊື່ອມຕໍ່ຜ່ານ %1$s ແລ້ວ"</string> + <!-- no translation found for ssid_by_passpoint_provider (7898171424140673315) --> + <skip /> <string name="available_via_passpoint" msgid="1617440946846329613">"ມີໃຫ້ຜ່ານ %1$s"</string> + <!-- no translation found for tap_to_set_up (2468970825530423314) --> + <skip /> <string name="wifi_connected_no_internet" msgid="8202906332837777829">"ເຊື່ອມຕໍ່ແລ້ວ, ບໍ່ມີອິນເຕີເນັດ"</string> <string name="wifi_status_no_internet" msgid="5784710974669608361">"ບໍ່ມີອິນເຕີເນັດ"</string> <string name="wifi_status_sign_in_required" msgid="123517180404752756">"ຈຳເປັນຕ້ອງເຂົ້າສູ່ລະບົບ"</string> <string name="wifi_ap_unable_to_handle_new_sta" msgid="5348824313514404541">"ຈຸດການເຂົ້າເຖິງເຕັມຊົ່ວຄາວ"</string> <string name="connected_via_carrier" msgid="7583780074526041912">"ເຊື່ອມຕໍ່ຜ່ານ %1$s ແລ້ວ"</string> <string name="available_via_carrier" msgid="1469036129740799053">"ໃຊ້ໄດ້ຜ່ານ %1$s"</string> + <!-- no translation found for osu_failure_ap_connection (598977488344424542) --> + <skip /> + <!-- no translation found for osu_failure_server_url_invalid (2237477219243136714) --> + <skip /> + <!-- no translation found for osu_failure_server_connection (8192988165059982174) --> + <skip /> + <!-- no translation found for osu_failure_server_validation (4631649978129606823) --> + <skip /> + <!-- no translation found for osu_failure_service_provider_verification (4854091521439785597) --> + <skip /> + <!-- no translation found for osu_failure_provisioning_aborted (424627208135320329) --> + <skip /> + <!-- no translation found for osu_failure_provisioning_not_available (3021783729256985432) --> + <skip /> + <!-- no translation found for osu_failure_invalid_server_url (8548886196179435758) --> + <skip /> + <!-- no translation found for osu_failure_unexpected_command_type (8245921319866603904) --> + <skip /> + <!-- no translation found for osu_failure_unexpected_soap_message_type (2255897608510053065) --> + <skip /> + <!-- no translation found for osu_failure_soap_message_exchange (4357358438685987192) --> + <skip /> + <!-- no translation found for osu_failure_start_redirect_listener (4292769407279548482) --> + <skip /> + <!-- no translation found for osu_failure_timed_out_redirect_listener (3168657820278807508) --> + <skip /> + <!-- no translation found for osu_failure_no_osu_activity_found (4593038891437878675) --> + <skip /> + <!-- no translation found for osu_failure_unexpected_soap_message_status (6568467710235256675) --> + <skip /> + <!-- no translation found for osu_failure_no_pps_mo (850567403039076835) --> + <skip /> + <!-- no translation found for osu_failure_no_aaa_server_trust_root_node (8961455873459838456) --> + <skip /> + <!-- no translation found for osu_failure_no_remediation_server_trust_root_node (5041179688081545244) --> + <skip /> + <!-- no translation found for osu_failure_no_policy_server_trust_root_node (6617290380940513539) --> + <skip /> + <!-- no translation found for osu_failure_retrieve_trust_root_certificates (1499136256195528265) --> + <skip /> + <!-- no translation found for osu_failure_no_aaa_trust_root_certificate (1904322497042226984) --> + <skip /> + <!-- no translation found for osu_failure_add_passpoint_configuration (2173557755811446047) --> + <skip /> + <!-- no translation found for osu_failure_osu_provider_not_found (6616172862116673082) --> + <skip /> + <!-- no translation found for osu_status_ap_connecting (5296821043003441437) --> + <skip /> + <!-- no translation found for osu_status_ap_connected (3777289375683170728) --> + <skip /> + <!-- no translation found for osu_status_server_connecting (8499785407540355867) --> + <skip /> + <!-- no translation found for osu_status_server_validated (3158727184762596355) --> + <skip /> + <!-- no translation found for osu_status_server_connected (8382024481520158168) --> + <skip /> + <!-- no translation found for osu_status_init_soap_exchange (8628063888912101981) --> + <skip /> + <!-- no translation found for osu_status_waiting_for_redirect_response (2343016207837053197) --> + <skip /> + <!-- no translation found for osu_status_redirect_response_received (5323368411922609405) --> + <skip /> + <!-- no translation found for osu_status_second_soap_exchange (7115332266758483909) --> + <skip /> + <!-- no translation found for osu_status_third_soap_exchange (8460901783597440766) --> + <skip /> + <!-- no translation found for osu_status_retrieving_trust_root_certs (1563445892926269689) --> + <skip /> + <!-- no translation found for osu_provisioning_complete (5120178802493970149) --> + <skip /> <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> diff --git a/packages/SettingsLib/res/values-lt/strings.xml b/packages/SettingsLib/res/values-lt/strings.xml index e1412e7b380a..f08a78b8b865 100644 --- a/packages/SettingsLib/res/values-lt/strings.xml +++ b/packages/SettingsLib/res/values-lt/strings.xml @@ -38,13 +38,87 @@ <string name="connected_via_network_scorer" msgid="5713793306870815341">"Automatiškai prisijungta naudojant „%1$s“"</string> <string name="connected_via_network_scorer_default" msgid="7867260222020343104">"Automatiškai prisijungta naudojant tinklo įvertinimo paslaugos teikėjo paslaugomis"</string> <string name="connected_via_passpoint" msgid="2826205693803088747">"Prisijungta naudojant „%1$s“"</string> + <!-- no translation found for ssid_by_passpoint_provider (7898171424140673315) --> + <skip /> <string name="available_via_passpoint" msgid="1617440946846329613">"Pasiekiama naudojant „%1$s“"</string> + <!-- no translation found for tap_to_set_up (2468970825530423314) --> + <skip /> <string name="wifi_connected_no_internet" msgid="8202906332837777829">"Prisijungta, nėra interneto"</string> <string name="wifi_status_no_internet" msgid="5784710974669608361">"Nėra interneto ryšio"</string> <string name="wifi_status_sign_in_required" msgid="123517180404752756">"Reikia prisijungti"</string> <string name="wifi_ap_unable_to_handle_new_sta" msgid="5348824313514404541">"Prieigos taškas laikinai visiškai užimtas"</string> <string name="connected_via_carrier" msgid="7583780074526041912">"Prisijungta naudojant „%1$s“"</string> <string name="available_via_carrier" msgid="1469036129740799053">"Pasiekiama naudojant „%1$s“"</string> + <!-- no translation found for osu_failure_ap_connection (598977488344424542) --> + <skip /> + <!-- no translation found for osu_failure_server_url_invalid (2237477219243136714) --> + <skip /> + <!-- no translation found for osu_failure_server_connection (8192988165059982174) --> + <skip /> + <!-- no translation found for osu_failure_server_validation (4631649978129606823) --> + <skip /> + <!-- no translation found for osu_failure_service_provider_verification (4854091521439785597) --> + <skip /> + <!-- no translation found for osu_failure_provisioning_aborted (424627208135320329) --> + <skip /> + <!-- no translation found for osu_failure_provisioning_not_available (3021783729256985432) --> + <skip /> + <!-- no translation found for osu_failure_invalid_server_url (8548886196179435758) --> + <skip /> + <!-- no translation found for osu_failure_unexpected_command_type (8245921319866603904) --> + <skip /> + <!-- no translation found for osu_failure_unexpected_soap_message_type (2255897608510053065) --> + <skip /> + <!-- no translation found for osu_failure_soap_message_exchange (4357358438685987192) --> + <skip /> + <!-- no translation found for osu_failure_start_redirect_listener (4292769407279548482) --> + <skip /> + <!-- no translation found for osu_failure_timed_out_redirect_listener (3168657820278807508) --> + <skip /> + <!-- no translation found for osu_failure_no_osu_activity_found (4593038891437878675) --> + <skip /> + <!-- no translation found for osu_failure_unexpected_soap_message_status (6568467710235256675) --> + <skip /> + <!-- no translation found for osu_failure_no_pps_mo (850567403039076835) --> + <skip /> + <!-- no translation found for osu_failure_no_aaa_server_trust_root_node (8961455873459838456) --> + <skip /> + <!-- no translation found for osu_failure_no_remediation_server_trust_root_node (5041179688081545244) --> + <skip /> + <!-- no translation found for osu_failure_no_policy_server_trust_root_node (6617290380940513539) --> + <skip /> + <!-- no translation found for osu_failure_retrieve_trust_root_certificates (1499136256195528265) --> + <skip /> + <!-- no translation found for osu_failure_no_aaa_trust_root_certificate (1904322497042226984) --> + <skip /> + <!-- no translation found for osu_failure_add_passpoint_configuration (2173557755811446047) --> + <skip /> + <!-- no translation found for osu_failure_osu_provider_not_found (6616172862116673082) --> + <skip /> + <!-- no translation found for osu_status_ap_connecting (5296821043003441437) --> + <skip /> + <!-- no translation found for osu_status_ap_connected (3777289375683170728) --> + <skip /> + <!-- no translation found for osu_status_server_connecting (8499785407540355867) --> + <skip /> + <!-- no translation found for osu_status_server_validated (3158727184762596355) --> + <skip /> + <!-- no translation found for osu_status_server_connected (8382024481520158168) --> + <skip /> + <!-- no translation found for osu_status_init_soap_exchange (8628063888912101981) --> + <skip /> + <!-- no translation found for osu_status_waiting_for_redirect_response (2343016207837053197) --> + <skip /> + <!-- no translation found for osu_status_redirect_response_received (5323368411922609405) --> + <skip /> + <!-- no translation found for osu_status_second_soap_exchange (7115332266758483909) --> + <skip /> + <!-- no translation found for osu_status_third_soap_exchange (8460901783597440766) --> + <skip /> + <!-- no translation found for osu_status_retrieving_trust_root_certs (1563445892926269689) --> + <skip /> + <!-- no translation found for osu_provisioning_complete (5120178802493970149) --> + <skip /> <string name="speed_label_very_slow" msgid="1867055264243608530">"Labai lėtas"</string> <string name="speed_label_slow" msgid="813109590815810235">"Lėtas"</string> <string name="speed_label_okay" msgid="2331665440671174858">"Gerai"</string> diff --git a/packages/SettingsLib/res/values-lv/strings.xml b/packages/SettingsLib/res/values-lv/strings.xml index 50827756534e..c768d11f3bbe 100644 --- a/packages/SettingsLib/res/values-lv/strings.xml +++ b/packages/SettingsLib/res/values-lv/strings.xml @@ -38,13 +38,87 @@ <string name="connected_via_network_scorer" msgid="5713793306870815341">"Automātiski savienots, izmantojot %1$s"</string> <string name="connected_via_network_scorer_default" msgid="7867260222020343104">"Automātiski izveidots savienojums, izmantojot tīkla vērtējuma sniedzēju"</string> <string name="connected_via_passpoint" msgid="2826205693803088747">"Savienots, izmantojot %1$s"</string> + <!-- no translation found for ssid_by_passpoint_provider (7898171424140673315) --> + <skip /> <string name="available_via_passpoint" msgid="1617440946846329613">"Pieejams, izmantojot %1$s"</string> + <!-- no translation found for tap_to_set_up (2468970825530423314) --> + <skip /> <string name="wifi_connected_no_internet" msgid="8202906332837777829">"Savienojums izveidots, nav piekļuves internetam"</string> <string name="wifi_status_no_internet" msgid="5784710974669608361">"Nav piekļuves internetam"</string> <string name="wifi_status_sign_in_required" msgid="123517180404752756">"Nepieciešama pierakstīšanās"</string> <string name="wifi_ap_unable_to_handle_new_sta" msgid="5348824313514404541">"Piekļuves punkts īslaicīgi ir pilns"</string> <string name="connected_via_carrier" msgid="7583780074526041912">"Savienojums izveidots, izmantojot %1$s"</string> <string name="available_via_carrier" msgid="1469036129740799053">"Pieejams, izmantojot %1$s"</string> + <!-- no translation found for osu_failure_ap_connection (598977488344424542) --> + <skip /> + <!-- no translation found for osu_failure_server_url_invalid (2237477219243136714) --> + <skip /> + <!-- no translation found for osu_failure_server_connection (8192988165059982174) --> + <skip /> + <!-- no translation found for osu_failure_server_validation (4631649978129606823) --> + <skip /> + <!-- no translation found for osu_failure_service_provider_verification (4854091521439785597) --> + <skip /> + <!-- no translation found for osu_failure_provisioning_aborted (424627208135320329) --> + <skip /> + <!-- no translation found for osu_failure_provisioning_not_available (3021783729256985432) --> + <skip /> + <!-- no translation found for osu_failure_invalid_server_url (8548886196179435758) --> + <skip /> + <!-- no translation found for osu_failure_unexpected_command_type (8245921319866603904) --> + <skip /> + <!-- no translation found for osu_failure_unexpected_soap_message_type (2255897608510053065) --> + <skip /> + <!-- no translation found for osu_failure_soap_message_exchange (4357358438685987192) --> + <skip /> + <!-- no translation found for osu_failure_start_redirect_listener (4292769407279548482) --> + <skip /> + <!-- no translation found for osu_failure_timed_out_redirect_listener (3168657820278807508) --> + <skip /> + <!-- no translation found for osu_failure_no_osu_activity_found (4593038891437878675) --> + <skip /> + <!-- no translation found for osu_failure_unexpected_soap_message_status (6568467710235256675) --> + <skip /> + <!-- no translation found for osu_failure_no_pps_mo (850567403039076835) --> + <skip /> + <!-- no translation found for osu_failure_no_aaa_server_trust_root_node (8961455873459838456) --> + <skip /> + <!-- no translation found for osu_failure_no_remediation_server_trust_root_node (5041179688081545244) --> + <skip /> + <!-- no translation found for osu_failure_no_policy_server_trust_root_node (6617290380940513539) --> + <skip /> + <!-- no translation found for osu_failure_retrieve_trust_root_certificates (1499136256195528265) --> + <skip /> + <!-- no translation found for osu_failure_no_aaa_trust_root_certificate (1904322497042226984) --> + <skip /> + <!-- no translation found for osu_failure_add_passpoint_configuration (2173557755811446047) --> + <skip /> + <!-- no translation found for osu_failure_osu_provider_not_found (6616172862116673082) --> + <skip /> + <!-- no translation found for osu_status_ap_connecting (5296821043003441437) --> + <skip /> + <!-- no translation found for osu_status_ap_connected (3777289375683170728) --> + <skip /> + <!-- no translation found for osu_status_server_connecting (8499785407540355867) --> + <skip /> + <!-- no translation found for osu_status_server_validated (3158727184762596355) --> + <skip /> + <!-- no translation found for osu_status_server_connected (8382024481520158168) --> + <skip /> + <!-- no translation found for osu_status_init_soap_exchange (8628063888912101981) --> + <skip /> + <!-- no translation found for osu_status_waiting_for_redirect_response (2343016207837053197) --> + <skip /> + <!-- no translation found for osu_status_redirect_response_received (5323368411922609405) --> + <skip /> + <!-- no translation found for osu_status_second_soap_exchange (7115332266758483909) --> + <skip /> + <!-- no translation found for osu_status_third_soap_exchange (8460901783597440766) --> + <skip /> + <!-- no translation found for osu_status_retrieving_trust_root_certs (1563445892926269689) --> + <skip /> + <!-- no translation found for osu_provisioning_complete (5120178802493970149) --> + <skip /> <string name="speed_label_very_slow" msgid="1867055264243608530">"Ļoti lēns"</string> <string name="speed_label_slow" msgid="813109590815810235">"Lēns"</string> <string name="speed_label_okay" msgid="2331665440671174858">"Labi"</string> diff --git a/packages/SettingsLib/res/values-mk/strings.xml b/packages/SettingsLib/res/values-mk/strings.xml index 99cf46896520..85430a64ee4c 100644 --- a/packages/SettingsLib/res/values-mk/strings.xml +++ b/packages/SettingsLib/res/values-mk/strings.xml @@ -38,13 +38,87 @@ <string name="connected_via_network_scorer" msgid="5713793306870815341">"Автоматски поврзано преку %1$s"</string> <string name="connected_via_network_scorer_default" msgid="7867260222020343104">"Автоматски поврзано преку оператор за оценување мрежа"</string> <string name="connected_via_passpoint" msgid="2826205693803088747">"Поврзано преку %1$s"</string> + <!-- no translation found for ssid_by_passpoint_provider (7898171424140673315) --> + <skip /> <string name="available_via_passpoint" msgid="1617440946846329613">"Достапно преку %1$s"</string> + <!-- no translation found for tap_to_set_up (2468970825530423314) --> + <skip /> <string name="wifi_connected_no_internet" msgid="8202906332837777829">"Поврзана, нема интернет"</string> <string name="wifi_status_no_internet" msgid="5784710974669608361">"Нема интернет"</string> <string name="wifi_status_sign_in_required" msgid="123517180404752756">"Потребно е најавување"</string> <string name="wifi_ap_unable_to_handle_new_sta" msgid="5348824313514404541">"Пристапната точка привремено е преоптоварена"</string> <string name="connected_via_carrier" msgid="7583780074526041912">"Поврзано преку %1$s"</string> <string name="available_via_carrier" msgid="1469036129740799053">"Достапно преку %1$s"</string> + <!-- no translation found for osu_failure_ap_connection (598977488344424542) --> + <skip /> + <!-- no translation found for osu_failure_server_url_invalid (2237477219243136714) --> + <skip /> + <!-- no translation found for osu_failure_server_connection (8192988165059982174) --> + <skip /> + <!-- no translation found for osu_failure_server_validation (4631649978129606823) --> + <skip /> + <!-- no translation found for osu_failure_service_provider_verification (4854091521439785597) --> + <skip /> + <!-- no translation found for osu_failure_provisioning_aborted (424627208135320329) --> + <skip /> + <!-- no translation found for osu_failure_provisioning_not_available (3021783729256985432) --> + <skip /> + <!-- no translation found for osu_failure_invalid_server_url (8548886196179435758) --> + <skip /> + <!-- no translation found for osu_failure_unexpected_command_type (8245921319866603904) --> + <skip /> + <!-- no translation found for osu_failure_unexpected_soap_message_type (2255897608510053065) --> + <skip /> + <!-- no translation found for osu_failure_soap_message_exchange (4357358438685987192) --> + <skip /> + <!-- no translation found for osu_failure_start_redirect_listener (4292769407279548482) --> + <skip /> + <!-- no translation found for osu_failure_timed_out_redirect_listener (3168657820278807508) --> + <skip /> + <!-- no translation found for osu_failure_no_osu_activity_found (4593038891437878675) --> + <skip /> + <!-- no translation found for osu_failure_unexpected_soap_message_status (6568467710235256675) --> + <skip /> + <!-- no translation found for osu_failure_no_pps_mo (850567403039076835) --> + <skip /> + <!-- no translation found for osu_failure_no_aaa_server_trust_root_node (8961455873459838456) --> + <skip /> + <!-- no translation found for osu_failure_no_remediation_server_trust_root_node (5041179688081545244) --> + <skip /> + <!-- no translation found for osu_failure_no_policy_server_trust_root_node (6617290380940513539) --> + <skip /> + <!-- no translation found for osu_failure_retrieve_trust_root_certificates (1499136256195528265) --> + <skip /> + <!-- no translation found for osu_failure_no_aaa_trust_root_certificate (1904322497042226984) --> + <skip /> + <!-- no translation found for osu_failure_add_passpoint_configuration (2173557755811446047) --> + <skip /> + <!-- no translation found for osu_failure_osu_provider_not_found (6616172862116673082) --> + <skip /> + <!-- no translation found for osu_status_ap_connecting (5296821043003441437) --> + <skip /> + <!-- no translation found for osu_status_ap_connected (3777289375683170728) --> + <skip /> + <!-- no translation found for osu_status_server_connecting (8499785407540355867) --> + <skip /> + <!-- no translation found for osu_status_server_validated (3158727184762596355) --> + <skip /> + <!-- no translation found for osu_status_server_connected (8382024481520158168) --> + <skip /> + <!-- no translation found for osu_status_init_soap_exchange (8628063888912101981) --> + <skip /> + <!-- no translation found for osu_status_waiting_for_redirect_response (2343016207837053197) --> + <skip /> + <!-- no translation found for osu_status_redirect_response_received (5323368411922609405) --> + <skip /> + <!-- no translation found for osu_status_second_soap_exchange (7115332266758483909) --> + <skip /> + <!-- no translation found for osu_status_third_soap_exchange (8460901783597440766) --> + <skip /> + <!-- no translation found for osu_status_retrieving_trust_root_certs (1563445892926269689) --> + <skip /> + <!-- no translation found for osu_provisioning_complete (5120178802493970149) --> + <skip /> <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> diff --git a/packages/SettingsLib/res/values-ml/strings.xml b/packages/SettingsLib/res/values-ml/strings.xml index a0222ad5f004..c3438dca9437 100644 --- a/packages/SettingsLib/res/values-ml/strings.xml +++ b/packages/SettingsLib/res/values-ml/strings.xml @@ -38,13 +38,87 @@ <string name="connected_via_network_scorer" msgid="5713793306870815341">"%1$s വഴി സ്വയമേവ ബന്ധിപ്പിച്ചു"</string> <string name="connected_via_network_scorer_default" msgid="7867260222020343104">"നെറ്റ്വർക്ക് റേറ്റിംഗ് ദാതാവുമായി സ്വയം കണക്റ്റുചെയ്തു"</string> <string name="connected_via_passpoint" msgid="2826205693803088747">"%1$s വഴി ബന്ധിപ്പിച്ചു"</string> + <!-- no translation found for ssid_by_passpoint_provider (7898171424140673315) --> + <skip /> <string name="available_via_passpoint" msgid="1617440946846329613">"%1$s വഴി ലഭ്യം"</string> + <!-- no translation found for tap_to_set_up (2468970825530423314) --> + <skip /> <string name="wifi_connected_no_internet" msgid="8202906332837777829">"കണക്റ്റ് ചെയ്തു, ഇന്റർനെറ്റ് ഇല്ല"</string> <string name="wifi_status_no_internet" msgid="5784710974669608361">"ഇന്റർനെറ്റ് ഇല്ല"</string> <string name="wifi_status_sign_in_required" msgid="123517180404752756">"സൈൻ ഇൻ ചെയ്യേണ്ടത് ആവശ്യമാണ്"</string> <string name="wifi_ap_unable_to_handle_new_sta" msgid="5348824313514404541">"ആക്സസ് പോയിന്റ് താൽക്കാലികമായി നിറഞ്ഞിരിക്കുന്നു"</string> <string name="connected_via_carrier" msgid="7583780074526041912">"%1$s വഴി ബന്ധിപ്പിച്ചു"</string> <string name="available_via_carrier" msgid="1469036129740799053">"%1$s വഴി ലഭ്യം"</string> + <!-- no translation found for osu_failure_ap_connection (598977488344424542) --> + <skip /> + <!-- no translation found for osu_failure_server_url_invalid (2237477219243136714) --> + <skip /> + <!-- no translation found for osu_failure_server_connection (8192988165059982174) --> + <skip /> + <!-- no translation found for osu_failure_server_validation (4631649978129606823) --> + <skip /> + <!-- no translation found for osu_failure_service_provider_verification (4854091521439785597) --> + <skip /> + <!-- no translation found for osu_failure_provisioning_aborted (424627208135320329) --> + <skip /> + <!-- no translation found for osu_failure_provisioning_not_available (3021783729256985432) --> + <skip /> + <!-- no translation found for osu_failure_invalid_server_url (8548886196179435758) --> + <skip /> + <!-- no translation found for osu_failure_unexpected_command_type (8245921319866603904) --> + <skip /> + <!-- no translation found for osu_failure_unexpected_soap_message_type (2255897608510053065) --> + <skip /> + <!-- no translation found for osu_failure_soap_message_exchange (4357358438685987192) --> + <skip /> + <!-- no translation found for osu_failure_start_redirect_listener (4292769407279548482) --> + <skip /> + <!-- no translation found for osu_failure_timed_out_redirect_listener (3168657820278807508) --> + <skip /> + <!-- no translation found for osu_failure_no_osu_activity_found (4593038891437878675) --> + <skip /> + <!-- no translation found for osu_failure_unexpected_soap_message_status (6568467710235256675) --> + <skip /> + <!-- no translation found for osu_failure_no_pps_mo (850567403039076835) --> + <skip /> + <!-- no translation found for osu_failure_no_aaa_server_trust_root_node (8961455873459838456) --> + <skip /> + <!-- no translation found for osu_failure_no_remediation_server_trust_root_node (5041179688081545244) --> + <skip /> + <!-- no translation found for osu_failure_no_policy_server_trust_root_node (6617290380940513539) --> + <skip /> + <!-- no translation found for osu_failure_retrieve_trust_root_certificates (1499136256195528265) --> + <skip /> + <!-- no translation found for osu_failure_no_aaa_trust_root_certificate (1904322497042226984) --> + <skip /> + <!-- no translation found for osu_failure_add_passpoint_configuration (2173557755811446047) --> + <skip /> + <!-- no translation found for osu_failure_osu_provider_not_found (6616172862116673082) --> + <skip /> + <!-- no translation found for osu_status_ap_connecting (5296821043003441437) --> + <skip /> + <!-- no translation found for osu_status_ap_connected (3777289375683170728) --> + <skip /> + <!-- no translation found for osu_status_server_connecting (8499785407540355867) --> + <skip /> + <!-- no translation found for osu_status_server_validated (3158727184762596355) --> + <skip /> + <!-- no translation found for osu_status_server_connected (8382024481520158168) --> + <skip /> + <!-- no translation found for osu_status_init_soap_exchange (8628063888912101981) --> + <skip /> + <!-- no translation found for osu_status_waiting_for_redirect_response (2343016207837053197) --> + <skip /> + <!-- no translation found for osu_status_redirect_response_received (5323368411922609405) --> + <skip /> + <!-- no translation found for osu_status_second_soap_exchange (7115332266758483909) --> + <skip /> + <!-- no translation found for osu_status_third_soap_exchange (8460901783597440766) --> + <skip /> + <!-- no translation found for osu_status_retrieving_trust_root_certs (1563445892926269689) --> + <skip /> + <!-- no translation found for osu_provisioning_complete (5120178802493970149) --> + <skip /> <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> diff --git a/packages/SettingsLib/res/values-mn/strings.xml b/packages/SettingsLib/res/values-mn/strings.xml index 5b2acac3ddd5..7c8aa8b1e00e 100644 --- a/packages/SettingsLib/res/values-mn/strings.xml +++ b/packages/SettingsLib/res/values-mn/strings.xml @@ -38,13 +38,87 @@ <string name="connected_via_network_scorer" msgid="5713793306870815341">"%1$s-р автоматаар холбогдсон"</string> <string name="connected_via_network_scorer_default" msgid="7867260222020343104">"Сүлжээний үнэлгээ үзүүлэгчээр автоматаар холбогдох"</string> <string name="connected_via_passpoint" msgid="2826205693803088747">"%1$s-р холбогдсон"</string> + <!-- no translation found for ssid_by_passpoint_provider (7898171424140673315) --> + <skip /> <string name="available_via_passpoint" msgid="1617440946846329613">"%1$s-р боломжтой"</string> + <!-- no translation found for tap_to_set_up (2468970825530423314) --> + <skip /> <string name="wifi_connected_no_internet" msgid="8202906332837777829">"Холбогдсон хэдий ч интернет алга"</string> <string name="wifi_status_no_internet" msgid="5784710974669608361">"Интернэт алга"</string> <string name="wifi_status_sign_in_required" msgid="123517180404752756">"Нэвтрэх шаардлагатай"</string> <string name="wifi_ap_unable_to_handle_new_sta" msgid="5348824313514404541">"Хандах цэг түр хугацаанд дүүрсэн байна"</string> <string name="connected_via_carrier" msgid="7583780074526041912">"%1$s-р холбогдсон"</string> <string name="available_via_carrier" msgid="1469036129740799053">"%1$s-р боломжтой"</string> + <!-- no translation found for osu_failure_ap_connection (598977488344424542) --> + <skip /> + <!-- no translation found for osu_failure_server_url_invalid (2237477219243136714) --> + <skip /> + <!-- no translation found for osu_failure_server_connection (8192988165059982174) --> + <skip /> + <!-- no translation found for osu_failure_server_validation (4631649978129606823) --> + <skip /> + <!-- no translation found for osu_failure_service_provider_verification (4854091521439785597) --> + <skip /> + <!-- no translation found for osu_failure_provisioning_aborted (424627208135320329) --> + <skip /> + <!-- no translation found for osu_failure_provisioning_not_available (3021783729256985432) --> + <skip /> + <!-- no translation found for osu_failure_invalid_server_url (8548886196179435758) --> + <skip /> + <!-- no translation found for osu_failure_unexpected_command_type (8245921319866603904) --> + <skip /> + <!-- no translation found for osu_failure_unexpected_soap_message_type (2255897608510053065) --> + <skip /> + <!-- no translation found for osu_failure_soap_message_exchange (4357358438685987192) --> + <skip /> + <!-- no translation found for osu_failure_start_redirect_listener (4292769407279548482) --> + <skip /> + <!-- no translation found for osu_failure_timed_out_redirect_listener (3168657820278807508) --> + <skip /> + <!-- no translation found for osu_failure_no_osu_activity_found (4593038891437878675) --> + <skip /> + <!-- no translation found for osu_failure_unexpected_soap_message_status (6568467710235256675) --> + <skip /> + <!-- no translation found for osu_failure_no_pps_mo (850567403039076835) --> + <skip /> + <!-- no translation found for osu_failure_no_aaa_server_trust_root_node (8961455873459838456) --> + <skip /> + <!-- no translation found for osu_failure_no_remediation_server_trust_root_node (5041179688081545244) --> + <skip /> + <!-- no translation found for osu_failure_no_policy_server_trust_root_node (6617290380940513539) --> + <skip /> + <!-- no translation found for osu_failure_retrieve_trust_root_certificates (1499136256195528265) --> + <skip /> + <!-- no translation found for osu_failure_no_aaa_trust_root_certificate (1904322497042226984) --> + <skip /> + <!-- no translation found for osu_failure_add_passpoint_configuration (2173557755811446047) --> + <skip /> + <!-- no translation found for osu_failure_osu_provider_not_found (6616172862116673082) --> + <skip /> + <!-- no translation found for osu_status_ap_connecting (5296821043003441437) --> + <skip /> + <!-- no translation found for osu_status_ap_connected (3777289375683170728) --> + <skip /> + <!-- no translation found for osu_status_server_connecting (8499785407540355867) --> + <skip /> + <!-- no translation found for osu_status_server_validated (3158727184762596355) --> + <skip /> + <!-- no translation found for osu_status_server_connected (8382024481520158168) --> + <skip /> + <!-- no translation found for osu_status_init_soap_exchange (8628063888912101981) --> + <skip /> + <!-- no translation found for osu_status_waiting_for_redirect_response (2343016207837053197) --> + <skip /> + <!-- no translation found for osu_status_redirect_response_received (5323368411922609405) --> + <skip /> + <!-- no translation found for osu_status_second_soap_exchange (7115332266758483909) --> + <skip /> + <!-- no translation found for osu_status_third_soap_exchange (8460901783597440766) --> + <skip /> + <!-- no translation found for osu_status_retrieving_trust_root_certs (1563445892926269689) --> + <skip /> + <!-- no translation found for osu_provisioning_complete (5120178802493970149) --> + <skip /> <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> diff --git a/packages/SettingsLib/res/values-mr/strings.xml b/packages/SettingsLib/res/values-mr/strings.xml index 891ada8c0507..3ab2a4b40dc1 100644 --- a/packages/SettingsLib/res/values-mr/strings.xml +++ b/packages/SettingsLib/res/values-mr/strings.xml @@ -38,13 +38,87 @@ <string name="connected_via_network_scorer" msgid="5713793306870815341">"%1$s द्वारे स्वयंचलितपणे कनेक्ट केले"</string> <string name="connected_via_network_scorer_default" msgid="7867260222020343104">"नेटवर्क रेटिंग प्रदात्याद्वारे स्वयंचलितपणे कनेक्ट केले"</string> <string name="connected_via_passpoint" msgid="2826205693803088747">"%1$s द्वारे कनेक्ट केले"</string> + <!-- no translation found for ssid_by_passpoint_provider (7898171424140673315) --> + <skip /> <string name="available_via_passpoint" msgid="1617440946846329613">"%1$s द्वारे उपलब्ध"</string> + <!-- no translation found for tap_to_set_up (2468970825530423314) --> + <skip /> <string name="wifi_connected_no_internet" msgid="8202906332837777829">"कनेक्ट केले, इंटरनेट नाही"</string> <string name="wifi_status_no_internet" msgid="5784710974669608361">"इंटरनेट नाही"</string> <string name="wifi_status_sign_in_required" msgid="123517180404752756">"साइन इन करणे आवश्यक आहे"</string> <string name="wifi_ap_unable_to_handle_new_sta" msgid="5348824313514404541">"अॅक्सेस पॉइंट तात्पुरते भरलेले"</string> <string name="connected_via_carrier" msgid="7583780074526041912">"%1$s ने कनेक्ट केले"</string> <string name="available_via_carrier" msgid="1469036129740799053">"%1$s ने उपलब्ध"</string> + <!-- no translation found for osu_failure_ap_connection (598977488344424542) --> + <skip /> + <!-- no translation found for osu_failure_server_url_invalid (2237477219243136714) --> + <skip /> + <!-- no translation found for osu_failure_server_connection (8192988165059982174) --> + <skip /> + <!-- no translation found for osu_failure_server_validation (4631649978129606823) --> + <skip /> + <!-- no translation found for osu_failure_service_provider_verification (4854091521439785597) --> + <skip /> + <!-- no translation found for osu_failure_provisioning_aborted (424627208135320329) --> + <skip /> + <!-- no translation found for osu_failure_provisioning_not_available (3021783729256985432) --> + <skip /> + <!-- no translation found for osu_failure_invalid_server_url (8548886196179435758) --> + <skip /> + <!-- no translation found for osu_failure_unexpected_command_type (8245921319866603904) --> + <skip /> + <!-- no translation found for osu_failure_unexpected_soap_message_type (2255897608510053065) --> + <skip /> + <!-- no translation found for osu_failure_soap_message_exchange (4357358438685987192) --> + <skip /> + <!-- no translation found for osu_failure_start_redirect_listener (4292769407279548482) --> + <skip /> + <!-- no translation found for osu_failure_timed_out_redirect_listener (3168657820278807508) --> + <skip /> + <!-- no translation found for osu_failure_no_osu_activity_found (4593038891437878675) --> + <skip /> + <!-- no translation found for osu_failure_unexpected_soap_message_status (6568467710235256675) --> + <skip /> + <!-- no translation found for osu_failure_no_pps_mo (850567403039076835) --> + <skip /> + <!-- no translation found for osu_failure_no_aaa_server_trust_root_node (8961455873459838456) --> + <skip /> + <!-- no translation found for osu_failure_no_remediation_server_trust_root_node (5041179688081545244) --> + <skip /> + <!-- no translation found for osu_failure_no_policy_server_trust_root_node (6617290380940513539) --> + <skip /> + <!-- no translation found for osu_failure_retrieve_trust_root_certificates (1499136256195528265) --> + <skip /> + <!-- no translation found for osu_failure_no_aaa_trust_root_certificate (1904322497042226984) --> + <skip /> + <!-- no translation found for osu_failure_add_passpoint_configuration (2173557755811446047) --> + <skip /> + <!-- no translation found for osu_failure_osu_provider_not_found (6616172862116673082) --> + <skip /> + <!-- no translation found for osu_status_ap_connecting (5296821043003441437) --> + <skip /> + <!-- no translation found for osu_status_ap_connected (3777289375683170728) --> + <skip /> + <!-- no translation found for osu_status_server_connecting (8499785407540355867) --> + <skip /> + <!-- no translation found for osu_status_server_validated (3158727184762596355) --> + <skip /> + <!-- no translation found for osu_status_server_connected (8382024481520158168) --> + <skip /> + <!-- no translation found for osu_status_init_soap_exchange (8628063888912101981) --> + <skip /> + <!-- no translation found for osu_status_waiting_for_redirect_response (2343016207837053197) --> + <skip /> + <!-- no translation found for osu_status_redirect_response_received (5323368411922609405) --> + <skip /> + <!-- no translation found for osu_status_second_soap_exchange (7115332266758483909) --> + <skip /> + <!-- no translation found for osu_status_third_soap_exchange (8460901783597440766) --> + <skip /> + <!-- no translation found for osu_status_retrieving_trust_root_certs (1563445892926269689) --> + <skip /> + <!-- no translation found for osu_provisioning_complete (5120178802493970149) --> + <skip /> <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> diff --git a/packages/SettingsLib/res/values-ms/strings.xml b/packages/SettingsLib/res/values-ms/strings.xml index 8030c3e7ce5e..5459b80b2ea2 100644 --- a/packages/SettingsLib/res/values-ms/strings.xml +++ b/packages/SettingsLib/res/values-ms/strings.xml @@ -38,13 +38,87 @@ <string name="connected_via_network_scorer" msgid="5713793306870815341">"Disambungkan secara automatik melalui %1$s"</string> <string name="connected_via_network_scorer_default" msgid="7867260222020343104">"Disambungkan secara automatik melalui pembekal penilaian rangkaian"</string> <string name="connected_via_passpoint" msgid="2826205693803088747">"Disambungkan melalui %1$s"</string> + <!-- no translation found for ssid_by_passpoint_provider (7898171424140673315) --> + <skip /> <string name="available_via_passpoint" msgid="1617440946846329613">"Tersedia melalui %1$s"</string> + <!-- no translation found for tap_to_set_up (2468970825530423314) --> + <skip /> <string name="wifi_connected_no_internet" msgid="8202906332837777829">"Disambungkan, tiada Internet"</string> <string name="wifi_status_no_internet" msgid="5784710974669608361">"Tiada Internet"</string> <string name="wifi_status_sign_in_required" msgid="123517180404752756">"Log masuk diperlukan"</string> <string name="wifi_ap_unable_to_handle_new_sta" msgid="5348824313514404541">"Titik akses penuh buat sementara waktu"</string> <string name="connected_via_carrier" msgid="7583780074526041912">"Disambungkan melalui %1$s"</string> <string name="available_via_carrier" msgid="1469036129740799053">"Tersedia melalui %1$s"</string> + <!-- no translation found for osu_failure_ap_connection (598977488344424542) --> + <skip /> + <!-- no translation found for osu_failure_server_url_invalid (2237477219243136714) --> + <skip /> + <!-- no translation found for osu_failure_server_connection (8192988165059982174) --> + <skip /> + <!-- no translation found for osu_failure_server_validation (4631649978129606823) --> + <skip /> + <!-- no translation found for osu_failure_service_provider_verification (4854091521439785597) --> + <skip /> + <!-- no translation found for osu_failure_provisioning_aborted (424627208135320329) --> + <skip /> + <!-- no translation found for osu_failure_provisioning_not_available (3021783729256985432) --> + <skip /> + <!-- no translation found for osu_failure_invalid_server_url (8548886196179435758) --> + <skip /> + <!-- no translation found for osu_failure_unexpected_command_type (8245921319866603904) --> + <skip /> + <!-- no translation found for osu_failure_unexpected_soap_message_type (2255897608510053065) --> + <skip /> + <!-- no translation found for osu_failure_soap_message_exchange (4357358438685987192) --> + <skip /> + <!-- no translation found for osu_failure_start_redirect_listener (4292769407279548482) --> + <skip /> + <!-- no translation found for osu_failure_timed_out_redirect_listener (3168657820278807508) --> + <skip /> + <!-- no translation found for osu_failure_no_osu_activity_found (4593038891437878675) --> + <skip /> + <!-- no translation found for osu_failure_unexpected_soap_message_status (6568467710235256675) --> + <skip /> + <!-- no translation found for osu_failure_no_pps_mo (850567403039076835) --> + <skip /> + <!-- no translation found for osu_failure_no_aaa_server_trust_root_node (8961455873459838456) --> + <skip /> + <!-- no translation found for osu_failure_no_remediation_server_trust_root_node (5041179688081545244) --> + <skip /> + <!-- no translation found for osu_failure_no_policy_server_trust_root_node (6617290380940513539) --> + <skip /> + <!-- no translation found for osu_failure_retrieve_trust_root_certificates (1499136256195528265) --> + <skip /> + <!-- no translation found for osu_failure_no_aaa_trust_root_certificate (1904322497042226984) --> + <skip /> + <!-- no translation found for osu_failure_add_passpoint_configuration (2173557755811446047) --> + <skip /> + <!-- no translation found for osu_failure_osu_provider_not_found (6616172862116673082) --> + <skip /> + <!-- no translation found for osu_status_ap_connecting (5296821043003441437) --> + <skip /> + <!-- no translation found for osu_status_ap_connected (3777289375683170728) --> + <skip /> + <!-- no translation found for osu_status_server_connecting (8499785407540355867) --> + <skip /> + <!-- no translation found for osu_status_server_validated (3158727184762596355) --> + <skip /> + <!-- no translation found for osu_status_server_connected (8382024481520158168) --> + <skip /> + <!-- no translation found for osu_status_init_soap_exchange (8628063888912101981) --> + <skip /> + <!-- no translation found for osu_status_waiting_for_redirect_response (2343016207837053197) --> + <skip /> + <!-- no translation found for osu_status_redirect_response_received (5323368411922609405) --> + <skip /> + <!-- no translation found for osu_status_second_soap_exchange (7115332266758483909) --> + <skip /> + <!-- no translation found for osu_status_third_soap_exchange (8460901783597440766) --> + <skip /> + <!-- no translation found for osu_status_retrieving_trust_root_certs (1563445892926269689) --> + <skip /> + <!-- no translation found for osu_provisioning_complete (5120178802493970149) --> + <skip /> <string name="speed_label_very_slow" msgid="1867055264243608530">"Sangat Perlahan"</string> <string name="speed_label_slow" msgid="813109590815810235">"Perlahan"</string> <string name="speed_label_okay" msgid="2331665440671174858">"OK"</string> diff --git a/packages/SettingsLib/res/values-my/strings.xml b/packages/SettingsLib/res/values-my/strings.xml index c54397463c43..254de2a6c6af 100644 --- a/packages/SettingsLib/res/values-my/strings.xml +++ b/packages/SettingsLib/res/values-my/strings.xml @@ -38,13 +38,87 @@ <string name="connected_via_network_scorer" msgid="5713793306870815341">"%1$s မှတစ်ဆင့် အလိုအလျောက် ချိတ်ဆက်ထားပါသည်"</string> <string name="connected_via_network_scorer_default" msgid="7867260222020343104">"ကွန်ရက်အဆင့်သတ်မှတ်ပေးသူ မှတစ်ဆင့် အလိုအလျောက် ချိတ်ဆက်ထားပါသည်"</string> <string name="connected_via_passpoint" msgid="2826205693803088747">"%1$s မှတစ်ဆင့် ချိတ်ဆက်ထားသည်"</string> + <!-- no translation found for ssid_by_passpoint_provider (7898171424140673315) --> + <skip /> <string name="available_via_passpoint" msgid="1617440946846329613">"%1$s မှတစ်ဆင့်ရနိုင်သည်"</string> + <!-- no translation found for tap_to_set_up (2468970825530423314) --> + <skip /> <string name="wifi_connected_no_internet" msgid="8202906332837777829">"ချိတ်ဆက်ထားသည်၊ အင်တာနက်မရှိ"</string> <string name="wifi_status_no_internet" msgid="5784710974669608361">"အင်တာနက် မရှိပါ"</string> <string name="wifi_status_sign_in_required" msgid="123517180404752756">"လက်မှတ်ထိုးဝင်ရန် လိုအပ်သည်"</string> <string name="wifi_ap_unable_to_handle_new_sta" msgid="5348824313514404541">"ကွန်ရက်ချိတ်ဆက်မှု ယာယီပြည့်နေသည်"</string> <string name="connected_via_carrier" msgid="7583780074526041912">"%1$s မှတစ်ဆင့် ချိတ်ဆက်ထားသည်"</string> <string name="available_via_carrier" msgid="1469036129740799053">"%1$s မှတစ်ဆင့် ရနိုင်သည်"</string> + <!-- no translation found for osu_failure_ap_connection (598977488344424542) --> + <skip /> + <!-- no translation found for osu_failure_server_url_invalid (2237477219243136714) --> + <skip /> + <!-- no translation found for osu_failure_server_connection (8192988165059982174) --> + <skip /> + <!-- no translation found for osu_failure_server_validation (4631649978129606823) --> + <skip /> + <!-- no translation found for osu_failure_service_provider_verification (4854091521439785597) --> + <skip /> + <!-- no translation found for osu_failure_provisioning_aborted (424627208135320329) --> + <skip /> + <!-- no translation found for osu_failure_provisioning_not_available (3021783729256985432) --> + <skip /> + <!-- no translation found for osu_failure_invalid_server_url (8548886196179435758) --> + <skip /> + <!-- no translation found for osu_failure_unexpected_command_type (8245921319866603904) --> + <skip /> + <!-- no translation found for osu_failure_unexpected_soap_message_type (2255897608510053065) --> + <skip /> + <!-- no translation found for osu_failure_soap_message_exchange (4357358438685987192) --> + <skip /> + <!-- no translation found for osu_failure_start_redirect_listener (4292769407279548482) --> + <skip /> + <!-- no translation found for osu_failure_timed_out_redirect_listener (3168657820278807508) --> + <skip /> + <!-- no translation found for osu_failure_no_osu_activity_found (4593038891437878675) --> + <skip /> + <!-- no translation found for osu_failure_unexpected_soap_message_status (6568467710235256675) --> + <skip /> + <!-- no translation found for osu_failure_no_pps_mo (850567403039076835) --> + <skip /> + <!-- no translation found for osu_failure_no_aaa_server_trust_root_node (8961455873459838456) --> + <skip /> + <!-- no translation found for osu_failure_no_remediation_server_trust_root_node (5041179688081545244) --> + <skip /> + <!-- no translation found for osu_failure_no_policy_server_trust_root_node (6617290380940513539) --> + <skip /> + <!-- no translation found for osu_failure_retrieve_trust_root_certificates (1499136256195528265) --> + <skip /> + <!-- no translation found for osu_failure_no_aaa_trust_root_certificate (1904322497042226984) --> + <skip /> + <!-- no translation found for osu_failure_add_passpoint_configuration (2173557755811446047) --> + <skip /> + <!-- no translation found for osu_failure_osu_provider_not_found (6616172862116673082) --> + <skip /> + <!-- no translation found for osu_status_ap_connecting (5296821043003441437) --> + <skip /> + <!-- no translation found for osu_status_ap_connected (3777289375683170728) --> + <skip /> + <!-- no translation found for osu_status_server_connecting (8499785407540355867) --> + <skip /> + <!-- no translation found for osu_status_server_validated (3158727184762596355) --> + <skip /> + <!-- no translation found for osu_status_server_connected (8382024481520158168) --> + <skip /> + <!-- no translation found for osu_status_init_soap_exchange (8628063888912101981) --> + <skip /> + <!-- no translation found for osu_status_waiting_for_redirect_response (2343016207837053197) --> + <skip /> + <!-- no translation found for osu_status_redirect_response_received (5323368411922609405) --> + <skip /> + <!-- no translation found for osu_status_second_soap_exchange (7115332266758483909) --> + <skip /> + <!-- no translation found for osu_status_third_soap_exchange (8460901783597440766) --> + <skip /> + <!-- no translation found for osu_status_retrieving_trust_root_certs (1563445892926269689) --> + <skip /> + <!-- no translation found for osu_provisioning_complete (5120178802493970149) --> + <skip /> <string name="speed_label_very_slow" msgid="1867055264243608530">"အလွန်နှေး"</string> <string name="speed_label_slow" msgid="813109590815810235">"နှေး"</string> <string name="speed_label_okay" msgid="2331665440671174858">"OK"</string> diff --git a/packages/SettingsLib/res/values-nb/strings.xml b/packages/SettingsLib/res/values-nb/strings.xml index c4ad033c966f..5d5568f12b57 100644 --- a/packages/SettingsLib/res/values-nb/strings.xml +++ b/packages/SettingsLib/res/values-nb/strings.xml @@ -38,13 +38,87 @@ <string name="connected_via_network_scorer" msgid="5713793306870815341">"Automatisk tilkoblet via %1$s"</string> <string name="connected_via_network_scorer_default" msgid="7867260222020343104">"Automatisk tilkoblet via leverandør av nettverksvurdering"</string> <string name="connected_via_passpoint" msgid="2826205693803088747">"Tilkoblet via %1$s"</string> + <!-- no translation found for ssid_by_passpoint_provider (7898171424140673315) --> + <skip /> <string name="available_via_passpoint" msgid="1617440946846329613">"Tilgjengelig via %1$s"</string> + <!-- no translation found for tap_to_set_up (2468970825530423314) --> + <skip /> <string name="wifi_connected_no_internet" msgid="8202906332837777829">"Tilkoblet – ingen Internett-tilgang"</string> <string name="wifi_status_no_internet" msgid="5784710974669608361">"Ingen internettilkobling"</string> <string name="wifi_status_sign_in_required" msgid="123517180404752756">"Pålogging kreves"</string> <string name="wifi_ap_unable_to_handle_new_sta" msgid="5348824313514404541">"Tilgangspunktet er midlertidig fullt"</string> <string name="connected_via_carrier" msgid="7583780074526041912">"Tilkoblet via %1$s"</string> <string name="available_via_carrier" msgid="1469036129740799053">"Tilgjengelig via %1$s"</string> + <!-- no translation found for osu_failure_ap_connection (598977488344424542) --> + <skip /> + <!-- no translation found for osu_failure_server_url_invalid (2237477219243136714) --> + <skip /> + <!-- no translation found for osu_failure_server_connection (8192988165059982174) --> + <skip /> + <!-- no translation found for osu_failure_server_validation (4631649978129606823) --> + <skip /> + <!-- no translation found for osu_failure_service_provider_verification (4854091521439785597) --> + <skip /> + <!-- no translation found for osu_failure_provisioning_aborted (424627208135320329) --> + <skip /> + <!-- no translation found for osu_failure_provisioning_not_available (3021783729256985432) --> + <skip /> + <!-- no translation found for osu_failure_invalid_server_url (8548886196179435758) --> + <skip /> + <!-- no translation found for osu_failure_unexpected_command_type (8245921319866603904) --> + <skip /> + <!-- no translation found for osu_failure_unexpected_soap_message_type (2255897608510053065) --> + <skip /> + <!-- no translation found for osu_failure_soap_message_exchange (4357358438685987192) --> + <skip /> + <!-- no translation found for osu_failure_start_redirect_listener (4292769407279548482) --> + <skip /> + <!-- no translation found for osu_failure_timed_out_redirect_listener (3168657820278807508) --> + <skip /> + <!-- no translation found for osu_failure_no_osu_activity_found (4593038891437878675) --> + <skip /> + <!-- no translation found for osu_failure_unexpected_soap_message_status (6568467710235256675) --> + <skip /> + <!-- no translation found for osu_failure_no_pps_mo (850567403039076835) --> + <skip /> + <!-- no translation found for osu_failure_no_aaa_server_trust_root_node (8961455873459838456) --> + <skip /> + <!-- no translation found for osu_failure_no_remediation_server_trust_root_node (5041179688081545244) --> + <skip /> + <!-- no translation found for osu_failure_no_policy_server_trust_root_node (6617290380940513539) --> + <skip /> + <!-- no translation found for osu_failure_retrieve_trust_root_certificates (1499136256195528265) --> + <skip /> + <!-- no translation found for osu_failure_no_aaa_trust_root_certificate (1904322497042226984) --> + <skip /> + <!-- no translation found for osu_failure_add_passpoint_configuration (2173557755811446047) --> + <skip /> + <!-- no translation found for osu_failure_osu_provider_not_found (6616172862116673082) --> + <skip /> + <!-- no translation found for osu_status_ap_connecting (5296821043003441437) --> + <skip /> + <!-- no translation found for osu_status_ap_connected (3777289375683170728) --> + <skip /> + <!-- no translation found for osu_status_server_connecting (8499785407540355867) --> + <skip /> + <!-- no translation found for osu_status_server_validated (3158727184762596355) --> + <skip /> + <!-- no translation found for osu_status_server_connected (8382024481520158168) --> + <skip /> + <!-- no translation found for osu_status_init_soap_exchange (8628063888912101981) --> + <skip /> + <!-- no translation found for osu_status_waiting_for_redirect_response (2343016207837053197) --> + <skip /> + <!-- no translation found for osu_status_redirect_response_received (5323368411922609405) --> + <skip /> + <!-- no translation found for osu_status_second_soap_exchange (7115332266758483909) --> + <skip /> + <!-- no translation found for osu_status_third_soap_exchange (8460901783597440766) --> + <skip /> + <!-- no translation found for osu_status_retrieving_trust_root_certs (1563445892926269689) --> + <skip /> + <!-- no translation found for osu_provisioning_complete (5120178802493970149) --> + <skip /> <string name="speed_label_very_slow" msgid="1867055264243608530">"Veldig treg"</string> <string name="speed_label_slow" msgid="813109590815810235">"Treg"</string> <string name="speed_label_okay" msgid="2331665440671174858">"Ok"</string> diff --git a/packages/SettingsLib/res/values-ne/strings.xml b/packages/SettingsLib/res/values-ne/strings.xml index f67e05c6b801..f63e9d7459e7 100644 --- a/packages/SettingsLib/res/values-ne/strings.xml +++ b/packages/SettingsLib/res/values-ne/strings.xml @@ -38,13 +38,87 @@ <string name="connected_via_network_scorer" msgid="5713793306870815341">"%1$s मार्फत् स्वतः जडान गरिएको"</string> <string name="connected_via_network_scorer_default" msgid="7867260222020343104">"नेटवर्कको दर्जा प्रदायक मार्फत स्वत: जडान गरिएको"</string> <string name="connected_via_passpoint" msgid="2826205693803088747">"%1$s मार्फत जडित"</string> + <!-- no translation found for ssid_by_passpoint_provider (7898171424140673315) --> + <skip /> <string name="available_via_passpoint" msgid="1617440946846329613">"%1$s मार्फत उपलब्ध"</string> + <!-- no translation found for tap_to_set_up (2468970825530423314) --> + <skip /> <string name="wifi_connected_no_internet" msgid="8202906332837777829">"जडान गरियो तर इन्टरनेट छैन"</string> <string name="wifi_status_no_internet" msgid="5784710974669608361">"इन्टरनेटमाथिको पहुँच छैन"</string> <string name="wifi_status_sign_in_required" msgid="123517180404752756">"साइन इन गर्न आवश्यक छ"</string> <string name="wifi_ap_unable_to_handle_new_sta" msgid="5348824313514404541">"पहुँचसम्बन्धी स्थान अस्थायी रूपमा भरिएको छ"</string> <string name="connected_via_carrier" msgid="7583780074526041912">"%1$s मार्फत जडान गरियो"</string> <string name="available_via_carrier" msgid="1469036129740799053">"%1$s मार्फत उपलब्ध"</string> + <!-- no translation found for osu_failure_ap_connection (598977488344424542) --> + <skip /> + <!-- no translation found for osu_failure_server_url_invalid (2237477219243136714) --> + <skip /> + <!-- no translation found for osu_failure_server_connection (8192988165059982174) --> + <skip /> + <!-- no translation found for osu_failure_server_validation (4631649978129606823) --> + <skip /> + <!-- no translation found for osu_failure_service_provider_verification (4854091521439785597) --> + <skip /> + <!-- no translation found for osu_failure_provisioning_aborted (424627208135320329) --> + <skip /> + <!-- no translation found for osu_failure_provisioning_not_available (3021783729256985432) --> + <skip /> + <!-- no translation found for osu_failure_invalid_server_url (8548886196179435758) --> + <skip /> + <!-- no translation found for osu_failure_unexpected_command_type (8245921319866603904) --> + <skip /> + <!-- no translation found for osu_failure_unexpected_soap_message_type (2255897608510053065) --> + <skip /> + <!-- no translation found for osu_failure_soap_message_exchange (4357358438685987192) --> + <skip /> + <!-- no translation found for osu_failure_start_redirect_listener (4292769407279548482) --> + <skip /> + <!-- no translation found for osu_failure_timed_out_redirect_listener (3168657820278807508) --> + <skip /> + <!-- no translation found for osu_failure_no_osu_activity_found (4593038891437878675) --> + <skip /> + <!-- no translation found for osu_failure_unexpected_soap_message_status (6568467710235256675) --> + <skip /> + <!-- no translation found for osu_failure_no_pps_mo (850567403039076835) --> + <skip /> + <!-- no translation found for osu_failure_no_aaa_server_trust_root_node (8961455873459838456) --> + <skip /> + <!-- no translation found for osu_failure_no_remediation_server_trust_root_node (5041179688081545244) --> + <skip /> + <!-- no translation found for osu_failure_no_policy_server_trust_root_node (6617290380940513539) --> + <skip /> + <!-- no translation found for osu_failure_retrieve_trust_root_certificates (1499136256195528265) --> + <skip /> + <!-- no translation found for osu_failure_no_aaa_trust_root_certificate (1904322497042226984) --> + <skip /> + <!-- no translation found for osu_failure_add_passpoint_configuration (2173557755811446047) --> + <skip /> + <!-- no translation found for osu_failure_osu_provider_not_found (6616172862116673082) --> + <skip /> + <!-- no translation found for osu_status_ap_connecting (5296821043003441437) --> + <skip /> + <!-- no translation found for osu_status_ap_connected (3777289375683170728) --> + <skip /> + <!-- no translation found for osu_status_server_connecting (8499785407540355867) --> + <skip /> + <!-- no translation found for osu_status_server_validated (3158727184762596355) --> + <skip /> + <!-- no translation found for osu_status_server_connected (8382024481520158168) --> + <skip /> + <!-- no translation found for osu_status_init_soap_exchange (8628063888912101981) --> + <skip /> + <!-- no translation found for osu_status_waiting_for_redirect_response (2343016207837053197) --> + <skip /> + <!-- no translation found for osu_status_redirect_response_received (5323368411922609405) --> + <skip /> + <!-- no translation found for osu_status_second_soap_exchange (7115332266758483909) --> + <skip /> + <!-- no translation found for osu_status_third_soap_exchange (8460901783597440766) --> + <skip /> + <!-- no translation found for osu_status_retrieving_trust_root_certs (1563445892926269689) --> + <skip /> + <!-- no translation found for osu_provisioning_complete (5120178802493970149) --> + <skip /> <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> diff --git a/packages/SettingsLib/res/values-nl/strings.xml b/packages/SettingsLib/res/values-nl/strings.xml index d2fd4e249aa4..798dc7ca8c9a 100644 --- a/packages/SettingsLib/res/values-nl/strings.xml +++ b/packages/SettingsLib/res/values-nl/strings.xml @@ -38,13 +38,87 @@ <string name="connected_via_network_scorer" msgid="5713793306870815341">"Automatisch verbonden via %1$s"</string> <string name="connected_via_network_scorer_default" msgid="7867260222020343104">"Automatisch verbonden via provider van netwerkbeoordelingen"</string> <string name="connected_via_passpoint" msgid="2826205693803088747">"Verbonden via %1$s"</string> + <!-- no translation found for ssid_by_passpoint_provider (7898171424140673315) --> + <skip /> <string name="available_via_passpoint" msgid="1617440946846329613">"Beschikbaar via %1$s"</string> + <!-- no translation found for tap_to_set_up (2468970825530423314) --> + <skip /> <string name="wifi_connected_no_internet" msgid="8202906332837777829">"Verbonden, geen internet"</string> <string name="wifi_status_no_internet" msgid="5784710974669608361">"Geen internet"</string> <string name="wifi_status_sign_in_required" msgid="123517180404752756">"Inloggen vereist"</string> <string name="wifi_ap_unable_to_handle_new_sta" msgid="5348824313514404541">"Toegangspunt tijdelijk vol"</string> <string name="connected_via_carrier" msgid="7583780074526041912">"Verbonden via %1$s"</string> <string name="available_via_carrier" msgid="1469036129740799053">"Beschikbaar via %1$s"</string> + <!-- no translation found for osu_failure_ap_connection (598977488344424542) --> + <skip /> + <!-- no translation found for osu_failure_server_url_invalid (2237477219243136714) --> + <skip /> + <!-- no translation found for osu_failure_server_connection (8192988165059982174) --> + <skip /> + <!-- no translation found for osu_failure_server_validation (4631649978129606823) --> + <skip /> + <!-- no translation found for osu_failure_service_provider_verification (4854091521439785597) --> + <skip /> + <!-- no translation found for osu_failure_provisioning_aborted (424627208135320329) --> + <skip /> + <!-- no translation found for osu_failure_provisioning_not_available (3021783729256985432) --> + <skip /> + <!-- no translation found for osu_failure_invalid_server_url (8548886196179435758) --> + <skip /> + <!-- no translation found for osu_failure_unexpected_command_type (8245921319866603904) --> + <skip /> + <!-- no translation found for osu_failure_unexpected_soap_message_type (2255897608510053065) --> + <skip /> + <!-- no translation found for osu_failure_soap_message_exchange (4357358438685987192) --> + <skip /> + <!-- no translation found for osu_failure_start_redirect_listener (4292769407279548482) --> + <skip /> + <!-- no translation found for osu_failure_timed_out_redirect_listener (3168657820278807508) --> + <skip /> + <!-- no translation found for osu_failure_no_osu_activity_found (4593038891437878675) --> + <skip /> + <!-- no translation found for osu_failure_unexpected_soap_message_status (6568467710235256675) --> + <skip /> + <!-- no translation found for osu_failure_no_pps_mo (850567403039076835) --> + <skip /> + <!-- no translation found for osu_failure_no_aaa_server_trust_root_node (8961455873459838456) --> + <skip /> + <!-- no translation found for osu_failure_no_remediation_server_trust_root_node (5041179688081545244) --> + <skip /> + <!-- no translation found for osu_failure_no_policy_server_trust_root_node (6617290380940513539) --> + <skip /> + <!-- no translation found for osu_failure_retrieve_trust_root_certificates (1499136256195528265) --> + <skip /> + <!-- no translation found for osu_failure_no_aaa_trust_root_certificate (1904322497042226984) --> + <skip /> + <!-- no translation found for osu_failure_add_passpoint_configuration (2173557755811446047) --> + <skip /> + <!-- no translation found for osu_failure_osu_provider_not_found (6616172862116673082) --> + <skip /> + <!-- no translation found for osu_status_ap_connecting (5296821043003441437) --> + <skip /> + <!-- no translation found for osu_status_ap_connected (3777289375683170728) --> + <skip /> + <!-- no translation found for osu_status_server_connecting (8499785407540355867) --> + <skip /> + <!-- no translation found for osu_status_server_validated (3158727184762596355) --> + <skip /> + <!-- no translation found for osu_status_server_connected (8382024481520158168) --> + <skip /> + <!-- no translation found for osu_status_init_soap_exchange (8628063888912101981) --> + <skip /> + <!-- no translation found for osu_status_waiting_for_redirect_response (2343016207837053197) --> + <skip /> + <!-- no translation found for osu_status_redirect_response_received (5323368411922609405) --> + <skip /> + <!-- no translation found for osu_status_second_soap_exchange (7115332266758483909) --> + <skip /> + <!-- no translation found for osu_status_third_soap_exchange (8460901783597440766) --> + <skip /> + <!-- no translation found for osu_status_retrieving_trust_root_certs (1563445892926269689) --> + <skip /> + <!-- no translation found for osu_provisioning_complete (5120178802493970149) --> + <skip /> <string name="speed_label_very_slow" msgid="1867055264243608530">"Zeer langzaam"</string> <string name="speed_label_slow" msgid="813109590815810235">"Langzaam"</string> <string name="speed_label_okay" msgid="2331665440671174858">"Redelijk"</string> @@ -144,7 +218,7 @@ <string name="tts_settings_title" msgid="1237820681016639683">"Spraakuitvoer"</string> <string name="tts_default_rate_title" msgid="6030550998379310088">"Spreeksnelheid"</string> <string name="tts_default_rate_summary" msgid="4061815292287182801">"Snelheid waarmee de tekst wordt gesproken"</string> - <string name="tts_default_pitch_title" msgid="6135942113172488671">"Hoogte"</string> + <string name="tts_default_pitch_title" msgid="6135942113172488671">"Toonhoogte"</string> <string name="tts_default_pitch_summary" msgid="1944885882882650009">"Is van invloed op de toon van de synthetisch gegenereerde spraak"</string> <string name="tts_default_lang_title" msgid="8018087612299820556">"Taal"</string> <string name="tts_lang_use_system" msgid="2679252467416513208">"Systeemtaal gebruiken"</string> diff --git a/packages/SettingsLib/res/values-or/strings.xml b/packages/SettingsLib/res/values-or/strings.xml index bed22a7526f9..9491af3253d0 100644 --- a/packages/SettingsLib/res/values-or/strings.xml +++ b/packages/SettingsLib/res/values-or/strings.xml @@ -38,13 +38,87 @@ <string name="connected_via_network_scorer" msgid="5713793306870815341">"%1$s ମାଧ୍ୟମରେ ଅଟୋମେଟିକାଲୀ ସଂଯୁକ୍ତ"</string> <string name="connected_via_network_scorer_default" msgid="7867260222020343104">"ନେଟୱର୍କ ମୂଲ୍ୟାୟନ ପ୍ରଦାତାଙ୍କ ମାଧ୍ୟମରେ ଅଟୋମେଟିକାଲ୍ୟ ସଂଯୁକ୍ତ"</string> <string name="connected_via_passpoint" msgid="2826205693803088747">"%1$s ମାଧ୍ୟମରେ ସଂଯୁକ୍ତ"</string> + <!-- no translation found for ssid_by_passpoint_provider (7898171424140673315) --> + <skip /> <string name="available_via_passpoint" msgid="1617440946846329613">"%1$s ମାଧ୍ୟମରେ ଉପଲବ୍ଧ"</string> + <!-- no translation found for tap_to_set_up (2468970825530423314) --> + <skip /> <string name="wifi_connected_no_internet" msgid="8202906332837777829">"ସଂଯୁକ୍ତ, ଇଣ୍ଟର୍ନେଟ୍ ନାହିଁ"</string> <string name="wifi_status_no_internet" msgid="5784710974669608361">"କୌଣସି ଇଣ୍ଟରନେଟ୍ ନାହିଁ"</string> <string name="wifi_status_sign_in_required" msgid="123517180404752756">"ସାଇନ୍-ଇନ୍ ଆବଶ୍ୟକ"</string> <string name="wifi_ap_unable_to_handle_new_sta" msgid="5348824313514404541">"ଆକ୍ସେସ୍ ପଏଣ୍ଟ ସାମୟିକ ଭାବେ ପୂର୍ଣ୍ଣ"</string> <string name="connected_via_carrier" msgid="7583780074526041912">"%1$s ମାଧ୍ୟମରେ ସଂଯୁକ୍ତ"</string> <string name="available_via_carrier" msgid="1469036129740799053">"%1$s ମାଧ୍ୟମରେ ଉପଲବ୍ଧ"</string> + <!-- no translation found for osu_failure_ap_connection (598977488344424542) --> + <skip /> + <!-- no translation found for osu_failure_server_url_invalid (2237477219243136714) --> + <skip /> + <!-- no translation found for osu_failure_server_connection (8192988165059982174) --> + <skip /> + <!-- no translation found for osu_failure_server_validation (4631649978129606823) --> + <skip /> + <!-- no translation found for osu_failure_service_provider_verification (4854091521439785597) --> + <skip /> + <!-- no translation found for osu_failure_provisioning_aborted (424627208135320329) --> + <skip /> + <!-- no translation found for osu_failure_provisioning_not_available (3021783729256985432) --> + <skip /> + <!-- no translation found for osu_failure_invalid_server_url (8548886196179435758) --> + <skip /> + <!-- no translation found for osu_failure_unexpected_command_type (8245921319866603904) --> + <skip /> + <!-- no translation found for osu_failure_unexpected_soap_message_type (2255897608510053065) --> + <skip /> + <!-- no translation found for osu_failure_soap_message_exchange (4357358438685987192) --> + <skip /> + <!-- no translation found for osu_failure_start_redirect_listener (4292769407279548482) --> + <skip /> + <!-- no translation found for osu_failure_timed_out_redirect_listener (3168657820278807508) --> + <skip /> + <!-- no translation found for osu_failure_no_osu_activity_found (4593038891437878675) --> + <skip /> + <!-- no translation found for osu_failure_unexpected_soap_message_status (6568467710235256675) --> + <skip /> + <!-- no translation found for osu_failure_no_pps_mo (850567403039076835) --> + <skip /> + <!-- no translation found for osu_failure_no_aaa_server_trust_root_node (8961455873459838456) --> + <skip /> + <!-- no translation found for osu_failure_no_remediation_server_trust_root_node (5041179688081545244) --> + <skip /> + <!-- no translation found for osu_failure_no_policy_server_trust_root_node (6617290380940513539) --> + <skip /> + <!-- no translation found for osu_failure_retrieve_trust_root_certificates (1499136256195528265) --> + <skip /> + <!-- no translation found for osu_failure_no_aaa_trust_root_certificate (1904322497042226984) --> + <skip /> + <!-- no translation found for osu_failure_add_passpoint_configuration (2173557755811446047) --> + <skip /> + <!-- no translation found for osu_failure_osu_provider_not_found (6616172862116673082) --> + <skip /> + <!-- no translation found for osu_status_ap_connecting (5296821043003441437) --> + <skip /> + <!-- no translation found for osu_status_ap_connected (3777289375683170728) --> + <skip /> + <!-- no translation found for osu_status_server_connecting (8499785407540355867) --> + <skip /> + <!-- no translation found for osu_status_server_validated (3158727184762596355) --> + <skip /> + <!-- no translation found for osu_status_server_connected (8382024481520158168) --> + <skip /> + <!-- no translation found for osu_status_init_soap_exchange (8628063888912101981) --> + <skip /> + <!-- no translation found for osu_status_waiting_for_redirect_response (2343016207837053197) --> + <skip /> + <!-- no translation found for osu_status_redirect_response_received (5323368411922609405) --> + <skip /> + <!-- no translation found for osu_status_second_soap_exchange (7115332266758483909) --> + <skip /> + <!-- no translation found for osu_status_third_soap_exchange (8460901783597440766) --> + <skip /> + <!-- no translation found for osu_status_retrieving_trust_root_certs (1563445892926269689) --> + <skip /> + <!-- no translation found for osu_provisioning_complete (5120178802493970149) --> + <skip /> <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> diff --git a/packages/SettingsLib/res/values-pa/strings.xml b/packages/SettingsLib/res/values-pa/strings.xml index 1c2a947747d1..eadc5545e96c 100644 --- a/packages/SettingsLib/res/values-pa/strings.xml +++ b/packages/SettingsLib/res/values-pa/strings.xml @@ -38,13 +38,87 @@ <string name="connected_via_network_scorer" msgid="5713793306870815341">"%1$s ਰਾਹੀਂ ਆਪਣੇ-ਆਪ ਕਨੈਕਟ ਹੋਇਆ"</string> <string name="connected_via_network_scorer_default" msgid="7867260222020343104">"ਨੈੱਟਵਰਕ ਰੇਟਿੰਗ ਪ੍ਰਦਾਨਕ ਰਾਹੀਂ ਸਵੈਚਲਿਤ ਤੌਰ \'ਤੇ ਕਨੈਕਟ ਹੋਇਆ"</string> <string name="connected_via_passpoint" msgid="2826205693803088747">"%1$s ਰਾਹੀਂ ਕਨੈਕਟ ਕੀਤਾ"</string> + <!-- no translation found for ssid_by_passpoint_provider (7898171424140673315) --> + <skip /> <string name="available_via_passpoint" msgid="1617440946846329613">"%1$s ਰਾਹੀਂ ਉਪਲਬਧ"</string> + <!-- no translation found for tap_to_set_up (2468970825530423314) --> + <skip /> <string name="wifi_connected_no_internet" msgid="8202906332837777829">"ਕਨੈਕਟ ਕੀਤਾ, ਕੋਈ ਇੰਟਰਨੈੱਟ ਨਹੀਂ"</string> <string name="wifi_status_no_internet" msgid="5784710974669608361">"ਇੰਟਰਨੈੱਟ ਨਹੀਂ"</string> <string name="wifi_status_sign_in_required" msgid="123517180404752756">"ਸਾਈਨ-ਇਨ ਲੋੜੀਂਦਾ ਹੈ"</string> <string name="wifi_ap_unable_to_handle_new_sta" msgid="5348824313514404541">"ਐਕਸੈੱਸ ਪੁਆਇੰਟ ਅਸਥਾਈ ਤੌਰ \'ਤੇ ਸੰਪੂਰਨ ਰੁਝੇਂਵੇਂ ਵਿੱਚ ਹੈ"</string> <string name="connected_via_carrier" msgid="7583780074526041912">"%1$s ਰਾਹੀਂ ਕਨੈਕਟ ਕੀਤਾ"</string> <string name="available_via_carrier" msgid="1469036129740799053">"%1$s ਰਾਹੀਂ ਉਪਲਬਧ"</string> + <!-- no translation found for osu_failure_ap_connection (598977488344424542) --> + <skip /> + <!-- no translation found for osu_failure_server_url_invalid (2237477219243136714) --> + <skip /> + <!-- no translation found for osu_failure_server_connection (8192988165059982174) --> + <skip /> + <!-- no translation found for osu_failure_server_validation (4631649978129606823) --> + <skip /> + <!-- no translation found for osu_failure_service_provider_verification (4854091521439785597) --> + <skip /> + <!-- no translation found for osu_failure_provisioning_aborted (424627208135320329) --> + <skip /> + <!-- no translation found for osu_failure_provisioning_not_available (3021783729256985432) --> + <skip /> + <!-- no translation found for osu_failure_invalid_server_url (8548886196179435758) --> + <skip /> + <!-- no translation found for osu_failure_unexpected_command_type (8245921319866603904) --> + <skip /> + <!-- no translation found for osu_failure_unexpected_soap_message_type (2255897608510053065) --> + <skip /> + <!-- no translation found for osu_failure_soap_message_exchange (4357358438685987192) --> + <skip /> + <!-- no translation found for osu_failure_start_redirect_listener (4292769407279548482) --> + <skip /> + <!-- no translation found for osu_failure_timed_out_redirect_listener (3168657820278807508) --> + <skip /> + <!-- no translation found for osu_failure_no_osu_activity_found (4593038891437878675) --> + <skip /> + <!-- no translation found for osu_failure_unexpected_soap_message_status (6568467710235256675) --> + <skip /> + <!-- no translation found for osu_failure_no_pps_mo (850567403039076835) --> + <skip /> + <!-- no translation found for osu_failure_no_aaa_server_trust_root_node (8961455873459838456) --> + <skip /> + <!-- no translation found for osu_failure_no_remediation_server_trust_root_node (5041179688081545244) --> + <skip /> + <!-- no translation found for osu_failure_no_policy_server_trust_root_node (6617290380940513539) --> + <skip /> + <!-- no translation found for osu_failure_retrieve_trust_root_certificates (1499136256195528265) --> + <skip /> + <!-- no translation found for osu_failure_no_aaa_trust_root_certificate (1904322497042226984) --> + <skip /> + <!-- no translation found for osu_failure_add_passpoint_configuration (2173557755811446047) --> + <skip /> + <!-- no translation found for osu_failure_osu_provider_not_found (6616172862116673082) --> + <skip /> + <!-- no translation found for osu_status_ap_connecting (5296821043003441437) --> + <skip /> + <!-- no translation found for osu_status_ap_connected (3777289375683170728) --> + <skip /> + <!-- no translation found for osu_status_server_connecting (8499785407540355867) --> + <skip /> + <!-- no translation found for osu_status_server_validated (3158727184762596355) --> + <skip /> + <!-- no translation found for osu_status_server_connected (8382024481520158168) --> + <skip /> + <!-- no translation found for osu_status_init_soap_exchange (8628063888912101981) --> + <skip /> + <!-- no translation found for osu_status_waiting_for_redirect_response (2343016207837053197) --> + <skip /> + <!-- no translation found for osu_status_redirect_response_received (5323368411922609405) --> + <skip /> + <!-- no translation found for osu_status_second_soap_exchange (7115332266758483909) --> + <skip /> + <!-- no translation found for osu_status_third_soap_exchange (8460901783597440766) --> + <skip /> + <!-- no translation found for osu_status_retrieving_trust_root_certs (1563445892926269689) --> + <skip /> + <!-- no translation found for osu_provisioning_complete (5120178802493970149) --> + <skip /> <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> @@ -142,7 +216,7 @@ <string name="launch_defaults_none" msgid="4241129108140034876">"ਕੋਈ ਡਿਫੌਲਟਸ ਸੈਟ ਨਹੀਂ ਕੀਤੇ"</string> <string name="tts_settings" msgid="8186971894801348327">"ਲਿਖਤ ਤੋਂ ਬੋਲੀ ਸੈਟਿੰਗਾਂ"</string> <string name="tts_settings_title" msgid="1237820681016639683">"ਲਿਖਤ-ਤੋਂ-ਬੋਲੀ ਆਊਟਪੁੱਟ"</string> - <string name="tts_default_rate_title" msgid="6030550998379310088">"ਸਪੀਚ ਰੇਟ"</string> + <string name="tts_default_rate_title" msgid="6030550998379310088">"ਬੋਲਣ ਦੀ ਗਤੀ"</string> <string name="tts_default_rate_summary" msgid="4061815292287182801">"ਸਪੀਡ ਜਿਸਤੇ ਟੈਕਸਟ ਬੋਲਿਆ ਜਾਂਦਾ ਹੈ"</string> <string name="tts_default_pitch_title" msgid="6135942113172488671">"ਪਿਚ"</string> <string name="tts_default_pitch_summary" msgid="1944885882882650009">"ਬਣਾਵਟੀ ਬੋਲੀ ਦੇ ਲਹਿਜੇ \'ਤੇ ਅਸਰ ਪਾਉਂਦੀ ਹੈ"</string> diff --git a/packages/SettingsLib/res/values-pl/strings.xml b/packages/SettingsLib/res/values-pl/strings.xml index 1a0a30dd4c35..f94308a3faaa 100644 --- a/packages/SettingsLib/res/values-pl/strings.xml +++ b/packages/SettingsLib/res/values-pl/strings.xml @@ -38,13 +38,87 @@ <string name="connected_via_network_scorer" msgid="5713793306870815341">"Automatycznie połączono przez: %1$s"</string> <string name="connected_via_network_scorer_default" msgid="7867260222020343104">"Automatycznie połączono przez dostawcę ocen jakości sieci"</string> <string name="connected_via_passpoint" msgid="2826205693803088747">"Połączono przez %1$s"</string> + <!-- no translation found for ssid_by_passpoint_provider (7898171424140673315) --> + <skip /> <string name="available_via_passpoint" msgid="1617440946846329613">"Dostępne przez %1$s"</string> + <!-- no translation found for tap_to_set_up (2468970825530423314) --> + <skip /> <string name="wifi_connected_no_internet" msgid="8202906332837777829">"Połączono, brak internetu"</string> <string name="wifi_status_no_internet" msgid="5784710974669608361">"Brak internetu"</string> <string name="wifi_status_sign_in_required" msgid="123517180404752756">"Musisz się zalogować"</string> <string name="wifi_ap_unable_to_handle_new_sta" msgid="5348824313514404541">"Punkt dostępu jest tymczasowo zajęty"</string> <string name="connected_via_carrier" msgid="7583780074526041912">"Połączono przez: %1$s"</string> <string name="available_via_carrier" msgid="1469036129740799053">"Dostępna przez: %1$s"</string> + <!-- no translation found for osu_failure_ap_connection (598977488344424542) --> + <skip /> + <!-- no translation found for osu_failure_server_url_invalid (2237477219243136714) --> + <skip /> + <!-- no translation found for osu_failure_server_connection (8192988165059982174) --> + <skip /> + <!-- no translation found for osu_failure_server_validation (4631649978129606823) --> + <skip /> + <!-- no translation found for osu_failure_service_provider_verification (4854091521439785597) --> + <skip /> + <!-- no translation found for osu_failure_provisioning_aborted (424627208135320329) --> + <skip /> + <!-- no translation found for osu_failure_provisioning_not_available (3021783729256985432) --> + <skip /> + <!-- no translation found for osu_failure_invalid_server_url (8548886196179435758) --> + <skip /> + <!-- no translation found for osu_failure_unexpected_command_type (8245921319866603904) --> + <skip /> + <!-- no translation found for osu_failure_unexpected_soap_message_type (2255897608510053065) --> + <skip /> + <!-- no translation found for osu_failure_soap_message_exchange (4357358438685987192) --> + <skip /> + <!-- no translation found for osu_failure_start_redirect_listener (4292769407279548482) --> + <skip /> + <!-- no translation found for osu_failure_timed_out_redirect_listener (3168657820278807508) --> + <skip /> + <!-- no translation found for osu_failure_no_osu_activity_found (4593038891437878675) --> + <skip /> + <!-- no translation found for osu_failure_unexpected_soap_message_status (6568467710235256675) --> + <skip /> + <!-- no translation found for osu_failure_no_pps_mo (850567403039076835) --> + <skip /> + <!-- no translation found for osu_failure_no_aaa_server_trust_root_node (8961455873459838456) --> + <skip /> + <!-- no translation found for osu_failure_no_remediation_server_trust_root_node (5041179688081545244) --> + <skip /> + <!-- no translation found for osu_failure_no_policy_server_trust_root_node (6617290380940513539) --> + <skip /> + <!-- no translation found for osu_failure_retrieve_trust_root_certificates (1499136256195528265) --> + <skip /> + <!-- no translation found for osu_failure_no_aaa_trust_root_certificate (1904322497042226984) --> + <skip /> + <!-- no translation found for osu_failure_add_passpoint_configuration (2173557755811446047) --> + <skip /> + <!-- no translation found for osu_failure_osu_provider_not_found (6616172862116673082) --> + <skip /> + <!-- no translation found for osu_status_ap_connecting (5296821043003441437) --> + <skip /> + <!-- no translation found for osu_status_ap_connected (3777289375683170728) --> + <skip /> + <!-- no translation found for osu_status_server_connecting (8499785407540355867) --> + <skip /> + <!-- no translation found for osu_status_server_validated (3158727184762596355) --> + <skip /> + <!-- no translation found for osu_status_server_connected (8382024481520158168) --> + <skip /> + <!-- no translation found for osu_status_init_soap_exchange (8628063888912101981) --> + <skip /> + <!-- no translation found for osu_status_waiting_for_redirect_response (2343016207837053197) --> + <skip /> + <!-- no translation found for osu_status_redirect_response_received (5323368411922609405) --> + <skip /> + <!-- no translation found for osu_status_second_soap_exchange (7115332266758483909) --> + <skip /> + <!-- no translation found for osu_status_third_soap_exchange (8460901783597440766) --> + <skip /> + <!-- no translation found for osu_status_retrieving_trust_root_certs (1563445892926269689) --> + <skip /> + <!-- no translation found for osu_provisioning_complete (5120178802493970149) --> + <skip /> <string name="speed_label_very_slow" msgid="1867055264243608530">"Bardzo wolna"</string> <string name="speed_label_slow" msgid="813109590815810235">"Wolna"</string> <string name="speed_label_okay" msgid="2331665440671174858">"OK"</string> diff --git a/packages/SettingsLib/res/values-pt-rBR/strings.xml b/packages/SettingsLib/res/values-pt-rBR/strings.xml index 2795d4728468..f1b043bcc470 100644 --- a/packages/SettingsLib/res/values-pt-rBR/strings.xml +++ b/packages/SettingsLib/res/values-pt-rBR/strings.xml @@ -38,13 +38,87 @@ <string name="connected_via_network_scorer" msgid="5713793306870815341">"Conectado automaticamente via %1$s"</string> <string name="connected_via_network_scorer_default" msgid="7867260222020343104">"Conectado automaticamente via provedor de avaliação de rede"</string> <string name="connected_via_passpoint" msgid="2826205693803088747">"Conectado via %1$s"</string> + <!-- no translation found for ssid_by_passpoint_provider (7898171424140673315) --> + <skip /> <string name="available_via_passpoint" msgid="1617440946846329613">"Disponível via %1$s"</string> + <!-- no translation found for tap_to_set_up (2468970825530423314) --> + <skip /> <string name="wifi_connected_no_internet" msgid="8202906332837777829">"Conectada, sem Internet"</string> <string name="wifi_status_no_internet" msgid="5784710974669608361">"Sem Internet"</string> <string name="wifi_status_sign_in_required" msgid="123517180404752756">"É necessário fazer login"</string> <string name="wifi_ap_unable_to_handle_new_sta" msgid="5348824313514404541">"Ponto de acesso temporariamente cheio"</string> <string name="connected_via_carrier" msgid="7583780074526041912">"Conectado via %1$s"</string> <string name="available_via_carrier" msgid="1469036129740799053">"Disponível via %1$s"</string> + <!-- no translation found for osu_failure_ap_connection (598977488344424542) --> + <skip /> + <!-- no translation found for osu_failure_server_url_invalid (2237477219243136714) --> + <skip /> + <!-- no translation found for osu_failure_server_connection (8192988165059982174) --> + <skip /> + <!-- no translation found for osu_failure_server_validation (4631649978129606823) --> + <skip /> + <!-- no translation found for osu_failure_service_provider_verification (4854091521439785597) --> + <skip /> + <!-- no translation found for osu_failure_provisioning_aborted (424627208135320329) --> + <skip /> + <!-- no translation found for osu_failure_provisioning_not_available (3021783729256985432) --> + <skip /> + <!-- no translation found for osu_failure_invalid_server_url (8548886196179435758) --> + <skip /> + <!-- no translation found for osu_failure_unexpected_command_type (8245921319866603904) --> + <skip /> + <!-- no translation found for osu_failure_unexpected_soap_message_type (2255897608510053065) --> + <skip /> + <!-- no translation found for osu_failure_soap_message_exchange (4357358438685987192) --> + <skip /> + <!-- no translation found for osu_failure_start_redirect_listener (4292769407279548482) --> + <skip /> + <!-- no translation found for osu_failure_timed_out_redirect_listener (3168657820278807508) --> + <skip /> + <!-- no translation found for osu_failure_no_osu_activity_found (4593038891437878675) --> + <skip /> + <!-- no translation found for osu_failure_unexpected_soap_message_status (6568467710235256675) --> + <skip /> + <!-- no translation found for osu_failure_no_pps_mo (850567403039076835) --> + <skip /> + <!-- no translation found for osu_failure_no_aaa_server_trust_root_node (8961455873459838456) --> + <skip /> + <!-- no translation found for osu_failure_no_remediation_server_trust_root_node (5041179688081545244) --> + <skip /> + <!-- no translation found for osu_failure_no_policy_server_trust_root_node (6617290380940513539) --> + <skip /> + <!-- no translation found for osu_failure_retrieve_trust_root_certificates (1499136256195528265) --> + <skip /> + <!-- no translation found for osu_failure_no_aaa_trust_root_certificate (1904322497042226984) --> + <skip /> + <!-- no translation found for osu_failure_add_passpoint_configuration (2173557755811446047) --> + <skip /> + <!-- no translation found for osu_failure_osu_provider_not_found (6616172862116673082) --> + <skip /> + <!-- no translation found for osu_status_ap_connecting (5296821043003441437) --> + <skip /> + <!-- no translation found for osu_status_ap_connected (3777289375683170728) --> + <skip /> + <!-- no translation found for osu_status_server_connecting (8499785407540355867) --> + <skip /> + <!-- no translation found for osu_status_server_validated (3158727184762596355) --> + <skip /> + <!-- no translation found for osu_status_server_connected (8382024481520158168) --> + <skip /> + <!-- no translation found for osu_status_init_soap_exchange (8628063888912101981) --> + <skip /> + <!-- no translation found for osu_status_waiting_for_redirect_response (2343016207837053197) --> + <skip /> + <!-- no translation found for osu_status_redirect_response_received (5323368411922609405) --> + <skip /> + <!-- no translation found for osu_status_second_soap_exchange (7115332266758483909) --> + <skip /> + <!-- no translation found for osu_status_third_soap_exchange (8460901783597440766) --> + <skip /> + <!-- no translation found for osu_status_retrieving_trust_root_certs (1563445892926269689) --> + <skip /> + <!-- no translation found for osu_provisioning_complete (5120178802493970149) --> + <skip /> <string name="speed_label_very_slow" msgid="1867055264243608530">"Muito lenta"</string> <string name="speed_label_slow" msgid="813109590815810235">"Lenta"</string> <string name="speed_label_okay" msgid="2331665440671174858">"Ok"</string> @@ -142,9 +216,9 @@ <string name="launch_defaults_none" msgid="4241129108140034876">"Nenhum padrão definido"</string> <string name="tts_settings" msgid="8186971894801348327">"Configurações da conversão de texto em voz"</string> <string name="tts_settings_title" msgid="1237820681016639683">"Conversão de texto em voz"</string> - <string name="tts_default_rate_title" msgid="6030550998379310088">"Taxa de fala"</string> + <string name="tts_default_rate_title" msgid="6030550998379310088">"Velocidade da fala"</string> <string name="tts_default_rate_summary" msgid="4061815292287182801">"Velocidade em que o texto é falado"</string> - <string name="tts_default_pitch_title" msgid="6135942113172488671">"Tom da fala"</string> + <string name="tts_default_pitch_title" msgid="6135942113172488671">"Tom de voz"</string> <string name="tts_default_pitch_summary" msgid="1944885882882650009">"Afeta o tom da voz sintetizada"</string> <string name="tts_default_lang_title" msgid="8018087612299820556">"Idioma"</string> <string name="tts_lang_use_system" msgid="2679252467416513208">"Usar idioma do sistema"</string> @@ -166,8 +240,8 @@ <string name="tts_engine_settings_button" msgid="1030512042040722285">"Iniciar configurações do mecanismo"</string> <string name="tts_engine_preference_section_title" msgid="448294500990971413">"Mecanismo preferencial"</string> <string name="tts_general_section_title" msgid="4402572014604490502">"Gerais"</string> - <string name="tts_reset_speech_pitch_title" msgid="5789394019544785915">"Redefinir o tom da fala"</string> - <string name="tts_reset_speech_pitch_summary" msgid="8700539616245004418">"Redefinir o tom no qual o texto é falado para o padrão."</string> + <string name="tts_reset_speech_pitch_title" msgid="5789394019544785915">"Redefinir o tom de voz"</string> + <string name="tts_reset_speech_pitch_summary" msgid="8700539616245004418">"Redefinir o tom de voz para o padrão."</string> <string-array name="tts_rate_entries"> <item msgid="6695494874362656215">"Muito devagar"</item> <item msgid="4795095314303559268">"Devagar"</item> diff --git a/packages/SettingsLib/res/values-pt-rPT/strings.xml b/packages/SettingsLib/res/values-pt-rPT/strings.xml index fd152109c895..b0694d1fb800 100644 --- a/packages/SettingsLib/res/values-pt-rPT/strings.xml +++ b/packages/SettingsLib/res/values-pt-rPT/strings.xml @@ -38,13 +38,87 @@ <string name="connected_via_network_scorer" msgid="5713793306870815341">"Ligado automaticamente através de %1$s"</string> <string name="connected_via_network_scorer_default" msgid="7867260222020343104">"Ligado automaticamente através do fornecedor de classificação de rede"</string> <string name="connected_via_passpoint" msgid="2826205693803088747">"Ligado através de %1$s"</string> + <!-- no translation found for ssid_by_passpoint_provider (7898171424140673315) --> + <skip /> <string name="available_via_passpoint" msgid="1617440946846329613">"Disponível através de %1$s"</string> + <!-- no translation found for tap_to_set_up (2468970825530423314) --> + <skip /> <string name="wifi_connected_no_internet" msgid="8202906332837777829">"Ligado, sem Internet."</string> <string name="wifi_status_no_internet" msgid="5784710974669608361">"Sem Internet"</string> <string name="wifi_status_sign_in_required" msgid="123517180404752756">"É necessário iniciar sessão"</string> <string name="wifi_ap_unable_to_handle_new_sta" msgid="5348824313514404541">"Ponto de acesso temporariamente cheio"</string> <string name="connected_via_carrier" msgid="7583780074526041912">"Ligado através de %1$s"</string> <string name="available_via_carrier" msgid="1469036129740799053">"Disponível através de %1$s"</string> + <!-- no translation found for osu_failure_ap_connection (598977488344424542) --> + <skip /> + <!-- no translation found for osu_failure_server_url_invalid (2237477219243136714) --> + <skip /> + <!-- no translation found for osu_failure_server_connection (8192988165059982174) --> + <skip /> + <!-- no translation found for osu_failure_server_validation (4631649978129606823) --> + <skip /> + <!-- no translation found for osu_failure_service_provider_verification (4854091521439785597) --> + <skip /> + <!-- no translation found for osu_failure_provisioning_aborted (424627208135320329) --> + <skip /> + <!-- no translation found for osu_failure_provisioning_not_available (3021783729256985432) --> + <skip /> + <!-- no translation found for osu_failure_invalid_server_url (8548886196179435758) --> + <skip /> + <!-- no translation found for osu_failure_unexpected_command_type (8245921319866603904) --> + <skip /> + <!-- no translation found for osu_failure_unexpected_soap_message_type (2255897608510053065) --> + <skip /> + <!-- no translation found for osu_failure_soap_message_exchange (4357358438685987192) --> + <skip /> + <!-- no translation found for osu_failure_start_redirect_listener (4292769407279548482) --> + <skip /> + <!-- no translation found for osu_failure_timed_out_redirect_listener (3168657820278807508) --> + <skip /> + <!-- no translation found for osu_failure_no_osu_activity_found (4593038891437878675) --> + <skip /> + <!-- no translation found for osu_failure_unexpected_soap_message_status (6568467710235256675) --> + <skip /> + <!-- no translation found for osu_failure_no_pps_mo (850567403039076835) --> + <skip /> + <!-- no translation found for osu_failure_no_aaa_server_trust_root_node (8961455873459838456) --> + <skip /> + <!-- no translation found for osu_failure_no_remediation_server_trust_root_node (5041179688081545244) --> + <skip /> + <!-- no translation found for osu_failure_no_policy_server_trust_root_node (6617290380940513539) --> + <skip /> + <!-- no translation found for osu_failure_retrieve_trust_root_certificates (1499136256195528265) --> + <skip /> + <!-- no translation found for osu_failure_no_aaa_trust_root_certificate (1904322497042226984) --> + <skip /> + <!-- no translation found for osu_failure_add_passpoint_configuration (2173557755811446047) --> + <skip /> + <!-- no translation found for osu_failure_osu_provider_not_found (6616172862116673082) --> + <skip /> + <!-- no translation found for osu_status_ap_connecting (5296821043003441437) --> + <skip /> + <!-- no translation found for osu_status_ap_connected (3777289375683170728) --> + <skip /> + <!-- no translation found for osu_status_server_connecting (8499785407540355867) --> + <skip /> + <!-- no translation found for osu_status_server_validated (3158727184762596355) --> + <skip /> + <!-- no translation found for osu_status_server_connected (8382024481520158168) --> + <skip /> + <!-- no translation found for osu_status_init_soap_exchange (8628063888912101981) --> + <skip /> + <!-- no translation found for osu_status_waiting_for_redirect_response (2343016207837053197) --> + <skip /> + <!-- no translation found for osu_status_redirect_response_received (5323368411922609405) --> + <skip /> + <!-- no translation found for osu_status_second_soap_exchange (7115332266758483909) --> + <skip /> + <!-- no translation found for osu_status_third_soap_exchange (8460901783597440766) --> + <skip /> + <!-- no translation found for osu_status_retrieving_trust_root_certs (1563445892926269689) --> + <skip /> + <!-- no translation found for osu_provisioning_complete (5120178802493970149) --> + <skip /> <string name="speed_label_very_slow" msgid="1867055264243608530">"Muito lenta"</string> <string name="speed_label_slow" msgid="813109590815810235">"Lenta"</string> <string name="speed_label_okay" msgid="2331665440671174858">"OK"</string> diff --git a/packages/SettingsLib/res/values-pt/strings.xml b/packages/SettingsLib/res/values-pt/strings.xml index 2795d4728468..f1b043bcc470 100644 --- a/packages/SettingsLib/res/values-pt/strings.xml +++ b/packages/SettingsLib/res/values-pt/strings.xml @@ -38,13 +38,87 @@ <string name="connected_via_network_scorer" msgid="5713793306870815341">"Conectado automaticamente via %1$s"</string> <string name="connected_via_network_scorer_default" msgid="7867260222020343104">"Conectado automaticamente via provedor de avaliação de rede"</string> <string name="connected_via_passpoint" msgid="2826205693803088747">"Conectado via %1$s"</string> + <!-- no translation found for ssid_by_passpoint_provider (7898171424140673315) --> + <skip /> <string name="available_via_passpoint" msgid="1617440946846329613">"Disponível via %1$s"</string> + <!-- no translation found for tap_to_set_up (2468970825530423314) --> + <skip /> <string name="wifi_connected_no_internet" msgid="8202906332837777829">"Conectada, sem Internet"</string> <string name="wifi_status_no_internet" msgid="5784710974669608361">"Sem Internet"</string> <string name="wifi_status_sign_in_required" msgid="123517180404752756">"É necessário fazer login"</string> <string name="wifi_ap_unable_to_handle_new_sta" msgid="5348824313514404541">"Ponto de acesso temporariamente cheio"</string> <string name="connected_via_carrier" msgid="7583780074526041912">"Conectado via %1$s"</string> <string name="available_via_carrier" msgid="1469036129740799053">"Disponível via %1$s"</string> + <!-- no translation found for osu_failure_ap_connection (598977488344424542) --> + <skip /> + <!-- no translation found for osu_failure_server_url_invalid (2237477219243136714) --> + <skip /> + <!-- no translation found for osu_failure_server_connection (8192988165059982174) --> + <skip /> + <!-- no translation found for osu_failure_server_validation (4631649978129606823) --> + <skip /> + <!-- no translation found for osu_failure_service_provider_verification (4854091521439785597) --> + <skip /> + <!-- no translation found for osu_failure_provisioning_aborted (424627208135320329) --> + <skip /> + <!-- no translation found for osu_failure_provisioning_not_available (3021783729256985432) --> + <skip /> + <!-- no translation found for osu_failure_invalid_server_url (8548886196179435758) --> + <skip /> + <!-- no translation found for osu_failure_unexpected_command_type (8245921319866603904) --> + <skip /> + <!-- no translation found for osu_failure_unexpected_soap_message_type (2255897608510053065) --> + <skip /> + <!-- no translation found for osu_failure_soap_message_exchange (4357358438685987192) --> + <skip /> + <!-- no translation found for osu_failure_start_redirect_listener (4292769407279548482) --> + <skip /> + <!-- no translation found for osu_failure_timed_out_redirect_listener (3168657820278807508) --> + <skip /> + <!-- no translation found for osu_failure_no_osu_activity_found (4593038891437878675) --> + <skip /> + <!-- no translation found for osu_failure_unexpected_soap_message_status (6568467710235256675) --> + <skip /> + <!-- no translation found for osu_failure_no_pps_mo (850567403039076835) --> + <skip /> + <!-- no translation found for osu_failure_no_aaa_server_trust_root_node (8961455873459838456) --> + <skip /> + <!-- no translation found for osu_failure_no_remediation_server_trust_root_node (5041179688081545244) --> + <skip /> + <!-- no translation found for osu_failure_no_policy_server_trust_root_node (6617290380940513539) --> + <skip /> + <!-- no translation found for osu_failure_retrieve_trust_root_certificates (1499136256195528265) --> + <skip /> + <!-- no translation found for osu_failure_no_aaa_trust_root_certificate (1904322497042226984) --> + <skip /> + <!-- no translation found for osu_failure_add_passpoint_configuration (2173557755811446047) --> + <skip /> + <!-- no translation found for osu_failure_osu_provider_not_found (6616172862116673082) --> + <skip /> + <!-- no translation found for osu_status_ap_connecting (5296821043003441437) --> + <skip /> + <!-- no translation found for osu_status_ap_connected (3777289375683170728) --> + <skip /> + <!-- no translation found for osu_status_server_connecting (8499785407540355867) --> + <skip /> + <!-- no translation found for osu_status_server_validated (3158727184762596355) --> + <skip /> + <!-- no translation found for osu_status_server_connected (8382024481520158168) --> + <skip /> + <!-- no translation found for osu_status_init_soap_exchange (8628063888912101981) --> + <skip /> + <!-- no translation found for osu_status_waiting_for_redirect_response (2343016207837053197) --> + <skip /> + <!-- no translation found for osu_status_redirect_response_received (5323368411922609405) --> + <skip /> + <!-- no translation found for osu_status_second_soap_exchange (7115332266758483909) --> + <skip /> + <!-- no translation found for osu_status_third_soap_exchange (8460901783597440766) --> + <skip /> + <!-- no translation found for osu_status_retrieving_trust_root_certs (1563445892926269689) --> + <skip /> + <!-- no translation found for osu_provisioning_complete (5120178802493970149) --> + <skip /> <string name="speed_label_very_slow" msgid="1867055264243608530">"Muito lenta"</string> <string name="speed_label_slow" msgid="813109590815810235">"Lenta"</string> <string name="speed_label_okay" msgid="2331665440671174858">"Ok"</string> @@ -142,9 +216,9 @@ <string name="launch_defaults_none" msgid="4241129108140034876">"Nenhum padrão definido"</string> <string name="tts_settings" msgid="8186971894801348327">"Configurações da conversão de texto em voz"</string> <string name="tts_settings_title" msgid="1237820681016639683">"Conversão de texto em voz"</string> - <string name="tts_default_rate_title" msgid="6030550998379310088">"Taxa de fala"</string> + <string name="tts_default_rate_title" msgid="6030550998379310088">"Velocidade da fala"</string> <string name="tts_default_rate_summary" msgid="4061815292287182801">"Velocidade em que o texto é falado"</string> - <string name="tts_default_pitch_title" msgid="6135942113172488671">"Tom da fala"</string> + <string name="tts_default_pitch_title" msgid="6135942113172488671">"Tom de voz"</string> <string name="tts_default_pitch_summary" msgid="1944885882882650009">"Afeta o tom da voz sintetizada"</string> <string name="tts_default_lang_title" msgid="8018087612299820556">"Idioma"</string> <string name="tts_lang_use_system" msgid="2679252467416513208">"Usar idioma do sistema"</string> @@ -166,8 +240,8 @@ <string name="tts_engine_settings_button" msgid="1030512042040722285">"Iniciar configurações do mecanismo"</string> <string name="tts_engine_preference_section_title" msgid="448294500990971413">"Mecanismo preferencial"</string> <string name="tts_general_section_title" msgid="4402572014604490502">"Gerais"</string> - <string name="tts_reset_speech_pitch_title" msgid="5789394019544785915">"Redefinir o tom da fala"</string> - <string name="tts_reset_speech_pitch_summary" msgid="8700539616245004418">"Redefinir o tom no qual o texto é falado para o padrão."</string> + <string name="tts_reset_speech_pitch_title" msgid="5789394019544785915">"Redefinir o tom de voz"</string> + <string name="tts_reset_speech_pitch_summary" msgid="8700539616245004418">"Redefinir o tom de voz para o padrão."</string> <string-array name="tts_rate_entries"> <item msgid="6695494874362656215">"Muito devagar"</item> <item msgid="4795095314303559268">"Devagar"</item> diff --git a/packages/SettingsLib/res/values-ro/strings.xml b/packages/SettingsLib/res/values-ro/strings.xml index ecdd003b0c93..032fcebba33b 100644 --- a/packages/SettingsLib/res/values-ro/strings.xml +++ b/packages/SettingsLib/res/values-ro/strings.xml @@ -38,13 +38,87 @@ <string name="connected_via_network_scorer" msgid="5713793306870815341">"Conectată automat prin %1$s"</string> <string name="connected_via_network_scorer_default" msgid="7867260222020343104">"Conectată automat prin furnizor de evaluări ale rețelei"</string> <string name="connected_via_passpoint" msgid="2826205693803088747">"Conectată prin %1$s"</string> + <!-- no translation found for ssid_by_passpoint_provider (7898171424140673315) --> + <skip /> <string name="available_via_passpoint" msgid="1617440946846329613">"Disponibilă prin %1$s"</string> + <!-- no translation found for tap_to_set_up (2468970825530423314) --> + <skip /> <string name="wifi_connected_no_internet" msgid="8202906332837777829">"Conectată, fără internet"</string> <string name="wifi_status_no_internet" msgid="5784710974669608361">"Fără conexiune la internet"</string> <string name="wifi_status_sign_in_required" msgid="123517180404752756">"Trebuie să vă conectați"</string> <string name="wifi_ap_unable_to_handle_new_sta" msgid="5348824313514404541">"Punctul de acces este temporar plin"</string> <string name="connected_via_carrier" msgid="7583780074526041912">"Conectată prin %1$s"</string> <string name="available_via_carrier" msgid="1469036129740799053">"Disponibilă prin %1$s"</string> + <!-- no translation found for osu_failure_ap_connection (598977488344424542) --> + <skip /> + <!-- no translation found for osu_failure_server_url_invalid (2237477219243136714) --> + <skip /> + <!-- no translation found for osu_failure_server_connection (8192988165059982174) --> + <skip /> + <!-- no translation found for osu_failure_server_validation (4631649978129606823) --> + <skip /> + <!-- no translation found for osu_failure_service_provider_verification (4854091521439785597) --> + <skip /> + <!-- no translation found for osu_failure_provisioning_aborted (424627208135320329) --> + <skip /> + <!-- no translation found for osu_failure_provisioning_not_available (3021783729256985432) --> + <skip /> + <!-- no translation found for osu_failure_invalid_server_url (8548886196179435758) --> + <skip /> + <!-- no translation found for osu_failure_unexpected_command_type (8245921319866603904) --> + <skip /> + <!-- no translation found for osu_failure_unexpected_soap_message_type (2255897608510053065) --> + <skip /> + <!-- no translation found for osu_failure_soap_message_exchange (4357358438685987192) --> + <skip /> + <!-- no translation found for osu_failure_start_redirect_listener (4292769407279548482) --> + <skip /> + <!-- no translation found for osu_failure_timed_out_redirect_listener (3168657820278807508) --> + <skip /> + <!-- no translation found for osu_failure_no_osu_activity_found (4593038891437878675) --> + <skip /> + <!-- no translation found for osu_failure_unexpected_soap_message_status (6568467710235256675) --> + <skip /> + <!-- no translation found for osu_failure_no_pps_mo (850567403039076835) --> + <skip /> + <!-- no translation found for osu_failure_no_aaa_server_trust_root_node (8961455873459838456) --> + <skip /> + <!-- no translation found for osu_failure_no_remediation_server_trust_root_node (5041179688081545244) --> + <skip /> + <!-- no translation found for osu_failure_no_policy_server_trust_root_node (6617290380940513539) --> + <skip /> + <!-- no translation found for osu_failure_retrieve_trust_root_certificates (1499136256195528265) --> + <skip /> + <!-- no translation found for osu_failure_no_aaa_trust_root_certificate (1904322497042226984) --> + <skip /> + <!-- no translation found for osu_failure_add_passpoint_configuration (2173557755811446047) --> + <skip /> + <!-- no translation found for osu_failure_osu_provider_not_found (6616172862116673082) --> + <skip /> + <!-- no translation found for osu_status_ap_connecting (5296821043003441437) --> + <skip /> + <!-- no translation found for osu_status_ap_connected (3777289375683170728) --> + <skip /> + <!-- no translation found for osu_status_server_connecting (8499785407540355867) --> + <skip /> + <!-- no translation found for osu_status_server_validated (3158727184762596355) --> + <skip /> + <!-- no translation found for osu_status_server_connected (8382024481520158168) --> + <skip /> + <!-- no translation found for osu_status_init_soap_exchange (8628063888912101981) --> + <skip /> + <!-- no translation found for osu_status_waiting_for_redirect_response (2343016207837053197) --> + <skip /> + <!-- no translation found for osu_status_redirect_response_received (5323368411922609405) --> + <skip /> + <!-- no translation found for osu_status_second_soap_exchange (7115332266758483909) --> + <skip /> + <!-- no translation found for osu_status_third_soap_exchange (8460901783597440766) --> + <skip /> + <!-- no translation found for osu_status_retrieving_trust_root_certs (1563445892926269689) --> + <skip /> + <!-- no translation found for osu_provisioning_complete (5120178802493970149) --> + <skip /> <string name="speed_label_very_slow" msgid="1867055264243608530">"Foarte lentă"</string> <string name="speed_label_slow" msgid="813109590815810235">"Lentă"</string> <string name="speed_label_okay" msgid="2331665440671174858">"Bine"</string> diff --git a/packages/SettingsLib/res/values-ru/strings.xml b/packages/SettingsLib/res/values-ru/strings.xml index 74075c535b76..a280285fef61 100644 --- a/packages/SettingsLib/res/values-ru/strings.xml +++ b/packages/SettingsLib/res/values-ru/strings.xml @@ -38,13 +38,87 @@ <string name="connected_via_network_scorer" msgid="5713793306870815341">"Автоматически подключено к %1$s"</string> <string name="connected_via_network_scorer_default" msgid="7867260222020343104">"Автоматически подключено через автора рейтинга сетей"</string> <string name="connected_via_passpoint" msgid="2826205693803088747">"Подключено к %1$s"</string> + <!-- no translation found for ssid_by_passpoint_provider (7898171424140673315) --> + <skip /> <string name="available_via_passpoint" msgid="1617440946846329613">"Доступно через %1$s"</string> + <!-- no translation found for tap_to_set_up (2468970825530423314) --> + <skip /> <string name="wifi_connected_no_internet" msgid="8202906332837777829">"Подключено, без доступа к Интернету"</string> <string name="wifi_status_no_internet" msgid="5784710974669608361">"Нет подключения к Интернету"</string> <string name="wifi_status_sign_in_required" msgid="123517180404752756">"Требуется выполнить вход."</string> <string name="wifi_ap_unable_to_handle_new_sta" msgid="5348824313514404541">"К точке доступа подключено слишком много устройств"</string> <string name="connected_via_carrier" msgid="7583780074526041912">"Подключено к %1$s"</string> <string name="available_via_carrier" msgid="1469036129740799053">"Доступно через %1$s"</string> + <!-- no translation found for osu_failure_ap_connection (598977488344424542) --> + <skip /> + <!-- no translation found for osu_failure_server_url_invalid (2237477219243136714) --> + <skip /> + <!-- no translation found for osu_failure_server_connection (8192988165059982174) --> + <skip /> + <!-- no translation found for osu_failure_server_validation (4631649978129606823) --> + <skip /> + <!-- no translation found for osu_failure_service_provider_verification (4854091521439785597) --> + <skip /> + <!-- no translation found for osu_failure_provisioning_aborted (424627208135320329) --> + <skip /> + <!-- no translation found for osu_failure_provisioning_not_available (3021783729256985432) --> + <skip /> + <!-- no translation found for osu_failure_invalid_server_url (8548886196179435758) --> + <skip /> + <!-- no translation found for osu_failure_unexpected_command_type (8245921319866603904) --> + <skip /> + <!-- no translation found for osu_failure_unexpected_soap_message_type (2255897608510053065) --> + <skip /> + <!-- no translation found for osu_failure_soap_message_exchange (4357358438685987192) --> + <skip /> + <!-- no translation found for osu_failure_start_redirect_listener (4292769407279548482) --> + <skip /> + <!-- no translation found for osu_failure_timed_out_redirect_listener (3168657820278807508) --> + <skip /> + <!-- no translation found for osu_failure_no_osu_activity_found (4593038891437878675) --> + <skip /> + <!-- no translation found for osu_failure_unexpected_soap_message_status (6568467710235256675) --> + <skip /> + <!-- no translation found for osu_failure_no_pps_mo (850567403039076835) --> + <skip /> + <!-- no translation found for osu_failure_no_aaa_server_trust_root_node (8961455873459838456) --> + <skip /> + <!-- no translation found for osu_failure_no_remediation_server_trust_root_node (5041179688081545244) --> + <skip /> + <!-- no translation found for osu_failure_no_policy_server_trust_root_node (6617290380940513539) --> + <skip /> + <!-- no translation found for osu_failure_retrieve_trust_root_certificates (1499136256195528265) --> + <skip /> + <!-- no translation found for osu_failure_no_aaa_trust_root_certificate (1904322497042226984) --> + <skip /> + <!-- no translation found for osu_failure_add_passpoint_configuration (2173557755811446047) --> + <skip /> + <!-- no translation found for osu_failure_osu_provider_not_found (6616172862116673082) --> + <skip /> + <!-- no translation found for osu_status_ap_connecting (5296821043003441437) --> + <skip /> + <!-- no translation found for osu_status_ap_connected (3777289375683170728) --> + <skip /> + <!-- no translation found for osu_status_server_connecting (8499785407540355867) --> + <skip /> + <!-- no translation found for osu_status_server_validated (3158727184762596355) --> + <skip /> + <!-- no translation found for osu_status_server_connected (8382024481520158168) --> + <skip /> + <!-- no translation found for osu_status_init_soap_exchange (8628063888912101981) --> + <skip /> + <!-- no translation found for osu_status_waiting_for_redirect_response (2343016207837053197) --> + <skip /> + <!-- no translation found for osu_status_redirect_response_received (5323368411922609405) --> + <skip /> + <!-- no translation found for osu_status_second_soap_exchange (7115332266758483909) --> + <skip /> + <!-- no translation found for osu_status_third_soap_exchange (8460901783597440766) --> + <skip /> + <!-- no translation found for osu_status_retrieving_trust_root_certs (1563445892926269689) --> + <skip /> + <!-- no translation found for osu_provisioning_complete (5120178802493970149) --> + <skip /> <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> diff --git a/packages/SettingsLib/res/values-si/strings.xml b/packages/SettingsLib/res/values-si/strings.xml index fc90db5b35d3..c143c766ff73 100644 --- a/packages/SettingsLib/res/values-si/strings.xml +++ b/packages/SettingsLib/res/values-si/strings.xml @@ -38,13 +38,87 @@ <string name="connected_via_network_scorer" msgid="5713793306870815341">"%1$s හරහා ස්වයංක්රියව සම්බන්ධ විය"</string> <string name="connected_via_network_scorer_default" msgid="7867260222020343104">"ජාල ශ්රේණිගත සපයන්නා හරහා ස්වයංක්රියව සම්බන්ධ විය"</string> <string name="connected_via_passpoint" msgid="2826205693803088747">"%1$s හරහා සම්බන්ධ විය"</string> + <!-- no translation found for ssid_by_passpoint_provider (7898171424140673315) --> + <skip /> <string name="available_via_passpoint" msgid="1617440946846329613">"%1$s හරහා ලබා ගැනීමට හැකිය"</string> + <!-- no translation found for tap_to_set_up (2468970825530423314) --> + <skip /> <string name="wifi_connected_no_internet" msgid="8202906332837777829">"සම්බන්ධයි, අන්තර්ජාලය නැත"</string> <string name="wifi_status_no_internet" msgid="5784710974669608361">"අන්තර්ජාලය නැත"</string> <string name="wifi_status_sign_in_required" msgid="123517180404752756">"පිරීම අවශ්යයි"</string> <string name="wifi_ap_unable_to_handle_new_sta" msgid="5348824313514404541">"ප්රවේශ ලක්ෂ්ය තාවකාලිකව පිරී ඇත"</string> <string name="connected_via_carrier" msgid="7583780074526041912">"%1$s හරහා සම්බන්ධ විය"</string> <string name="available_via_carrier" msgid="1469036129740799053">"%1$s හරහා ලබා ගැනීමට හැකිය"</string> + <!-- no translation found for osu_failure_ap_connection (598977488344424542) --> + <skip /> + <!-- no translation found for osu_failure_server_url_invalid (2237477219243136714) --> + <skip /> + <!-- no translation found for osu_failure_server_connection (8192988165059982174) --> + <skip /> + <!-- no translation found for osu_failure_server_validation (4631649978129606823) --> + <skip /> + <!-- no translation found for osu_failure_service_provider_verification (4854091521439785597) --> + <skip /> + <!-- no translation found for osu_failure_provisioning_aborted (424627208135320329) --> + <skip /> + <!-- no translation found for osu_failure_provisioning_not_available (3021783729256985432) --> + <skip /> + <!-- no translation found for osu_failure_invalid_server_url (8548886196179435758) --> + <skip /> + <!-- no translation found for osu_failure_unexpected_command_type (8245921319866603904) --> + <skip /> + <!-- no translation found for osu_failure_unexpected_soap_message_type (2255897608510053065) --> + <skip /> + <!-- no translation found for osu_failure_soap_message_exchange (4357358438685987192) --> + <skip /> + <!-- no translation found for osu_failure_start_redirect_listener (4292769407279548482) --> + <skip /> + <!-- no translation found for osu_failure_timed_out_redirect_listener (3168657820278807508) --> + <skip /> + <!-- no translation found for osu_failure_no_osu_activity_found (4593038891437878675) --> + <skip /> + <!-- no translation found for osu_failure_unexpected_soap_message_status (6568467710235256675) --> + <skip /> + <!-- no translation found for osu_failure_no_pps_mo (850567403039076835) --> + <skip /> + <!-- no translation found for osu_failure_no_aaa_server_trust_root_node (8961455873459838456) --> + <skip /> + <!-- no translation found for osu_failure_no_remediation_server_trust_root_node (5041179688081545244) --> + <skip /> + <!-- no translation found for osu_failure_no_policy_server_trust_root_node (6617290380940513539) --> + <skip /> + <!-- no translation found for osu_failure_retrieve_trust_root_certificates (1499136256195528265) --> + <skip /> + <!-- no translation found for osu_failure_no_aaa_trust_root_certificate (1904322497042226984) --> + <skip /> + <!-- no translation found for osu_failure_add_passpoint_configuration (2173557755811446047) --> + <skip /> + <!-- no translation found for osu_failure_osu_provider_not_found (6616172862116673082) --> + <skip /> + <!-- no translation found for osu_status_ap_connecting (5296821043003441437) --> + <skip /> + <!-- no translation found for osu_status_ap_connected (3777289375683170728) --> + <skip /> + <!-- no translation found for osu_status_server_connecting (8499785407540355867) --> + <skip /> + <!-- no translation found for osu_status_server_validated (3158727184762596355) --> + <skip /> + <!-- no translation found for osu_status_server_connected (8382024481520158168) --> + <skip /> + <!-- no translation found for osu_status_init_soap_exchange (8628063888912101981) --> + <skip /> + <!-- no translation found for osu_status_waiting_for_redirect_response (2343016207837053197) --> + <skip /> + <!-- no translation found for osu_status_redirect_response_received (5323368411922609405) --> + <skip /> + <!-- no translation found for osu_status_second_soap_exchange (7115332266758483909) --> + <skip /> + <!-- no translation found for osu_status_third_soap_exchange (8460901783597440766) --> + <skip /> + <!-- no translation found for osu_status_retrieving_trust_root_certs (1563445892926269689) --> + <skip /> + <!-- no translation found for osu_provisioning_complete (5120178802493970149) --> + <skip /> <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> diff --git a/packages/SettingsLib/res/values-sk/strings.xml b/packages/SettingsLib/res/values-sk/strings.xml index ed51f5533bd5..b41d5d344449 100644 --- a/packages/SettingsLib/res/values-sk/strings.xml +++ b/packages/SettingsLib/res/values-sk/strings.xml @@ -38,13 +38,87 @@ <string name="connected_via_network_scorer" msgid="5713793306870815341">"Automaticky pripojené prostredníctvom %1$s"</string> <string name="connected_via_network_scorer_default" msgid="7867260222020343104">"Automaticky pripojené prostredníctvom poskytovateľa hodnotenia siete"</string> <string name="connected_via_passpoint" msgid="2826205693803088747">"Pripojené prostredníctvom %1$s"</string> + <!-- no translation found for ssid_by_passpoint_provider (7898171424140673315) --> + <skip /> <string name="available_via_passpoint" msgid="1617440946846329613">"K dispozícii prostredníctvom %1$s"</string> + <!-- no translation found for tap_to_set_up (2468970825530423314) --> + <skip /> <string name="wifi_connected_no_internet" msgid="8202906332837777829">"Pripojené, žiadny internet"</string> <string name="wifi_status_no_internet" msgid="5784710974669608361">"Žiadny internet"</string> <string name="wifi_status_sign_in_required" msgid="123517180404752756">"Vyžaduje sa prihlásenie"</string> <string name="wifi_ap_unable_to_handle_new_sta" msgid="5348824313514404541">"Prístupový bod je dočasne plný"</string> <string name="connected_via_carrier" msgid="7583780074526041912">"Pripojené prostredníctvom operátora %1$s"</string> <string name="available_via_carrier" msgid="1469036129740799053">"K dispozícii prostredníctvom operátora %1$s"</string> + <!-- no translation found for osu_failure_ap_connection (598977488344424542) --> + <skip /> + <!-- no translation found for osu_failure_server_url_invalid (2237477219243136714) --> + <skip /> + <!-- no translation found for osu_failure_server_connection (8192988165059982174) --> + <skip /> + <!-- no translation found for osu_failure_server_validation (4631649978129606823) --> + <skip /> + <!-- no translation found for osu_failure_service_provider_verification (4854091521439785597) --> + <skip /> + <!-- no translation found for osu_failure_provisioning_aborted (424627208135320329) --> + <skip /> + <!-- no translation found for osu_failure_provisioning_not_available (3021783729256985432) --> + <skip /> + <!-- no translation found for osu_failure_invalid_server_url (8548886196179435758) --> + <skip /> + <!-- no translation found for osu_failure_unexpected_command_type (8245921319866603904) --> + <skip /> + <!-- no translation found for osu_failure_unexpected_soap_message_type (2255897608510053065) --> + <skip /> + <!-- no translation found for osu_failure_soap_message_exchange (4357358438685987192) --> + <skip /> + <!-- no translation found for osu_failure_start_redirect_listener (4292769407279548482) --> + <skip /> + <!-- no translation found for osu_failure_timed_out_redirect_listener (3168657820278807508) --> + <skip /> + <!-- no translation found for osu_failure_no_osu_activity_found (4593038891437878675) --> + <skip /> + <!-- no translation found for osu_failure_unexpected_soap_message_status (6568467710235256675) --> + <skip /> + <!-- no translation found for osu_failure_no_pps_mo (850567403039076835) --> + <skip /> + <!-- no translation found for osu_failure_no_aaa_server_trust_root_node (8961455873459838456) --> + <skip /> + <!-- no translation found for osu_failure_no_remediation_server_trust_root_node (5041179688081545244) --> + <skip /> + <!-- no translation found for osu_failure_no_policy_server_trust_root_node (6617290380940513539) --> + <skip /> + <!-- no translation found for osu_failure_retrieve_trust_root_certificates (1499136256195528265) --> + <skip /> + <!-- no translation found for osu_failure_no_aaa_trust_root_certificate (1904322497042226984) --> + <skip /> + <!-- no translation found for osu_failure_add_passpoint_configuration (2173557755811446047) --> + <skip /> + <!-- no translation found for osu_failure_osu_provider_not_found (6616172862116673082) --> + <skip /> + <!-- no translation found for osu_status_ap_connecting (5296821043003441437) --> + <skip /> + <!-- no translation found for osu_status_ap_connected (3777289375683170728) --> + <skip /> + <!-- no translation found for osu_status_server_connecting (8499785407540355867) --> + <skip /> + <!-- no translation found for osu_status_server_validated (3158727184762596355) --> + <skip /> + <!-- no translation found for osu_status_server_connected (8382024481520158168) --> + <skip /> + <!-- no translation found for osu_status_init_soap_exchange (8628063888912101981) --> + <skip /> + <!-- no translation found for osu_status_waiting_for_redirect_response (2343016207837053197) --> + <skip /> + <!-- no translation found for osu_status_redirect_response_received (5323368411922609405) --> + <skip /> + <!-- no translation found for osu_status_second_soap_exchange (7115332266758483909) --> + <skip /> + <!-- no translation found for osu_status_third_soap_exchange (8460901783597440766) --> + <skip /> + <!-- no translation found for osu_status_retrieving_trust_root_certs (1563445892926269689) --> + <skip /> + <!-- no translation found for osu_provisioning_complete (5120178802493970149) --> + <skip /> <string name="speed_label_very_slow" msgid="1867055264243608530">"Veľmi nízka"</string> <string name="speed_label_slow" msgid="813109590815810235">"Nízka"</string> <string name="speed_label_okay" msgid="2331665440671174858">"OK"</string> diff --git a/packages/SettingsLib/res/values-sl/strings.xml b/packages/SettingsLib/res/values-sl/strings.xml index ad47f750d172..298acb93d818 100644 --- a/packages/SettingsLib/res/values-sl/strings.xml +++ b/packages/SettingsLib/res/values-sl/strings.xml @@ -38,13 +38,87 @@ <string name="connected_via_network_scorer" msgid="5713793306870815341">"Samodejno vzpostavljena povezava prek: %1$s"</string> <string name="connected_via_network_scorer_default" msgid="7867260222020343104">"Samodejno vzpostavljena povezava prek ponudnika ocenjevanja omrežij"</string> <string name="connected_via_passpoint" msgid="2826205693803088747">"Vzpostavljena povezava prek: %1$s"</string> + <!-- no translation found for ssid_by_passpoint_provider (7898171424140673315) --> + <skip /> <string name="available_via_passpoint" msgid="1617440946846329613">"Na voljo prek: %1$s"</string> + <!-- no translation found for tap_to_set_up (2468970825530423314) --> + <skip /> <string name="wifi_connected_no_internet" msgid="8202906332837777829">"Vzpostavljena povezava, brez interneta"</string> <string name="wifi_status_no_internet" msgid="5784710974669608361">"Brez internetne povezave"</string> <string name="wifi_status_sign_in_required" msgid="123517180404752756">"Zahtevana je prijava"</string> <string name="wifi_ap_unable_to_handle_new_sta" msgid="5348824313514404541">"Dostopna točka je trenutno zasedena"</string> <string name="connected_via_carrier" msgid="7583780074526041912">"Vzpostavljena povezava prek: %1$s"</string> <string name="available_via_carrier" msgid="1469036129740799053">"Na voljo prek: %1$s"</string> + <!-- no translation found for osu_failure_ap_connection (598977488344424542) --> + <skip /> + <!-- no translation found for osu_failure_server_url_invalid (2237477219243136714) --> + <skip /> + <!-- no translation found for osu_failure_server_connection (8192988165059982174) --> + <skip /> + <!-- no translation found for osu_failure_server_validation (4631649978129606823) --> + <skip /> + <!-- no translation found for osu_failure_service_provider_verification (4854091521439785597) --> + <skip /> + <!-- no translation found for osu_failure_provisioning_aborted (424627208135320329) --> + <skip /> + <!-- no translation found for osu_failure_provisioning_not_available (3021783729256985432) --> + <skip /> + <!-- no translation found for osu_failure_invalid_server_url (8548886196179435758) --> + <skip /> + <!-- no translation found for osu_failure_unexpected_command_type (8245921319866603904) --> + <skip /> + <!-- no translation found for osu_failure_unexpected_soap_message_type (2255897608510053065) --> + <skip /> + <!-- no translation found for osu_failure_soap_message_exchange (4357358438685987192) --> + <skip /> + <!-- no translation found for osu_failure_start_redirect_listener (4292769407279548482) --> + <skip /> + <!-- no translation found for osu_failure_timed_out_redirect_listener (3168657820278807508) --> + <skip /> + <!-- no translation found for osu_failure_no_osu_activity_found (4593038891437878675) --> + <skip /> + <!-- no translation found for osu_failure_unexpected_soap_message_status (6568467710235256675) --> + <skip /> + <!-- no translation found for osu_failure_no_pps_mo (850567403039076835) --> + <skip /> + <!-- no translation found for osu_failure_no_aaa_server_trust_root_node (8961455873459838456) --> + <skip /> + <!-- no translation found for osu_failure_no_remediation_server_trust_root_node (5041179688081545244) --> + <skip /> + <!-- no translation found for osu_failure_no_policy_server_trust_root_node (6617290380940513539) --> + <skip /> + <!-- no translation found for osu_failure_retrieve_trust_root_certificates (1499136256195528265) --> + <skip /> + <!-- no translation found for osu_failure_no_aaa_trust_root_certificate (1904322497042226984) --> + <skip /> + <!-- no translation found for osu_failure_add_passpoint_configuration (2173557755811446047) --> + <skip /> + <!-- no translation found for osu_failure_osu_provider_not_found (6616172862116673082) --> + <skip /> + <!-- no translation found for osu_status_ap_connecting (5296821043003441437) --> + <skip /> + <!-- no translation found for osu_status_ap_connected (3777289375683170728) --> + <skip /> + <!-- no translation found for osu_status_server_connecting (8499785407540355867) --> + <skip /> + <!-- no translation found for osu_status_server_validated (3158727184762596355) --> + <skip /> + <!-- no translation found for osu_status_server_connected (8382024481520158168) --> + <skip /> + <!-- no translation found for osu_status_init_soap_exchange (8628063888912101981) --> + <skip /> + <!-- no translation found for osu_status_waiting_for_redirect_response (2343016207837053197) --> + <skip /> + <!-- no translation found for osu_status_redirect_response_received (5323368411922609405) --> + <skip /> + <!-- no translation found for osu_status_second_soap_exchange (7115332266758483909) --> + <skip /> + <!-- no translation found for osu_status_third_soap_exchange (8460901783597440766) --> + <skip /> + <!-- no translation found for osu_status_retrieving_trust_root_certs (1563445892926269689) --> + <skip /> + <!-- no translation found for osu_provisioning_complete (5120178802493970149) --> + <skip /> <string name="speed_label_very_slow" msgid="1867055264243608530">"Zelo počasna"</string> <string name="speed_label_slow" msgid="813109590815810235">"Počasna"</string> <string name="speed_label_okay" msgid="2331665440671174858">"V redu"</string> diff --git a/packages/SettingsLib/res/values-sq/strings.xml b/packages/SettingsLib/res/values-sq/strings.xml index f8f491bb365f..569b4d9e91d9 100644 --- a/packages/SettingsLib/res/values-sq/strings.xml +++ b/packages/SettingsLib/res/values-sq/strings.xml @@ -38,13 +38,87 @@ <string name="connected_via_network_scorer" msgid="5713793306870815341">"Lidhur automatikisht përmes %1$s"</string> <string name="connected_via_network_scorer_default" msgid="7867260222020343104">"Lidhur automatikisht nëpërmjet ofruesit të vlerësimit të rrjetit"</string> <string name="connected_via_passpoint" msgid="2826205693803088747">"E lidhur përmes %1$s"</string> + <!-- no translation found for ssid_by_passpoint_provider (7898171424140673315) --> + <skip /> <string name="available_via_passpoint" msgid="1617440946846329613">"E mundshme përmes %1$s"</string> + <!-- no translation found for tap_to_set_up (2468970825530423314) --> + <skip /> <string name="wifi_connected_no_internet" msgid="8202906332837777829">"U lidh, por nuk ka internet"</string> <string name="wifi_status_no_internet" msgid="5784710974669608361">"Nuk ka internet"</string> <string name="wifi_status_sign_in_required" msgid="123517180404752756">"Kërkohet identifikimi"</string> <string name="wifi_ap_unable_to_handle_new_sta" msgid="5348824313514404541">"Pika e qasjes është përkohësisht plot"</string> <string name="connected_via_carrier" msgid="7583780074526041912">"E lidhur përmes %1$s"</string> <string name="available_via_carrier" msgid="1469036129740799053">"E disponueshme përmes %1$s"</string> + <!-- no translation found for osu_failure_ap_connection (598977488344424542) --> + <skip /> + <!-- no translation found for osu_failure_server_url_invalid (2237477219243136714) --> + <skip /> + <!-- no translation found for osu_failure_server_connection (8192988165059982174) --> + <skip /> + <!-- no translation found for osu_failure_server_validation (4631649978129606823) --> + <skip /> + <!-- no translation found for osu_failure_service_provider_verification (4854091521439785597) --> + <skip /> + <!-- no translation found for osu_failure_provisioning_aborted (424627208135320329) --> + <skip /> + <!-- no translation found for osu_failure_provisioning_not_available (3021783729256985432) --> + <skip /> + <!-- no translation found for osu_failure_invalid_server_url (8548886196179435758) --> + <skip /> + <!-- no translation found for osu_failure_unexpected_command_type (8245921319866603904) --> + <skip /> + <!-- no translation found for osu_failure_unexpected_soap_message_type (2255897608510053065) --> + <skip /> + <!-- no translation found for osu_failure_soap_message_exchange (4357358438685987192) --> + <skip /> + <!-- no translation found for osu_failure_start_redirect_listener (4292769407279548482) --> + <skip /> + <!-- no translation found for osu_failure_timed_out_redirect_listener (3168657820278807508) --> + <skip /> + <!-- no translation found for osu_failure_no_osu_activity_found (4593038891437878675) --> + <skip /> + <!-- no translation found for osu_failure_unexpected_soap_message_status (6568467710235256675) --> + <skip /> + <!-- no translation found for osu_failure_no_pps_mo (850567403039076835) --> + <skip /> + <!-- no translation found for osu_failure_no_aaa_server_trust_root_node (8961455873459838456) --> + <skip /> + <!-- no translation found for osu_failure_no_remediation_server_trust_root_node (5041179688081545244) --> + <skip /> + <!-- no translation found for osu_failure_no_policy_server_trust_root_node (6617290380940513539) --> + <skip /> + <!-- no translation found for osu_failure_retrieve_trust_root_certificates (1499136256195528265) --> + <skip /> + <!-- no translation found for osu_failure_no_aaa_trust_root_certificate (1904322497042226984) --> + <skip /> + <!-- no translation found for osu_failure_add_passpoint_configuration (2173557755811446047) --> + <skip /> + <!-- no translation found for osu_failure_osu_provider_not_found (6616172862116673082) --> + <skip /> + <!-- no translation found for osu_status_ap_connecting (5296821043003441437) --> + <skip /> + <!-- no translation found for osu_status_ap_connected (3777289375683170728) --> + <skip /> + <!-- no translation found for osu_status_server_connecting (8499785407540355867) --> + <skip /> + <!-- no translation found for osu_status_server_validated (3158727184762596355) --> + <skip /> + <!-- no translation found for osu_status_server_connected (8382024481520158168) --> + <skip /> + <!-- no translation found for osu_status_init_soap_exchange (8628063888912101981) --> + <skip /> + <!-- no translation found for osu_status_waiting_for_redirect_response (2343016207837053197) --> + <skip /> + <!-- no translation found for osu_status_redirect_response_received (5323368411922609405) --> + <skip /> + <!-- no translation found for osu_status_second_soap_exchange (7115332266758483909) --> + <skip /> + <!-- no translation found for osu_status_third_soap_exchange (8460901783597440766) --> + <skip /> + <!-- no translation found for osu_status_retrieving_trust_root_certs (1563445892926269689) --> + <skip /> + <!-- no translation found for osu_provisioning_complete (5120178802493970149) --> + <skip /> <string name="speed_label_very_slow" msgid="1867055264243608530">"Shumë e ulët"</string> <string name="speed_label_slow" msgid="813109590815810235">"E ngadaltë"</string> <string name="speed_label_okay" msgid="2331665440671174858">"Në rregull"</string> diff --git a/packages/SettingsLib/res/values-sr/strings.xml b/packages/SettingsLib/res/values-sr/strings.xml index 3fe40f914a09..bf5e311d5174 100644 --- a/packages/SettingsLib/res/values-sr/strings.xml +++ b/packages/SettingsLib/res/values-sr/strings.xml @@ -38,13 +38,87 @@ <string name="connected_via_network_scorer" msgid="5713793306870815341">"Аутоматски повезано преко %1$s"</string> <string name="connected_via_network_scorer_default" msgid="7867260222020343104">"Аутоматски повезано преко добављача оцене мреже"</string> <string name="connected_via_passpoint" msgid="2826205693803088747">"Веза је успостављена преко приступне тачке %1$s"</string> + <!-- no translation found for ssid_by_passpoint_provider (7898171424140673315) --> + <skip /> <string name="available_via_passpoint" msgid="1617440946846329613">"Доступна је преко приступне тачке %1$s"</string> + <!-- no translation found for tap_to_set_up (2468970825530423314) --> + <skip /> <string name="wifi_connected_no_internet" msgid="8202906332837777829">"Веза је успостављена, нема интернета"</string> <string name="wifi_status_no_internet" msgid="5784710974669608361">"Нема интернета"</string> <string name="wifi_status_sign_in_required" msgid="123517180404752756">"Треба да се пријавите"</string> <string name="wifi_ap_unable_to_handle_new_sta" msgid="5348824313514404541">"Приступна тачка је привремено заузета"</string> <string name="connected_via_carrier" msgid="7583780074526041912">"Повезано преко %1$s"</string> <string name="available_via_carrier" msgid="1469036129740799053">"Доступно преко %1$s"</string> + <!-- no translation found for osu_failure_ap_connection (598977488344424542) --> + <skip /> + <!-- no translation found for osu_failure_server_url_invalid (2237477219243136714) --> + <skip /> + <!-- no translation found for osu_failure_server_connection (8192988165059982174) --> + <skip /> + <!-- no translation found for osu_failure_server_validation (4631649978129606823) --> + <skip /> + <!-- no translation found for osu_failure_service_provider_verification (4854091521439785597) --> + <skip /> + <!-- no translation found for osu_failure_provisioning_aborted (424627208135320329) --> + <skip /> + <!-- no translation found for osu_failure_provisioning_not_available (3021783729256985432) --> + <skip /> + <!-- no translation found for osu_failure_invalid_server_url (8548886196179435758) --> + <skip /> + <!-- no translation found for osu_failure_unexpected_command_type (8245921319866603904) --> + <skip /> + <!-- no translation found for osu_failure_unexpected_soap_message_type (2255897608510053065) --> + <skip /> + <!-- no translation found for osu_failure_soap_message_exchange (4357358438685987192) --> + <skip /> + <!-- no translation found for osu_failure_start_redirect_listener (4292769407279548482) --> + <skip /> + <!-- no translation found for osu_failure_timed_out_redirect_listener (3168657820278807508) --> + <skip /> + <!-- no translation found for osu_failure_no_osu_activity_found (4593038891437878675) --> + <skip /> + <!-- no translation found for osu_failure_unexpected_soap_message_status (6568467710235256675) --> + <skip /> + <!-- no translation found for osu_failure_no_pps_mo (850567403039076835) --> + <skip /> + <!-- no translation found for osu_failure_no_aaa_server_trust_root_node (8961455873459838456) --> + <skip /> + <!-- no translation found for osu_failure_no_remediation_server_trust_root_node (5041179688081545244) --> + <skip /> + <!-- no translation found for osu_failure_no_policy_server_trust_root_node (6617290380940513539) --> + <skip /> + <!-- no translation found for osu_failure_retrieve_trust_root_certificates (1499136256195528265) --> + <skip /> + <!-- no translation found for osu_failure_no_aaa_trust_root_certificate (1904322497042226984) --> + <skip /> + <!-- no translation found for osu_failure_add_passpoint_configuration (2173557755811446047) --> + <skip /> + <!-- no translation found for osu_failure_osu_provider_not_found (6616172862116673082) --> + <skip /> + <!-- no translation found for osu_status_ap_connecting (5296821043003441437) --> + <skip /> + <!-- no translation found for osu_status_ap_connected (3777289375683170728) --> + <skip /> + <!-- no translation found for osu_status_server_connecting (8499785407540355867) --> + <skip /> + <!-- no translation found for osu_status_server_validated (3158727184762596355) --> + <skip /> + <!-- no translation found for osu_status_server_connected (8382024481520158168) --> + <skip /> + <!-- no translation found for osu_status_init_soap_exchange (8628063888912101981) --> + <skip /> + <!-- no translation found for osu_status_waiting_for_redirect_response (2343016207837053197) --> + <skip /> + <!-- no translation found for osu_status_redirect_response_received (5323368411922609405) --> + <skip /> + <!-- no translation found for osu_status_second_soap_exchange (7115332266758483909) --> + <skip /> + <!-- no translation found for osu_status_third_soap_exchange (8460901783597440766) --> + <skip /> + <!-- no translation found for osu_status_retrieving_trust_root_certs (1563445892926269689) --> + <skip /> + <!-- no translation found for osu_provisioning_complete (5120178802493970149) --> + <skip /> <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> diff --git a/packages/SettingsLib/res/values-sv/strings.xml b/packages/SettingsLib/res/values-sv/strings.xml index 186395e3ef09..6e004df13926 100644 --- a/packages/SettingsLib/res/values-sv/strings.xml +++ b/packages/SettingsLib/res/values-sv/strings.xml @@ -38,13 +38,87 @@ <string name="connected_via_network_scorer" msgid="5713793306870815341">"Automatiskt ansluten via %1$s"</string> <string name="connected_via_network_scorer_default" msgid="7867260222020343104">"Automatiskt ansluten via leverantör av nätverksbetyg"</string> <string name="connected_via_passpoint" msgid="2826205693803088747">"Anslutet via %1$s"</string> + <!-- no translation found for ssid_by_passpoint_provider (7898171424140673315) --> + <skip /> <string name="available_via_passpoint" msgid="1617440946846329613">"Tillgängligt via %1$s"</string> + <!-- no translation found for tap_to_set_up (2468970825530423314) --> + <skip /> <string name="wifi_connected_no_internet" msgid="8202906332837777829">"Ansluten, inget internet"</string> <string name="wifi_status_no_internet" msgid="5784710974669608361">"Inget internet"</string> <string name="wifi_status_sign_in_required" msgid="123517180404752756">"Inloggning krävs"</string> <string name="wifi_ap_unable_to_handle_new_sta" msgid="5348824313514404541">"Åtkomstpunkten har inga platser över för tillfället"</string> <string name="connected_via_carrier" msgid="7583780074526041912">"Anslutet via %1$s"</string> <string name="available_via_carrier" msgid="1469036129740799053">"Tillgängligt via %1$s"</string> + <!-- no translation found for osu_failure_ap_connection (598977488344424542) --> + <skip /> + <!-- no translation found for osu_failure_server_url_invalid (2237477219243136714) --> + <skip /> + <!-- no translation found for osu_failure_server_connection (8192988165059982174) --> + <skip /> + <!-- no translation found for osu_failure_server_validation (4631649978129606823) --> + <skip /> + <!-- no translation found for osu_failure_service_provider_verification (4854091521439785597) --> + <skip /> + <!-- no translation found for osu_failure_provisioning_aborted (424627208135320329) --> + <skip /> + <!-- no translation found for osu_failure_provisioning_not_available (3021783729256985432) --> + <skip /> + <!-- no translation found for osu_failure_invalid_server_url (8548886196179435758) --> + <skip /> + <!-- no translation found for osu_failure_unexpected_command_type (8245921319866603904) --> + <skip /> + <!-- no translation found for osu_failure_unexpected_soap_message_type (2255897608510053065) --> + <skip /> + <!-- no translation found for osu_failure_soap_message_exchange (4357358438685987192) --> + <skip /> + <!-- no translation found for osu_failure_start_redirect_listener (4292769407279548482) --> + <skip /> + <!-- no translation found for osu_failure_timed_out_redirect_listener (3168657820278807508) --> + <skip /> + <!-- no translation found for osu_failure_no_osu_activity_found (4593038891437878675) --> + <skip /> + <!-- no translation found for osu_failure_unexpected_soap_message_status (6568467710235256675) --> + <skip /> + <!-- no translation found for osu_failure_no_pps_mo (850567403039076835) --> + <skip /> + <!-- no translation found for osu_failure_no_aaa_server_trust_root_node (8961455873459838456) --> + <skip /> + <!-- no translation found for osu_failure_no_remediation_server_trust_root_node (5041179688081545244) --> + <skip /> + <!-- no translation found for osu_failure_no_policy_server_trust_root_node (6617290380940513539) --> + <skip /> + <!-- no translation found for osu_failure_retrieve_trust_root_certificates (1499136256195528265) --> + <skip /> + <!-- no translation found for osu_failure_no_aaa_trust_root_certificate (1904322497042226984) --> + <skip /> + <!-- no translation found for osu_failure_add_passpoint_configuration (2173557755811446047) --> + <skip /> + <!-- no translation found for osu_failure_osu_provider_not_found (6616172862116673082) --> + <skip /> + <!-- no translation found for osu_status_ap_connecting (5296821043003441437) --> + <skip /> + <!-- no translation found for osu_status_ap_connected (3777289375683170728) --> + <skip /> + <!-- no translation found for osu_status_server_connecting (8499785407540355867) --> + <skip /> + <!-- no translation found for osu_status_server_validated (3158727184762596355) --> + <skip /> + <!-- no translation found for osu_status_server_connected (8382024481520158168) --> + <skip /> + <!-- no translation found for osu_status_init_soap_exchange (8628063888912101981) --> + <skip /> + <!-- no translation found for osu_status_waiting_for_redirect_response (2343016207837053197) --> + <skip /> + <!-- no translation found for osu_status_redirect_response_received (5323368411922609405) --> + <skip /> + <!-- no translation found for osu_status_second_soap_exchange (7115332266758483909) --> + <skip /> + <!-- no translation found for osu_status_third_soap_exchange (8460901783597440766) --> + <skip /> + <!-- no translation found for osu_status_retrieving_trust_root_certs (1563445892926269689) --> + <skip /> + <!-- no translation found for osu_provisioning_complete (5120178802493970149) --> + <skip /> <string name="speed_label_very_slow" msgid="1867055264243608530">"Mycket långsam"</string> <string name="speed_label_slow" msgid="813109590815810235">"Långsam"</string> <string name="speed_label_okay" msgid="2331665440671174858">"Okej"</string> diff --git a/packages/SettingsLib/res/values-sw/strings.xml b/packages/SettingsLib/res/values-sw/strings.xml index 03e0c3a8d57c..bf034761f2f1 100644 --- a/packages/SettingsLib/res/values-sw/strings.xml +++ b/packages/SettingsLib/res/values-sw/strings.xml @@ -38,13 +38,87 @@ <string name="connected_via_network_scorer" msgid="5713793306870815341">"Imeunganishwa kiotomatiki kupitia %1$s"</string> <string name="connected_via_network_scorer_default" msgid="7867260222020343104">"Imeunganishwa kiotomatiki kupitia mtoa huduma wa ukadiriaji wa mtandao"</string> <string name="connected_via_passpoint" msgid="2826205693803088747">"Imeunganishwa kupitia %1$s"</string> + <!-- no translation found for ssid_by_passpoint_provider (7898171424140673315) --> + <skip /> <string name="available_via_passpoint" msgid="1617440946846329613">"Inapatikana kupitia %1$s"</string> + <!-- no translation found for tap_to_set_up (2468970825530423314) --> + <skip /> <string name="wifi_connected_no_internet" msgid="8202906332837777829">"Imeunganishwa, hakuna intaneti"</string> <string name="wifi_status_no_internet" msgid="5784710974669608361">"Hakuna intaneti"</string> <string name="wifi_status_sign_in_required" msgid="123517180404752756">"Unahitaji kuingia katika akaunti"</string> <string name="wifi_ap_unable_to_handle_new_sta" msgid="5348824313514404541">"Lango la mtandao lina shughuli nyingi kwa sasa"</string> <string name="connected_via_carrier" msgid="7583780074526041912">"Imeunganishwa kupitia %1$s"</string> <string name="available_via_carrier" msgid="1469036129740799053">"Inapatikana kupitia %1$s"</string> + <!-- no translation found for osu_failure_ap_connection (598977488344424542) --> + <skip /> + <!-- no translation found for osu_failure_server_url_invalid (2237477219243136714) --> + <skip /> + <!-- no translation found for osu_failure_server_connection (8192988165059982174) --> + <skip /> + <!-- no translation found for osu_failure_server_validation (4631649978129606823) --> + <skip /> + <!-- no translation found for osu_failure_service_provider_verification (4854091521439785597) --> + <skip /> + <!-- no translation found for osu_failure_provisioning_aborted (424627208135320329) --> + <skip /> + <!-- no translation found for osu_failure_provisioning_not_available (3021783729256985432) --> + <skip /> + <!-- no translation found for osu_failure_invalid_server_url (8548886196179435758) --> + <skip /> + <!-- no translation found for osu_failure_unexpected_command_type (8245921319866603904) --> + <skip /> + <!-- no translation found for osu_failure_unexpected_soap_message_type (2255897608510053065) --> + <skip /> + <!-- no translation found for osu_failure_soap_message_exchange (4357358438685987192) --> + <skip /> + <!-- no translation found for osu_failure_start_redirect_listener (4292769407279548482) --> + <skip /> + <!-- no translation found for osu_failure_timed_out_redirect_listener (3168657820278807508) --> + <skip /> + <!-- no translation found for osu_failure_no_osu_activity_found (4593038891437878675) --> + <skip /> + <!-- no translation found for osu_failure_unexpected_soap_message_status (6568467710235256675) --> + <skip /> + <!-- no translation found for osu_failure_no_pps_mo (850567403039076835) --> + <skip /> + <!-- no translation found for osu_failure_no_aaa_server_trust_root_node (8961455873459838456) --> + <skip /> + <!-- no translation found for osu_failure_no_remediation_server_trust_root_node (5041179688081545244) --> + <skip /> + <!-- no translation found for osu_failure_no_policy_server_trust_root_node (6617290380940513539) --> + <skip /> + <!-- no translation found for osu_failure_retrieve_trust_root_certificates (1499136256195528265) --> + <skip /> + <!-- no translation found for osu_failure_no_aaa_trust_root_certificate (1904322497042226984) --> + <skip /> + <!-- no translation found for osu_failure_add_passpoint_configuration (2173557755811446047) --> + <skip /> + <!-- no translation found for osu_failure_osu_provider_not_found (6616172862116673082) --> + <skip /> + <!-- no translation found for osu_status_ap_connecting (5296821043003441437) --> + <skip /> + <!-- no translation found for osu_status_ap_connected (3777289375683170728) --> + <skip /> + <!-- no translation found for osu_status_server_connecting (8499785407540355867) --> + <skip /> + <!-- no translation found for osu_status_server_validated (3158727184762596355) --> + <skip /> + <!-- no translation found for osu_status_server_connected (8382024481520158168) --> + <skip /> + <!-- no translation found for osu_status_init_soap_exchange (8628063888912101981) --> + <skip /> + <!-- no translation found for osu_status_waiting_for_redirect_response (2343016207837053197) --> + <skip /> + <!-- no translation found for osu_status_redirect_response_received (5323368411922609405) --> + <skip /> + <!-- no translation found for osu_status_second_soap_exchange (7115332266758483909) --> + <skip /> + <!-- no translation found for osu_status_third_soap_exchange (8460901783597440766) --> + <skip /> + <!-- no translation found for osu_status_retrieving_trust_root_certs (1563445892926269689) --> + <skip /> + <!-- no translation found for osu_provisioning_complete (5120178802493970149) --> + <skip /> <string name="speed_label_very_slow" msgid="1867055264243608530">"Polepole Sana"</string> <string name="speed_label_slow" msgid="813109590815810235">"Polepole"</string> <string name="speed_label_okay" msgid="2331665440671174858">"Sawa"</string> diff --git a/packages/SettingsLib/res/values-ta/strings.xml b/packages/SettingsLib/res/values-ta/strings.xml index 0efd2855effd..58e5967cd407 100644 --- a/packages/SettingsLib/res/values-ta/strings.xml +++ b/packages/SettingsLib/res/values-ta/strings.xml @@ -38,13 +38,87 @@ <string name="connected_via_network_scorer" msgid="5713793306870815341">"%1$s மூலம் தானாக இணைக்கப்பட்டது"</string> <string name="connected_via_network_scorer_default" msgid="7867260222020343104">"நெட்வொர்க் மதிப்பீடு வழங்குநரால் தானாக இணைக்கப்பட்டது"</string> <string name="connected_via_passpoint" msgid="2826205693803088747">"%1$s வழியாக இணைக்கப்பட்டது"</string> + <!-- no translation found for ssid_by_passpoint_provider (7898171424140673315) --> + <skip /> <string name="available_via_passpoint" msgid="1617440946846329613">"%1$s வழியாகக் கிடைக்கிறது"</string> + <!-- no translation found for tap_to_set_up (2468970825530423314) --> + <skip /> <string name="wifi_connected_no_internet" msgid="8202906332837777829">"இணைக்கப்பட்டுள்ளது, ஆனால் இண்டர்நெட் இல்லை"</string> <string name="wifi_status_no_internet" msgid="5784710974669608361">"இணைய இணைப்பு இல்லை"</string> <string name="wifi_status_sign_in_required" msgid="123517180404752756">"உள்நுழைய வேண்டும்"</string> <string name="wifi_ap_unable_to_handle_new_sta" msgid="5348824313514404541">"தற்காலிகமாக அணுகல் புள்ளி நிரம்பியுள்ளது"</string> <string name="connected_via_carrier" msgid="7583780074526041912">"%1$s வழியாக இணைக்கப்பட்டது"</string> <string name="available_via_carrier" msgid="1469036129740799053">"%1$s வழியாகக் கிடைக்கிறது"</string> + <!-- no translation found for osu_failure_ap_connection (598977488344424542) --> + <skip /> + <!-- no translation found for osu_failure_server_url_invalid (2237477219243136714) --> + <skip /> + <!-- no translation found for osu_failure_server_connection (8192988165059982174) --> + <skip /> + <!-- no translation found for osu_failure_server_validation (4631649978129606823) --> + <skip /> + <!-- no translation found for osu_failure_service_provider_verification (4854091521439785597) --> + <skip /> + <!-- no translation found for osu_failure_provisioning_aborted (424627208135320329) --> + <skip /> + <!-- no translation found for osu_failure_provisioning_not_available (3021783729256985432) --> + <skip /> + <!-- no translation found for osu_failure_invalid_server_url (8548886196179435758) --> + <skip /> + <!-- no translation found for osu_failure_unexpected_command_type (8245921319866603904) --> + <skip /> + <!-- no translation found for osu_failure_unexpected_soap_message_type (2255897608510053065) --> + <skip /> + <!-- no translation found for osu_failure_soap_message_exchange (4357358438685987192) --> + <skip /> + <!-- no translation found for osu_failure_start_redirect_listener (4292769407279548482) --> + <skip /> + <!-- no translation found for osu_failure_timed_out_redirect_listener (3168657820278807508) --> + <skip /> + <!-- no translation found for osu_failure_no_osu_activity_found (4593038891437878675) --> + <skip /> + <!-- no translation found for osu_failure_unexpected_soap_message_status (6568467710235256675) --> + <skip /> + <!-- no translation found for osu_failure_no_pps_mo (850567403039076835) --> + <skip /> + <!-- no translation found for osu_failure_no_aaa_server_trust_root_node (8961455873459838456) --> + <skip /> + <!-- no translation found for osu_failure_no_remediation_server_trust_root_node (5041179688081545244) --> + <skip /> + <!-- no translation found for osu_failure_no_policy_server_trust_root_node (6617290380940513539) --> + <skip /> + <!-- no translation found for osu_failure_retrieve_trust_root_certificates (1499136256195528265) --> + <skip /> + <!-- no translation found for osu_failure_no_aaa_trust_root_certificate (1904322497042226984) --> + <skip /> + <!-- no translation found for osu_failure_add_passpoint_configuration (2173557755811446047) --> + <skip /> + <!-- no translation found for osu_failure_osu_provider_not_found (6616172862116673082) --> + <skip /> + <!-- no translation found for osu_status_ap_connecting (5296821043003441437) --> + <skip /> + <!-- no translation found for osu_status_ap_connected (3777289375683170728) --> + <skip /> + <!-- no translation found for osu_status_server_connecting (8499785407540355867) --> + <skip /> + <!-- no translation found for osu_status_server_validated (3158727184762596355) --> + <skip /> + <!-- no translation found for osu_status_server_connected (8382024481520158168) --> + <skip /> + <!-- no translation found for osu_status_init_soap_exchange (8628063888912101981) --> + <skip /> + <!-- no translation found for osu_status_waiting_for_redirect_response (2343016207837053197) --> + <skip /> + <!-- no translation found for osu_status_redirect_response_received (5323368411922609405) --> + <skip /> + <!-- no translation found for osu_status_second_soap_exchange (7115332266758483909) --> + <skip /> + <!-- no translation found for osu_status_third_soap_exchange (8460901783597440766) --> + <skip /> + <!-- no translation found for osu_status_retrieving_trust_root_certs (1563445892926269689) --> + <skip /> + <!-- no translation found for osu_provisioning_complete (5120178802493970149) --> + <skip /> <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> diff --git a/packages/SettingsLib/res/values-te/arrays.xml b/packages/SettingsLib/res/values-te/arrays.xml index ddb40ce96c94..5d79065885d2 100644 --- a/packages/SettingsLib/res/values-te/arrays.xml +++ b/packages/SettingsLib/res/values-te/arrays.xml @@ -173,7 +173,7 @@ <item msgid="2850427388488887328">"కెర్నెల్ మాత్రమే"</item> </string-array> <string-array name="select_logpersist_summaries"> - <item msgid="2216470072500521830">"ఆఫ్ చేయి"</item> + <item msgid="2216470072500521830">"ఆఫ్"</item> <item msgid="172978079776521897">"అన్ని లాగ్ బఫర్లు"</item> <item msgid="3873873912383879240">"అన్నీ కానీ రేడియో లాగ్ బఫర్లు"</item> <item msgid="8489661142527693381">"కెర్నెల్ లాగ్ బఫర్ మాత్రమే"</item> diff --git a/packages/SettingsLib/res/values-te/strings.xml b/packages/SettingsLib/res/values-te/strings.xml index 2caa2ef8421a..9d1b23e77807 100644 --- a/packages/SettingsLib/res/values-te/strings.xml +++ b/packages/SettingsLib/res/values-te/strings.xml @@ -38,13 +38,87 @@ <string name="connected_via_network_scorer" msgid="5713793306870815341">"%1$s ద్వారా స్వయంచాలకంగా కనెక్ట్ చేయబడింది"</string> <string name="connected_via_network_scorer_default" msgid="7867260222020343104">"నెట్వర్క్ రేటింగ్ ప్రదాత ద్వారా స్వయంచాలకంగా కనెక్ట్ చేయబడింది"</string> <string name="connected_via_passpoint" msgid="2826205693803088747">"%1$s ద్వారా కనెక్ట్ చేయబడింది"</string> + <!-- no translation found for ssid_by_passpoint_provider (7898171424140673315) --> + <skip /> <string name="available_via_passpoint" msgid="1617440946846329613">"%1$s ద్వారా అందుబాటులో ఉంది"</string> + <!-- no translation found for tap_to_set_up (2468970825530423314) --> + <skip /> <string name="wifi_connected_no_internet" msgid="8202906332837777829">"కనెక్ట్ చేయబడింది, ఇంటర్నెట్ లేదు"</string> <string name="wifi_status_no_internet" msgid="5784710974669608361">"ఇంటర్నెట్ లేదు"</string> <string name="wifi_status_sign_in_required" msgid="123517180404752756">"సైన్ ఇన్ చేయాలి"</string> <string name="wifi_ap_unable_to_handle_new_sta" msgid="5348824313514404541">"యాక్సెస్ పాయింట్ తాత్కాలికంగా నిండుకుంది"</string> <string name="connected_via_carrier" msgid="7583780074526041912">"%1$s ద్వారా కనెక్ట్ చేయబడింది"</string> <string name="available_via_carrier" msgid="1469036129740799053">"%1$s ద్వారా అందుబాటులో ఉంది"</string> + <!-- no translation found for osu_failure_ap_connection (598977488344424542) --> + <skip /> + <!-- no translation found for osu_failure_server_url_invalid (2237477219243136714) --> + <skip /> + <!-- no translation found for osu_failure_server_connection (8192988165059982174) --> + <skip /> + <!-- no translation found for osu_failure_server_validation (4631649978129606823) --> + <skip /> + <!-- no translation found for osu_failure_service_provider_verification (4854091521439785597) --> + <skip /> + <!-- no translation found for osu_failure_provisioning_aborted (424627208135320329) --> + <skip /> + <!-- no translation found for osu_failure_provisioning_not_available (3021783729256985432) --> + <skip /> + <!-- no translation found for osu_failure_invalid_server_url (8548886196179435758) --> + <skip /> + <!-- no translation found for osu_failure_unexpected_command_type (8245921319866603904) --> + <skip /> + <!-- no translation found for osu_failure_unexpected_soap_message_type (2255897608510053065) --> + <skip /> + <!-- no translation found for osu_failure_soap_message_exchange (4357358438685987192) --> + <skip /> + <!-- no translation found for osu_failure_start_redirect_listener (4292769407279548482) --> + <skip /> + <!-- no translation found for osu_failure_timed_out_redirect_listener (3168657820278807508) --> + <skip /> + <!-- no translation found for osu_failure_no_osu_activity_found (4593038891437878675) --> + <skip /> + <!-- no translation found for osu_failure_unexpected_soap_message_status (6568467710235256675) --> + <skip /> + <!-- no translation found for osu_failure_no_pps_mo (850567403039076835) --> + <skip /> + <!-- no translation found for osu_failure_no_aaa_server_trust_root_node (8961455873459838456) --> + <skip /> + <!-- no translation found for osu_failure_no_remediation_server_trust_root_node (5041179688081545244) --> + <skip /> + <!-- no translation found for osu_failure_no_policy_server_trust_root_node (6617290380940513539) --> + <skip /> + <!-- no translation found for osu_failure_retrieve_trust_root_certificates (1499136256195528265) --> + <skip /> + <!-- no translation found for osu_failure_no_aaa_trust_root_certificate (1904322497042226984) --> + <skip /> + <!-- no translation found for osu_failure_add_passpoint_configuration (2173557755811446047) --> + <skip /> + <!-- no translation found for osu_failure_osu_provider_not_found (6616172862116673082) --> + <skip /> + <!-- no translation found for osu_status_ap_connecting (5296821043003441437) --> + <skip /> + <!-- no translation found for osu_status_ap_connected (3777289375683170728) --> + <skip /> + <!-- no translation found for osu_status_server_connecting (8499785407540355867) --> + <skip /> + <!-- no translation found for osu_status_server_validated (3158727184762596355) --> + <skip /> + <!-- no translation found for osu_status_server_connected (8382024481520158168) --> + <skip /> + <!-- no translation found for osu_status_init_soap_exchange (8628063888912101981) --> + <skip /> + <!-- no translation found for osu_status_waiting_for_redirect_response (2343016207837053197) --> + <skip /> + <!-- no translation found for osu_status_redirect_response_received (5323368411922609405) --> + <skip /> + <!-- no translation found for osu_status_second_soap_exchange (7115332266758483909) --> + <skip /> + <!-- no translation found for osu_status_third_soap_exchange (8460901783597440766) --> + <skip /> + <!-- no translation found for osu_status_retrieving_trust_root_certs (1563445892926269689) --> + <skip /> + <!-- no translation found for osu_provisioning_complete (5120178802493970149) --> + <skip /> <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> diff --git a/packages/SettingsLib/res/values-th/strings.xml b/packages/SettingsLib/res/values-th/strings.xml index 03bf354ecd3e..ddd9aae69bd3 100644 --- a/packages/SettingsLib/res/values-th/strings.xml +++ b/packages/SettingsLib/res/values-th/strings.xml @@ -38,13 +38,87 @@ <string name="connected_via_network_scorer" msgid="5713793306870815341">"เชื่อมต่ออัตโนมัติผ่าน %1$s แล้ว"</string> <string name="connected_via_network_scorer_default" msgid="7867260222020343104">"เชื่อมต่ออัตโนมัติผ่านผู้ให้บริการการจัดอันดับเครือข่าย"</string> <string name="connected_via_passpoint" msgid="2826205693803088747">"เชื่อมต่อผ่าน %1$s แล้ว"</string> + <!-- no translation found for ssid_by_passpoint_provider (7898171424140673315) --> + <skip /> <string name="available_via_passpoint" msgid="1617440946846329613">"พร้อมใช้งานผ่านทาง %1$s"</string> + <!-- no translation found for tap_to_set_up (2468970825530423314) --> + <skip /> <string name="wifi_connected_no_internet" msgid="8202906332837777829">"เชื่อมต่อแล้ว ไม่พบอินเทอร์เน็ต"</string> <string name="wifi_status_no_internet" msgid="5784710974669608361">"ไม่มีอินเทอร์เน็ต"</string> <string name="wifi_status_sign_in_required" msgid="123517180404752756">"ต้องลงชื่อเข้าใช้"</string> <string name="wifi_ap_unable_to_handle_new_sta" msgid="5348824313514404541">"จุดเข้าใช้งานเต็มชั่วคราว"</string> <string name="connected_via_carrier" msgid="7583780074526041912">"เชื่อมต่อผ่าน %1$s แล้ว"</string> <string name="available_via_carrier" msgid="1469036129740799053">"พร้อมใช้งานผ่านทาง %1$s"</string> + <!-- no translation found for osu_failure_ap_connection (598977488344424542) --> + <skip /> + <!-- no translation found for osu_failure_server_url_invalid (2237477219243136714) --> + <skip /> + <!-- no translation found for osu_failure_server_connection (8192988165059982174) --> + <skip /> + <!-- no translation found for osu_failure_server_validation (4631649978129606823) --> + <skip /> + <!-- no translation found for osu_failure_service_provider_verification (4854091521439785597) --> + <skip /> + <!-- no translation found for osu_failure_provisioning_aborted (424627208135320329) --> + <skip /> + <!-- no translation found for osu_failure_provisioning_not_available (3021783729256985432) --> + <skip /> + <!-- no translation found for osu_failure_invalid_server_url (8548886196179435758) --> + <skip /> + <!-- no translation found for osu_failure_unexpected_command_type (8245921319866603904) --> + <skip /> + <!-- no translation found for osu_failure_unexpected_soap_message_type (2255897608510053065) --> + <skip /> + <!-- no translation found for osu_failure_soap_message_exchange (4357358438685987192) --> + <skip /> + <!-- no translation found for osu_failure_start_redirect_listener (4292769407279548482) --> + <skip /> + <!-- no translation found for osu_failure_timed_out_redirect_listener (3168657820278807508) --> + <skip /> + <!-- no translation found for osu_failure_no_osu_activity_found (4593038891437878675) --> + <skip /> + <!-- no translation found for osu_failure_unexpected_soap_message_status (6568467710235256675) --> + <skip /> + <!-- no translation found for osu_failure_no_pps_mo (850567403039076835) --> + <skip /> + <!-- no translation found for osu_failure_no_aaa_server_trust_root_node (8961455873459838456) --> + <skip /> + <!-- no translation found for osu_failure_no_remediation_server_trust_root_node (5041179688081545244) --> + <skip /> + <!-- no translation found for osu_failure_no_policy_server_trust_root_node (6617290380940513539) --> + <skip /> + <!-- no translation found for osu_failure_retrieve_trust_root_certificates (1499136256195528265) --> + <skip /> + <!-- no translation found for osu_failure_no_aaa_trust_root_certificate (1904322497042226984) --> + <skip /> + <!-- no translation found for osu_failure_add_passpoint_configuration (2173557755811446047) --> + <skip /> + <!-- no translation found for osu_failure_osu_provider_not_found (6616172862116673082) --> + <skip /> + <!-- no translation found for osu_status_ap_connecting (5296821043003441437) --> + <skip /> + <!-- no translation found for osu_status_ap_connected (3777289375683170728) --> + <skip /> + <!-- no translation found for osu_status_server_connecting (8499785407540355867) --> + <skip /> + <!-- no translation found for osu_status_server_validated (3158727184762596355) --> + <skip /> + <!-- no translation found for osu_status_server_connected (8382024481520158168) --> + <skip /> + <!-- no translation found for osu_status_init_soap_exchange (8628063888912101981) --> + <skip /> + <!-- no translation found for osu_status_waiting_for_redirect_response (2343016207837053197) --> + <skip /> + <!-- no translation found for osu_status_redirect_response_received (5323368411922609405) --> + <skip /> + <!-- no translation found for osu_status_second_soap_exchange (7115332266758483909) --> + <skip /> + <!-- no translation found for osu_status_third_soap_exchange (8460901783597440766) --> + <skip /> + <!-- no translation found for osu_status_retrieving_trust_root_certs (1563445892926269689) --> + <skip /> + <!-- no translation found for osu_provisioning_complete (5120178802493970149) --> + <skip /> <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> diff --git a/packages/SettingsLib/res/values-tl/strings.xml b/packages/SettingsLib/res/values-tl/strings.xml index 3f5cca23fee9..644548000641 100644 --- a/packages/SettingsLib/res/values-tl/strings.xml +++ b/packages/SettingsLib/res/values-tl/strings.xml @@ -38,13 +38,87 @@ <string name="connected_via_network_scorer" msgid="5713793306870815341">"Awtomatikong nakakonekta sa pamamagitan ng %1$s"</string> <string name="connected_via_network_scorer_default" msgid="7867260222020343104">"Awtomatikong nakakonekta sa pamamagitan ng provider ng rating ng network"</string> <string name="connected_via_passpoint" msgid="2826205693803088747">"Nakakonekta sa pamamagitan ng %1$s"</string> + <!-- no translation found for ssid_by_passpoint_provider (7898171424140673315) --> + <skip /> <string name="available_via_passpoint" msgid="1617440946846329613">"Available sa pamamagitan ng %1$s"</string> + <!-- no translation found for tap_to_set_up (2468970825530423314) --> + <skip /> <string name="wifi_connected_no_internet" msgid="8202906332837777829">"Nakakonekta, walang internet"</string> <string name="wifi_status_no_internet" msgid="5784710974669608361">"Walang internet"</string> <string name="wifi_status_sign_in_required" msgid="123517180404752756">"Kinakailangang mag-sign in"</string> <string name="wifi_ap_unable_to_handle_new_sta" msgid="5348824313514404541">"Pansamantalang puno ang access point"</string> <string name="connected_via_carrier" msgid="7583780074526041912">"Nakakonekta sa pamamagitan ng %1$s"</string> <string name="available_via_carrier" msgid="1469036129740799053">"Available sa pamamagitan ng %1$s"</string> + <!-- no translation found for osu_failure_ap_connection (598977488344424542) --> + <skip /> + <!-- no translation found for osu_failure_server_url_invalid (2237477219243136714) --> + <skip /> + <!-- no translation found for osu_failure_server_connection (8192988165059982174) --> + <skip /> + <!-- no translation found for osu_failure_server_validation (4631649978129606823) --> + <skip /> + <!-- no translation found for osu_failure_service_provider_verification (4854091521439785597) --> + <skip /> + <!-- no translation found for osu_failure_provisioning_aborted (424627208135320329) --> + <skip /> + <!-- no translation found for osu_failure_provisioning_not_available (3021783729256985432) --> + <skip /> + <!-- no translation found for osu_failure_invalid_server_url (8548886196179435758) --> + <skip /> + <!-- no translation found for osu_failure_unexpected_command_type (8245921319866603904) --> + <skip /> + <!-- no translation found for osu_failure_unexpected_soap_message_type (2255897608510053065) --> + <skip /> + <!-- no translation found for osu_failure_soap_message_exchange (4357358438685987192) --> + <skip /> + <!-- no translation found for osu_failure_start_redirect_listener (4292769407279548482) --> + <skip /> + <!-- no translation found for osu_failure_timed_out_redirect_listener (3168657820278807508) --> + <skip /> + <!-- no translation found for osu_failure_no_osu_activity_found (4593038891437878675) --> + <skip /> + <!-- no translation found for osu_failure_unexpected_soap_message_status (6568467710235256675) --> + <skip /> + <!-- no translation found for osu_failure_no_pps_mo (850567403039076835) --> + <skip /> + <!-- no translation found for osu_failure_no_aaa_server_trust_root_node (8961455873459838456) --> + <skip /> + <!-- no translation found for osu_failure_no_remediation_server_trust_root_node (5041179688081545244) --> + <skip /> + <!-- no translation found for osu_failure_no_policy_server_trust_root_node (6617290380940513539) --> + <skip /> + <!-- no translation found for osu_failure_retrieve_trust_root_certificates (1499136256195528265) --> + <skip /> + <!-- no translation found for osu_failure_no_aaa_trust_root_certificate (1904322497042226984) --> + <skip /> + <!-- no translation found for osu_failure_add_passpoint_configuration (2173557755811446047) --> + <skip /> + <!-- no translation found for osu_failure_osu_provider_not_found (6616172862116673082) --> + <skip /> + <!-- no translation found for osu_status_ap_connecting (5296821043003441437) --> + <skip /> + <!-- no translation found for osu_status_ap_connected (3777289375683170728) --> + <skip /> + <!-- no translation found for osu_status_server_connecting (8499785407540355867) --> + <skip /> + <!-- no translation found for osu_status_server_validated (3158727184762596355) --> + <skip /> + <!-- no translation found for osu_status_server_connected (8382024481520158168) --> + <skip /> + <!-- no translation found for osu_status_init_soap_exchange (8628063888912101981) --> + <skip /> + <!-- no translation found for osu_status_waiting_for_redirect_response (2343016207837053197) --> + <skip /> + <!-- no translation found for osu_status_redirect_response_received (5323368411922609405) --> + <skip /> + <!-- no translation found for osu_status_second_soap_exchange (7115332266758483909) --> + <skip /> + <!-- no translation found for osu_status_third_soap_exchange (8460901783597440766) --> + <skip /> + <!-- no translation found for osu_status_retrieving_trust_root_certs (1563445892926269689) --> + <skip /> + <!-- no translation found for osu_provisioning_complete (5120178802493970149) --> + <skip /> <string name="speed_label_very_slow" msgid="1867055264243608530">"Napakabagal"</string> <string name="speed_label_slow" msgid="813109590815810235">"Mabagal"</string> <string name="speed_label_okay" msgid="2331665440671174858">"OK"</string> diff --git a/packages/SettingsLib/res/values-tr/strings.xml b/packages/SettingsLib/res/values-tr/strings.xml index b0a782a50f49..c3a3ff25da33 100644 --- a/packages/SettingsLib/res/values-tr/strings.xml +++ b/packages/SettingsLib/res/values-tr/strings.xml @@ -38,13 +38,87 @@ <string name="connected_via_network_scorer" msgid="5713793306870815341">"%1$s üzerinden otomatik olarak bağlı"</string> <string name="connected_via_network_scorer_default" msgid="7867260222020343104">"Ağ derecelendirme sağlayıcı aracılığıyla otomatik olarak bağlandı"</string> <string name="connected_via_passpoint" msgid="2826205693803088747">"%1$s üzerinden bağlı"</string> + <!-- no translation found for ssid_by_passpoint_provider (7898171424140673315) --> + <skip /> <string name="available_via_passpoint" msgid="1617440946846329613">"%1$s üzerinden kullanılabilir"</string> + <!-- no translation found for tap_to_set_up (2468970825530423314) --> + <skip /> <string name="wifi_connected_no_internet" msgid="8202906332837777829">"Bağlı, internet yok"</string> <string name="wifi_status_no_internet" msgid="5784710974669608361">"İnternet yok"</string> <string name="wifi_status_sign_in_required" msgid="123517180404752756">"Oturum açılması gerekiyor"</string> <string name="wifi_ap_unable_to_handle_new_sta" msgid="5348824313514404541">"Erişim noktası geçici olarak dolu"</string> <string name="connected_via_carrier" msgid="7583780074526041912">"%1$s üzerinden bağlı"</string> <string name="available_via_carrier" msgid="1469036129740799053">"%1$s üzerinden kullanılabilir"</string> + <!-- no translation found for osu_failure_ap_connection (598977488344424542) --> + <skip /> + <!-- no translation found for osu_failure_server_url_invalid (2237477219243136714) --> + <skip /> + <!-- no translation found for osu_failure_server_connection (8192988165059982174) --> + <skip /> + <!-- no translation found for osu_failure_server_validation (4631649978129606823) --> + <skip /> + <!-- no translation found for osu_failure_service_provider_verification (4854091521439785597) --> + <skip /> + <!-- no translation found for osu_failure_provisioning_aborted (424627208135320329) --> + <skip /> + <!-- no translation found for osu_failure_provisioning_not_available (3021783729256985432) --> + <skip /> + <!-- no translation found for osu_failure_invalid_server_url (8548886196179435758) --> + <skip /> + <!-- no translation found for osu_failure_unexpected_command_type (8245921319866603904) --> + <skip /> + <!-- no translation found for osu_failure_unexpected_soap_message_type (2255897608510053065) --> + <skip /> + <!-- no translation found for osu_failure_soap_message_exchange (4357358438685987192) --> + <skip /> + <!-- no translation found for osu_failure_start_redirect_listener (4292769407279548482) --> + <skip /> + <!-- no translation found for osu_failure_timed_out_redirect_listener (3168657820278807508) --> + <skip /> + <!-- no translation found for osu_failure_no_osu_activity_found (4593038891437878675) --> + <skip /> + <!-- no translation found for osu_failure_unexpected_soap_message_status (6568467710235256675) --> + <skip /> + <!-- no translation found for osu_failure_no_pps_mo (850567403039076835) --> + <skip /> + <!-- no translation found for osu_failure_no_aaa_server_trust_root_node (8961455873459838456) --> + <skip /> + <!-- no translation found for osu_failure_no_remediation_server_trust_root_node (5041179688081545244) --> + <skip /> + <!-- no translation found for osu_failure_no_policy_server_trust_root_node (6617290380940513539) --> + <skip /> + <!-- no translation found for osu_failure_retrieve_trust_root_certificates (1499136256195528265) --> + <skip /> + <!-- no translation found for osu_failure_no_aaa_trust_root_certificate (1904322497042226984) --> + <skip /> + <!-- no translation found for osu_failure_add_passpoint_configuration (2173557755811446047) --> + <skip /> + <!-- no translation found for osu_failure_osu_provider_not_found (6616172862116673082) --> + <skip /> + <!-- no translation found for osu_status_ap_connecting (5296821043003441437) --> + <skip /> + <!-- no translation found for osu_status_ap_connected (3777289375683170728) --> + <skip /> + <!-- no translation found for osu_status_server_connecting (8499785407540355867) --> + <skip /> + <!-- no translation found for osu_status_server_validated (3158727184762596355) --> + <skip /> + <!-- no translation found for osu_status_server_connected (8382024481520158168) --> + <skip /> + <!-- no translation found for osu_status_init_soap_exchange (8628063888912101981) --> + <skip /> + <!-- no translation found for osu_status_waiting_for_redirect_response (2343016207837053197) --> + <skip /> + <!-- no translation found for osu_status_redirect_response_received (5323368411922609405) --> + <skip /> + <!-- no translation found for osu_status_second_soap_exchange (7115332266758483909) --> + <skip /> + <!-- no translation found for osu_status_third_soap_exchange (8460901783597440766) --> + <skip /> + <!-- no translation found for osu_status_retrieving_trust_root_certs (1563445892926269689) --> + <skip /> + <!-- no translation found for osu_provisioning_complete (5120178802493970149) --> + <skip /> <string name="speed_label_very_slow" msgid="1867055264243608530">"Çok Yavaş"</string> <string name="speed_label_slow" msgid="813109590815810235">"Yavaş"</string> <string name="speed_label_okay" msgid="2331665440671174858">"Tamam"</string> diff --git a/packages/SettingsLib/res/values-uk/strings.xml b/packages/SettingsLib/res/values-uk/strings.xml index 2b635736a480..a28dc18ca7b2 100644 --- a/packages/SettingsLib/res/values-uk/strings.xml +++ b/packages/SettingsLib/res/values-uk/strings.xml @@ -38,13 +38,87 @@ <string name="connected_via_network_scorer" msgid="5713793306870815341">"Автоматично під’єднано через %1$s"</string> <string name="connected_via_network_scorer_default" msgid="7867260222020343104">"Автоматично під’єднано через постачальника оцінки якості мережі"</string> <string name="connected_via_passpoint" msgid="2826205693803088747">"Під’єднано через %1$s"</string> + <!-- no translation found for ssid_by_passpoint_provider (7898171424140673315) --> + <skip /> <string name="available_via_passpoint" msgid="1617440946846329613">"Доступ через %1$s"</string> + <!-- no translation found for tap_to_set_up (2468970825530423314) --> + <skip /> <string name="wifi_connected_no_internet" msgid="8202906332837777829">"Під’єднано, але немає доступу до Інтернету"</string> <string name="wifi_status_no_internet" msgid="5784710974669608361">"Немає Інтернету"</string> <string name="wifi_status_sign_in_required" msgid="123517180404752756">"Потрібно ввійти в обліковий запис"</string> <string name="wifi_ap_unable_to_handle_new_sta" msgid="5348824313514404541">"Точка доступу тимчасово переповнена"</string> <string name="connected_via_carrier" msgid="7583780074526041912">"Під’єднано через мережу %1$s"</string> <string name="available_via_carrier" msgid="1469036129740799053">"Доступ через мережу %1$s"</string> + <!-- no translation found for osu_failure_ap_connection (598977488344424542) --> + <skip /> + <!-- no translation found for osu_failure_server_url_invalid (2237477219243136714) --> + <skip /> + <!-- no translation found for osu_failure_server_connection (8192988165059982174) --> + <skip /> + <!-- no translation found for osu_failure_server_validation (4631649978129606823) --> + <skip /> + <!-- no translation found for osu_failure_service_provider_verification (4854091521439785597) --> + <skip /> + <!-- no translation found for osu_failure_provisioning_aborted (424627208135320329) --> + <skip /> + <!-- no translation found for osu_failure_provisioning_not_available (3021783729256985432) --> + <skip /> + <!-- no translation found for osu_failure_invalid_server_url (8548886196179435758) --> + <skip /> + <!-- no translation found for osu_failure_unexpected_command_type (8245921319866603904) --> + <skip /> + <!-- no translation found for osu_failure_unexpected_soap_message_type (2255897608510053065) --> + <skip /> + <!-- no translation found for osu_failure_soap_message_exchange (4357358438685987192) --> + <skip /> + <!-- no translation found for osu_failure_start_redirect_listener (4292769407279548482) --> + <skip /> + <!-- no translation found for osu_failure_timed_out_redirect_listener (3168657820278807508) --> + <skip /> + <!-- no translation found for osu_failure_no_osu_activity_found (4593038891437878675) --> + <skip /> + <!-- no translation found for osu_failure_unexpected_soap_message_status (6568467710235256675) --> + <skip /> + <!-- no translation found for osu_failure_no_pps_mo (850567403039076835) --> + <skip /> + <!-- no translation found for osu_failure_no_aaa_server_trust_root_node (8961455873459838456) --> + <skip /> + <!-- no translation found for osu_failure_no_remediation_server_trust_root_node (5041179688081545244) --> + <skip /> + <!-- no translation found for osu_failure_no_policy_server_trust_root_node (6617290380940513539) --> + <skip /> + <!-- no translation found for osu_failure_retrieve_trust_root_certificates (1499136256195528265) --> + <skip /> + <!-- no translation found for osu_failure_no_aaa_trust_root_certificate (1904322497042226984) --> + <skip /> + <!-- no translation found for osu_failure_add_passpoint_configuration (2173557755811446047) --> + <skip /> + <!-- no translation found for osu_failure_osu_provider_not_found (6616172862116673082) --> + <skip /> + <!-- no translation found for osu_status_ap_connecting (5296821043003441437) --> + <skip /> + <!-- no translation found for osu_status_ap_connected (3777289375683170728) --> + <skip /> + <!-- no translation found for osu_status_server_connecting (8499785407540355867) --> + <skip /> + <!-- no translation found for osu_status_server_validated (3158727184762596355) --> + <skip /> + <!-- no translation found for osu_status_server_connected (8382024481520158168) --> + <skip /> + <!-- no translation found for osu_status_init_soap_exchange (8628063888912101981) --> + <skip /> + <!-- no translation found for osu_status_waiting_for_redirect_response (2343016207837053197) --> + <skip /> + <!-- no translation found for osu_status_redirect_response_received (5323368411922609405) --> + <skip /> + <!-- no translation found for osu_status_second_soap_exchange (7115332266758483909) --> + <skip /> + <!-- no translation found for osu_status_third_soap_exchange (8460901783597440766) --> + <skip /> + <!-- no translation found for osu_status_retrieving_trust_root_certs (1563445892926269689) --> + <skip /> + <!-- no translation found for osu_provisioning_complete (5120178802493970149) --> + <skip /> <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> diff --git a/packages/SettingsLib/res/values-ur/strings.xml b/packages/SettingsLib/res/values-ur/strings.xml index d7123a615811..397f4b2007d2 100644 --- a/packages/SettingsLib/res/values-ur/strings.xml +++ b/packages/SettingsLib/res/values-ur/strings.xml @@ -38,13 +38,87 @@ <string name="connected_via_network_scorer" msgid="5713793306870815341">"%1$s کے ذریعے از خود منسلک کردہ"</string> <string name="connected_via_network_scorer_default" msgid="7867260222020343104">"نیٹ ورک درجہ بندی کے فراہم کنندہ کے ذریعے از خود منسلک"</string> <string name="connected_via_passpoint" msgid="2826205693803088747">"منسلک بذریعہ %1$s"</string> + <!-- no translation found for ssid_by_passpoint_provider (7898171424140673315) --> + <skip /> <string name="available_via_passpoint" msgid="1617440946846329613">"دستیاب بذریعہ %1$s"</string> + <!-- no translation found for tap_to_set_up (2468970825530423314) --> + <skip /> <string name="wifi_connected_no_internet" msgid="8202906332837777829">"منسلک، انٹرنیٹ نہیں ہے"</string> <string name="wifi_status_no_internet" msgid="5784710974669608361">"انٹرنیٹ نہیں ہے"</string> <string name="wifi_status_sign_in_required" msgid="123517180404752756">"سائن ان درکار ہے"</string> <string name="wifi_ap_unable_to_handle_new_sta" msgid="5348824313514404541">"رسائی پوائنٹ عارضی طور پر فُل ہے"</string> <string name="connected_via_carrier" msgid="7583780074526041912">"منسلک بذریعہ %1$s"</string> <string name="available_via_carrier" msgid="1469036129740799053">"دستیاب بذریعہ %1$s"</string> + <!-- no translation found for osu_failure_ap_connection (598977488344424542) --> + <skip /> + <!-- no translation found for osu_failure_server_url_invalid (2237477219243136714) --> + <skip /> + <!-- no translation found for osu_failure_server_connection (8192988165059982174) --> + <skip /> + <!-- no translation found for osu_failure_server_validation (4631649978129606823) --> + <skip /> + <!-- no translation found for osu_failure_service_provider_verification (4854091521439785597) --> + <skip /> + <!-- no translation found for osu_failure_provisioning_aborted (424627208135320329) --> + <skip /> + <!-- no translation found for osu_failure_provisioning_not_available (3021783729256985432) --> + <skip /> + <!-- no translation found for osu_failure_invalid_server_url (8548886196179435758) --> + <skip /> + <!-- no translation found for osu_failure_unexpected_command_type (8245921319866603904) --> + <skip /> + <!-- no translation found for osu_failure_unexpected_soap_message_type (2255897608510053065) --> + <skip /> + <!-- no translation found for osu_failure_soap_message_exchange (4357358438685987192) --> + <skip /> + <!-- no translation found for osu_failure_start_redirect_listener (4292769407279548482) --> + <skip /> + <!-- no translation found for osu_failure_timed_out_redirect_listener (3168657820278807508) --> + <skip /> + <!-- no translation found for osu_failure_no_osu_activity_found (4593038891437878675) --> + <skip /> + <!-- no translation found for osu_failure_unexpected_soap_message_status (6568467710235256675) --> + <skip /> + <!-- no translation found for osu_failure_no_pps_mo (850567403039076835) --> + <skip /> + <!-- no translation found for osu_failure_no_aaa_server_trust_root_node (8961455873459838456) --> + <skip /> + <!-- no translation found for osu_failure_no_remediation_server_trust_root_node (5041179688081545244) --> + <skip /> + <!-- no translation found for osu_failure_no_policy_server_trust_root_node (6617290380940513539) --> + <skip /> + <!-- no translation found for osu_failure_retrieve_trust_root_certificates (1499136256195528265) --> + <skip /> + <!-- no translation found for osu_failure_no_aaa_trust_root_certificate (1904322497042226984) --> + <skip /> + <!-- no translation found for osu_failure_add_passpoint_configuration (2173557755811446047) --> + <skip /> + <!-- no translation found for osu_failure_osu_provider_not_found (6616172862116673082) --> + <skip /> + <!-- no translation found for osu_status_ap_connecting (5296821043003441437) --> + <skip /> + <!-- no translation found for osu_status_ap_connected (3777289375683170728) --> + <skip /> + <!-- no translation found for osu_status_server_connecting (8499785407540355867) --> + <skip /> + <!-- no translation found for osu_status_server_validated (3158727184762596355) --> + <skip /> + <!-- no translation found for osu_status_server_connected (8382024481520158168) --> + <skip /> + <!-- no translation found for osu_status_init_soap_exchange (8628063888912101981) --> + <skip /> + <!-- no translation found for osu_status_waiting_for_redirect_response (2343016207837053197) --> + <skip /> + <!-- no translation found for osu_status_redirect_response_received (5323368411922609405) --> + <skip /> + <!-- no translation found for osu_status_second_soap_exchange (7115332266758483909) --> + <skip /> + <!-- no translation found for osu_status_third_soap_exchange (8460901783597440766) --> + <skip /> + <!-- no translation found for osu_status_retrieving_trust_root_certs (1563445892926269689) --> + <skip /> + <!-- no translation found for osu_provisioning_complete (5120178802493970149) --> + <skip /> <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> diff --git a/packages/SettingsLib/res/values-uz/strings.xml b/packages/SettingsLib/res/values-uz/strings.xml index 51156d710ca8..5f214ce4767e 100644 --- a/packages/SettingsLib/res/values-uz/strings.xml +++ b/packages/SettingsLib/res/values-uz/strings.xml @@ -38,13 +38,87 @@ <string name="connected_via_network_scorer" msgid="5713793306870815341">"%1$s orqali avtomatik ulandi"</string> <string name="connected_via_network_scorer_default" msgid="7867260222020343104">"Tarmoqlar reytingi muallifi orqali avtomatik ulandi"</string> <string name="connected_via_passpoint" msgid="2826205693803088747">"%1$s orqali ulangan"</string> + <!-- no translation found for ssid_by_passpoint_provider (7898171424140673315) --> + <skip /> <string name="available_via_passpoint" msgid="1617440946846329613">"%1$s orqali ishlaydi"</string> + <!-- no translation found for tap_to_set_up (2468970825530423314) --> + <skip /> <string name="wifi_connected_no_internet" msgid="8202906332837777829">"Ulangan, lekin internet aloqasi yo‘q"</string> <string name="wifi_status_no_internet" msgid="5784710974669608361">"Internet yo‘q"</string> <string name="wifi_status_sign_in_required" msgid="123517180404752756">"Hisob bilan kirish zarur"</string> <string name="wifi_ap_unable_to_handle_new_sta" msgid="5348824313514404541">"Internet kirish nuqtasi vaqtinchalik to‘lgan"</string> <string name="connected_via_carrier" msgid="7583780074526041912">"%1$s orqali ulangan"</string> <string name="available_via_carrier" msgid="1469036129740799053">"%1$s orqali ishlaydi"</string> + <!-- no translation found for osu_failure_ap_connection (598977488344424542) --> + <skip /> + <!-- no translation found for osu_failure_server_url_invalid (2237477219243136714) --> + <skip /> + <!-- no translation found for osu_failure_server_connection (8192988165059982174) --> + <skip /> + <!-- no translation found for osu_failure_server_validation (4631649978129606823) --> + <skip /> + <!-- no translation found for osu_failure_service_provider_verification (4854091521439785597) --> + <skip /> + <!-- no translation found for osu_failure_provisioning_aborted (424627208135320329) --> + <skip /> + <!-- no translation found for osu_failure_provisioning_not_available (3021783729256985432) --> + <skip /> + <!-- no translation found for osu_failure_invalid_server_url (8548886196179435758) --> + <skip /> + <!-- no translation found for osu_failure_unexpected_command_type (8245921319866603904) --> + <skip /> + <!-- no translation found for osu_failure_unexpected_soap_message_type (2255897608510053065) --> + <skip /> + <!-- no translation found for osu_failure_soap_message_exchange (4357358438685987192) --> + <skip /> + <!-- no translation found for osu_failure_start_redirect_listener (4292769407279548482) --> + <skip /> + <!-- no translation found for osu_failure_timed_out_redirect_listener (3168657820278807508) --> + <skip /> + <!-- no translation found for osu_failure_no_osu_activity_found (4593038891437878675) --> + <skip /> + <!-- no translation found for osu_failure_unexpected_soap_message_status (6568467710235256675) --> + <skip /> + <!-- no translation found for osu_failure_no_pps_mo (850567403039076835) --> + <skip /> + <!-- no translation found for osu_failure_no_aaa_server_trust_root_node (8961455873459838456) --> + <skip /> + <!-- no translation found for osu_failure_no_remediation_server_trust_root_node (5041179688081545244) --> + <skip /> + <!-- no translation found for osu_failure_no_policy_server_trust_root_node (6617290380940513539) --> + <skip /> + <!-- no translation found for osu_failure_retrieve_trust_root_certificates (1499136256195528265) --> + <skip /> + <!-- no translation found for osu_failure_no_aaa_trust_root_certificate (1904322497042226984) --> + <skip /> + <!-- no translation found for osu_failure_add_passpoint_configuration (2173557755811446047) --> + <skip /> + <!-- no translation found for osu_failure_osu_provider_not_found (6616172862116673082) --> + <skip /> + <!-- no translation found for osu_status_ap_connecting (5296821043003441437) --> + <skip /> + <!-- no translation found for osu_status_ap_connected (3777289375683170728) --> + <skip /> + <!-- no translation found for osu_status_server_connecting (8499785407540355867) --> + <skip /> + <!-- no translation found for osu_status_server_validated (3158727184762596355) --> + <skip /> + <!-- no translation found for osu_status_server_connected (8382024481520158168) --> + <skip /> + <!-- no translation found for osu_status_init_soap_exchange (8628063888912101981) --> + <skip /> + <!-- no translation found for osu_status_waiting_for_redirect_response (2343016207837053197) --> + <skip /> + <!-- no translation found for osu_status_redirect_response_received (5323368411922609405) --> + <skip /> + <!-- no translation found for osu_status_second_soap_exchange (7115332266758483909) --> + <skip /> + <!-- no translation found for osu_status_third_soap_exchange (8460901783597440766) --> + <skip /> + <!-- no translation found for osu_status_retrieving_trust_root_certs (1563445892926269689) --> + <skip /> + <!-- no translation found for osu_provisioning_complete (5120178802493970149) --> + <skip /> <string name="speed_label_very_slow" msgid="1867055264243608530">"Juda sekin"</string> <string name="speed_label_slow" msgid="813109590815810235">"Sekin"</string> <string name="speed_label_okay" msgid="2331665440671174858">"OK"</string> diff --git a/packages/SettingsLib/res/values-vi/strings.xml b/packages/SettingsLib/res/values-vi/strings.xml index 13a93227a249..e019953a902f 100644 --- a/packages/SettingsLib/res/values-vi/strings.xml +++ b/packages/SettingsLib/res/values-vi/strings.xml @@ -38,13 +38,87 @@ <string name="connected_via_network_scorer" msgid="5713793306870815341">"Tự động được kết nối qua %1$s"</string> <string name="connected_via_network_scorer_default" msgid="7867260222020343104">"Tự động được kết nối qua nhà cung cấp dịch vụ xếp hạng mạng"</string> <string name="connected_via_passpoint" msgid="2826205693803088747">"Được kết nối qua %1$s"</string> + <!-- no translation found for ssid_by_passpoint_provider (7898171424140673315) --> + <skip /> <string name="available_via_passpoint" msgid="1617440946846329613">"Có sẵn qua %1$s"</string> + <!-- no translation found for tap_to_set_up (2468970825530423314) --> + <skip /> <string name="wifi_connected_no_internet" msgid="8202906332837777829">"Đã kết nối, không có Internet"</string> <string name="wifi_status_no_internet" msgid="5784710974669608361">"Không có Internet"</string> <string name="wifi_status_sign_in_required" msgid="123517180404752756">"Yêu cầu đăng nhập"</string> <string name="wifi_ap_unable_to_handle_new_sta" msgid="5348824313514404541">"Điểm truy cập tạm thời đã đạt đến giới hạn số lượng thiết bị truy cập."</string> <string name="connected_via_carrier" msgid="7583780074526041912">"Được kết nối qua %1$s"</string> <string name="available_via_carrier" msgid="1469036129740799053">"Có sẵn qua %1$s"</string> + <!-- no translation found for osu_failure_ap_connection (598977488344424542) --> + <skip /> + <!-- no translation found for osu_failure_server_url_invalid (2237477219243136714) --> + <skip /> + <!-- no translation found for osu_failure_server_connection (8192988165059982174) --> + <skip /> + <!-- no translation found for osu_failure_server_validation (4631649978129606823) --> + <skip /> + <!-- no translation found for osu_failure_service_provider_verification (4854091521439785597) --> + <skip /> + <!-- no translation found for osu_failure_provisioning_aborted (424627208135320329) --> + <skip /> + <!-- no translation found for osu_failure_provisioning_not_available (3021783729256985432) --> + <skip /> + <!-- no translation found for osu_failure_invalid_server_url (8548886196179435758) --> + <skip /> + <!-- no translation found for osu_failure_unexpected_command_type (8245921319866603904) --> + <skip /> + <!-- no translation found for osu_failure_unexpected_soap_message_type (2255897608510053065) --> + <skip /> + <!-- no translation found for osu_failure_soap_message_exchange (4357358438685987192) --> + <skip /> + <!-- no translation found for osu_failure_start_redirect_listener (4292769407279548482) --> + <skip /> + <!-- no translation found for osu_failure_timed_out_redirect_listener (3168657820278807508) --> + <skip /> + <!-- no translation found for osu_failure_no_osu_activity_found (4593038891437878675) --> + <skip /> + <!-- no translation found for osu_failure_unexpected_soap_message_status (6568467710235256675) --> + <skip /> + <!-- no translation found for osu_failure_no_pps_mo (850567403039076835) --> + <skip /> + <!-- no translation found for osu_failure_no_aaa_server_trust_root_node (8961455873459838456) --> + <skip /> + <!-- no translation found for osu_failure_no_remediation_server_trust_root_node (5041179688081545244) --> + <skip /> + <!-- no translation found for osu_failure_no_policy_server_trust_root_node (6617290380940513539) --> + <skip /> + <!-- no translation found for osu_failure_retrieve_trust_root_certificates (1499136256195528265) --> + <skip /> + <!-- no translation found for osu_failure_no_aaa_trust_root_certificate (1904322497042226984) --> + <skip /> + <!-- no translation found for osu_failure_add_passpoint_configuration (2173557755811446047) --> + <skip /> + <!-- no translation found for osu_failure_osu_provider_not_found (6616172862116673082) --> + <skip /> + <!-- no translation found for osu_status_ap_connecting (5296821043003441437) --> + <skip /> + <!-- no translation found for osu_status_ap_connected (3777289375683170728) --> + <skip /> + <!-- no translation found for osu_status_server_connecting (8499785407540355867) --> + <skip /> + <!-- no translation found for osu_status_server_validated (3158727184762596355) --> + <skip /> + <!-- no translation found for osu_status_server_connected (8382024481520158168) --> + <skip /> + <!-- no translation found for osu_status_init_soap_exchange (8628063888912101981) --> + <skip /> + <!-- no translation found for osu_status_waiting_for_redirect_response (2343016207837053197) --> + <skip /> + <!-- no translation found for osu_status_redirect_response_received (5323368411922609405) --> + <skip /> + <!-- no translation found for osu_status_second_soap_exchange (7115332266758483909) --> + <skip /> + <!-- no translation found for osu_status_third_soap_exchange (8460901783597440766) --> + <skip /> + <!-- no translation found for osu_status_retrieving_trust_root_certs (1563445892926269689) --> + <skip /> + <!-- no translation found for osu_provisioning_complete (5120178802493970149) --> + <skip /> <string name="speed_label_very_slow" msgid="1867055264243608530">"Rất chậm"</string> <string name="speed_label_slow" msgid="813109590815810235">"Chậm"</string> <string name="speed_label_okay" msgid="2331665440671174858">"Khá tốt"</string> diff --git a/packages/SettingsLib/res/values-zh-rCN/strings.xml b/packages/SettingsLib/res/values-zh-rCN/strings.xml index 866c143158f6..fd0d36e72e27 100644 --- a/packages/SettingsLib/res/values-zh-rCN/strings.xml +++ b/packages/SettingsLib/res/values-zh-rCN/strings.xml @@ -38,13 +38,87 @@ <string name="connected_via_network_scorer" msgid="5713793306870815341">"已通过%1$s自动连接"</string> <string name="connected_via_network_scorer_default" msgid="7867260222020343104">"已自动连接(通过网络评分服务提供方)"</string> <string name="connected_via_passpoint" msgid="2826205693803088747">"已通过%1$s连接"</string> + <!-- no translation found for ssid_by_passpoint_provider (7898171424140673315) --> + <skip /> <string name="available_via_passpoint" msgid="1617440946846329613">"可通过%1$s连接"</string> + <!-- no translation found for tap_to_set_up (2468970825530423314) --> + <skip /> <string name="wifi_connected_no_internet" msgid="8202906332837777829">"已连接,但无法访问互联网"</string> <string name="wifi_status_no_internet" msgid="5784710974669608361">"无法访问互联网"</string> <string name="wifi_status_sign_in_required" msgid="123517180404752756">"必须登录"</string> <string name="wifi_ap_unable_to_handle_new_sta" msgid="5348824313514404541">"接入点暂时满载"</string> <string name="connected_via_carrier" msgid="7583780074526041912">"已通过%1$s连接"</string> <string name="available_via_carrier" msgid="1469036129740799053">"可通过%1$s连接"</string> + <!-- no translation found for osu_failure_ap_connection (598977488344424542) --> + <skip /> + <!-- no translation found for osu_failure_server_url_invalid (2237477219243136714) --> + <skip /> + <!-- no translation found for osu_failure_server_connection (8192988165059982174) --> + <skip /> + <!-- no translation found for osu_failure_server_validation (4631649978129606823) --> + <skip /> + <!-- no translation found for osu_failure_service_provider_verification (4854091521439785597) --> + <skip /> + <!-- no translation found for osu_failure_provisioning_aborted (424627208135320329) --> + <skip /> + <!-- no translation found for osu_failure_provisioning_not_available (3021783729256985432) --> + <skip /> + <!-- no translation found for osu_failure_invalid_server_url (8548886196179435758) --> + <skip /> + <!-- no translation found for osu_failure_unexpected_command_type (8245921319866603904) --> + <skip /> + <!-- no translation found for osu_failure_unexpected_soap_message_type (2255897608510053065) --> + <skip /> + <!-- no translation found for osu_failure_soap_message_exchange (4357358438685987192) --> + <skip /> + <!-- no translation found for osu_failure_start_redirect_listener (4292769407279548482) --> + <skip /> + <!-- no translation found for osu_failure_timed_out_redirect_listener (3168657820278807508) --> + <skip /> + <!-- no translation found for osu_failure_no_osu_activity_found (4593038891437878675) --> + <skip /> + <!-- no translation found for osu_failure_unexpected_soap_message_status (6568467710235256675) --> + <skip /> + <!-- no translation found for osu_failure_no_pps_mo (850567403039076835) --> + <skip /> + <!-- no translation found for osu_failure_no_aaa_server_trust_root_node (8961455873459838456) --> + <skip /> + <!-- no translation found for osu_failure_no_remediation_server_trust_root_node (5041179688081545244) --> + <skip /> + <!-- no translation found for osu_failure_no_policy_server_trust_root_node (6617290380940513539) --> + <skip /> + <!-- no translation found for osu_failure_retrieve_trust_root_certificates (1499136256195528265) --> + <skip /> + <!-- no translation found for osu_failure_no_aaa_trust_root_certificate (1904322497042226984) --> + <skip /> + <!-- no translation found for osu_failure_add_passpoint_configuration (2173557755811446047) --> + <skip /> + <!-- no translation found for osu_failure_osu_provider_not_found (6616172862116673082) --> + <skip /> + <!-- no translation found for osu_status_ap_connecting (5296821043003441437) --> + <skip /> + <!-- no translation found for osu_status_ap_connected (3777289375683170728) --> + <skip /> + <!-- no translation found for osu_status_server_connecting (8499785407540355867) --> + <skip /> + <!-- no translation found for osu_status_server_validated (3158727184762596355) --> + <skip /> + <!-- no translation found for osu_status_server_connected (8382024481520158168) --> + <skip /> + <!-- no translation found for osu_status_init_soap_exchange (8628063888912101981) --> + <skip /> + <!-- no translation found for osu_status_waiting_for_redirect_response (2343016207837053197) --> + <skip /> + <!-- no translation found for osu_status_redirect_response_received (5323368411922609405) --> + <skip /> + <!-- no translation found for osu_status_second_soap_exchange (7115332266758483909) --> + <skip /> + <!-- no translation found for osu_status_third_soap_exchange (8460901783597440766) --> + <skip /> + <!-- no translation found for osu_status_retrieving_trust_root_certs (1563445892926269689) --> + <skip /> + <!-- no translation found for osu_provisioning_complete (5120178802493970149) --> + <skip /> <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> diff --git a/packages/SettingsLib/res/values-zh-rHK/strings.xml b/packages/SettingsLib/res/values-zh-rHK/strings.xml index f63ba3a4ff83..024299b0fd8d 100644 --- a/packages/SettingsLib/res/values-zh-rHK/strings.xml +++ b/packages/SettingsLib/res/values-zh-rHK/strings.xml @@ -38,13 +38,87 @@ <string name="connected_via_network_scorer" msgid="5713793306870815341">"已透過 %1$s 自動連線"</string> <string name="connected_via_network_scorer_default" msgid="7867260222020343104">"已透過網絡評分供應商自動連線"</string> <string name="connected_via_passpoint" msgid="2826205693803088747">"已透過 %1$s 連線"</string> + <!-- no translation found for ssid_by_passpoint_provider (7898171424140673315) --> + <skip /> <string name="available_via_passpoint" msgid="1617440946846329613">"可透過 %1$s 連線"</string> + <!-- no translation found for tap_to_set_up (2468970825530423314) --> + <skip /> <string name="wifi_connected_no_internet" msgid="8202906332837777829">"已連線,但沒有互聯網"</string> <string name="wifi_status_no_internet" msgid="5784710974669608361">"沒有互聯網連線"</string> <string name="wifi_status_sign_in_required" msgid="123517180404752756">"必須登入"</string> <string name="wifi_ap_unable_to_handle_new_sta" msgid="5348824313514404541">"存取點暫時已滿"</string> <string name="connected_via_carrier" msgid="7583780074526041912">"已透過 %1$s 連線"</string> <string name="available_via_carrier" msgid="1469036129740799053">"可透過 %1$s 連線"</string> + <!-- no translation found for osu_failure_ap_connection (598977488344424542) --> + <skip /> + <!-- no translation found for osu_failure_server_url_invalid (2237477219243136714) --> + <skip /> + <!-- no translation found for osu_failure_server_connection (8192988165059982174) --> + <skip /> + <!-- no translation found for osu_failure_server_validation (4631649978129606823) --> + <skip /> + <!-- no translation found for osu_failure_service_provider_verification (4854091521439785597) --> + <skip /> + <!-- no translation found for osu_failure_provisioning_aborted (424627208135320329) --> + <skip /> + <!-- no translation found for osu_failure_provisioning_not_available (3021783729256985432) --> + <skip /> + <!-- no translation found for osu_failure_invalid_server_url (8548886196179435758) --> + <skip /> + <!-- no translation found for osu_failure_unexpected_command_type (8245921319866603904) --> + <skip /> + <!-- no translation found for osu_failure_unexpected_soap_message_type (2255897608510053065) --> + <skip /> + <!-- no translation found for osu_failure_soap_message_exchange (4357358438685987192) --> + <skip /> + <!-- no translation found for osu_failure_start_redirect_listener (4292769407279548482) --> + <skip /> + <!-- no translation found for osu_failure_timed_out_redirect_listener (3168657820278807508) --> + <skip /> + <!-- no translation found for osu_failure_no_osu_activity_found (4593038891437878675) --> + <skip /> + <!-- no translation found for osu_failure_unexpected_soap_message_status (6568467710235256675) --> + <skip /> + <!-- no translation found for osu_failure_no_pps_mo (850567403039076835) --> + <skip /> + <!-- no translation found for osu_failure_no_aaa_server_trust_root_node (8961455873459838456) --> + <skip /> + <!-- no translation found for osu_failure_no_remediation_server_trust_root_node (5041179688081545244) --> + <skip /> + <!-- no translation found for osu_failure_no_policy_server_trust_root_node (6617290380940513539) --> + <skip /> + <!-- no translation found for osu_failure_retrieve_trust_root_certificates (1499136256195528265) --> + <skip /> + <!-- no translation found for osu_failure_no_aaa_trust_root_certificate (1904322497042226984) --> + <skip /> + <!-- no translation found for osu_failure_add_passpoint_configuration (2173557755811446047) --> + <skip /> + <!-- no translation found for osu_failure_osu_provider_not_found (6616172862116673082) --> + <skip /> + <!-- no translation found for osu_status_ap_connecting (5296821043003441437) --> + <skip /> + <!-- no translation found for osu_status_ap_connected (3777289375683170728) --> + <skip /> + <!-- no translation found for osu_status_server_connecting (8499785407540355867) --> + <skip /> + <!-- no translation found for osu_status_server_validated (3158727184762596355) --> + <skip /> + <!-- no translation found for osu_status_server_connected (8382024481520158168) --> + <skip /> + <!-- no translation found for osu_status_init_soap_exchange (8628063888912101981) --> + <skip /> + <!-- no translation found for osu_status_waiting_for_redirect_response (2343016207837053197) --> + <skip /> + <!-- no translation found for osu_status_redirect_response_received (5323368411922609405) --> + <skip /> + <!-- no translation found for osu_status_second_soap_exchange (7115332266758483909) --> + <skip /> + <!-- no translation found for osu_status_third_soap_exchange (8460901783597440766) --> + <skip /> + <!-- no translation found for osu_status_retrieving_trust_root_certs (1563445892926269689) --> + <skip /> + <!-- no translation found for osu_provisioning_complete (5120178802493970149) --> + <skip /> <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> diff --git a/packages/SettingsLib/res/values-zh-rTW/strings.xml b/packages/SettingsLib/res/values-zh-rTW/strings.xml index 93592a798378..146ffacb7a17 100644 --- a/packages/SettingsLib/res/values-zh-rTW/strings.xml +++ b/packages/SettingsLib/res/values-zh-rTW/strings.xml @@ -38,13 +38,87 @@ <string name="connected_via_network_scorer" msgid="5713793306870815341">"已透過 %1$s 自動連線"</string> <string name="connected_via_network_scorer_default" msgid="7867260222020343104">"已透過網路評分供應商自動連線"</string> <string name="connected_via_passpoint" msgid="2826205693803088747">"已透過 %1$s 連線"</string> + <!-- no translation found for ssid_by_passpoint_provider (7898171424140673315) --> + <skip /> <string name="available_via_passpoint" msgid="1617440946846329613">"可透過 %1$s 使用"</string> + <!-- no translation found for tap_to_set_up (2468970825530423314) --> + <skip /> <string name="wifi_connected_no_internet" msgid="8202906332837777829">"已連線,沒有網際網路"</string> <string name="wifi_status_no_internet" msgid="5784710974669608361">"沒有網際網路連線"</string> <string name="wifi_status_sign_in_required" msgid="123517180404752756">"必須登入"</string> <string name="wifi_ap_unable_to_handle_new_sta" msgid="5348824313514404541">"存取點暫時滿載"</string> <string name="connected_via_carrier" msgid="7583780074526041912">"已透過 %1$s 連線"</string> <string name="available_via_carrier" msgid="1469036129740799053">"可透過 %1$s 使用"</string> + <!-- no translation found for osu_failure_ap_connection (598977488344424542) --> + <skip /> + <!-- no translation found for osu_failure_server_url_invalid (2237477219243136714) --> + <skip /> + <!-- no translation found for osu_failure_server_connection (8192988165059982174) --> + <skip /> + <!-- no translation found for osu_failure_server_validation (4631649978129606823) --> + <skip /> + <!-- no translation found for osu_failure_service_provider_verification (4854091521439785597) --> + <skip /> + <!-- no translation found for osu_failure_provisioning_aborted (424627208135320329) --> + <skip /> + <!-- no translation found for osu_failure_provisioning_not_available (3021783729256985432) --> + <skip /> + <!-- no translation found for osu_failure_invalid_server_url (8548886196179435758) --> + <skip /> + <!-- no translation found for osu_failure_unexpected_command_type (8245921319866603904) --> + <skip /> + <!-- no translation found for osu_failure_unexpected_soap_message_type (2255897608510053065) --> + <skip /> + <!-- no translation found for osu_failure_soap_message_exchange (4357358438685987192) --> + <skip /> + <!-- no translation found for osu_failure_start_redirect_listener (4292769407279548482) --> + <skip /> + <!-- no translation found for osu_failure_timed_out_redirect_listener (3168657820278807508) --> + <skip /> + <!-- no translation found for osu_failure_no_osu_activity_found (4593038891437878675) --> + <skip /> + <!-- no translation found for osu_failure_unexpected_soap_message_status (6568467710235256675) --> + <skip /> + <!-- no translation found for osu_failure_no_pps_mo (850567403039076835) --> + <skip /> + <!-- no translation found for osu_failure_no_aaa_server_trust_root_node (8961455873459838456) --> + <skip /> + <!-- no translation found for osu_failure_no_remediation_server_trust_root_node (5041179688081545244) --> + <skip /> + <!-- no translation found for osu_failure_no_policy_server_trust_root_node (6617290380940513539) --> + <skip /> + <!-- no translation found for osu_failure_retrieve_trust_root_certificates (1499136256195528265) --> + <skip /> + <!-- no translation found for osu_failure_no_aaa_trust_root_certificate (1904322497042226984) --> + <skip /> + <!-- no translation found for osu_failure_add_passpoint_configuration (2173557755811446047) --> + <skip /> + <!-- no translation found for osu_failure_osu_provider_not_found (6616172862116673082) --> + <skip /> + <!-- no translation found for osu_status_ap_connecting (5296821043003441437) --> + <skip /> + <!-- no translation found for osu_status_ap_connected (3777289375683170728) --> + <skip /> + <!-- no translation found for osu_status_server_connecting (8499785407540355867) --> + <skip /> + <!-- no translation found for osu_status_server_validated (3158727184762596355) --> + <skip /> + <!-- no translation found for osu_status_server_connected (8382024481520158168) --> + <skip /> + <!-- no translation found for osu_status_init_soap_exchange (8628063888912101981) --> + <skip /> + <!-- no translation found for osu_status_waiting_for_redirect_response (2343016207837053197) --> + <skip /> + <!-- no translation found for osu_status_redirect_response_received (5323368411922609405) --> + <skip /> + <!-- no translation found for osu_status_second_soap_exchange (7115332266758483909) --> + <skip /> + <!-- no translation found for osu_status_third_soap_exchange (8460901783597440766) --> + <skip /> + <!-- no translation found for osu_status_retrieving_trust_root_certs (1563445892926269689) --> + <skip /> + <!-- no translation found for osu_provisioning_complete (5120178802493970149) --> + <skip /> <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> diff --git a/packages/SettingsLib/res/values-zu/strings.xml b/packages/SettingsLib/res/values-zu/strings.xml index dd2f3d8bca24..fc7b9b412c8c 100644 --- a/packages/SettingsLib/res/values-zu/strings.xml +++ b/packages/SettingsLib/res/values-zu/strings.xml @@ -38,13 +38,87 @@ <string name="connected_via_network_scorer" msgid="5713793306870815341">"Ixhumeke ngokuzenzakalela nge-%1$s"</string> <string name="connected_via_network_scorer_default" msgid="7867260222020343104">"Kuxhunywe ngokuzenzakalelayo ngomhlinzeki wesilinganiso wenethiwekhi"</string> <string name="connected_via_passpoint" msgid="2826205693803088747">"Kuxhumeke nge-%1$s"</string> + <!-- no translation found for ssid_by_passpoint_provider (7898171424140673315) --> + <skip /> <string name="available_via_passpoint" msgid="1617440946846329613">"Iyatholakala nge-%1$s"</string> + <!-- no translation found for tap_to_set_up (2468970825530423314) --> + <skip /> <string name="wifi_connected_no_internet" msgid="8202906332837777829">"Kuxhunyiwe, ayikho i-inthanethi"</string> <string name="wifi_status_no_internet" msgid="5784710974669608361">"Ayikho i-inthanethi"</string> <string name="wifi_status_sign_in_required" msgid="123517180404752756">"Ukungena ngemvume kuyadingeka"</string> <string name="wifi_ap_unable_to_handle_new_sta" msgid="5348824313514404541">"Iphoyinti lokufinyelela ligcwele okwesikhashana"</string> <string name="connected_via_carrier" msgid="7583780074526041912">"Kuxhumeke nge-%1$s"</string> <string name="available_via_carrier" msgid="1469036129740799053">"Iyatholakala nge-%1$s"</string> + <!-- no translation found for osu_failure_ap_connection (598977488344424542) --> + <skip /> + <!-- no translation found for osu_failure_server_url_invalid (2237477219243136714) --> + <skip /> + <!-- no translation found for osu_failure_server_connection (8192988165059982174) --> + <skip /> + <!-- no translation found for osu_failure_server_validation (4631649978129606823) --> + <skip /> + <!-- no translation found for osu_failure_service_provider_verification (4854091521439785597) --> + <skip /> + <!-- no translation found for osu_failure_provisioning_aborted (424627208135320329) --> + <skip /> + <!-- no translation found for osu_failure_provisioning_not_available (3021783729256985432) --> + <skip /> + <!-- no translation found for osu_failure_invalid_server_url (8548886196179435758) --> + <skip /> + <!-- no translation found for osu_failure_unexpected_command_type (8245921319866603904) --> + <skip /> + <!-- no translation found for osu_failure_unexpected_soap_message_type (2255897608510053065) --> + <skip /> + <!-- no translation found for osu_failure_soap_message_exchange (4357358438685987192) --> + <skip /> + <!-- no translation found for osu_failure_start_redirect_listener (4292769407279548482) --> + <skip /> + <!-- no translation found for osu_failure_timed_out_redirect_listener (3168657820278807508) --> + <skip /> + <!-- no translation found for osu_failure_no_osu_activity_found (4593038891437878675) --> + <skip /> + <!-- no translation found for osu_failure_unexpected_soap_message_status (6568467710235256675) --> + <skip /> + <!-- no translation found for osu_failure_no_pps_mo (850567403039076835) --> + <skip /> + <!-- no translation found for osu_failure_no_aaa_server_trust_root_node (8961455873459838456) --> + <skip /> + <!-- no translation found for osu_failure_no_remediation_server_trust_root_node (5041179688081545244) --> + <skip /> + <!-- no translation found for osu_failure_no_policy_server_trust_root_node (6617290380940513539) --> + <skip /> + <!-- no translation found for osu_failure_retrieve_trust_root_certificates (1499136256195528265) --> + <skip /> + <!-- no translation found for osu_failure_no_aaa_trust_root_certificate (1904322497042226984) --> + <skip /> + <!-- no translation found for osu_failure_add_passpoint_configuration (2173557755811446047) --> + <skip /> + <!-- no translation found for osu_failure_osu_provider_not_found (6616172862116673082) --> + <skip /> + <!-- no translation found for osu_status_ap_connecting (5296821043003441437) --> + <skip /> + <!-- no translation found for osu_status_ap_connected (3777289375683170728) --> + <skip /> + <!-- no translation found for osu_status_server_connecting (8499785407540355867) --> + <skip /> + <!-- no translation found for osu_status_server_validated (3158727184762596355) --> + <skip /> + <!-- no translation found for osu_status_server_connected (8382024481520158168) --> + <skip /> + <!-- no translation found for osu_status_init_soap_exchange (8628063888912101981) --> + <skip /> + <!-- no translation found for osu_status_waiting_for_redirect_response (2343016207837053197) --> + <skip /> + <!-- no translation found for osu_status_redirect_response_received (5323368411922609405) --> + <skip /> + <!-- no translation found for osu_status_second_soap_exchange (7115332266758483909) --> + <skip /> + <!-- no translation found for osu_status_third_soap_exchange (8460901783597440766) --> + <skip /> + <!-- no translation found for osu_status_retrieving_trust_root_certs (1563445892926269689) --> + <skip /> + <!-- no translation found for osu_provisioning_complete (5120178802493970149) --> + <skip /> <string name="speed_label_very_slow" msgid="1867055264243608530">"Phansi kakhulu"</string> <string name="speed_label_slow" msgid="813109590815810235">"Phansi"</string> <string name="speed_label_okay" msgid="2331665440671174858">"KULUNGILE"</string> diff --git a/packages/SettingsLib/src/com/android/settingslib/net/DataUsageController.java b/packages/SettingsLib/src/com/android/settingslib/net/DataUsageController.java index 180b77e7503b..8cb252ed6283 100644 --- a/packages/SettingsLib/src/com/android/settingslib/net/DataUsageController.java +++ b/packages/SettingsLib/src/com/android/settingslib/net/DataUsageController.java @@ -66,6 +66,7 @@ public class DataUsageController { private INetworkStatsSession mSession; private Callback mCallback; private NetworkNameProvider mNetworkController; + private int mSubscriptionId; public DataUsageController(Context context) { mContext = context; @@ -75,6 +76,7 @@ public class DataUsageController { ServiceManager.getService(Context.NETWORK_STATS_SERVICE)); mPolicyManager = NetworkPolicyManager.from(mContext); mNetworkStatsManager = context.getSystemService(NetworkStatsManager.class); + mSubscriptionId = SubscriptionManager.INVALID_SUBSCRIPTION_ID; } public void setNetworkController(NetworkNameProvider networkController) { @@ -82,6 +84,15 @@ public class DataUsageController { } /** + * By default this class will just get data usage information for the default data subscription, + * but this method can be called to require it to use an explicit subscription id which may be + * different from the default one (this is useful for the case of multi-SIM devices). + */ + public void setSubscriptionId(int subscriptionId) { + mSubscriptionId = subscriptionId; + } + + /** * Returns the default warning level in bytes. */ public long getDefaultWarningLevel() { @@ -99,7 +110,7 @@ public class DataUsageController { } public DataUsageInfo getDataUsageInfo() { - final String subscriberId = getActiveSubscriberId(mContext); + final String subscriberId = getActiveSubscriberId(); if (subscriberId == null) { return warn("no subscriber id"); } @@ -164,7 +175,8 @@ public class DataUsageController { private long getUsageLevel(NetworkTemplate template, long start, long end) { try { final Bucket bucket = mNetworkStatsManager.querySummaryForDevice( - getNetworkType(template), getActiveSubscriberId(mContext), start, end); + getNetworkType(template), getActiveSubscriberId(), + start, end); if (bucket != null) { return bucket.getRxBytes() + bucket.getTxBytes(); } @@ -237,10 +249,13 @@ public class DataUsageController { } } - private static String getActiveSubscriberId(Context context) { - final TelephonyManager tele = TelephonyManager.from(context); - final String actualSubscriberId = tele.getSubscriberId( - SubscriptionManager.getDefaultDataSubscriptionId()); + private String getActiveSubscriberId() { + final TelephonyManager tele = TelephonyManager.from(mContext); + int subscriptionId = mSubscriptionId; + if (subscriptionId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) { + subscriptionId = SubscriptionManager.getDefaultDataSubscriptionId(); + } + final String actualSubscriberId = tele.getSubscriberId(subscriptionId); return actualSubscriberId; } diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/net/DataUsageControllerTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/net/DataUsageControllerTest.java index acf99a24e96c..220463b1f06c 100644 --- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/net/DataUsageControllerTest.java +++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/net/DataUsageControllerTest.java @@ -45,6 +45,7 @@ import org.junit.runner.RunWith; import org.mockito.Mock; import org.mockito.MockitoAnnotations; import org.robolectric.RobolectricTestRunner; +import org.robolectric.shadows.ShadowSubscriptionManager; @RunWith(RobolectricTestRunner.class) public class DataUsageControllerTest { @@ -73,7 +74,9 @@ public class DataUsageControllerTest { new NetworkStatsHistory(DateUtils.DAY_IN_MILLIS /* bucketDuration */)); doReturn(mNetworkStatsHistory) .when(mSession).getHistoryForNetwork(any(NetworkTemplate.class), anyInt()); - doReturn(SUB_ID).when(mTelephonyManager).getSubscriberId(anyInt()); + final int defaultSubscriptionId = 1234; + ShadowSubscriptionManager.setDefaultDataSubscriptionId(defaultSubscriptionId); + doReturn(SUB_ID).when(mTelephonyManager).getSubscriberId(eq(defaultSubscriptionId)); } @Test @@ -107,4 +110,39 @@ public class DataUsageControllerTest { assertThat(mController.getHistoricalUsageLevel(NetworkTemplate.buildTemplateWifiWildcard())) .isEqualTo(receivedBytes + transmittedBytes); } + + @Test + public void getDataUsageInfo_hasUsageData_shouldReturnCorrectUsageForExplicitSubId() + throws Exception { + // First setup a stats bucket for the default subscription / subscriber ID. + final long defaultSubRx = 1234567L; + final long defaultSubTx = 123456L; + final NetworkStats.Bucket defaultSubscriberBucket = mock(NetworkStats.Bucket.class); + when(defaultSubscriberBucket.getRxBytes()).thenReturn(defaultSubRx); + when(defaultSubscriberBucket.getTxBytes()).thenReturn(defaultSubTx); + when(mNetworkStatsManager.querySummaryForDevice(eq(ConnectivityManager.TYPE_MOBILE), + eq(SUB_ID), eq(0L)/* startTime */, anyLong() /* endTime */)).thenReturn( + defaultSubscriberBucket); + + // Now setup a stats bucket for a different, non-default subscription / subscriber ID. + final long nonDefaultSubRx = 7654321L; + final long nonDefaultSubTx = 654321L; + final NetworkStats.Bucket nonDefaultSubscriberBucket = mock(NetworkStats.Bucket.class); + when(nonDefaultSubscriberBucket.getRxBytes()).thenReturn(nonDefaultSubRx); + when(nonDefaultSubscriberBucket.getTxBytes()).thenReturn(nonDefaultSubTx); + final int explictSubscriptionId = 55; + final String subscriberId2 = "Test Subscriber 2"; + when(mNetworkStatsManager.querySummaryForDevice(eq(ConnectivityManager.TYPE_MOBILE), + eq(subscriberId2), eq(0L)/* startTime */, anyLong() /* endTime */)).thenReturn( + nonDefaultSubscriberBucket); + doReturn(subscriberId2).when(mTelephonyManager).getSubscriberId(explictSubscriptionId); + + // Now verify that when we're asking for stats on the non-default subscription, we get + // the data back for that subscription and *not* the default one. + mController.setSubscriptionId(explictSubscriptionId); + + assertThat(mController.getHistoricalUsageLevel( + NetworkTemplate.buildTemplateMobileAll(subscriberId2))).isEqualTo( + nonDefaultSubRx + nonDefaultSubTx); + } } diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/widget/AppEntitiesHeaderControllerTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/widget/AppEntitiesHeaderControllerTest.java index c3bc8da89685..8c18c356159e 100644 --- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/widget/AppEntitiesHeaderControllerTest.java +++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/widget/AppEntitiesHeaderControllerTest.java @@ -19,7 +19,6 @@ package com.android.settingslib.widget; import static com.google.common.truth.Truth.assertThat; import android.content.Context; -import android.graphics.drawable.Drawable; import android.view.LayoutInflater; import android.view.View; import android.widget.ImageView; @@ -43,18 +42,24 @@ public class AppEntitiesHeaderControllerTest { public final ExpectedException thrown = ExpectedException.none(); private Context mContext; - private Drawable mIcon; private View mAppEntitiesHeaderView; private AppEntitiesHeaderController mController; + private AppEntityInfo mAppEntityInfo; @Before public void setUp() { mContext = RuntimeEnvironment.application; mAppEntitiesHeaderView = LayoutInflater.from(mContext).inflate( R.layout.app_entities_header, null /* root */); - mIcon = mContext.getDrawable(R.drawable.ic_menu); mController = AppEntitiesHeaderController.newInstance(mContext, mAppEntitiesHeaderView); + mAppEntityInfo = new AppEntityInfo.Builder() + .setIcon(mContext.getDrawable(R.drawable.ic_menu)) + .setTitle(TITLE) + .setSummary(SUMMARY) + .setOnClickListener(v -> { + }) + .build(); } @Test @@ -91,26 +96,26 @@ public class AppEntitiesHeaderControllerTest { public void setAppEntity_indexLessThanZero_shouldThrowArrayIndexOutOfBoundsException() { thrown.expect(ArrayIndexOutOfBoundsException.class); - mController.setAppEntity(-1, mIcon, TITLE, SUMMARY); + mController.setAppEntity(-1, mAppEntityInfo); } @Test public void asetAppEntity_indexGreaterThanMaximum_shouldThrowArrayIndexOutOfBoundsException() { thrown.expect(ArrayIndexOutOfBoundsException.class); - mController.setAppEntity(AppEntitiesHeaderController.MAXIMUM_APPS + 1, mIcon, TITLE, - SUMMARY); + mController.setAppEntity(AppEntitiesHeaderController.MAXIMUM_APPS + 1, mAppEntityInfo); } @Test public void setAppEntity_addAppToIndex0_shouldShowAppView1() { - mController.setAppEntity(0, mIcon, TITLE, SUMMARY).apply(); + mController.setAppEntity(0, mAppEntityInfo).apply(); final View app1View = mAppEntitiesHeaderView.findViewById(R.id.app1_view); final ImageView appIconView = app1View.findViewById(R.id.app_icon); final TextView appTitle = app1View.findViewById(R.id.app_title); final TextView appSummary = app1View.findViewById(R.id.app_summary); assertThat(app1View.getVisibility()).isEqualTo(View.VISIBLE); + assertThat(app1View.hasOnClickListeners()).isTrue(); assertThat(appIconView.getDrawable()).isNotNull(); assertThat(appTitle.getText()).isEqualTo(TITLE); assertThat(appSummary.getText()).isEqualTo(SUMMARY); @@ -118,13 +123,14 @@ public class AppEntitiesHeaderControllerTest { @Test public void setAppEntity_addAppToIndex1_shouldShowAppView2() { - mController.setAppEntity(1, mIcon, TITLE, SUMMARY).apply(); + mController.setAppEntity(1, mAppEntityInfo).apply(); final View app2View = mAppEntitiesHeaderView.findViewById(R.id.app2_view); final ImageView appIconView = app2View.findViewById(R.id.app_icon); final TextView appTitle = app2View.findViewById(R.id.app_title); final TextView appSummary = app2View.findViewById(R.id.app_summary); assertThat(app2View.getVisibility()).isEqualTo(View.VISIBLE); + assertThat(app2View.hasOnClickListeners()).isTrue(); assertThat(appIconView.getDrawable()).isNotNull(); assertThat(appTitle.getText()).isEqualTo(TITLE); assertThat(appSummary.getText()).isEqualTo(SUMMARY); @@ -132,13 +138,14 @@ public class AppEntitiesHeaderControllerTest { @Test public void setAppEntity_addAppToIndex2_shouldShowAppView3() { - mController.setAppEntity(2, mIcon, TITLE, SUMMARY).apply(); + mController.setAppEntity(2, mAppEntityInfo).apply(); final View app3View = mAppEntitiesHeaderView.findViewById(R.id.app3_view); final ImageView appIconView = app3View.findViewById(R.id.app_icon); final TextView appTitle = app3View.findViewById(R.id.app_title); final TextView appSummary = app3View.findViewById(R.id.app_summary); assertThat(app3View.getVisibility()).isEqualTo(View.VISIBLE); + assertThat(app3View.hasOnClickListeners()).isTrue(); assertThat(appIconView.getDrawable()).isNotNull(); assertThat(appTitle.getText()).isEqualTo(TITLE); assertThat(appSummary.getText()).isEqualTo(SUMMARY); @@ -146,8 +153,8 @@ public class AppEntitiesHeaderControllerTest { @Test public void removeAppEntity_removeIndex0_shouldNotShowAppView1() { - mController.setAppEntity(0, mIcon, TITLE, SUMMARY) - .setAppEntity(1, mIcon, TITLE, SUMMARY).apply(); + mController.setAppEntity(0, mAppEntityInfo) + .setAppEntity(1, mAppEntityInfo).apply(); final View app1View = mAppEntitiesHeaderView.findViewById(R.id.app1_view); final View app2View = mAppEntitiesHeaderView.findViewById(R.id.app2_view); @@ -162,9 +169,9 @@ public class AppEntitiesHeaderControllerTest { @Test public void clearAllAppEntities_shouldNotShowAllAppViews() { - mController.setAppEntity(0, mIcon, TITLE, SUMMARY) - .setAppEntity(1, mIcon, TITLE, SUMMARY) - .setAppEntity(2, mIcon, TITLE, SUMMARY).apply(); + mController.setAppEntity(0, mAppEntityInfo) + .setAppEntity(1, mAppEntityInfo) + .setAppEntity(2, mAppEntityInfo).apply(); final View app1View = mAppEntitiesHeaderView.findViewById(R.id.app1_view); final View app2View = mAppEntitiesHeaderView.findViewById(R.id.app2_view); final View app3View = mAppEntitiesHeaderView.findViewById(R.id.app3_view); diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java index 18bdb20ad0a6..e843eb43a3a6 100644 --- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java +++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java @@ -705,14 +705,17 @@ class SettingsProtoDumpUtil { Settings.Global.GPU_DEBUG_LAYERS_GLES, GlobalSettingsProto.Gpu.DEBUG_LAYERS_GLES); dumpSetting(s, p, + Settings.Global.GUP_DEV_ALL_APPS, + GlobalSettingsProto.Gpu.GUP_DEV_ALL_APPS); + dumpSetting(s, p, Settings.Global.GUP_DEV_OPT_IN_APPS, GlobalSettingsProto.Gpu.GUP_DEV_OPT_IN_APPS); dumpSetting(s, p, Settings.Global.GUP_DEV_OPT_OUT_APPS, GlobalSettingsProto.Gpu.GUP_DEV_OPT_OUT_APPS); dumpSetting(s, p, - Settings.Global.GUP_BLACK_LIST, - GlobalSettingsProto.Gpu.GUP_BLACK_LIST); + Settings.Global.GUP_BLACKLIST, + GlobalSettingsProto.Gpu.GUP_BLACKLIST); p.end(gpuToken); final long hdmiToken = p.start(GlobalSettingsProto.HDMI); @@ -1879,6 +1882,9 @@ class SettingsProtoDumpUtil { dumpSetting(s, p, Settings.Secure.DOZE_DOUBLE_TAP_GESTURE, SecureSettingsProto.Doze.PULSE_ON_DOUBLE_TAP); + dumpSetting(s, p, + Settings.Secure.DOZE_TAP_SCREEN_GESTURE, + SecureSettingsProto.Doze.PULSE_ON_TAP); p.end(dozeToken); dumpSetting(s, p, diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java index bce559396ddd..5105ff46703d 100644 --- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java +++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java @@ -84,6 +84,8 @@ import com.android.providers.settings.SettingsState.Setting; import com.android.server.LocalServices; import com.android.server.SystemConfig; +import com.google.android.collect.Sets; + import java.io.File; import java.io.FileDescriptor; import java.io.FileNotFoundException; @@ -957,12 +959,12 @@ public class SettingsProvider extends ContentProvider { UserManagerInternal userManager = LocalServices.getService(UserManagerInternal.class); userManager.addUserRestrictionsListener((int userId, Bundle newRestrictions, Bundle prevRestrictions) -> { + Set<String> changedRestrictions = getRestrictionDiff(prevRestrictions, newRestrictions); // We are changing the settings affected by restrictions to their current // value with a forced update to ensure that all cross profile dependencies // are taken into account. Also make sure the settings update to.. the same // value passes the security checks, so clear binder calling id. - if (newRestrictions.getBoolean(UserManager.DISALLOW_SHARE_LOCATION) - != prevRestrictions.getBoolean(UserManager.DISALLOW_SHARE_LOCATION)) { + if (changedRestrictions.contains(UserManager.DISALLOW_SHARE_LOCATION)) { final long identity = Binder.clearCallingIdentity(); try { synchronized (mLock) { @@ -976,11 +978,8 @@ public class SettingsProvider extends ContentProvider { Binder.restoreCallingIdentity(identity); } } - if (newRestrictions.getBoolean(UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES) - != prevRestrictions.getBoolean(UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES) || - newRestrictions.getBoolean( - UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES_GLOBALLY) - != prevRestrictions.getBoolean( + if (changedRestrictions.contains(UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES) + || changedRestrictions.contains( UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES_GLOBALLY)) { final long identity = Binder.clearCallingIdentity(); try { @@ -994,8 +993,7 @@ public class SettingsProvider extends ContentProvider { Binder.restoreCallingIdentity(identity); } } - if (newRestrictions.getBoolean(UserManager.DISALLOW_DEBUGGING_FEATURES) - != prevRestrictions.getBoolean(UserManager.DISALLOW_DEBUGGING_FEATURES)) { + if (changedRestrictions.contains(UserManager.DISALLOW_DEBUGGING_FEATURES)) { final long identity = Binder.clearCallingIdentity(); try { synchronized (mLock) { @@ -1008,8 +1006,7 @@ public class SettingsProvider extends ContentProvider { Binder.restoreCallingIdentity(identity); } } - if (newRestrictions.getBoolean(UserManager.ENSURE_VERIFY_APPS) - != prevRestrictions.getBoolean(UserManager.ENSURE_VERIFY_APPS)) { + if (changedRestrictions.contains(UserManager.ENSURE_VERIFY_APPS)) { final long identity = Binder.clearCallingIdentity(); try { synchronized (mLock) { @@ -1028,8 +1025,7 @@ public class SettingsProvider extends ContentProvider { Binder.restoreCallingIdentity(identity); } } - if (newRestrictions.getBoolean(UserManager.DISALLOW_CONFIG_MOBILE_NETWORKS) - != prevRestrictions.getBoolean(UserManager.DISALLOW_CONFIG_MOBILE_NETWORKS)) { + if (changedRestrictions.contains(UserManager.DISALLOW_CONFIG_MOBILE_NETWORKS)) { final long identity = Binder.clearCallingIdentity(); try { synchronized (mLock) { @@ -1046,13 +1042,27 @@ public class SettingsProvider extends ContentProvider { }); } + private static Set<String> getRestrictionDiff(Bundle prevRestrictions, Bundle newRestrictions) { + Set<String> restrictionNames = Sets.newArraySet(); + restrictionNames.addAll(prevRestrictions.keySet()); + restrictionNames.addAll(newRestrictions.keySet()); + Set<String> diff = Sets.newArraySet(); + for (String restrictionName : restrictionNames) { + if (prevRestrictions.getBoolean(restrictionName) != newRestrictions.getBoolean( + restrictionName)) { + diff.add(restrictionName); + } + } + return diff; + } + private Setting getConfigSetting(String name) { if (DEBUG) { Slog.v(LOG_TAG, "getConfigSetting(" + name + ")"); } // TODO(b/117663715): Ensure the caller can access the setting. - // enforceSettingReadable(name, SETTINGS_TYPE_CONFIG, UserHandle.getCallingUserId()); + // enforceReadPermission(READ_DEVICE_CONFIG); // Get the value. synchronized (mLock) { @@ -1088,8 +1098,9 @@ public class SettingsProvider extends ContentProvider { private boolean mutateConfigSetting(String name, String value, String prefix, boolean makeDefault, int operation, int mode) { - // TODO(b/117663715): check the new permission when it's added. - // enforceWritePermission(Manifest.permission.WRITE_SECURE_SETTINGS); + + // TODO(b/117663715): Ensure the caller can access the setting. + // enforceReadPermission(WRITE_DEVICE_CONFIG); // Perform the mutation. synchronized (mLock) { diff --git a/packages/SettingsProvider/test/AndroidManifest.xml b/packages/SettingsProvider/test/AndroidManifest.xml index 87a4f603f70b..ebdf9b1a2791 100644 --- a/packages/SettingsProvider/test/AndroidManifest.xml +++ b/packages/SettingsProvider/test/AndroidManifest.xml @@ -20,6 +20,8 @@ <uses-sdk android:minSdkVersion="21" android:targetSdkVersion="21" /> <uses-permission android:name="android.permission.WRITE_SETTINGS"/> + <uses-permission android:name="android.permission.WRITE_DEVICE_CONFIG"/> + <uses-permission android:name="android.permission.READ_DEVICE_CONFIG"/> <uses-permission android:name="android.permission.WRITE_SECURE_SETTINGS"/> <uses-permission android:name="android.permission.INTERACT_ACROSS_USERS_FULL"/> <uses-permission android:name="android.permission.MANAGE_USERS"/> diff --git a/packages/Shell/AndroidManifest.xml b/packages/Shell/AndroidManifest.xml index 9b775e058ea8..b903142c44c6 100644 --- a/packages/Shell/AndroidManifest.xml +++ b/packages/Shell/AndroidManifest.xml @@ -57,6 +57,8 @@ <uses-permission android:name="android.permission.SET_PREFERRED_APPLICATIONS" /> <uses-permission android:name="android.permission.WRITE_SETTINGS" /> <uses-permission android:name="android.permission.WRITE_SECURE_SETTINGS" /> + <uses-permission android:name="android.permission.READ_DEVICE_CONFIG" /> + <uses-permission android:name="android.permission.WRITE_DEVICE_CONFIG" /> <uses-permission android:name="android.permission.BROADCAST_STICKY" /> <uses-permission android:name="android.permission.MANAGE_ACCESSIBILITY" /> <!-- Development tool permissions granted to the shell. --> diff --git a/packages/SystemUI/res-keyguard/layout/bubble_clock.xml b/packages/SystemUI/res-keyguard/layout/bubble_clock.xml index 0d72657bb2df..6f7f39810608 100644 --- a/packages/SystemUI/res-keyguard/layout/bubble_clock.xml +++ b/packages/SystemUI/res-keyguard/layout/bubble_clock.xml @@ -19,15 +19,9 @@ android:layout_width="match_parent" android:layout_height="match_parent" > - <TextClock + <include android:id="@+id/digital_clock" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:letterSpacing="0.03" - android:singleLine="true" - style="@style/widget_big" - android:format12Hour="@string/keyguard_widget_12_hours_format" - android:format24Hour="@string/keyguard_widget_24_hours_format" + layout="@layout/text_clock" /> <com.android.keyguard.clock.ImageClock android:id="@+id/analog_clock" diff --git a/packages/SystemUI/res-keyguard/layout/digital_clock.xml b/packages/SystemUI/res-keyguard/layout/digital_clock.xml index cf4a573834dd..e88e2c94e74f 100644 --- a/packages/SystemUI/res-keyguard/layout/digital_clock.xml +++ b/packages/SystemUI/res-keyguard/layout/digital_clock.xml @@ -20,16 +20,9 @@ android:layout_height="wrap_content" android:layout_gravity="center_horizontal" android:layout_alignParentTop="true"> - <TextClock + <include android:id="@+id/lock_screen_clock" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_gravity="center_horizontal" - android:letterSpacing="0.03" - android:singleLine="true" - style="@style/widget_big" - android:format12Hour="@string/keyguard_widget_12_hours_format" - android:format24Hour="@string/keyguard_widget_24_hours_format" /> + layout="@layout/text_clock" /> </FrameLayout> diff --git a/packages/SystemUI/res-keyguard/layout/keyguard_clock_switch.xml b/packages/SystemUI/res-keyguard/layout/keyguard_clock_switch.xml index d52866fbd444..463367b2c600 100644 --- a/packages/SystemUI/res-keyguard/layout/keyguard_clock_switch.xml +++ b/packages/SystemUI/res-keyguard/layout/keyguard_clock_switch.xml @@ -30,17 +30,9 @@ android:layout_height="wrap_content" android:layout_gravity="center_horizontal" android:layout_alignParentTop="true"> - <TextClock + <include android:id="@+id/default_clock_view" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_gravity="center_horizontal" - android:letterSpacing="0.03" - android:textColor="?attr/wallpaperTextColor" - android:singleLine="true" - style="@style/widget_big" - android:format12Hour="@string/keyguard_widget_12_hours_format" - android:format24Hour="@string/keyguard_widget_24_hours_format" /> + layout="@layout/text_clock" /> </FrameLayout> <include layout="@layout/keyguard_status_area" android:id="@+id/keyguard_status_area" diff --git a/packages/SystemUI/res-keyguard/layout/stretchanalog_clock.xml b/packages/SystemUI/res-keyguard/layout/stretchanalog_clock.xml index 9033fce881c4..64b676f55fd6 100644 --- a/packages/SystemUI/res-keyguard/layout/stretchanalog_clock.xml +++ b/packages/SystemUI/res-keyguard/layout/stretchanalog_clock.xml @@ -19,15 +19,9 @@ android:layout_width="match_parent" android:layout_height="match_parent" > - <TextClock + <include android:id="@+id/digital_clock" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:letterSpacing="0.03" - android:singleLine="true" - style="@style/widget_big" - android:format12Hour="@string/keyguard_widget_12_hours_format" - android:format24Hour="@string/keyguard_widget_24_hours_format" + layout="@layout/text_clock" /> <com.android.keyguard.clock.StretchAnalogClock android:id="@+id/analog_clock" diff --git a/packages/SystemUI/res-keyguard/layout/text_clock.xml b/packages/SystemUI/res-keyguard/layout/text_clock.xml new file mode 100644 index 000000000000..b61ad9c4fc11 --- /dev/null +++ b/packages/SystemUI/res-keyguard/layout/text_clock.xml @@ -0,0 +1,29 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + Copyright (C) 2019 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + --> +<TextClock + xmlns:android="http://schemas.android.com/apk/res/android" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_gravity="center_horizontal" + android:letterSpacing="0.03" + android:textColor="?attr/wallpaperTextColor" + android:singleLine="true" + style="@style/widget_big" + android:format12Hour="@string/keyguard_widget_12_hours_format" + android:format24Hour="@string/keyguard_widget_24_hours_format" + android:elegantTextHeight="false" +/> diff --git a/packages/SystemUI/res-keyguard/layout/type_clock.xml b/packages/SystemUI/res-keyguard/layout/type_clock.xml new file mode 100644 index 000000000000..21c64e9c7dbe --- /dev/null +++ b/packages/SystemUI/res-keyguard/layout/type_clock.xml @@ -0,0 +1,55 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + Copyright (C) 2019 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + --> +<com.android.keyguard.clock.ClockLayout + xmlns:android="http://schemas.android.com/apk/res/android" + android:layout_width="match_parent" + android:layout_height="match_parent" + > + <com.android.keyguard.clock.TypographicClock + android:id="@+id/type_clock" + android:orientation="vertical" + android:layout_width="match_parent" + android:layout_height="wrap_content" + > + <TextView + android:id="@+id/header" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_marginLeft="50dp" + style="@style/widget_big" + android:textColor="@color/typeClockAccentColor" + android:text="@string/type_clock_header" + android:textSize="40dp" + /> + <TextView + android:id="@+id/hour" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_marginLeft="50dp" + style="@style/widget_big" + android:textSize="40dp" + /> + <TextView + android:id="@+id/minute" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_marginLeft="50dp" + style="@style/widget_big" + android:textSize="40dp" + /> + </com.android.keyguard.clock.TypographicClock> +</com.android.keyguard.clock.ClockLayout> diff --git a/packages/SystemUI/res-keyguard/values/colors.xml b/packages/SystemUI/res-keyguard/values/colors.xml index 7a849ebd481d..74ee7ffad3f6 100644 --- a/packages/SystemUI/res-keyguard/values/colors.xml +++ b/packages/SystemUI/res-keyguard/values/colors.xml @@ -19,4 +19,6 @@ <color name="bubbleHourHandColor">#C97343</color> <!-- Default color for minute hand of Bubble clock. --> <color name="bubbleMinuteHandColor">#F5C983</color> + <!-- Accent color for Typographic clock. --> + <color name="typeClockAccentColor">#F5C983</color> </resources> diff --git a/packages/SystemUI/res-keyguard/values/dimens.xml b/packages/SystemUI/res-keyguard/values/dimens.xml index 9245c300acf5..e2ba23ec898c 100644 --- a/packages/SystemUI/res-keyguard/values/dimens.xml +++ b/packages/SystemUI/res-keyguard/values/dimens.xml @@ -47,8 +47,6 @@ <dimen name="bottom_text_spacing_digital">0dp</dimen> <!-- Slice subtitle --> <dimen name="widget_label_font_size">16dp</dimen> - <!-- Slice offset when pulsing --> - <dimen name="widget_pulsing_bottom_padding">48dp</dimen> <!-- Clock without header --> <dimen name="widget_big_font_size">64dp</dimen> <!-- Clock with header --> diff --git a/packages/SystemUI/res-keyguard/values/strings.xml b/packages/SystemUI/res-keyguard/values/strings.xml index 1d5aa6d76991..7432f9cde639 100644 --- a/packages/SystemUI/res-keyguard/values/strings.xml +++ b/packages/SystemUI/res-keyguard/values/strings.xml @@ -402,4 +402,87 @@ number">%d</xliff:g> remaining attempt before SIM becomes permanently unusable. number">%d</xliff:g> remaining attempts before SIM becomes permanently unusable. Contact carrier for details.</item> </plurals> + <!-- Header for typographic clock face. [CHAR LIMIT=8] --> + <string name="type_clock_header">It\u2019s</string> + + <!-- Hour displayed in words on the typographic clock face. [CHAR LIMIT=8] --> + <string-array name="type_clock_hours"> + <item>Twelve</item> + <item>One</item> + <item>Two</item> + <item>Three</item> + <item>Four</item> + <item>Five</item> + <item>Six</item> + <item>Seven</item> + <item>Eight</item> + <item>Nine</item> + <item>Ten</item> + <item>Eleven</item> + </string-array> + + <!-- Minutes displayed in words on the typographic clock face. [CHAR LIMIT=16] --> + <string-array name="type_clock_minutes"> + <item>O\u2019Clock</item> + <item>O\u2019One</item> + <item>O\u2019Two</item> + <item>O\u2019Three</item> + <item>O\u2019Four</item> + <item>O\u2019Five</item> + <item>O\u2019Six</item> + <item>O\u2019Seven</item> + <item>O\u2019Eight</item> + <item>O\u2019Nine</item> + <item>Ten</item> + <item>Eleven</item> + <item>Twelve</item> + <item>Thirteen</item> + <item>Fourteen</item> + <item>Fifteen</item> + <item>Sixteen</item> + <item>Seventeen</item> + <item>Eighteen</item> + <item>Nineteen</item> + <item>Twenty</item> + <item>Twenty\nOne</item> + <item>Twenty\nTwo</item> + <item>Twenty\nThree</item> + <item>Twenty\nFour</item> + <item>Twenty\nFive</item> + <item>Twenty\nSix</item> + <item>Twenty\nSeven</item> + <item>Twenty\nEight</item> + <item>Twenty\nNine</item> + <item>Thirty</item> + <item>Thirty\nOne</item> + <item>Thirty\nTwo</item> + <item>Thirty\nThree</item> + <item>Thirty\nFour</item> + <item>Thirty\nFive</item> + <item>Thirty\nSix</item> + <item>Thirty\nSeven</item> + <item>Thirty\nEight</item> + <item>Thirty\nNine</item> + <item>Forty</item> + <item>Forty\nOne</item> + <item>Forty\nTwo</item> + <item>Forty\nThree</item> + <item>Forty\nFour</item> + <item>Forty\nFive</item> + <item>Forty\nSix</item> + <item>Forty\nSeven</item> + <item>Forty\nEight</item> + <item>Forty\nNine</item> + <item>Fifty</item> + <item>Fifty\nOne</item> + <item>Fifty\nTwo</item> + <item>Fifty\nThree</item> + <item>Fifty\nFour</item> + <item>Fifty\nFive</item> + <item>Fifty\nSix</item> + <item>Fifty\nSeven</item> + <item>Fifty\nEight</item> + <item>Fifty\nNine</item> + </string-array> + </resources> diff --git a/core/res/res/layout/notification_template_ambient_header.xml b/packages/SystemUI/res/layout/dock_info_overlay.xml index be5d9b436b79..430143ca3bc2 100644 --- a/core/res/res/layout/notification_template_ambient_header.xml +++ b/packages/SystemUI/res/layout/dock_info_overlay.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="utf-8"?> <!-- - ~ Copyright (C) 2017 The Android Open Source Project + ~ Copyright (C) 2019 The Android Open Source Project ~ ~ Licensed under the Apache License, Version 2.0 (the "License"); ~ you may not use this file except in compliance with the License. @@ -15,14 +15,5 @@ ~ limitations under the License. --> -<!-- hack to work around <include /> not being supported at the top level --> -<FrameLayout - xmlns:android="http://schemas.android.com/apk/res/android" - android:paddingStart="@dimen/notification_extra_margin_ambient" - android:paddingEnd="@dimen/notification_extra_margin_ambient" - android:layout_width="wrap_content" - android:layout_height="wrap_content"> - <include - layout="@layout/notification_template_header" - android:theme="@style/Theme.DeviceDefault.Notification.Ambient"/> -</FrameLayout> +<!-- empty stub --> +<merge /> diff --git a/packages/SystemUI/res/layout/global_actions_wrapped.xml b/packages/SystemUI/res/layout/global_actions_wrapped.xml index 7f4e0d21078f..f932303473bd 100644 --- a/packages/SystemUI/res/layout/global_actions_wrapped.xml +++ b/packages/SystemUI/res/layout/global_actions_wrapped.xml @@ -1,6 +1,7 @@ <?xml version="1.0" encoding="utf-8"?> <com.android.systemui.HardwareUiLayout xmlns:android="http://schemas.android.com/apk/res/android" + android:id="@id/global_actions_view" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_gravity="top|right" diff --git a/packages/SystemUI/res/layout/status_bar_expanded.xml b/packages/SystemUI/res/layout/status_bar_expanded.xml index 75c0ec3ced43..7d403b24354c 100644 --- a/packages/SystemUI/res/layout/status_bar_expanded.xml +++ b/packages/SystemUI/res/layout/status_bar_expanded.xml @@ -43,6 +43,8 @@ android:clipToPadding="false" android:clipChildren="false"> + <include layout="@layout/dock_info_overlay" /> + <FrameLayout android:id="@+id/qs_frame" android:layout="@layout/qs_panel" diff --git a/packages/SystemUI/res/values/config.xml b/packages/SystemUI/res/values/config.xml index 476089aa3aac..98f0cbe29110 100644 --- a/packages/SystemUI/res/values/config.xml +++ b/packages/SystemUI/res/values/config.xml @@ -106,7 +106,7 @@ <!-- The default tiles to display in QuickSettings --> <string name="quick_settings_tiles_default" translatable="false"> - wifi,bt,dnd,flashlight,rotation,battery,cell,airplane,cast + wifi,bt,dnd,flashlight,rotation,battery,cell,airplane,cast,sensorprivacy </string> <!-- Tiles native to System UI. Order should match "quick_settings_tiles_default" --> diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml index 5a00b4526c32..ab0bbe10c37c 100644 --- a/packages/SystemUI/res/values/dimens.xml +++ b/packages/SystemUI/res/values/dimens.xml @@ -66,9 +66,7 @@ <item name="status_bar_icon_scale_factor" format="float" type="dimen">1.0</item> <dimen name="group_overflow_number_size">@*android:dimen/notification_text_size</dimen> - <dimen name="group_overflow_number_size_dark">16sp</dimen> <dimen name="group_overflow_number_padding">@*android:dimen/notification_content_margin_end</dimen> - <dimen name="group_overflow_number_extra_padding_dark">@*android:dimen/notification_extra_margin_ambient</dimen> <!-- max height of a notification such that the content can still fade out when closing --> <dimen name="max_notification_fadeout_height">100dp</dimen> @@ -94,9 +92,6 @@ <!-- Height of a large notification in the status bar --> <dimen name="notification_max_height">294dp</dimen> - <!-- Height of an ambient notification on ambient display --> - <dimen name="notification_ambient_height">400dp</dimen> - <!-- Height of a heads up notification in the status bar for legacy custom views --> <dimen name="notification_max_heads_up_height_legacy">128dp</dimen> diff --git a/packages/SystemUI/res/values/ids.xml b/packages/SystemUI/res/values/ids.xml index 633f8686b804..bd34beac7fd6 100644 --- a/packages/SystemUI/res/values/ids.xml +++ b/packages/SystemUI/res/values/ids.xml @@ -114,5 +114,8 @@ <item type="id" name="aod_mask_transition_progress_tag" /> <item type="id" name="aod_mask_transition_progress_end_tag" /> <item type="id" name="aod_mask_transition_progress_start_tag" /> + + <!-- Global Actions Menu --> + <item type="id" name="global_actions_view" /> </resources> diff --git a/packages/SystemUI/res/values/styles.xml b/packages/SystemUI/res/values/styles.xml index 22a0b3642a35..fa675b75d85d 100644 --- a/packages/SystemUI/res/values/styles.xml +++ b/packages/SystemUI/res/values/styles.xml @@ -64,48 +64,16 @@ <item name="hybridNotificationTextStyle">@style/hybrid_notification_text</item> </style> - <style name="HybridNotification.Ambient"> - <item name="hybridNotificationStyle">@style/hybrid_notification_ambient</item> - <item name="hybridNotificationTitleStyle">@style/hybrid_notification_title_ambient</item> - <item name="hybridNotificationTextStyle">@style/hybrid_notification_text_ambient</item> - </style> - - <style name="hybrid_notification_ambient"> - <item name="android:paddingStart">@*android:dimen/notification_extra_margin_ambient</item> - <item name="android:paddingEnd">@*android:dimen/notification_extra_margin_ambient</item> - <item name="android:orientation">vertical</item> - </style> - <style name="hybrid_notification"> <item name="android:paddingStart">@*android:dimen/notification_content_margin_start</item> <item name="android:paddingEnd">12dp</item> </style> - <style name="hybrid_notification_title_ambient"> - <item name="android:layout_marginTop">@*android:dimen/notification_header_margin_top_ambient</item> - <item name="android:paddingStart">@*android:dimen/notification_content_margin_start</item> - <item name="android:paddingEnd">@*android:dimen/notification_content_margin_end</item> - <item name="android:textAppearance">@*android:style/Notification.Header.Ambient</item> - <item name="android:layout_gravity">top|center_horizontal</item> - <item name="android:textSize">@*android:dimen/notification_ambient_title_text_size</item> - <item name="android:textColor">#ffffffff</item> - </style> - <style name="hybrid_notification_title"> <item name="android:paddingEnd">4dp</item> <item name="android:textAppearance">@*android:style/TextAppearance.Material.Notification.Title</item> </style> - <style name="hybrid_notification_text_ambient"> - <item name="android:paddingStart">@*android:dimen/notification_content_margin_start</item> - <item name="android:paddingEnd">@*android:dimen/notification_content_margin_end</item> - <item name="android:textSize">@*android:dimen/notification_ambient_text_size</item> - <item name="android:textColor">#eeffffff</item> - <item name="android:gravity">top|center_horizontal</item> - <item name="android:ellipsize">end</item> - <item name="android:maxLines">3</item> - </style> - <style name="hybrid_notification_text" parent="@*android:style/Widget.Material.Notification.Text"> <item name="android:paddingEnd">4dp</item> diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitch.java b/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitch.java index a8094d20d5a2..1aff3949a74b 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitch.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitch.java @@ -20,6 +20,7 @@ import androidx.annotation.VisibleForTesting; import com.android.keyguard.clock.BubbleClockController; import com.android.keyguard.clock.StretchAnalogClockController; +import com.android.keyguard.clock.TypeClockController; import com.android.systemui.Dependency; import com.android.systemui.plugins.ClockPlugin; import com.android.systemui.statusbar.StatusBarState; @@ -153,6 +154,12 @@ public class KeyguardClockSwitch extends RelativeLayout { Settings.Secure.LOCK_SCREEN_CUSTOM_CLOCK_FACE, StretchAnalogClockController.class.getName(), () -> StretchAnalogClockController.build(mLayoutInflater))) + .withDefault( + new SettingsGattedSupplier( + mContentResolver, + Settings.Secure.LOCK_SCREEN_CUSTOM_CLOCK_FACE, + TypeClockController.class.getName(), + () -> TypeClockController.build(mLayoutInflater))) .build(); mContentResolver.registerContentObserver( Settings.Secure.getUriFor(Settings.Secure.LOCK_SCREEN_CUSTOM_CLOCK_FACE), @@ -248,10 +255,6 @@ public class KeyguardClockSwitch extends RelativeLayout { mClockView.setShowCurrentUserTime(showCurrentUserTime); } - public void setElegantTextHeight(boolean elegant) { - mClockView.setElegantTextHeight(elegant); - } - public void setTextSize(int unit, float size) { mClockView.setTextSize(unit, size); } diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSliceView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSliceView.java index 669e6fff525b..bac7844c024b 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardSliceView.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSliceView.java @@ -90,7 +90,7 @@ public class KeyguardSliceView extends LinearLayout implements View.OnClickListe */ private Runnable mContentChangeListener; private Slice mSlice; - private boolean mPulsing; + private boolean mHasHeader; public KeyguardSliceView(Context context) { this(context, null, 0); @@ -150,10 +150,18 @@ public class KeyguardSliceView extends LinearLayout implements View.OnClickListe Dependency.get(ConfigurationController.class).removeCallback(this); } + /** + * Returns whether the current visible slice has a title/header. + */ + public boolean hasHeader() { + return mHasHeader; + } + private void showSlice() { Trace.beginSection("KeyguardSliceView#showSlice"); - if (mPulsing || mSlice == null) { + if (mSlice == null) { mRow.setVisibility(GONE); + mHasHeader = false; if (mContentChangeListener != null) { mContentChangeListener.run(); } @@ -162,7 +170,7 @@ public class KeyguardSliceView extends LinearLayout implements View.OnClickListe ListContent lc = new ListContent(getContext(), mSlice); SliceContent headerContent = lc.getHeader(); - boolean hasHeader = headerContent != null + mHasHeader = headerContent != null && !headerContent.getSliceItem().hasHint(HINT_LIST_ITEM); List<SliceContent> subItems = new ArrayList<>(); for (int i = 0; i < lc.getRowItems().size(); i++) { @@ -177,7 +185,7 @@ public class KeyguardSliceView extends LinearLayout implements View.OnClickListe mClickActions.clear(); final int subItemsCount = subItems.size(); final int blendedColor = getTextColor(); - final int startIndex = hasHeader ? 1 : 0; // First item is header; skip it + final int startIndex = mHasHeader ? 1 : 0; // First item is header; skip it mRow.setVisibility(subItemsCount > 0 ? VISIBLE : GONE); for (int i = startIndex; i < subItemsCount; i++) { RowContent rc = (RowContent) subItems.get(i); @@ -189,7 +197,7 @@ public class KeyguardSliceView extends LinearLayout implements View.OnClickListe button = new KeyguardSliceButton(mContext); button.setTextColor(blendedColor); button.setTag(itemTag); - final int viewIndex = i - (hasHeader ? 1 : 0); + final int viewIndex = i - (mHasHeader ? 1 : 0); mRow.addView(button, viewIndex); } @@ -234,18 +242,6 @@ public class KeyguardSliceView extends LinearLayout implements View.OnClickListe Trace.endSection(); } - public void setPulsing(boolean pulsing, boolean animate) { - mPulsing = pulsing; - LayoutTransition transition = getLayoutTransition(); - if (!animate) { - setLayoutTransition(null); - } - showSlice(); - if (!animate) { - setLayoutTransition(transition); - } - } - public void setDarkAmount(float darkAmount) { mDarkAmount = darkAmount; mRow.setDarkAmount(darkAmount); diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardStatusView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardStatusView.java index f0cdc890306f..bb549ada6830 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardStatusView.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardStatusView.java @@ -72,7 +72,6 @@ public class KeyguardStatusView extends GridLayout implements private ArraySet<View> mVisibleInDoze; private boolean mPulsing; - private boolean mWasPulsing; private float mDarkAmount = 0; private int mTextColor; private int mLastLayoutHeight; @@ -202,10 +201,6 @@ public class KeyguardStatusView extends GridLayout implements updateOwnerInfo(); updateLogoutView(); updateDark(); - - // Disable elegant text height because our fancy colon makes the ymin value huge for no - // reason. - mClockView.setElegantTextHeight(false); } /** @@ -214,7 +209,7 @@ public class KeyguardStatusView extends GridLayout implements private void onSliceContentChanged() { LinearLayout.LayoutParams layoutParams = (LinearLayout.LayoutParams) mClockView.getLayoutParams(); - layoutParams.bottomMargin = mPulsing ? mSmallClockPadding : 0; + layoutParams.bottomMargin = mKeyguardSlice.hasHeader() ? mSmallClockPadding : 0; mClockView.setLayoutParams(layoutParams); } @@ -224,16 +219,16 @@ public class KeyguardStatusView extends GridLayout implements @Override public void onLayoutChange(View view, int left, int top, int right, int bottom, int oldLeft, int oldTop, int oldRight, int oldBottom) { - int heightOffset = mPulsing || mWasPulsing ? 0 : getHeight() - mLastLayoutHeight; + boolean smallClock = mKeyguardSlice.hasHeader(); + int heightOffset = smallClock ? 0 : getHeight() - mLastLayoutHeight; long duration = KeyguardSliceView.DEFAULT_ANIM_DURATION; - long delay = mPulsing || mWasPulsing ? 0 : duration / 4; - mWasPulsing = false; + long delay = smallClock ? 0 : duration / 4; boolean shouldAnimate = mKeyguardSlice.getLayoutTransition() != null && mKeyguardSlice.getLayoutTransition().isRunning(); if (view == mClockView) { - float clockScale = mPulsing ? mSmallClockScale : 1; - Paint.Style style = mPulsing ? Paint.Style.FILL_AND_STROKE : Paint.Style.FILL; + float clockScale = smallClock ? mSmallClockScale : 1; + Paint.Style style = smallClock ? Paint.Style.FILL_AND_STROKE : Paint.Style.FILL; mClockView.animate().cancel(); if (shouldAnimate) { mClockView.setY(oldTop + heightOffset); @@ -438,15 +433,11 @@ public class KeyguardStatusView extends GridLayout implements } } - public void setPulsing(boolean pulsing, boolean animate) { + public void setPulsing(boolean pulsing) { if (mPulsing == pulsing) { return; } - if (mPulsing) { - mWasPulsing = true; - } mPulsing = pulsing; - mKeyguardSlice.setPulsing(pulsing, animate); updateDozeVisibleViews(); } diff --git a/packages/SystemUI/src/com/android/keyguard/clock/ClockLayout.java b/packages/SystemUI/src/com/android/keyguard/clock/ClockLayout.java index 5aa566848732..3591dc82c8ec 100644 --- a/packages/SystemUI/src/com/android/keyguard/clock/ClockLayout.java +++ b/packages/SystemUI/src/com/android/keyguard/clock/ClockLayout.java @@ -36,6 +36,7 @@ public class ClockLayout extends FrameLayout { */ private View mDigitalClock; private View mAnalogClock; + private View mTypeClock; /** * Pixel shifting amplitidues used to prevent screen burn-in. @@ -60,6 +61,7 @@ public class ClockLayout extends FrameLayout { super.onFinishInflate(); mDigitalClock = findViewById(R.id.digital_clock); mAnalogClock = findViewById(R.id.analog_clock); + mTypeClock = findViewById(R.id.type_clock); // Get pixel shifting X, Y amplitudes from resources. Resources resources = getResources(); @@ -89,5 +91,11 @@ public class ClockLayout extends FrameLayout { mAnalogClock.setY(Math.max(0f, 0.5f * (getHeight() - mAnalogClock.getHeight())) + offsetY); } + + // Put the typographic clock part way down the screen. + if (mTypeClock != null) { + mTypeClock.setX(offsetX); + mTypeClock.setY(0.2f * getHeight() + offsetY); + } } } diff --git a/packages/SystemUI/src/com/android/keyguard/clock/StretchAnalogClock.java b/packages/SystemUI/src/com/android/keyguard/clock/StretchAnalogClock.java index 91cec86392d6..8734754541a6 100644 --- a/packages/SystemUI/src/com/android/keyguard/clock/StretchAnalogClock.java +++ b/packages/SystemUI/src/com/android/keyguard/clock/StretchAnalogClock.java @@ -80,6 +80,7 @@ public class StretchAnalogClock extends View { */ public void setMinuteHandColor(int color) { mMinutePaint.setColor(color); + invalidate(); } private void init() { diff --git a/packages/SystemUI/src/com/android/keyguard/clock/TypeClockController.java b/packages/SystemUI/src/com/android/keyguard/clock/TypeClockController.java new file mode 100644 index 000000000000..17d929dc8a3b --- /dev/null +++ b/packages/SystemUI/src/com/android/keyguard/clock/TypeClockController.java @@ -0,0 +1,106 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.keyguard.clock; + +import android.graphics.Paint.Style; +import android.view.LayoutInflater; +import android.view.View; + +import com.android.keyguard.R; +import com.android.systemui.plugins.ClockPlugin; + +import java.util.TimeZone; + +/** + * Plugin for a custom Typographic clock face that displays the time in words. + */ +public class TypeClockController implements ClockPlugin { + + /** + * Custom clock shown on AOD screen and behind stack scroller on lock. + */ + private View mView; + private TypographicClock mTypeClock; + + /** + * Small clock shown on lock screen above stack scroller. + */ + private View mLockClockContainer; + + /** + * Controller for transition into dark state. + */ + private CrossFadeDarkController mDarkController; + + private TypeClockController() {} + + /** + * Create a TypeClockController instance. + * + * @param inflater Inflater used to inflate custom clock views. + */ + public static TypeClockController build(LayoutInflater inflater) { + TypeClockController controller = new TypeClockController(); + controller.createViews(inflater); + return controller; + } + + private void createViews(LayoutInflater inflater) { + mView = inflater.inflate(R.layout.type_clock, null); + mTypeClock = mView.findViewById(R.id.type_clock); + + // For now, this view is used to hide the default digital clock. + // Need better transition to lock screen. + mLockClockContainer = inflater.inflate(R.layout.digital_clock, null); + mLockClockContainer.setVisibility(View.GONE); + } + + @Override + public View getView() { + return mLockClockContainer; + } + + @Override + public View getBigClockView() { + return mView; + } + + @Override + public void setStyle(Style style) {} + + @Override + public void setTextColor(int color) { + mTypeClock.setTextColor(color); + } + + @Override + public void dozeTimeTick() { + mTypeClock.onTimeChanged(); + } + + @Override + public void setDarkAmount(float darkAmount) {} + + @Override + public void onTimeZoneChanged(TimeZone timeZone) { + mTypeClock.onTimeZoneChanged(timeZone); + } + + @Override + public boolean shouldShowStatusArea() { + return false; + } +} diff --git a/packages/SystemUI/src/com/android/keyguard/clock/TypographicClock.java b/packages/SystemUI/src/com/android/keyguard/clock/TypographicClock.java new file mode 100644 index 000000000000..5f9da3ee33bb --- /dev/null +++ b/packages/SystemUI/src/com/android/keyguard/clock/TypographicClock.java @@ -0,0 +1,110 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.keyguard.clock; + +import android.content.Context; +import android.content.res.Resources; +import android.text.format.DateFormat; +import android.util.AttributeSet; +import android.widget.LinearLayout; +import android.widget.TextView; + +import com.android.keyguard.R; + +import java.text.SimpleDateFormat; +import java.util.Calendar; +import java.util.TimeZone; + +/** + * Clock that presents the time in words. + */ +public class TypographicClock extends LinearLayout { + + private final String[] mHours; + private final String[] mMinutes; + private TextView mHeaderText; + private TextView mHourText; + private TextView mMinuteText; + private Calendar mTime; + private String mDescFormat; + private TimeZone mTimeZone; + + public TypographicClock(Context context) { + this(context, null); + } + + public TypographicClock(Context context, AttributeSet attrs) { + this(context, attrs, 0); + } + + public TypographicClock(Context context, AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + mTime = Calendar.getInstance(); + mDescFormat = ((SimpleDateFormat) DateFormat.getTimeFormat(context)).toLocalizedPattern(); + Resources res = context.getResources(); + mHours = res.getStringArray(R.array.type_clock_hours); + mMinutes = res.getStringArray(R.array.type_clock_minutes); + } + + /** + * Call when the time changes to update the text of the time. + */ + public void onTimeChanged() { + mTime.setTimeInMillis(System.currentTimeMillis()); + setContentDescription(DateFormat.format(mDescFormat, mTime)); + final int hour = mTime.get(Calendar.HOUR); + mHourText.setText(mHours[hour % 12]); + final int minute = mTime.get(Calendar.MINUTE); + mMinuteText.setText(mMinutes[minute % 60]); + invalidate(); + } + + /** + * Call when the time zone has changed to update clock time. + * + * @param timeZone The updated time zone that will be used. + */ + public void onTimeZoneChanged(TimeZone timeZone) { + mTimeZone = timeZone; + mTime.setTimeZone(timeZone); + } + + /** + * Set the color of the text used to display the time. + * + * This is necessary when the wallpaper shown behind the clock on the + * lock screen changes. + */ + public void setTextColor(int color) { + mHourText.setTextColor(color); + mMinuteText.setTextColor(color); + } + + @Override + protected void onFinishInflate() { + super.onFinishInflate(); + mHeaderText = findViewById(R.id.header); + mHourText = findViewById(R.id.hour); + mMinuteText = findViewById(R.id.minute); + } + + @Override + protected void onAttachedToWindow() { + super.onAttachedToWindow(); + mTime = Calendar.getInstance(mTimeZone != null ? mTimeZone : TimeZone.getDefault()); + onTimeChanged(); + } +} diff --git a/packages/SystemUI/src/com/android/systemui/HardwareUiLayout.java b/packages/SystemUI/src/com/android/systemui/HardwareUiLayout.java index 16e869e9d317..e28aa9d369cb 100644 --- a/packages/SystemUI/src/com/android/systemui/HardwareUiLayout.java +++ b/packages/SystemUI/src/com/android/systemui/HardwareUiLayout.java @@ -37,23 +37,25 @@ import com.android.systemui.tuner.TunerService; import com.android.systemui.tuner.TunerService.Tunable; import com.android.systemui.util.leak.RotationUtils; -public class HardwareUiLayout extends LinearLayout implements Tunable { +/** + * Layout for placing two containers at a specific physical position on the device, relative to the + * device's hardware, regardless of screen rotation. + */ +public class HardwareUiLayout extends MultiListLayout implements Tunable { private static final String EDGE_BLEED = "sysui_hwui_edge_bleed"; private static final String ROUNDED_DIVIDER = "sysui_hwui_rounded_divider"; private final int[] mTmp2 = new int[2]; - private View mList; - private View mSeparatedView; + private ViewGroup mList; + private ViewGroup mSeparatedView; private int mOldHeight; private boolean mAnimating; private AnimatorSet mAnimation; private View mDivision; - private boolean mHasOutsideTouch; private HardwareBgDrawable mListBackground; private HardwareBgDrawable mSeparatedViewBackground; private Animator mAnimator; private boolean mCollapse; - private boolean mHasSeparatedButton; private int mEndPoint; private boolean mEdgeBleed; private boolean mRoundedDivider; @@ -67,6 +69,35 @@ public class HardwareUiLayout extends LinearLayout implements Tunable { } @Override + protected ViewGroup getSeparatedView() { + return findViewById(com.android.systemui.R.id.separated_button); + } + + @Override + protected ViewGroup getListView() { + return findViewById(android.R.id.list); + } + + @Override + public void removeAllItems() { + if (mList != null) { + mList.removeAllViews(); + } + if (mSeparatedView != null) { + mSeparatedView.removeAllViews(); + } + } + + @Override + public ViewGroup getParentView(boolean separated, int index) { + if (separated) { + return getSeparatedView(); + } else { + return getListView(); + } + } + + @Override protected void onAttachedToWindow() { super.onAttachedToWindow(); updateSettings(); @@ -137,9 +168,9 @@ public class HardwareUiLayout extends LinearLayout implements Tunable { super.onMeasure(widthMeasureSpec, heightMeasureSpec); if (mList == null) { if (getChildCount() != 0) { - mList = getChildAt(0); + mList = getListView(); mList.setBackground(mListBackground); - mSeparatedView = getChildAt(1); + mSeparatedView = getSeparatedView(); mSeparatedView.setBackground(mSeparatedViewBackground); updateEdgeMargin(mEdgeBleed ? 0 : getEdgePadding()); mOldHeight = mList.getMeasuredHeight(); @@ -187,7 +218,7 @@ public class HardwareUiLayout extends LinearLayout implements Tunable { } else { rotateLeft(); } - if (mHasSeparatedButton) { + if (mHasSeparatedView) { if (from == ROTATION_SEASCAPE || to == ROTATION_SEASCAPE) { // Separated view has top margin, so seascape separated view need special rotation, // not a full left or right rotation. @@ -408,8 +439,8 @@ public class HardwareUiLayout extends LinearLayout implements Tunable { if (mList == null) return; // If got separated button, setRotatedBackground to false, // all items won't get white background. - mListBackground.setRotatedBackground(mHasSeparatedButton); - mSeparatedViewBackground.setRotatedBackground(mHasSeparatedButton); + mListBackground.setRotatedBackground(mHasSeparatedView); + mSeparatedViewBackground.setRotatedBackground(mHasSeparatedView); if (mDivision != null && mDivision.getVisibility() == VISIBLE) { int index = mRotatedBackground ? 0 : 1; mDivision.getLocationOnScreen(mTmp2); @@ -460,21 +491,21 @@ public class HardwareUiLayout extends LinearLayout implements Tunable { case RotationUtils.ROTATION_LANDSCAPE: defaultTopPadding = getPaddingLeft(); viewsTotalHeight = mList.getMeasuredWidth() + mSeparatedView.getMeasuredWidth(); - separatedViewTopMargin = mHasSeparatedButton ? params.leftMargin : 0; + separatedViewTopMargin = mHasSeparatedView ? params.leftMargin : 0; screenHeight = getMeasuredWidth(); targetGravity = Gravity.CENTER_HORIZONTAL|Gravity.TOP; break; case RotationUtils.ROTATION_SEASCAPE: defaultTopPadding = getPaddingRight(); viewsTotalHeight = mList.getMeasuredWidth() + mSeparatedView.getMeasuredWidth(); - separatedViewTopMargin = mHasSeparatedButton ? params.leftMargin : 0; + separatedViewTopMargin = mHasSeparatedView ? params.leftMargin : 0; screenHeight = getMeasuredWidth(); targetGravity = Gravity.CENTER_HORIZONTAL|Gravity.BOTTOM; break; default: // Portrait defaultTopPadding = getPaddingTop(); viewsTotalHeight = mList.getMeasuredHeight() + mSeparatedView.getMeasuredHeight(); - separatedViewTopMargin = mHasSeparatedButton ? params.topMargin : 0; + separatedViewTopMargin = mHasSeparatedView ? params.topMargin : 0; screenHeight = getMeasuredHeight(); targetGravity = Gravity.CENTER_VERTICAL|Gravity.RIGHT; break; @@ -491,30 +522,10 @@ public class HardwareUiLayout extends LinearLayout implements Tunable { return super.getOutlineProvider(); } - public void setOutsideTouchListener(OnClickListener onClickListener) { - mHasOutsideTouch = true; - requestLayout(); - setOnClickListener(onClickListener); - setClickable(true); - setFocusable(true); - } - public void setCollapse() { mCollapse = true; } - public void setHasSeparatedButton(boolean hasSeparatedButton) { - mHasSeparatedButton = hasSeparatedButton; - } - - public static HardwareUiLayout get(View v) { - if (v instanceof HardwareUiLayout) return (HardwareUiLayout) v; - if (v.getParent() instanceof View) { - return get((View) v.getParent()); - } - return null; - } - private final ViewTreeObserver.OnComputeInternalInsetsListener mInsetsListener = inoutInfo -> { if (mHasOutsideTouch || (mList == null)) { inoutInfo.setTouchableInsets( diff --git a/packages/SystemUI/src/com/android/systemui/MultiListLayout.java b/packages/SystemUI/src/com/android/systemui/MultiListLayout.java new file mode 100644 index 000000000000..0c7a9a9fffd2 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/MultiListLayout.java @@ -0,0 +1,124 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui; + +import android.content.Context; +import android.util.AttributeSet; +import android.view.View; +import android.view.ViewGroup; +import android.widget.LinearLayout; + +/** + * Layout class representing the Global Actions menu which appears when the power button is held. + */ +public abstract class MultiListLayout extends LinearLayout { + boolean mHasOutsideTouch; + boolean mHasSeparatedView; + + int mExpectedSeparatedItemCount; + int mExpectedListItemCount; + + public MultiListLayout(Context context, AttributeSet attrs) { + super(context, attrs); + } + + protected abstract ViewGroup getSeparatedView(); + + protected abstract ViewGroup getListView(); + + /** + * Removes all child items from the separated and list views, if they exist. + */ + public abstract void removeAllItems(); + + /** + * Get the parent view which will be used to contain the item at the specified index. + * @param separated Whether or not this index refers to a position in the separated or list + * container. + * @param index The index of the item within the container. + * @return The parent ViewGroup which will be used to contain the specified item + * after it has been added to the layout. + */ + public abstract ViewGroup getParentView(boolean separated, int index); + + /** + * Sets the divided view, which may have a differently-colored background. + */ + public abstract void setDivisionView(View v); + + /** + * Set the view accessibility delegate for the list view container. + */ + public void setListViewAccessibilityDelegate(View.AccessibilityDelegate delegate) { + getListView().setAccessibilityDelegate(delegate); + } + + protected void setSeparatedViewVisibility(boolean visible) { + getSeparatedView().setVisibility(visible ? View.VISIBLE : View.GONE); + } + + /** + * Sets the number of items expected to be rendered in the separated container. This allows the + * layout to correctly determine which parent containers will be used for items before they have + * beenadded to the layout. + * @param count The number of items expected. + */ + public void setExpectedSeparatedItemCount(int count) { + mExpectedSeparatedItemCount = count; + } + + /** + * Sets the number of items expected to be rendered in the list container. This allows the + * layout to correctly determine which parent containers will be used for items before they have + * beenadded to the layout. + * @param count The number of items expected. + */ + public void setExpectedListItemCount(int count) { + mExpectedListItemCount = count; + } + + /** + * Sets whether the separated view should be shown, and handles updating visibility on + * that view. + */ + public void setHasSeparatedView(boolean hasSeparatedView) { + mHasSeparatedView = hasSeparatedView; + setSeparatedViewVisibility(hasSeparatedView); + } + + /** + * Sets this layout to respond to an outside touch listener. + */ + public void setOutsideTouchListener(OnClickListener onClickListener) { + mHasOutsideTouch = true; + requestLayout(); + setOnClickListener(onClickListener); + setClickable(true); + setFocusable(true); + } + + /** + * Retrieve the MultiListLayout associated with the given view. + */ + public static MultiListLayout get(View v) { + if (v instanceof MultiListLayout) return (MultiListLayout) v; + if (v.getParent() instanceof View) { + return get((View) v.getParent()); + } + return null; + } +} diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeHost.java b/packages/SystemUI/src/com/android/systemui/doze/DozeHost.java index 4cb1feebcce4..bd7a421e9762 100644 --- a/packages/SystemUI/src/com/android/systemui/doze/DozeHost.java +++ b/packages/SystemUI/src/com/android/systemui/doze/DozeHost.java @@ -38,7 +38,13 @@ public interface DozeHost { void setAnimateWakeup(boolean animateWakeup); void setAnimateScreenOff(boolean animateScreenOff); - void onDoubleTap(float x, float y); + /** + * Reports that a tap event happend on the Sensors Low Power Island. + * + * @param x Touch X, or -1 if sensor doesn't support touch location. + * @param y Touch Y, or -1 if sensor doesn't support touch location. + */ + void onSlpiTap(float x, float y); default void setAodDimmingScrim(float scrimOpacity) {} void setDozeScreenBrightness(int value); diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeLog.java b/packages/SystemUI/src/com/android/systemui/doze/DozeLog.java index 50003e3a6a38..a7847739cd00 100644 --- a/packages/SystemUI/src/com/android/systemui/doze/DozeLog.java +++ b/packages/SystemUI/src/com/android/systemui/doze/DozeLog.java @@ -35,7 +35,7 @@ public class DozeLog { private static final int SIZE = Build.IS_DEBUGGABLE ? 400 : 50; static final SimpleDateFormat FORMAT = new SimpleDateFormat("MM-dd HH:mm:ss.SSS"); - private static final int REASONS = 9; + private static final int REASONS = 10; public static final int PULSE_REASON_NONE = -1; public static final int PULSE_REASON_INTENT = 0; @@ -47,6 +47,7 @@ public class DozeLog { public static final int PULSE_REASON_DOCKING = 6; public static final int REASON_SENSOR_WAKE_UP = 7; public static final int PULSE_REASON_SENSOR_WAKE_LOCK_SCREEN = 8; + public static final int PULSE_REASON_SENSOR_TAP = 9; private static boolean sRegisterKeyguardCallback = true; @@ -207,6 +208,7 @@ public class DozeLog { case PULSE_REASON_DOCKING: return "docking"; case PULSE_REASON_SENSOR_WAKE_LOCK_SCREEN: return "wakelockscreen"; case REASON_SENSOR_WAKE_UP: return "wakeup"; + case PULSE_REASON_SENSOR_TAP: return "tap"; default: throw new IllegalArgumentException("bad reason: " + pulseReason); } } diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java b/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java index b6fc35553760..78374a0b1621 100644 --- a/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java +++ b/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java @@ -107,6 +107,13 @@ public class DozeSensors { dozeParameters.doubleTapReportsTouchCoordinates(), true /* touchscreen */), new TriggerSensor( + findSensorWithType(config.tapSensorType()), + Settings.Secure.DOZE_TAP_SCREEN_GESTURE, + true /* configured */, + DozeLog.PULSE_REASON_SENSOR_TAP, + false /* reports touch coordinates */, + true /* touchscreen */), + new TriggerSensor( findSensorWithType(config.longPressSensorType()), Settings.Secure.DOZE_PULSE_ON_LONG_PRESS, false /* settingDef */, diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java b/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java index 6a9b6899d509..e2e448bb0d0c 100644 --- a/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java +++ b/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java @@ -132,6 +132,7 @@ public class DozeTriggers implements DozeMachine.Part { private void onSensor(int pulseReason, boolean sensorPerformedProxCheck, float screenX, float screenY, float[] rawValues) { boolean isDoubleTap = pulseReason == DozeLog.PULSE_REASON_SENSOR_DOUBLE_TAP; + boolean isTap = pulseReason == DozeLog.PULSE_REASON_SENSOR_TAP; boolean isPickup = pulseReason == DozeLog.PULSE_REASON_SENSOR_PICKUP; boolean isLongPress = pulseReason == DozeLog.PULSE_REASON_SENSOR_LONG_PRESS; boolean isWakeDisplay = pulseReason == DozeLog.REASON_SENSOR_WAKE_UP; @@ -148,8 +149,10 @@ public class DozeTriggers implements DozeMachine.Part { // In pocket, drop event. return; } - if (isDoubleTap) { - mDozeHost.onDoubleTap(screenX, screenY); + if (isDoubleTap || isTap) { + if (screenX != -1 && screenY != -1) { + mDozeHost.onSlpiTap(screenX, screenY); + } mMachine.wakeUp(); } else if (isPickup) { mMachine.wakeUp(); diff --git a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java index 268245bd4acd..7b18fad0e105 100644 --- a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java +++ b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java @@ -67,10 +67,8 @@ import android.view.WindowManagerGlobal; import android.view.accessibility.AccessibilityEvent; import android.widget.AdapterView.OnItemLongClickListener; import android.widget.BaseAdapter; -import android.widget.FrameLayout; import android.widget.ImageView; import android.widget.ImageView.ScaleType; -import android.widget.LinearLayout; import android.widget.TextView; import com.android.internal.R; @@ -86,8 +84,8 @@ import com.android.internal.util.ScreenRecordHelper; import com.android.internal.util.ScreenshotHelper; import com.android.internal.widget.LockPatternUtils; import com.android.systemui.Dependency; -import com.android.systemui.HardwareUiLayout; import com.android.systemui.Interpolators; +import com.android.systemui.MultiListLayout; import com.android.systemui.colorextraction.SysuiColorExtractor; import com.android.systemui.plugins.GlobalActions.GlobalActionsManager; import com.android.systemui.statusbar.phone.ScrimController; @@ -490,6 +488,11 @@ class GlobalActionsDialog implements DialogInterface.OnDismissListener, public boolean showBeforeProvisioning() { return true; } + + @Override + public boolean shouldBeSeparated() { + return true; + } } private final class RestartAction extends SinglePressAction implements LongPressAction { @@ -926,6 +929,34 @@ class GlobalActionsDialog implements DialogInterface.OnDismissListener, return getItem(position).isEnabled(); } + public ArrayList<Action> getSeparatedActions(boolean shouldUseSeparatedView) { + ArrayList<Action> separatedActions = new ArrayList<Action>(); + if (!shouldUseSeparatedView) { + return separatedActions; + } + for (int i = 0; i < mItems.size(); i++) { + final Action action = mItems.get(i); + if (action.shouldBeSeparated()) { + separatedActions.add(action); + } + } + return separatedActions; + } + + public ArrayList<Action> getListActions(boolean shouldUseSeparatedView) { + if (!shouldUseSeparatedView) { + return new ArrayList<Action>(mItems); + } + ArrayList<Action> listActions = new ArrayList<Action>(); + for (int i = 0; i < mItems.size(); i++) { + final Action action = mItems.get(i); + if (!action.shouldBeSeparated()) { + listActions.add(action); + } + } + return listActions; + } + @Override public boolean areAllItemsEnabled() { return false; @@ -965,7 +996,7 @@ class GlobalActionsDialog implements DialogInterface.OnDismissListener, View view = action.create(mContext, convertView, parent, LayoutInflater.from(mContext)); // Everything but screenshot, the last item, gets white background. if (position == getCount() - 1) { - HardwareUiLayout.get(parent).setDivisionView(view); + MultiListLayout.get(parent).setDivisionView(view); } return view; } @@ -1004,6 +1035,10 @@ class GlobalActionsDialog implements DialogInterface.OnDismissListener, boolean showBeforeProvisioning(); boolean isEnabled(); + + default boolean shouldBeSeparated() { + return false; + } } /** @@ -1423,9 +1458,7 @@ class GlobalActionsDialog implements DialogInterface.OnDismissListener, private final Context mContext; private final MyAdapter mAdapter; - private final LinearLayout mListView; - private final FrameLayout mSeparatedView; - private final HardwareUiLayout mHardwareLayout; + private final MultiListLayout mGlobalActionsLayout; private final OnClickListener mClickListener; private final OnItemLongClickListener mLongClickListener; private final GradientDrawable mGradientDrawable; @@ -1466,16 +1499,11 @@ class GlobalActionsDialog implements DialogInterface.OnDismissListener, window.setType(WindowManager.LayoutParams.TYPE_VOLUME_OVERLAY); setContentView(com.android.systemui.R.layout.global_actions_wrapped); - mListView = findViewById(android.R.id.list); - mSeparatedView = findViewById(com.android.systemui.R.id.separated_button); - if (!mShouldDisplaySeparatedButton) { - mSeparatedView.setVisibility(View.GONE); - } - mHardwareLayout = HardwareUiLayout.get(mListView); - mHardwareLayout.setOutsideTouchListener(view -> dismiss()); - mHardwareLayout.setHasSeparatedButton(mShouldDisplaySeparatedButton); - setTitle(R.string.global_actions); - mListView.setAccessibilityDelegate(new View.AccessibilityDelegate() { + mGlobalActionsLayout = (MultiListLayout) + findViewById(com.android.systemui.R.id.global_actions_view); + mGlobalActionsLayout.setOutsideTouchListener(view -> dismiss()); + mGlobalActionsLayout.setHasSeparatedView(mShouldDisplaySeparatedButton); + mGlobalActionsLayout.setListViewAccessibilityDelegate(new View.AccessibilityDelegate() { @Override public boolean dispatchPopulateAccessibilityEvent( View host, AccessibilityEvent event) { @@ -1484,20 +1512,33 @@ class GlobalActionsDialog implements DialogInterface.OnDismissListener, return true; } }); + setTitle(R.string.global_actions); } private void updateList() { - mListView.removeAllViews(); - mSeparatedView.removeAllViews(); + mGlobalActionsLayout.removeAllItems(); + ArrayList<Action> separatedActions = + mAdapter.getSeparatedActions(mShouldDisplaySeparatedButton); + ArrayList<Action> listActions = mAdapter.getListActions(mShouldDisplaySeparatedButton); + mGlobalActionsLayout.setExpectedListItemCount(listActions.size()); + mGlobalActionsLayout.setExpectedSeparatedItemCount(separatedActions.size()); + for (int i = 0; i < mAdapter.getCount(); i++) { - ViewGroup parentView = mShouldDisplaySeparatedButton && i == mAdapter.getCount() - 1 - ? mSeparatedView : mListView; - View v = mAdapter.getView(i, null, parentView); + Action action = mAdapter.getItem(i); + int separatedIndex = separatedActions.indexOf(action); + ViewGroup parent; + if (separatedIndex != -1) { + parent = mGlobalActionsLayout.getParentView(true, separatedIndex); + } else { + int listIndex = listActions.indexOf(action); + parent = mGlobalActionsLayout.getParentView(false, listIndex); + } + View v = mAdapter.getView(i, null, parent); final int pos = i; v.setOnClickListener(view -> mClickListener.onClick(this, pos)); v.setOnLongClickListener(view -> mLongClickListener.onItemLongClick(null, v, pos, 0)); - parentView.addView(v); + parent.addView(v); } } @@ -1543,9 +1584,9 @@ class GlobalActionsDialog implements DialogInterface.OnDismissListener, super.show(); mShowing = true; mGradientDrawable.setAlpha(0); - mHardwareLayout.setTranslationX(getAnimTranslation()); - mHardwareLayout.setAlpha(0); - mHardwareLayout.animate() + mGlobalActionsLayout.setTranslationX(getAnimTranslation()); + mGlobalActionsLayout.setAlpha(0); + mGlobalActionsLayout.animate() .alpha(1) .translationX(0) .setDuration(300) @@ -1564,9 +1605,9 @@ class GlobalActionsDialog implements DialogInterface.OnDismissListener, return; } mShowing = false; - mHardwareLayout.setTranslationX(0); - mHardwareLayout.setAlpha(1); - mHardwareLayout.animate() + mGlobalActionsLayout.setTranslationX(0); + mGlobalActionsLayout.setAlpha(1); + mGlobalActionsLayout.animate() .alpha(0) .translationX(getAnimTranslation()) .setDuration(300) diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/SensorPrivacyTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/SensorPrivacyTile.java index 5230cea88e8e..7ee37d567a55 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/SensorPrivacyTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/SensorPrivacyTile.java @@ -84,7 +84,7 @@ public class SensorPrivacyTile extends QSTileImpl<BooleanState> implements @Override public Intent getLongClickIntent() { - return null; + return new Intent(); } @Override diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java index bd9ca1aa32f8..9ef9c94d7cdc 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java @@ -65,12 +65,12 @@ public class NotificationShelf extends ActivatableNotificationView implements private static final String TAG = "NotificationShelf"; private static final long SHELF_IN_TRANSLATION_DURATION = 200; - private boolean mDark; private NotificationIconContainer mShelfIcons; private int[] mTmp = new int[2]; private boolean mHideBackground; private int mIconAppearTopPadding; private int mShelfAppearTranslation; + private float mDarkShelfPadding; private int mStatusBarHeight; private int mStatusBarPaddingStart; private AmbientState mAmbientState; @@ -140,6 +140,7 @@ public class NotificationShelf extends ActivatableNotificationView implements mStatusBarPaddingStart = res.getDimensionPixelOffset(R.dimen.status_bar_padding_start); mPaddingBetweenElements = res.getDimensionPixelSize(R.dimen.notification_divider_height); mShelfAppearTranslation = res.getDimensionPixelSize(R.dimen.shelf_appear_translation); + mDarkShelfPadding = res.getDimensionPixelSize(R.dimen.widget_bottom_separator_padding); ViewGroup.LayoutParams layoutParams = getLayoutParams(); layoutParams.height = res.getDimensionPixelOffset(R.dimen.notification_shelf_height); @@ -165,11 +166,11 @@ public class NotificationShelf extends ActivatableNotificationView implements @Override public void setDark(boolean dark, boolean fade, long delay) { - super.setDark(dark, fade, delay); if (mDark == dark) return; - mDark = dark; + super.setDark(dark, fade, delay); mShelfIcons.setDark(dark, fade, delay); updateInteractiveness(); + updateOutline(); } /** @@ -218,10 +219,9 @@ public class NotificationShelf extends ActivatableNotificationView implements float awakenTranslation = Math.max(Math.min(viewEnd, maxShelfEnd) - viewState.height, getFullyClosedTranslation()); - float darkTranslation = mAmbientState.getDarkTopPadding(); float yRatio = mAmbientState.hasPulsingNotifications() ? 0 : mAmbientState.getDarkAmount(); - viewState.yTranslation = MathUtils.lerp(awakenTranslation, darkTranslation, yRatio); + viewState.yTranslation = awakenTranslation + mDarkShelfPadding * yRatio; viewState.zTranslation = ambientState.getBaseZHeight(); // For the small display size, it's not enough to make the icon not covered by // the top cutout so the denominator add the height of cutout. @@ -763,18 +763,14 @@ public class NotificationShelf extends ActivatableNotificationView implements } } - public boolean hidesBackground() { - return mHideBackground; - } - @Override protected boolean needsOutline() { - return !mHideBackground && super.needsOutline(); + return !mHideBackground && !mDark && super.needsOutline(); } @Override protected boolean shouldHideBackground() { - return super.shouldHideBackground() || mHideBackground; + return super.shouldHideBackground() || mHideBackground || mDark; } @Override diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryListener.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryListener.java index eea44906029d..839b06cec496 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryListener.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryListener.java @@ -33,6 +33,13 @@ public interface NotificationEntryListener { default void onPendingEntryAdded(NotificationEntry entry) { } + // TODO: Combine this with onPreEntryUpdated into "onBeforeEntryFiltered" or similar + /** + * Called when a new entry is created but before it has been filtered or displayed to the user. + */ + default void onBeforeNotificationAdded(NotificationEntry entry) { + } + /** * Called when a new entry is created. */ diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryManager.java index 45db00210a2e..989e781ab5ba 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryManager.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryManager.java @@ -18,11 +18,9 @@ package com.android.systemui.statusbar.notification; import android.annotation.Nullable; import android.app.Notification; import android.content.Context; -import android.os.UserHandle; import android.service.notification.NotificationListenerService; import android.service.notification.StatusBarNotification; import android.util.ArrayMap; -import android.util.ArraySet; import android.util.Log; import com.android.internal.annotations.VisibleForTesting; @@ -41,7 +39,6 @@ import com.android.systemui.statusbar.notification.collection.NotificationEntry; import com.android.systemui.statusbar.notification.row.NotificationInflater; import com.android.systemui.statusbar.notification.row.NotificationInflater.InflationFlag; import com.android.systemui.statusbar.notification.stack.NotificationListContainer; -import com.android.systemui.statusbar.policy.DeviceProvisionedController; import com.android.systemui.statusbar.policy.HeadsUpManager; import com.android.systemui.util.leak.LeakDetector; @@ -68,8 +65,6 @@ public class NotificationEntryManager implements @VisibleForTesting protected final HashMap<String, NotificationEntry> mPendingNotifications = new HashMap<>(); - private final DeviceProvisionedController mDeviceProvisionedController = - Dependency.get(DeviceProvisionedController.class); private final ForegroundServiceController mForegroundServiceController = Dependency.get(ForegroundServiceController.class); @@ -81,25 +76,12 @@ public class NotificationEntryManager implements private NotificationListenerService.RankingMap mLatestRankingMap; @VisibleForTesting protected NotificationData mNotificationData; - private NotificationListContainer mListContainer; + @VisibleForTesting final ArrayList<NotificationLifetimeExtender> mNotificationLifetimeExtenders = new ArrayList<>(); private final List<NotificationEntryListener> mNotificationEntryListeners = new ArrayList<>(); - private final DeviceProvisionedController.DeviceProvisionedListener - mDeviceProvisionedListener = - new DeviceProvisionedController.DeviceProvisionedListener() { - @Override - public void onDeviceProvisionedChanged() { - updateNotifications(); - } - }; - - public void destroy() { - mDeviceProvisionedController.removeCallback(mDeviceProvisionedListener); - } - @Override public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { pw.println("NotificationEntryManager state:"); @@ -151,9 +133,6 @@ public class NotificationEntryManager implements HeadsUpManager headsUpManager) { mPresenter = presenter; mNotificationData.setHeadsUpManager(headsUpManager); - mListContainer = listContainer; - - mDeviceProvisionedController.addCallback(mDeviceProvisionedListener); } /** Adds multiple {@link NotificationLifetimeExtender}s. */ @@ -227,7 +206,9 @@ public class NotificationEntryManager implements listener.onEntryInflated(entry, inflatedFlags); } mNotificationData.add(entry); - tagForeground(entry.notification); + for (NotificationEntryListener listener : mNotificationEntryListeners) { + listener.onBeforeNotificationAdded(entry); + } updateNotifications(); for (NotificationEntryListener listener : mNotificationEntryListeners) { listener.onNotificationAdded(entry); @@ -283,7 +264,6 @@ public class NotificationEntryManager implements if (entry.rowExists()) { entry.removeRow(); - mListContainer.cleanUpViewStateForEntry(entry); } // Let's remove the children if this was a summary @@ -368,19 +348,6 @@ public class NotificationEntryManager implements } } - @VisibleForTesting - void tagForeground(StatusBarNotification notification) { - ArraySet<Integer> activeOps = mForegroundServiceController.getAppOps( - notification.getUserId(), notification.getPackageName()); - if (activeOps != null) { - int N = activeOps.size(); - for (int i = 0; i < N; i++) { - updateNotificationsForAppOp(activeOps.valueAt(i), notification.getUid(), - notification.getPackageName(), true); - } - } - } - @Override public void addNotification(StatusBarNotification notification, NotificationListenerService.RankingMap ranking) { @@ -391,15 +358,6 @@ public class NotificationEntryManager implements } } - public void updateNotificationsForAppOp(int appOp, int uid, String pkg, boolean showIcon) { - String foregroundKey = mForegroundServiceController.getStandardLayoutKey( - UserHandle.getUserId(uid), pkg); - if (foregroundKey != null) { - mNotificationData.updateAppOp(appOp, uid, pkg, foregroundKey, showIcon); - updateNotifications(); - } - } - private void updateNotificationInternal(StatusBarNotification notification, NotificationListenerService.RankingMap ranking) throws InflationException { if (DEBUG) Log.d(TAG, "updateNotification(" + notification + ")"); @@ -452,8 +410,9 @@ public class NotificationEntryManager implements public void updateNotifications() { mNotificationData.filterAndSort(); - - mPresenter.updateNotificationViews(); + if (mPresenter != null) { + mPresenter.updateNotificationViews(); + } } public void updateNotificationRanking(NotificationListenerService.RankingMap rankingMap) { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationListController.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationListController.java new file mode 100644 index 000000000000..88f4ca239af4 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationListController.java @@ -0,0 +1,117 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.statusbar.notification; + +import static com.android.internal.util.Preconditions.checkNotNull; + +import android.os.UserHandle; +import android.service.notification.StatusBarNotification; +import android.util.ArraySet; + +import com.android.internal.statusbar.NotificationVisibility; +import com.android.systemui.ForegroundServiceController; +import com.android.systemui.statusbar.notification.collection.NotificationEntry; +import com.android.systemui.statusbar.notification.stack.NotificationListContainer; +import com.android.systemui.statusbar.policy.DeviceProvisionedController; +import com.android.systemui.statusbar.policy.DeviceProvisionedController.DeviceProvisionedListener; + +/** + * Root controller for the list of notifications in the shade. + * + * TODO: Much of the code in NotificationPresenter should eventually move in here. It will proxy + * domain-specific behavior (ARC, etc) to subcontrollers. + */ +public class NotificationListController { + private final NotificationEntryManager mEntryManager; + private final NotificationListContainer mListContainer; + private final ForegroundServiceController mForegroundServiceController; + private final DeviceProvisionedController mDeviceProvisionedController; + + public NotificationListController( + NotificationEntryManager entryManager, + NotificationListContainer listContainer, + ForegroundServiceController foregroundServiceController, + DeviceProvisionedController deviceProvisionedController) { + mEntryManager = checkNotNull(entryManager); + mListContainer = checkNotNull(listContainer); + mForegroundServiceController = checkNotNull(foregroundServiceController); + mDeviceProvisionedController = checkNotNull(deviceProvisionedController); + } + + /** + * Causes the controller to register listeners on its dependencies. This method must be called + * before the controller is ready to perform its duties. + */ + public void bind() { + mEntryManager.addNotificationEntryListener(mEntryListener); + mDeviceProvisionedController.addCallback(mDeviceProvisionedListener); + } + + /** Should be called when the list controller is being destroyed. */ + public void destroy() { + mDeviceProvisionedController.removeCallback(mDeviceProvisionedListener); + } + + @SuppressWarnings("FieldCanBeLocal") + private final NotificationEntryListener mEntryListener = new NotificationEntryListener() { + @Override + public void onEntryRemoved( + NotificationEntry entry, + NotificationVisibility visibility, + boolean removedByUser) { + mListContainer.cleanUpViewStateForEntry(entry); + } + + @Override + public void onBeforeNotificationAdded(NotificationEntry entry) { + tagForeground(entry.notification); + } + }; + + private final DeviceProvisionedListener mDeviceProvisionedListener = + new DeviceProvisionedListener() { + @Override + public void onDeviceProvisionedChanged() { + mEntryManager.updateNotifications(); + } + }; + + // TODO: This method is horrifically inefficient + private void tagForeground(StatusBarNotification notification) { + ArraySet<Integer> activeOps = + mForegroundServiceController.getAppOps( + notification.getUserId(), notification.getPackageName()); + if (activeOps != null) { + int len = activeOps.size(); + for (int i = 0; i < len; i++) { + updateNotificationsForAppOp(activeOps.valueAt(i), notification.getUid(), + notification.getPackageName(), true); + } + } + } + + /** When an app op changes, propagate that change to notifications. */ + public void updateNotificationsForAppOp(int appOp, int uid, String pkg, boolean showIcon) { + String foregroundKey = + mForegroundServiceController.getStandardLayoutKey(UserHandle.getUserId(uid), pkg); + if (foregroundKey != null) { + mEntryManager + .getNotificationData().updateAppOp(appOp, uid, pkg, foregroundKey, showIcon); + mEntryManager.updateNotifications(); + } + } +} diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ActivatableNotificationView.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ActivatableNotificationView.java index 8b0a6828205d..c34d567da0be 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ActivatableNotificationView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ActivatableNotificationView.java @@ -105,7 +105,7 @@ public abstract class ActivatableNotificationView extends ExpandableOutlineView private final DoubleTapHelper mDoubleTapHelper; private boolean mDimmed; - private boolean mDark; + protected boolean mDark; protected int mBgTint = NO_COLOR; private float mBgAlpha = 1f; @@ -140,7 +140,6 @@ public abstract class ActivatableNotificationView extends ExpandableOutlineView private FalsingManager mFalsingManager; private float mNormalBackgroundVisibilityAmount; - private ValueAnimator mFadeInFromDarkAnimator; private float mDimmedBackgroundFadeInAmount = -1; private ValueAnimator.AnimatorUpdateListener mBackgroundVisibilityUpdater = new ValueAnimator.AnimatorUpdateListener() { @@ -150,22 +149,6 @@ public abstract class ActivatableNotificationView extends ExpandableOutlineView mDimmedBackgroundFadeInAmount = mBackgroundDimmed.getAlpha(); } }; - private AnimatorListenerAdapter mFadeInEndListener = new AnimatorListenerAdapter() { - @Override - public void onAnimationEnd(Animator animation) { - super.onAnimationEnd(animation); - mFadeInFromDarkAnimator = null; - mDimmedBackgroundFadeInAmount = -1; - updateBackground(); - } - }; - private ValueAnimator.AnimatorUpdateListener mUpdateOutlineListener - = new ValueAnimator.AnimatorUpdateListener() { - @Override - public void onAnimationUpdate(ValueAnimator animation) { - updateOutlineAlpha(); - } - }; private FakeShadowView mFakeShadow; private int mCurrentBackgroundTint; private int mTargetTint; @@ -465,22 +448,11 @@ public abstract class ActivatableNotificationView extends ExpandableOutlineView mDark = dark; updateBackground(); updateBackgroundTint(false); - if (!dark && fade && !shouldHideBackground()) { - fadeInFromDark(delay); - } - updateOutlineAlpha(); } private void updateOutlineAlpha() { - if (mDark) { - setOutlineAlpha(0f); - return; - } float alpha = NotificationStackScrollLayout.BACKGROUND_ALPHA_DIMMED; alpha = (alpha + (1.0f - alpha) * mNormalBackgroundVisibilityAmount); - if (mFadeInFromDarkAnimator != null) { - alpha *= mFadeInFromDarkAnimator.getAnimatedFraction(); - } setOutlineAlpha(alpha); } @@ -638,36 +610,6 @@ public abstract class ActivatableNotificationView extends ExpandableOutlineView } /** - * Fades in the background when exiting dark mode. - */ - private void fadeInFromDark(long delay) { - final View background = mDimmed ? mBackgroundDimmed : mBackgroundNormal; - background.setAlpha(0f); - mBackgroundVisibilityUpdater.onAnimationUpdate(null); - background.animate() - .alpha(1f) - .setDuration(DARK_ANIMATION_LENGTH) - .setStartDelay(delay) - .setInterpolator(Interpolators.ALPHA_IN) - .setListener(new AnimatorListenerAdapter() { - @Override - public void onAnimationCancel(Animator animation) { - // Jump state if we are cancelled - background.setAlpha(1f); - } - }) - .setUpdateListener(mBackgroundVisibilityUpdater) - .start(); - mFadeInFromDarkAnimator = TimeAnimator.ofFloat(0.0f, 1.0f); - mFadeInFromDarkAnimator.setDuration(DARK_ANIMATION_LENGTH); - mFadeInFromDarkAnimator.setStartDelay(delay); - mFadeInFromDarkAnimator.setInterpolator(Interpolators.LINEAR_OUT_SLOW_IN); - mFadeInFromDarkAnimator.addListener(mFadeInEndListener); - mFadeInFromDarkAnimator.addUpdateListener(mUpdateOutlineListener); - mFadeInFromDarkAnimator.start(); - } - - /** * Fades the background when the dimmed state changes. */ private void fadeDimmedBackground() { @@ -708,9 +650,7 @@ public abstract class ActivatableNotificationView extends ExpandableOutlineView public void onAnimationEnd(Animator animation) { updateBackground(); mBackgroundAnimator = null; - if (mFadeInFromDarkAnimator == null) { - mDimmedBackgroundFadeInAmount = -1; - } + mDimmedBackgroundFadeInAmount = -1; } }); mBackgroundAnimator.addUpdateListener(mBackgroundVisibilityUpdater); @@ -736,7 +676,7 @@ public abstract class ActivatableNotificationView extends ExpandableOutlineView mBackgroundNormal.setVisibility(mActivated ? VISIBLE : INVISIBLE); } else if (mDimmed) { // When groups are animating to the expanded state from the lockscreen, show the - // normal background instead of the dimmed background + // normal background instead of the dimmed background. final boolean dontShowDimmed = isGroupExpansionChanging() && isChildInGroup(); mBackgroundDimmed.setVisibility(dontShowDimmed ? View.INVISIBLE : View.VISIBLE); mBackgroundNormal.setVisibility((mActivated || dontShowDimmed) @@ -760,7 +700,7 @@ public abstract class ActivatableNotificationView extends ExpandableOutlineView } protected boolean shouldHideBackground() { - return mDark; + return false; } private void cancelFadeAnimations() { @@ -1023,14 +963,11 @@ public abstract class ActivatableNotificationView extends ExpandableOutlineView /** * @param withTint should a possible tint be factored in? - * @param withOverRide should the value be interpolated with {@link #mOverrideTint} + * @param withOverride should the value be interpolated with {@link #mOverrideTint} * @return the calculated background color */ - private int calculateBgColor(boolean withTint, boolean withOverRide) { - if (withTint && mDark) { - return getContext().getColor(R.color.notification_material_background_dark_color); - } - if (withOverRide && mOverrideTint != NO_COLOR) { + private int calculateBgColor(boolean withTint, boolean withOverride) { + if (withOverride && mOverrideTint != NO_COLOR) { int defaultTint = calculateBgColor(withTint, false); return NotificationUtils.interpolateColors(defaultTint, mOverrideTint, mOverrideAmount); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java index df0189fc4c4a..296c061459bc 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java @@ -132,7 +132,6 @@ public class ExpandableNotificationRow extends ActivatableNotificationView } private LayoutListener mLayoutListener; - private boolean mDark; private boolean mLowPriorityStateUpdated; private final NotificationInflater mNotificationInflater; private int mIconTransformContentShift; @@ -146,7 +145,6 @@ public class ExpandableNotificationRow extends ActivatableNotificationView private int mNotificationMinHeight; private int mNotificationMinHeightLarge; private int mNotificationMaxHeight; - private int mNotificationAmbientHeight; private int mIncreasedPaddingBetweenElements; private int mNotificationLaunchHeight; private boolean mMustStayOnScreen; @@ -677,8 +675,7 @@ public class ExpandableNotificationRow extends ActivatableNotificationView if (headsUpWrapper != null) { headsUpHeight = Math.max(headsUpHeight, headsUpWrapper.getMinLayoutHeight()); } - layout.setHeights(minHeight, headsUpHeight, mNotificationMaxHeight, - mNotificationAmbientHeight); + layout.setHeights(minHeight, headsUpHeight, mNotificationMaxHeight, headsUpHeight); } public StatusBarNotification getStatusBarNotification() { @@ -1647,8 +1644,6 @@ public class ExpandableNotificationRow extends ActivatableNotificationView R.dimen.notification_min_height_increased); mNotificationMaxHeight = NotificationUtils.getFontScaledHeight(mContext, R.dimen.notification_max_height); - mNotificationAmbientHeight = NotificationUtils.getFontScaledHeight(mContext, - R.dimen.notification_ambient_height); mMaxHeadsUpHeightBeforeN = NotificationUtils.getFontScaledHeight(mContext, R.dimen.notification_max_heads_up_height_legacy); mMaxHeadsUpHeightBeforeP = NotificationUtils.getFontScaledHeight(mContext, @@ -2008,8 +2003,10 @@ public class ExpandableNotificationRow extends ActivatableNotificationView @Override public void setDark(boolean dark, boolean fade, long delay) { + if (mDark == dark) { + return; + } super.setDark(dark, fade, delay); - mDark = dark; if (!mIsAmbientPulsing) { // Only fade the showing view of the pulsing notification. fade = false; @@ -2018,9 +2015,6 @@ public class ExpandableNotificationRow extends ActivatableNotificationView if (showing != null) { showing.setDark(dark, fade, delay); } - if (mIsSummaryWithChildren) { - mChildrenContainer.setDark(dark, fade, delay); - } updateShelfIconColor(); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/HybridGroupManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/HybridGroupManager.java index 33badafd5488..90ff4a728915 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/HybridGroupManager.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/HybridGroupManager.java @@ -39,14 +39,10 @@ public class HybridGroupManager { private final NotificationDozeHelper mDozer; private final ViewGroup mParent; - private float mOverflowNumberSizeDark; - private int mOverflowNumberPaddingDark; private float mOverflowNumberSize; private int mOverflowNumberPadding; private int mOverflowNumberColor; - private int mOverflowNumberColorDark; - private float mDarkAmount = 0f; public HybridGroupManager(Context ctx, ViewGroup parent) { mContext = ctx; @@ -59,12 +55,8 @@ public class HybridGroupManager { Resources res = mContext.getResources(); mOverflowNumberSize = res.getDimensionPixelSize( R.dimen.group_overflow_number_size); - mOverflowNumberSizeDark = res.getDimensionPixelSize( - R.dimen.group_overflow_number_size_dark); mOverflowNumberPadding = res.getDimensionPixelSize( R.dimen.group_overflow_number_padding); - mOverflowNumberPaddingDark = mOverflowNumberPadding + res.getDimensionPixelSize( - R.dimen.group_overflow_number_extra_padding_dark); } private HybridNotificationView inflateHybridViewWithStyle(int style) { @@ -86,13 +78,11 @@ public class HybridGroupManager { } private void updateOverFlowNumberColor(TextView numberView) { - numberView.setTextColor(NotificationUtils.interpolateColors( - mOverflowNumberColor, mOverflowNumberColorDark, mDarkAmount)); + numberView.setTextColor(mOverflowNumberColor); } - public void setOverflowNumberColor(TextView numberView, int colorRegular, int colorDark) { + public void setOverflowNumberColor(TextView numberView, int colorRegular) { mOverflowNumberColor = colorRegular; - mOverflowNumberColorDark = colorDark; if (numberView != null) { updateOverFlowNumberColor(numberView); } @@ -107,7 +97,7 @@ public class HybridGroupManager { public HybridNotificationView bindAmbientFromNotification(HybridNotificationView reusableView, Notification notification) { return bindFromNotificationWithStyle(reusableView, notification, - R.style.HybridNotification_Ambient); + R.style.HybridNotification); } private HybridNotificationView bindFromNotificationWithStyle( @@ -150,6 +140,11 @@ public class HybridGroupManager { R.plurals.notification_group_overflow_description, number), number); reusableView.setContentDescription(contentDescription); + reusableView.setTextSize(TypedValue.COMPLEX_UNIT_PX, mOverflowNumberSize); + reusableView.setPaddingRelative(reusableView.getPaddingStart(), + reusableView.getPaddingTop(), mOverflowNumberPadding, + reusableView.getPaddingBottom()); + updateOverFlowNumberColor(reusableView); return reusableView; } @@ -163,16 +158,4 @@ public class HybridGroupManager { } return titleView; } - - public void setOverflowNumberDark(TextView view, boolean dark, boolean fade, long delay) { - mDozer.setIntensityDark((f)->{ - mDarkAmount = f; - updateOverFlowNumberColor(view); - }, dark, fade, delay, view); - view.setTextSize(TypedValue.COMPLEX_UNIT_PX, - dark ? mOverflowNumberSizeDark : mOverflowNumberSize); - int paddingEnd = dark ? mOverflowNumberPaddingDark : mOverflowNumberPadding; - view.setPaddingRelative(view.getPaddingStart(), view.getPaddingTop(), paddingEnd, - view.getPaddingBottom()); - } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/AmbientState.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/AmbientState.java index cbec37effe18..1b5013dedb0e 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/AmbientState.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/AmbientState.java @@ -75,7 +75,6 @@ public class AmbientState { private int mIntrinsicPadding; private int mExpandAnimationTopChange; private ExpandableNotificationRow mExpandingNotification; - private int mDarkTopPadding; private float mDarkAmount; private boolean mAppearing; @@ -351,7 +350,8 @@ public class AmbientState { } public boolean hasPulsingNotifications() { - return mPulsing; + return mPulsing && mAmbientPulseManager != null + && mAmbientPulseManager.hasNotifications(); } public void setPulsing(boolean hasPulsing) { @@ -458,14 +458,6 @@ public class AmbientState { return mDarkAmount != 0; } - public void setDarkTopPadding(int darkTopPadding) { - mDarkTopPadding = darkTopPadding; - } - - public int getDarkTopPadding() { - return mDarkTopPadding; - } - public void setAppearing(boolean appearing) { mAppearing = appearing; } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationChildrenContainer.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationChildrenContainer.java index 51180361806b..8ffada43c53f 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationChildrenContainer.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationChildrenContainer.java @@ -316,7 +316,7 @@ public class NotificationChildrenContainer extends ViewGroup { StatusBarNotification notification = mContainingNotification.getStatusBarNotification(); final Notification.Builder builder = Notification.Builder.recoverBuilder(getContext(), notification.getNotification()); - RemoteViews header = builder.makeNotificationHeader(false /* ambient */); + RemoteViews header = builder.makeNotificationHeader(); if (mNotificationHeader == null) { mNotificationHeader = (NotificationHeaderView) header.apply(getContext(), this); final View expandButton = mNotificationHeader.findViewById( @@ -344,7 +344,7 @@ public class NotificationChildrenContainer extends ViewGroup { builder = Notification.Builder.recoverBuilder(getContext(), notification.getNotification()); } - header = builder.makeNotificationHeader(true /* ambient */); + header = builder.makeNotificationHeader(); if (mNotificationHeaderAmbient == null) { mNotificationHeaderAmbient = (ViewGroup) header.apply(getContext(), this); mNotificationHeaderWrapperAmbient = NotificationViewWrapper.wrap(getContext(), @@ -1171,12 +1171,6 @@ public class NotificationChildrenContainer extends ViewGroup { return mIsLowPriority && !mContainingNotification.isExpanded(); } - public void setDark(boolean dark, boolean fade, long delay) { - if (mOverflowNumber != null) { - mHybridGroupManager.setOverflowNumberDark(mOverflowNumber, dark, fade, delay); - } - } - public void reInflateViews(OnClickListener listener, StatusBarNotification notification) { if (mNotificationHeader != null) { removeView(mNotificationHeader); @@ -1227,8 +1221,7 @@ public class NotificationChildrenContainer extends ViewGroup { public void onNotificationUpdated() { mHybridGroupManager.setOverflowNumberColor(mOverflowNumber, - mContainingNotification.getNotificationColor(), - mContainingNotification.getNotificationColorAmbient()); + mContainingNotification.getNotificationColor()); } public int getPositionInLinearLayout(View childInGroup) { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationRoundnessManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationRoundnessManager.java index 941860177d1b..c5ab9f6049c6 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationRoundnessManager.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationRoundnessManager.java @@ -18,6 +18,7 @@ package com.android.systemui.statusbar.notification.stack; import static com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout.NUM_SECTIONS; +import com.android.systemui.statusbar.AmbientPulseManager; import com.android.systemui.statusbar.notification.collection.NotificationEntry; import com.android.systemui.statusbar.notification.row.ActivatableNotificationView; import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow; @@ -26,26 +27,34 @@ import com.android.systemui.statusbar.policy.OnHeadsUpChangedListener; import java.util.HashSet; +import javax.inject.Inject; +import javax.inject.Singleton; + /** * A class that manages the roundness for notification views */ -class NotificationRoundnessManager implements OnHeadsUpChangedListener { - +@Singleton +class NotificationRoundnessManager implements OnHeadsUpChangedListener, + AmbientPulseManager.OnAmbientChangedListener { + + private final ActivatableNotificationView[] mFirstInSectionViews; + private final ActivatableNotificationView[] mLastInSectionViews; + private final ActivatableNotificationView[] mTmpFirstInSectionViews; + private final ActivatableNotificationView[] mTmpLastInSectionViews; private boolean mExpanded; - private ActivatableNotificationView[] mFirstInSectionViews; - private ActivatableNotificationView[] mLastInSectionViews; - private ActivatableNotificationView[] mTmpFirstInSectionViews; - private ActivatableNotificationView[] mTmpLastInSectionViews; private HashSet<ExpandableView> mAnimatedChildren; private Runnable mRoundingChangedCallback; private ExpandableNotificationRow mTrackedHeadsUp; + private ActivatableNotificationView mTrackedAmbient; private float mAppearFraction; - NotificationRoundnessManager() { + @Inject + NotificationRoundnessManager(AmbientPulseManager ambientPulseManager) { mFirstInSectionViews = new ActivatableNotificationView[NUM_SECTIONS]; mLastInSectionViews = new ActivatableNotificationView[NUM_SECTIONS]; mTmpFirstInSectionViews = new ActivatableNotificationView[NUM_SECTIONS]; mTmpLastInSectionViews = new ActivatableNotificationView[NUM_SECTIONS]; + ambientPulseManager.addListener(this); } @Override @@ -63,6 +72,17 @@ class NotificationRoundnessManager implements OnHeadsUpChangedListener { updateView(row, false /* animate */); } + @Override + public void onAmbientStateChanged(NotificationEntry entry, boolean isPulsing) { + ActivatableNotificationView row = entry.getRow(); + if (isPulsing) { + mTrackedAmbient = row; + } else if (mTrackedAmbient == row) { + mTrackedAmbient = null; + } + updateView(row, false /* animate */); + } + private void updateView(ActivatableNotificationView view, boolean animate) { boolean changed = updateViewWithoutCallback(view, animate); if (changed) { @@ -125,6 +145,9 @@ class NotificationRoundnessManager implements OnHeadsUpChangedListener { // rounded. return 1.0f; } + if (view == mTrackedAmbient) { + return 1.0f; + } return 0.0f; } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java index 2d1f989fb1c9..d0665670bf8f 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java @@ -201,12 +201,7 @@ public class NotificationStackScrollLayout extends ViewGroup implements ScrollAd private int mPaddingBetweenElements; private int mIncreasedPaddingBetweenElements; private int mMaxTopPadding; - private int mRegularTopPadding; - private int mDarkTopPadding; - // Current padding, will be either mRegularTopPadding or mDarkTopPadding private int mTopPadding; - // Distance between AOD separator and shelf - private int mDarkShelfPadding; private int mBottomMargin; private int mBottomInset = 0; private float mQsExpansionFraction; @@ -318,7 +313,7 @@ public class NotificationStackScrollLayout extends ViewGroup implements ScrollAd private HashSet<Pair<ExpandableNotificationRow, Boolean>> mHeadsUpChangeAnimations = new HashSet<>(); private HeadsUpManagerPhone mHeadsUpManager; - private NotificationRoundnessManager mRoundnessManager = new NotificationRoundnessManager(); + private final NotificationRoundnessManager mRoundnessManager; private boolean mTrackingHeadsUp; private ScrimController mScrimController; private boolean mForceNoOverlappingRendering; @@ -441,7 +436,8 @@ public class NotificationStackScrollLayout extends ViewGroup implements ScrollAd Dependency.get(NotificationEntryManager.class); private final IStatusBarService mBarService = IStatusBarService.Stub.asInterface( ServiceManager.getService(Context.STATUS_BAR_SERVICE)); - private final MetricsLogger mMetricsLogger = Dependency.get(MetricsLogger.class); + @VisibleForTesting + protected final MetricsLogger mMetricsLogger = Dependency.get(MetricsLogger.class); private final NotificationRemoteInputManager mRemoteInputManager = Dependency.get(NotificationRemoteInputManager.class); private final SysuiColorExtractor mColorExtractor = Dependency.get(SysuiColorExtractor.class); @@ -468,7 +464,8 @@ public class NotificationStackScrollLayout extends ViewGroup implements ScrollAd public NotificationStackScrollLayout( @Named(VIEW_CONTEXT) Context context, AttributeSet attrs, - @Named(ALLOW_NOTIFICATION_LONG_PRESS_NAME) boolean allowLongPress) { + @Named(ALLOW_NOTIFICATION_LONG_PRESS_NAME) boolean allowLongPress, + NotificationRoundnessManager notificationRoundnessManager) { super(context, attrs, 0, 0); Resources res = getResources(); @@ -479,6 +476,7 @@ public class NotificationStackScrollLayout extends ViewGroup implements ScrollAd } mAmbientState = new AmbientState(context); + mRoundnessManager = notificationRoundnessManager; mBgColor = context.getColor(R.color.notification_shade_background_color); int minHeight = res.getDimensionPixelSize(R.dimen.notification_min_height); int maxHeight = res.getDimensionPixelSize(R.dimen.notification_max_height); @@ -495,7 +493,6 @@ public class NotificationStackScrollLayout extends ViewGroup implements ScrollAd res.getBoolean(R.bool.config_drawNotificationBackground); mFadeNotificationsOnDismiss = res.getBoolean(R.bool.config_fadeNotificationsOnDismiss); - mDarkShelfPadding = res.getDimensionPixelSize(R.dimen.widget_bottom_separator_padding); mRoundnessManager.setAnimatedChildren(mChildrenToAddAnimated); mRoundnessManager.setOnRoundingChangedCallback(this::invalidate); addOnExpandedHeightListener(mRoundnessManager::setExpanded); @@ -684,7 +681,7 @@ public class NotificationStackScrollLayout extends ViewGroup implements ScrollAd int lockScreenTop = mSections[0].getCurrentBounds().top; int lockScreenBottom = mSections[NUM_SECTIONS - 1].getCurrentBounds().bottom; int darkLeft = getWidth() / 2; - int darkTop = mRegularTopPadding; + int darkTop = mTopPadding; float yProgress = 1 - mInterpolatedDarkAmount; float xProgress = mDarkXInterpolator.getInterpolation( @@ -952,8 +949,6 @@ public class NotificationStackScrollLayout extends ViewGroup implements ScrollAd @ShadeViewRefactor(RefactorComponent.LAYOUT_ALGORITHM) private void updateAlgorithmHeightAndPadding() { - mTopPadding = (int) MathUtils.lerp(mRegularTopPadding, mDarkTopPadding, - mInterpolatedDarkAmount); mAmbientState.setLayoutHeight(getLayoutHeight()); updateAlgorithmLayoutMinHeight(); mAmbientState.setTopPadding(mTopPadding); @@ -1091,10 +1086,8 @@ public class NotificationStackScrollLayout extends ViewGroup implements ScrollAd @ShadeViewRefactor(RefactorComponent.SHADE_VIEW) private void setTopPadding(int topPadding, boolean animate) { - if (mRegularTopPadding != topPadding) { - mRegularTopPadding = topPadding; - mDarkTopPadding = topPadding + mDarkShelfPadding; - mAmbientState.setDarkTopPadding(mDarkTopPadding); + if (mTopPadding != topPadding) { + mTopPadding = topPadding; updateAlgorithmHeightAndPadding(); updateContentHeight(); if (animate && mAnimationsEnabled && mIsExpanded) { @@ -2059,10 +2052,7 @@ public class NotificationStackScrollLayout extends ViewGroup implements ScrollAd } mIntrinsicContentHeight = height; - // We don't want to use the toppadding since that might be interpolated and we want - // to take the final value of the animation. - int topPadding = mAmbientState.isFullyDark() ? mDarkTopPadding : mRegularTopPadding; - mContentHeight = height + topPadding + mBottomMargin; + mContentHeight = height + mTopPadding + mBottomMargin; updateScrollability(); clampScrollPosition(); mAmbientState.setLayoutMaxHeight(mContentHeight); @@ -2226,13 +2216,16 @@ public class NotificationStackScrollLayout extends ViewGroup implements ScrollAd int top = 0; if (section != null) { ActivatableNotificationView firstView = section.getFirstVisibleChild(); - // Round Y up to avoid seeing the background during animation - int finalTranslationY = (int) Math.ceil(ViewState.getFinalTranslationY(firstView)); - if (alreadyAnimating || section.isTargetTop(finalTranslationY)) { - // we're ending up at the same location as we are now, let's just skip the animation - top = finalTranslationY; - } else { - top = (int) Math.ceil(firstView.getTranslationY()); + if (firstView != null) { + // Round Y up to avoid seeing the background during animation + int finalTranslationY = (int) Math.ceil(ViewState.getFinalTranslationY(firstView)); + if (alreadyAnimating || section.isTargetTop(finalTranslationY)) { + // we're ending up at the same location as we are now, let's just skip the + // animation + top = finalTranslationY; + } else { + top = (int) Math.ceil(firstView.getTranslationY()); + } } } return top; @@ -5218,9 +5211,6 @@ public class NotificationStackScrollLayout extends ViewGroup implements ScrollAd // another "changeViewPosition" call is ever added. changeViewPosition(mShelf, getChildCount() - offsetFromEnd); - - // Scrim opacity varies based on notification count - mScrimController.setNotificationCount(getNotGoneChildCount()); } @ShadeViewRefactor(RefactorComponent.SHADE_VIEW) @@ -5638,8 +5628,9 @@ public class NotificationStackScrollLayout extends ViewGroup implements ScrollAd } }; + @VisibleForTesting @ShadeViewRefactor(RefactorComponent.INPUT) - private final OnMenuEventListener mMenuEventListener = new OnMenuEventListener() { + protected final OnMenuEventListener mMenuEventListener = new OnMenuEventListener() { @Override public void onMenuClicked(View view, int x, int y, MenuItem item) { if (mLongPressListener == null) { @@ -5647,8 +5638,10 @@ public class NotificationStackScrollLayout extends ViewGroup implements ScrollAd } if (view instanceof ExpandableNotificationRow) { ExpandableNotificationRow row = (ExpandableNotificationRow) view; - MetricsLogger.action(mContext, MetricsEvent.ACTION_TOUCH_GEAR, - row.getStatusBarNotification().getPackageName()); + mMetricsLogger.write(row.getStatusBarNotification().getLogMaker() + .setCategory(MetricsEvent.ACTION_TOUCH_GEAR) + .setType(MetricsEvent.TYPE_ACTION) + ); } mLongPressListener.onLongPress(view, x, y, item); } @@ -5671,8 +5664,9 @@ public class NotificationStackScrollLayout extends ViewGroup implements ScrollAd public void onMenuShown(View row) { if (row instanceof ExpandableNotificationRow) { ExpandableNotificationRow notificationRow = (ExpandableNotificationRow) row; - MetricsLogger.action(mContext, MetricsEvent.ACTION_REVEAL_GEAR, - notificationRow.getStatusBarNotification().getPackageName()); + mMetricsLogger.write(notificationRow.getStatusBarNotification().getLogMaker() + .setCategory(MetricsEvent.ACTION_REVEAL_GEAR) + .setType(MetricsEvent.TYPE_ACTION)); mHeadsUpManager.setMenuShown(notificationRow.getEntry(), true); } mSwipeHelper.onMenuShown(row); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackStateAnimator.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackStateAnimator.java index 19fce485b0c7..b4c205ab980c 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackStateAnimator.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackStateAnimator.java @@ -426,6 +426,9 @@ public class StackStateAnimator { mTmpState.yTranslation += mPulsingAppearingTranslation; mTmpState.alpha = 0; mTmpState.applyToView(changingView); + + mTmpState.copyFrom(mShelf.getViewState()); + mTmpState.applyToView(mShelf); } } else if (event.animationType == NotificationStackScrollLayout .AnimationEvent.ANIMATION_TYPE_PULSE_DISAPPEAR) { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeParameters.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeParameters.java index 6f2b63d2e64d..10497734d0b1 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeParameters.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeParameters.java @@ -158,8 +158,7 @@ public class DozeParameters implements TunerService.Tunable { * @return duration in millis. */ public long getWallpaperAodDuration() { - if (mAmbientDisplayConfiguration.wakeLockScreenGestureEnabled(UserHandle.USER_CURRENT) - || shouldControlScreenOff()) { + if (shouldControlScreenOff()) { return DozeScreenState.ENTER_DOZE_HIDE_WALLPAPER_DELAY; } return mAlwaysOnPolicy.wallpaperVisibilityDuration; diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeScrimController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeScrimController.java index 577e8d614acb..280dda0cd1dc 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeScrimController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeScrimController.java @@ -84,14 +84,6 @@ public class DozeScrimController implements StateListener { public void onCancelled() { pulseFinished(); } - - /** - * Whether to fade out wallpaper. - */ - @Override - public boolean isFadeOutWallpaper() { - return mPulseReason == DozeLog.PULSE_REASON_DOCKING; - } }; public DozeScrimController(DozeParameters dozeParameters) { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithm.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithm.java index a81b7e572a79..c68fdd4ec4a7 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithm.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithm.java @@ -91,11 +91,6 @@ public class KeyguardClockPositionAlgorithm { private int mBurnInPreventionOffsetY; /** - * Clock vertical padding when pulsing. - */ - private int mPulsingPadding; - - /** * Doze/AOD transition amount. */ private float mDarkAmount; @@ -105,10 +100,6 @@ public class KeyguardClockPositionAlgorithm { */ private boolean mCurrentlySecure; - /** - * Dozing and receiving a notification (AOD notification.) - */ - private boolean mPulsing; private float mEmptyDragAmount; /** @@ -123,13 +114,11 @@ public class KeyguardClockPositionAlgorithm { R.dimen.burn_in_prevention_offset_x); mBurnInPreventionOffsetY = res.getDimensionPixelSize( R.dimen.burn_in_prevention_offset_y); - mPulsingPadding = res.getDimensionPixelSize( - R.dimen.widget_pulsing_bottom_padding); } public void setup(int minTopMargin, int maxShadeBottom, int notificationStackHeight, float panelExpansion, int parentHeight, int keyguardStatusHeight, float dark, - boolean secure, boolean pulsing, float emptyDragAmount) { + boolean secure, float emptyDragAmount) { mMinTopMargin = minTopMargin + mContainerTopPadding; mMaxShadeBottom = maxShadeBottom; mNotificationStackHeight = notificationStackHeight; @@ -138,7 +127,6 @@ public class KeyguardClockPositionAlgorithm { mKeyguardStatusHeight = keyguardStatusHeight; mDarkAmount = dark; mCurrentlySecure = secure; - mPulsing = pulsing; mEmptyDragAmount = emptyDragAmount; } @@ -146,7 +134,7 @@ public class KeyguardClockPositionAlgorithm { final int y = getClockY(); result.clockY = y; result.clockAlpha = getClockAlpha(y); - result.stackScrollerPadding = y + (mPulsing ? mPulsingPadding : mKeyguardStatusHeight); + result.stackScrollerPadding = y + mKeyguardStatusHeight; result.clockX = (int) interpolate(0, burnInPreventionOffsetX(), mDarkAmount); } @@ -185,9 +173,6 @@ public class KeyguardClockPositionAlgorithm { private int getClockY() { // Dark: Align the bottom edge of the clock at about half of the screen: float clockYDark = getMaxClockY() + burnInPreventionOffsetY(); - if (mPulsing) { - clockYDark -= mPulsingPadding; - } clockYDark = MathUtils.max(0, clockYDark); float clockYRegular = getExpandedClockPosition(); @@ -230,11 +215,6 @@ public class KeyguardClockPositionAlgorithm { - mBurnInPreventionOffsetX; } - @VisibleForTesting - void setPulsingPadding(int padding) { - mPulsingPadding = padding; - } - public static class Result { /** diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationAssistantAction.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationAssistantAction.java index ebcd39b99778..323e7761b475 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationAssistantAction.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationAssistantAction.java @@ -43,6 +43,11 @@ public class NavigationAssistantAction extends NavigationGestureAction { } @Override + public boolean disableProxyEvents() { + return true; + } + + @Override public void onGestureStart(MotionEvent event) { mAssistManager.startAssist(new Bundle()); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBackAction.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBackAction.java index 93605adf4589..7a42b03947ae 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBackAction.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBackAction.java @@ -95,6 +95,11 @@ public class NavigationBackAction extends NavigationGestureAction { } } + @Override + public boolean disableProxyEvents() { + return true; + } + private void performBack() { sendEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_BACK); sendEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_BACK); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java index 31310f5f2043..0d5ebb9b6578 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java @@ -141,6 +141,7 @@ public class NotificationPanelView extends PanelView implements private KeyguardAffordanceHelper mAffordanceHelper; private KeyguardUserSwitcher mKeyguardUserSwitcher; private KeyguardStatusBarView mKeyguardStatusBar; + private ViewGroup mBigClockContainer; private QS mQs; private FrameLayout mQsFrame; @VisibleForTesting @@ -348,8 +349,8 @@ public class NotificationPanelView extends PanelView implements mKeyguardStatusView = findViewById(R.id.keyguard_status_view); KeyguardClockSwitch keyguardClockSwitch = findViewById(R.id.keyguard_clock_container); - ViewGroup bigClockContainer = findViewById(R.id.big_clock_container); - keyguardClockSwitch.setBigClockContainer(bigClockContainer); + mBigClockContainer = findViewById(R.id.big_clock_container); + keyguardClockSwitch.setBigClockContainer(mBigClockContainer); mNotificationContainerParent = findViewById(R.id.notification_container_parent); mNotificationStackScroller = findViewById(R.id.notification_stack_scroller); @@ -578,18 +579,23 @@ public class NotificationPanelView extends PanelView implements mKeyguardStatusView.getHeight(), mInterpolatedDarkAmount, mStatusBar.isKeyguardCurrentlySecure(), - mPulsing, mEmptyDragAmount); mClockPositionAlgorithm.run(mClockPositionResult); PropertyAnimator.setProperty(mKeyguardStatusView, AnimatableProperty.X, mClockPositionResult.clockX, CLOCK_ANIMATION_PROPERTIES, animateClock); PropertyAnimator.setProperty(mKeyguardStatusView, AnimatableProperty.Y, mClockPositionResult.clockY, CLOCK_ANIMATION_PROPERTIES, animateClock); + // Move big clock up while pulling up the bouncer + PropertyAnimator.setProperty(mBigClockContainer, AnimatableProperty.Y, + MathUtils.lerp(-mBigClockContainer.getHeight(), 0, + Interpolators.FAST_OUT_LINEAR_IN.getInterpolation(getExpandedFraction())), + CLOCK_ANIMATION_PROPERTIES, animateClock); updateClock(); stackScrollerPadding = mClockPositionResult.stackScrollerPadding; } mNotificationStackScroller.setIntrinsicPadding(stackScrollerPadding); - mNotificationStackScroller.setAntiBurnInOffsetX(mClockPositionResult.clockX); + int burnInXOffset = mPulsing ? 0 : mClockPositionResult.clockX; + mNotificationStackScroller.setAntiBurnInOffsetX(burnInXOffset); mStackScrollerMeasuringPass++; requestScrollerTopPaddingUpdate(animate); @@ -2824,7 +2830,7 @@ public class NotificationPanelView extends PanelView implements mAnimateNextPositionUpdate = false; } mNotificationStackScroller.setPulsing(pulsing, animatePulse); - mKeyguardStatusView.setPulsing(pulsing, animatePulse); + mKeyguardStatusView.setPulsing(pulsing); mKeyguardBottomArea.setPulsing(pulsing, animatePulse); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickStepController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickStepController.java index 0cec6371d813..9e91ab70e3de 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickStepController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickStepController.java @@ -34,13 +34,20 @@ import android.content.Context; import android.graphics.Canvas; import android.graphics.Matrix; import android.graphics.Rect; +import android.hardware.input.InputManager; import android.os.RemoteException; +import android.os.SystemClock; import android.provider.Settings; import android.util.Log; +import android.view.InputDevice; import android.view.MotionEvent; import android.view.View; +import android.view.ViewGroup; import android.view.ViewPropertyAnimator; +import android.view.WindowManager; +import android.view.WindowManager.LayoutParams; + import com.android.systemui.Dependency; import com.android.systemui.Interpolators; import com.android.systemui.R; @@ -64,7 +71,10 @@ public class QuickStepController implements GestureHelper { /** Experiment to swipe home button left to execute a back key press */ private static final String HIDE_BACK_BUTTON_PROP = "quickstepcontroller_hideback"; + private static final String ENABLE_CLICK_THROUGH_NAV_PROP = "quickstepcontroller_clickthrough"; private static final long BACK_BUTTON_FADE_IN_ALPHA = 150; + private static final long CLICK_THROUGH_TAP_DELAY = 70; + private static final long CLICK_THROUGH_TAP_RESET_DELAY = 100; /** When the home-swipe-back gesture is disallowed, make it harder to pull */ private static final float HORIZONTAL_GESTURE_DAMPING = 0.3f; @@ -100,6 +110,9 @@ public class QuickStepController implements GestureHelper { private float mMinDragLimit; private float mDragDampeningFactor; private float mEdgeSwipeThreshold; + private boolean mClickThroughPressed; + private float mClickThroughPressX; + private float mClickThroughPressY; private NavigationGestureAction mCurrentAction; private NavigationGestureAction[] mGestureActions = new NavigationGestureAction[MAX_GESTURES]; @@ -117,6 +130,19 @@ public class QuickStepController implements GestureHelper { mOverviewEventSender = Dependency.get(OverviewProxyService.class); } + private final Runnable mClickThroughSendTap = new Runnable() { + @Override + public void run() { + sendTap(mClickThroughPressX, mClickThroughPressY); + mNavigationBarView.postDelayed(mClickThroughResetTap, CLICK_THROUGH_TAP_RESET_DELAY); + } + }; + + private final Runnable mClickThroughResetTap = () -> { + setWindowTouchable(true); + mClickThroughPressed = false; + }; + public void setComponents(NavigationBarView navigationBarView) { mNavigationBarView = navigationBarView; @@ -320,6 +346,25 @@ public class QuickStepController implements GestureHelper { case MotionEvent.ACTION_UP: if (mCurrentAction != null) { mCurrentAction.endGesture(); + } else if (action == MotionEvent.ACTION_UP + && getBoolGlobalSetting(mContext, ENABLE_CLICK_THROUGH_NAV_PROP) + && !mClickThroughPressed) { + // Enable click through functionality where no gesture has been detected and not + // passed the drag slop so inject a touch event at the same location + // after making the navigation bar window untouchable. After a some time, the + // navigation bar will be able to take input events again + float diffX = Math.abs(event.getX() - mTouchDownX); + float diffY = Math.abs(event.getY() - mTouchDownY); + + if ((diffX <= NavigationBarCompat.getQuickStepDragSlopPx() + && diffY <= NavigationBarCompat.getQuickStepDragSlopPx())) { + setWindowTouchable(false); + mClickThroughPressX = event.getRawX(); + mClickThroughPressY = event.getRawY(); + mClickThroughPressed = true; + mNavigationBarView.postDelayed(mClickThroughSendTap, + CLICK_THROUGH_TAP_DELAY); + } } // Return the hit target back to its original position @@ -350,6 +395,19 @@ public class QuickStepController implements GestureHelper { return mCurrentAction != null || deadZoneConsumed; } + private void setWindowTouchable(boolean flag) { + final WindowManager.LayoutParams lp = (WindowManager.LayoutParams) + ((ViewGroup) mNavigationBarView.getParent()).getLayoutParams(); + if (flag) { + lp.flags &= ~LayoutParams.FLAG_NOT_TOUCHABLE; + } else { + lp.flags |= LayoutParams.FLAG_NOT_TOUCHABLE; + } + final WindowManager wm = (WindowManager) mNavigationBarView.getContext() + .getSystemService(Context.WINDOW_SERVICE); + wm.updateViewLayout((View) mNavigationBarView.getParent(), lp); + } + private boolean isEdgeSwipeAlongNavBar(int touchDown, boolean dragPositiveDirection) { // Detect edge swipe from side of 0 -> threshold if (dragPositiveDirection) { @@ -562,6 +620,38 @@ public class QuickStepController implements GestureHelper { return false; } + private void sendTap(float x, float y) { + long now = SystemClock.uptimeMillis(); + injectMotionEvent(InputDevice.SOURCE_TOUCHSCREEN, MotionEvent.ACTION_DOWN, now, x, y, 1.0f); + injectMotionEvent(InputDevice.SOURCE_TOUCHSCREEN, MotionEvent.ACTION_UP, now, x, y, 0.0f); + } + + private int getInputDeviceId(int inputSource) { + int[] devIds = InputDevice.getDeviceIds(); + for (int devId : devIds) { + InputDevice inputDev = InputDevice.getDevice(devId); + if (inputDev.supportsSource(inputSource)) { + return devId; + } + } + return 0; + } + + private void injectMotionEvent(int inputSource, int action, long when, float x, float y, + float pressure) { + final float defaultSize = 1.0f; + final int defaultMetaState = 0; + final float defaultPrecisionX = 1.0f; + final float defaultPrecisionY = 1.0f; + final int defaultEdgeFlags = 0; + MotionEvent event = MotionEvent.obtain(when, when, action, x, y, pressure, defaultSize, + defaultMetaState, defaultPrecisionX, defaultPrecisionY, + getInputDeviceId(inputSource), defaultEdgeFlags); + event.setSource(inputSource); + InputManager.getInstance().injectInputEvent(event, + InputManager.INJECT_INPUT_EVENT_MODE_ASYNC); + } + private boolean proxyMotionEvents(MotionEvent event) { final IOverviewProxy overviewProxy = mOverviewEventSender.getProxy(); event.transform(mTransformGlobalMatrix); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java index 853d7ab9a76d..bf143c8940e5 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java @@ -88,16 +88,12 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, OnCo /** * Default alpha value for most scrims. */ - public static final float GRADIENT_SCRIM_ALPHA = 0.45f; + public static final float GRADIENT_SCRIM_ALPHA = 0.2f; /** * A scrim varies its opacity based on a busyness factor, for example * how many notifications are currently visible. */ public static final float GRADIENT_SCRIM_ALPHA_BUSY = 0.7f; - /** - * Scrim opacity when a wallpaper doesn't support ambient mode. - */ - public static final float PULSING_WALLPAPER_SCRIM_ALPHA = 0.6f; /** * The most common scrim, the one under the keyguard. @@ -154,7 +150,6 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, OnCo private Callback mCallback; private boolean mWallpaperSupportsAmbientMode; private boolean mScreenOn; - private float mNotificationDensity; // Scrim blanking callbacks private Runnable mPendingFrameCallback; @@ -245,7 +240,7 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, OnCo mCurrentInFrontTint = state.getFrontTint(); mCurrentBehindTint = state.getBehindTint(); mCurrentInFrontAlpha = state.getFrontAlpha(); - mCurrentBehindAlpha = state.getBehindAlpha(mNotificationDensity); + mCurrentBehindAlpha = state.getBehindAlpha(); applyExpansionToAlpha(); // Scrim might acquire focus when user is navigating with a D-pad or a keyboard. @@ -279,8 +274,7 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, OnCo // Docking pulses may take a long time, wallpapers should also fade away after a while. if (mWallpaperSupportsAmbientMode && ( mDozeParameters.getAlwaysOn() && mState == ScrimState.AOD - || mState == ScrimState.PULSING && mCallback != null - && mCallback.isFadeOutWallpaper())) { + || mState == ScrimState.PULSING && mCallback != null)) { if (!mWallpaperVisibilityTimedOut) { mTimeTicker.schedule(mDozeParameters.getWallpaperAodDuration(), AlarmTimeout.MODE_IGNORE_IF_SCHEDULED); @@ -416,7 +410,7 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, OnCo // Either darken of make the scrim transparent when you // pull down the shade float interpolatedFract = getInterpolatedFraction(); - float alphaBehind = mState.getBehindAlpha(mNotificationDensity); + float alphaBehind = mState.getBehindAlpha(); if (mDarkenWhileDragging) { mCurrentBehindAlpha = MathUtils.lerp(GRADIENT_SCRIM_ALPHA_BUSY, alphaBehind, interpolatedFract); @@ -430,24 +424,6 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, OnCo } /** - * Keyguard and shade scrim opacity varies according to how many notifications are visible. - * @param notificationCount Number of visible notifications. - */ - public void setNotificationCount(int notificationCount) { - final float maxNotificationDensity = 3; - float notificationDensity = Math.min(notificationCount / maxNotificationDensity, 1f); - if (mNotificationDensity == notificationDensity) { - return; - } - mNotificationDensity = notificationDensity; - - if (mState == ScrimState.KEYGUARD) { - applyExpansionToAlpha(); - scheduleUpdate(); - } - } - - /** * Sets the given drawable as the background of the scrim that shows up behind the * notifications. */ @@ -612,9 +588,11 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, OnCo anim.setStartDelay(mAnimationDelay); anim.setDuration(mAnimationDuration); anim.addListener(new AnimatorListenerAdapter() { + private Callback lastCallback = mCallback; + @Override public void onAnimationEnd(Animator animation) { - onFinished(); + onFinished(lastCallback); scrim.setTag(TAG_KEY_ANIM, null); dispatchScrimsVisible(); @@ -672,14 +650,23 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, OnCo } private void onFinished() { + onFinished(mCallback); + } + + private void onFinished(Callback callback) { if (mWakeLockHeld) { mWakeLock.release(); mWakeLockHeld = false; } - if (mCallback != null) { - mCallback.onFinished(); - mCallback = null; + + if (callback != null) { + callback.onFinished(); + + if (callback == mCallback) { + mCallback = null; + } } + // When unlocking with fingerprint, we'll fade the scrims from black to transparent. // At the end of the animation we need to remove the tint. if (mState == ScrimState.UNLOCKED) { @@ -898,7 +885,7 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, OnCo // Backdrop event may arrive after state was already applied, // in this case, back-scrim needs to be re-evaluated if (mState == ScrimState.AOD || mState == ScrimState.PULSING) { - float newBehindAlpha = mState.getBehindAlpha(mNotificationDensity); + float newBehindAlpha = mState.getBehindAlpha(); if (mCurrentBehindAlpha != newBehindAlpha) { mCurrentBehindAlpha = newBehindAlpha; updateScrims(); @@ -912,6 +899,10 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, OnCo } } + public void setPulseReason(int pulseReason) { + ScrimState.PULSING.setPulseReason(pulseReason); + } + public interface Callback { default void onStart() { } @@ -921,9 +912,6 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, OnCo } default void onCancelled() { } - default boolean isFadeOutWallpaper() { - return false; - } } /** diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimState.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimState.java index 72519ba3503c..11a2d32c9dd6 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimState.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimState.java @@ -18,8 +18,8 @@ package com.android.systemui.statusbar.phone; import android.graphics.Color; import android.os.Trace; -import android.util.MathUtils; +import com.android.systemui.doze.DozeLog; import com.android.systemui.statusbar.ScrimView; import com.android.systemui.statusbar.notification.stack.StackStateAnimator; @@ -57,13 +57,6 @@ public enum ScrimState { mCurrentBehindAlpha = mScrimBehindAlphaKeyguard; mCurrentInFrontAlpha = 0; } - - @Override - public float getBehindAlpha(float busynessFactor) { - return MathUtils.map(0 /* start */, 1 /* stop */, - mScrimBehindAlphaKeyguard, ScrimController.GRADIENT_SCRIM_ALPHA_BUSY, - busynessFactor); - } }, /** @@ -117,7 +110,7 @@ public enum ScrimState { } @Override - public float getBehindAlpha(float busyness) { + public float getBehindAlpha() { return mWallpaperSupportsAmbientMode && !mHasBackdrop ? 0f : 1f; } @@ -133,17 +126,17 @@ public enum ScrimState { PULSING(5) { @Override public void prepare(ScrimState previousState) { - mCurrentInFrontAlpha = 0; - mCurrentInFrontTint = Color.BLACK; - mCurrentBehindTint = Color.BLACK; + mCurrentInFrontAlpha = 0f; + if (mPulseReason == DozeLog.PULSE_REASON_NOTIFICATION + || mPulseReason == DozeLog.PULSE_REASON_DOCKING) { + mCurrentBehindAlpha = previousState.getBehindAlpha(); + mCurrentBehindTint = Color.BLACK; + } else { + mCurrentBehindAlpha = mScrimBehindAlphaKeyguard; + mCurrentBehindTint = Color.TRANSPARENT; + } mBlankScreen = mDisplayRequiresBlanking; } - - @Override - public float getBehindAlpha(float busyness) { - return mWallpaperSupportsAmbientMode && !mHasBackdrop ? 0f - : ScrimController.PULSING_WALLPAPER_SCRIM_ALPHA; - } }, /** @@ -204,6 +197,7 @@ public enum ScrimState { int mIndex; boolean mHasBackdrop; boolean mLaunchingAffordanceWithPreview; + int mPulseReason; ScrimState(int index) { mIndex = index; @@ -235,7 +229,7 @@ public enum ScrimState { return mCurrentInFrontAlpha; } - public float getBehindAlpha(float busyness) { + public float getBehindAlpha() { return mCurrentBehindAlpha; } @@ -276,6 +270,10 @@ public enum ScrimState { mAodFrontScrimAlpha = aodFrontScrimAlpha; } + public void setPulseReason(int pulseReason) { + mPulseReason = pulseReason; + } + public void setScrimBehindAlphaKeyguard(float scrimBehindAlphaKeyguard) { mScrimBehindAlphaKeyguard = scrimBehindAlphaKeyguard; } 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 514bb228cd97..1470d0f44266 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java @@ -196,6 +196,7 @@ import com.android.systemui.statusbar.notification.NotificationAlertingManager; import com.android.systemui.statusbar.notification.NotificationClicker; import com.android.systemui.statusbar.notification.NotificationEntryManager; import com.android.systemui.statusbar.notification.NotificationInterruptionStateProvider; +import com.android.systemui.statusbar.notification.NotificationListController; import com.android.systemui.statusbar.notification.NotificationRowBinder; import com.android.systemui.statusbar.notification.VisualStabilityManager; import com.android.systemui.statusbar.notification.collection.NotificationEntry; @@ -387,6 +388,7 @@ public class StatusBar extends SystemUI implements DemoMode, private NotificationGutsManager mGutsManager; protected NotificationLogger mNotificationLogger; protected NotificationEntryManager mEntryManager; + private NotificationListController mNotificationListController; private NotificationInterruptionStateProvider mNotificationInterruptionStateProvider; private NotificationRowBinder mNotificationRowBinder; protected NotificationViewHierarchyManager mViewHierarchyManager; @@ -593,7 +595,7 @@ public class StatusBar extends SystemUI implements DemoMode, public void onActiveStateChanged(int code, int uid, String packageName, boolean active) { mForegroundServiceController.onAppOpChanged(code, uid, packageName, active); Dependency.get(Dependency.MAIN_HANDLER).post(() -> { - mEntryManager.updateNotificationsForAppOp(code, uid, packageName, active); + mNotificationListController.updateNotificationsForAppOp(code, uid, packageName, active); }); } @@ -1044,6 +1046,13 @@ public class StatusBar extends SystemUI implements DemoMode, mScrimController, mActivityLaunchAnimator, mStatusBarKeyguardViewManager, mNotificationAlertingManager); + mNotificationListController = + new NotificationListController( + mEntryManager, + (NotificationListContainer) mStackScroller, + mForegroundServiceController, + mDeviceProvisionedController); + mAppOpsController.addCallback(APP_OPS, this); mNotificationListener.setUpWithPresenter(mPresenter); mNotificationShelf.setOnActivatedListener(mPresenter); @@ -1056,6 +1065,7 @@ public class StatusBar extends SystemUI implements DemoMode, this, Dependency.get(BubbleController.class), mNotificationActivityStarter)); mGroupAlertTransferHelper.bind(mEntryManager, mGroupManager); + mNotificationListController.bind(); } /** @@ -2831,7 +2841,7 @@ public class StatusBar extends SystemUI implements DemoMode, } catch (RemoteException e) { // Ignore. } - mEntryManager.destroy(); + mNotificationListController.destroy(); // End old BaseStatusBar.destroy(). if (mStatusBarWindow != null) { mWindowManager.removeViewImmediate(mStatusBarWindow); @@ -3873,6 +3883,7 @@ public class StatusBar extends SystemUI implements DemoMode, @Override public void pulseWhileDozing(@NonNull PulseCallback callback, int reason) { + mScrimController.setPulseReason(reason); if (reason == DozeLog.PULSE_REASON_SENSOR_LONG_PRESS) { mPowerManager.wakeUp(SystemClock.uptimeMillis(), "com.android.systemui:NODOZE"); startAssist(new Bundle()); @@ -3999,7 +4010,7 @@ public class StatusBar extends SystemUI implements DemoMode, } @Override - public void onDoubleTap(float screenX, float screenY) { + public void onSlpiTap(float screenX, float screenY) { if (screenX > 0 && screenY > 0 && mAmbientIndicationContainer != null && mAmbientIndicationContainer.getVisibility() == View.VISIBLE) { mAmbientIndicationContainer.getLocationOnScreen(mTmpInt2); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarter.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarter.java index 04d24dc18f05..4f61009095c7 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarter.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarter.java @@ -346,7 +346,7 @@ public class StatusBarNotificationActivityStarter implements NotificationActivit } private void handleFullScreenIntent(NotificationEntry entry) { - boolean isHeadsUped = mNotificationInterruptionStateProvider.canHeadsUpCommon(entry); + boolean isHeadsUped = mNotificationInterruptionStateProvider.shouldHeadsUp(entry); if (!isHeadsUped && entry.notification.getNotification().fullScreenIntent != null) { if (shouldSuppressFullScreenIntent(entry)) { if (DEBUG) { diff --git a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeHostFake.java b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeHostFake.java index ce28b50436eb..dc4287287b03 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeHostFake.java +++ b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeHostFake.java @@ -104,7 +104,7 @@ class DozeHostFake implements DozeHost { } @Override - public void onDoubleTap(float x, float y) { + public void onSlpiTap(float x, float y) { doubleTapX = y; doubleTapY = y; } diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationEntryManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationEntryManagerTest.java index d937f93482d5..9ce6ae139998 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationEntryManagerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationEntryManagerTest.java @@ -22,19 +22,15 @@ import static junit.framework.Assert.assertTrue; import static org.junit.Assert.assertEquals; import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.anyInt; -import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.doAnswer; import static org.mockito.Mockito.inOrder; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; -import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import android.app.ActivityManager; -import android.app.AppOpsManager; import android.app.Notification; import android.app.NotificationManager; import android.app.PendingIntent; @@ -49,7 +45,6 @@ import android.service.notification.StatusBarNotification; import android.support.test.filters.SmallTest; import android.testing.AndroidTestingRunner; import android.testing.TestableLooper; -import android.util.ArraySet; import android.widget.FrameLayout; import com.android.internal.logging.MetricsLogger; @@ -79,8 +74,6 @@ import com.android.systemui.statusbar.phone.ShadeController; import com.android.systemui.statusbar.policy.DeviceProvisionedController; import com.android.systemui.statusbar.policy.HeadsUpManager; -import junit.framework.Assert; - import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; @@ -346,7 +339,6 @@ public class NotificationEntryManagerTest extends SysuiTestCase { verify(mEntryListener, never()).onInflationError(any(), any()); - verify(mListContainer).cleanUpViewStateForEntry(mEntry); verify(mPresenter).updateNotificationViews(); verify(mEntryListener).onEntryRemoved( mEntry, null, false /* removedByUser */); @@ -401,90 +393,6 @@ public class NotificationEntryManagerTest extends SysuiTestCase { } @Test - public void testUpdateAppOps_foregroundNoti() { - com.android.systemui.util.Assert.isNotMainThread(); - - when(mForegroundServiceController.getStandardLayoutKey(anyInt(), anyString())) - .thenReturn(mEntry.key); - mEntry.setRow(mRow); - mEntryManager.getNotificationData().add(mEntry); - - mEntryManager.updateNotificationsForAppOp( - AppOpsManager.OP_CAMERA, mEntry.notification.getUid(), - mEntry.notification.getPackageName(), true); - - verify(mPresenter, times(1)).updateNotificationViews(); - assertTrue(mEntryManager.getNotificationData().get(mEntry.key).mActiveAppOps.contains( - AppOpsManager.OP_CAMERA)); - } - - @Test - public void testUpdateAppOps_otherNoti() { - com.android.systemui.util.Assert.isNotMainThread(); - - when(mForegroundServiceController.getStandardLayoutKey(anyInt(), anyString())) - .thenReturn(null); - mEntryManager.updateNotificationsForAppOp(AppOpsManager.OP_CAMERA, 1000, "pkg", true); - - verify(mPresenter, never()).updateNotificationViews(); - } - - @Test - public void testAddNotificationExistingAppOps() { - mEntry.setRow(mRow); - mEntryManager.getNotificationData().add(mEntry); - ArraySet<Integer> expected = new ArraySet<>(); - expected.add(3); - expected.add(235); - expected.add(1); - - when(mForegroundServiceController.getAppOps(mEntry.notification.getUserId(), - mEntry.notification.getPackageName())).thenReturn(expected); - when(mForegroundServiceController.getStandardLayoutKey( - mEntry.notification.getUserId(), - mEntry.notification.getPackageName())).thenReturn(mEntry.key); - - mEntryManager.tagForeground(mEntry.notification); - - Assert.assertEquals(expected.size(), mEntry.mActiveAppOps.size()); - for (int op : expected) { - assertTrue("Entry missing op " + op, mEntry.mActiveAppOps.contains(op)); - } - } - - @Test - public void testAdd_noExistingAppOps() { - mEntry.setRow(mRow); - mEntryManager.getNotificationData().add(mEntry); - when(mForegroundServiceController.getStandardLayoutKey( - mEntry.notification.getUserId(), - mEntry.notification.getPackageName())).thenReturn(mEntry.key); - when(mForegroundServiceController.getAppOps(mEntry.notification.getUserId(), - mEntry.notification.getPackageName())).thenReturn(null); - - mEntryManager.tagForeground(mEntry.notification); - Assert.assertEquals(0, mEntry.mActiveAppOps.size()); - } - - @Test - public void testAdd_existingAppOpsNotForegroundNoti() { - mEntry.setRow(mRow); - mEntryManager.getNotificationData().add(mEntry); - ArraySet<Integer> ops = new ArraySet<>(); - ops.add(3); - ops.add(235); - ops.add(1); - when(mForegroundServiceController.getAppOps(mEntry.notification.getUserId(), - mEntry.notification.getPackageName())).thenReturn(ops); - when(mForegroundServiceController.getStandardLayoutKey( - mEntry.notification.getUserId(), - mEntry.notification.getPackageName())).thenReturn("something else"); - - mEntryManager.tagForeground(mEntry.notification); - Assert.assertEquals(0, mEntry.mActiveAppOps.size()); - } - - @Test public void testUpdateNotificationRanking() { when(mDeviceProvisionedController.isDeviceProvisioned()).thenReturn(true); when(mEnvironment.isDeviceProvisioned()).thenReturn(true); diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationListControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationListControllerTest.java new file mode 100644 index 000000000000..4b5037bb3f64 --- /dev/null +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationListControllerTest.java @@ -0,0 +1,241 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.statusbar.notification; + +import static junit.framework.Assert.assertEquals; +import static junit.framework.Assert.assertTrue; + +import static org.mockito.ArgumentMatchers.anyInt; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import android.app.ActivityManager; +import android.app.AppOpsManager; +import android.app.Notification; +import android.os.UserHandle; +import android.service.notification.StatusBarNotification; +import android.support.test.filters.SmallTest; +import android.testing.AndroidTestingRunner; +import android.testing.TestableLooper; +import android.util.ArraySet; + +import com.android.internal.statusbar.NotificationVisibility; +import com.android.systemui.ForegroundServiceController; +import com.android.systemui.R; +import com.android.systemui.SysuiTestCase; +import com.android.systemui.statusbar.notification.collection.NotificationData; +import com.android.systemui.statusbar.notification.collection.NotificationEntry; +import com.android.systemui.statusbar.notification.stack.NotificationListContainer; +import com.android.systemui.statusbar.policy.DeviceProvisionedController; +import com.android.systemui.statusbar.policy.DeviceProvisionedController.DeviceProvisionedListener; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.ArgumentCaptor; +import org.mockito.Captor; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; + +@SmallTest +@RunWith(AndroidTestingRunner.class) +@TestableLooper.RunWithLooper +public class NotificationListControllerTest extends SysuiTestCase { + private NotificationListController mController; + + @Mock private NotificationEntryManager mEntryManager; + @Mock private NotificationListContainer mListContainer; + @Mock private ForegroundServiceController mForegroundServiceController; + @Mock private DeviceProvisionedController mDeviceProvisionedController; + + @Captor private ArgumentCaptor<NotificationEntryListener> mEntryListenerCaptor; + @Captor private ArgumentCaptor<DeviceProvisionedListener> mProvisionedCaptor; + + private NotificationEntryListener mEntryListener; + private DeviceProvisionedListener mProvisionedListener; + + // TODO: Remove this once EntryManager no longer needs to be mocked + private NotificationData mNotificationData = new NotificationData(); + + private int mNextNotifId = 0; + + @Before + public void setUp() { + MockitoAnnotations.initMocks(this); + + when(mEntryManager.getNotificationData()).thenReturn(mNotificationData); + + mController = new NotificationListController( + mEntryManager, + mListContainer, + mForegroundServiceController, + mDeviceProvisionedController); + mController.bind(); + + // Capture callbacks passed to mocks + verify(mEntryManager).addNotificationEntryListener(mEntryListenerCaptor.capture()); + mEntryListener = mEntryListenerCaptor.getValue(); + verify(mDeviceProvisionedController).addCallback(mProvisionedCaptor.capture()); + mProvisionedListener = mProvisionedCaptor.getValue(); + } + + @Test + public void testCleanUpViewStateOnEntryRemoved() { + final NotificationEntry entry = buildEntry(); + mEntryListener.onEntryRemoved( + entry, + NotificationVisibility.obtain(entry.key, 0, 0, true), + false); + verify(mListContainer).cleanUpViewStateForEntry(entry); + } + + @Test + public void testCallUpdateNotificationsOnDeviceProvisionedChange() { + mProvisionedListener.onDeviceProvisionedChanged(); + verify(mEntryManager).updateNotifications(); + } + + @Test + public void testAppOps_appOpAddedToForegroundNotif() { + // GIVEN a notification associated with a foreground service + final NotificationEntry entry = buildEntry(); + mNotificationData.add(entry); + when(mForegroundServiceController.getStandardLayoutKey(anyInt(), anyString())) + .thenReturn(entry.key); + + // WHEN we are notified of a new app op + mController.updateNotificationsForAppOp( + AppOpsManager.OP_CAMERA, + entry.notification.getUid(), + entry.notification.getPackageName(), + true); + + // THEN the app op is added to the entry + assertTrue(entry.mActiveAppOps.contains(AppOpsManager.OP_CAMERA)); + // THEN updateNotifications() is called + verify(mEntryManager, times(1)).updateNotifications(); + } + + @Test + public void testAppOps_appOpAddedToUnrelatedNotif() { + // GIVEN No current foreground notifs + when(mForegroundServiceController.getStandardLayoutKey(anyInt(), anyString())) + .thenReturn(null); + + // WHEN An unrelated notification gets a new app op + mController.updateNotificationsForAppOp(AppOpsManager.OP_CAMERA, 1000, "pkg", true); + + // THEN We never call updateNotifications() + verify(mEntryManager, never()).updateNotifications(); + } + + @Test + public void testAppOps_addNotificationWithExistingAppOps() { + // GIVEN a notification with three associated app ops that is associated with a foreground + // service + final NotificationEntry entry = buildEntry(); + mNotificationData.add(entry); + ArraySet<Integer> expected = new ArraySet<>(); + expected.add(3); + expected.add(235); + expected.add(1); + when(mForegroundServiceController.getStandardLayoutKey( + entry.notification.getUserId(), + entry.notification.getPackageName())).thenReturn(entry.key); + when(mForegroundServiceController.getAppOps(entry.notification.getUserId(), + entry.notification.getPackageName())).thenReturn(expected); + + // WHEN the notification is added + mEntryListener.onBeforeNotificationAdded(entry); + + // THEN the entry is tagged with all three app ops + assertEquals(expected.size(), entry.mActiveAppOps.size()); + for (int op : expected) { + assertTrue("Entry missing op " + op, entry.mActiveAppOps.contains(op)); + } + } + + @Test + public void testAdd_addNotificationWithNoExistingAppOps() { + // GIVEN a notification with NO associated app ops + final NotificationEntry entry = buildEntry(); + + mNotificationData.add(entry); + when(mForegroundServiceController.getStandardLayoutKey( + entry.notification.getUserId(), + entry.notification.getPackageName())).thenReturn(entry.key); + when(mForegroundServiceController.getAppOps(entry.notification.getUserId(), + entry.notification.getPackageName())).thenReturn(null); + + // WHEN the notification is added + mEntryListener.onBeforeNotificationAdded(entry); + + // THEN the entry doesn't have any app ops associated with it + assertEquals(0, entry.mActiveAppOps.size()); + } + + @Test + public void testAdd_addNonForegroundNotificationWithExistingAppOps() { + // GIVEN a notification with app ops that isn't associated with a foreground service + final NotificationEntry entry = buildEntry(); + mNotificationData.add(entry); + ArraySet<Integer> ops = new ArraySet<>(); + ops.add(3); + ops.add(235); + ops.add(1); + when(mForegroundServiceController.getAppOps(entry.notification.getUserId(), + entry.notification.getPackageName())).thenReturn(ops); + when(mForegroundServiceController.getStandardLayoutKey( + entry.notification.getUserId(), + entry.notification.getPackageName())).thenReturn("something else"); + + // WHEN the notification is added + mEntryListener.onBeforeNotificationAdded(entry); + + // THEN the entry doesn't have any app ops associated with it + assertEquals(0, entry.mActiveAppOps.size()); + } + + private NotificationEntry buildEntry() { + mNextNotifId++; + + Notification.Builder n = new Notification.Builder(mContext, "") + .setSmallIcon(R.drawable.ic_person) + .setContentTitle("Title") + .setContentText("Text"); + + StatusBarNotification notification = + new StatusBarNotification( + TEST_PACKAGE_NAME, + TEST_PACKAGE_NAME, + mNextNotifId, + null, + TEST_UID, + 0, + n.build(), + new UserHandle(ActivityManager.getCurrentUser()), + null, + 0); + return new NotificationEntry(notification); + } + + private static final String TEST_PACKAGE_NAME = "test"; + private static final int TEST_UID = 0; +} diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationRoundnessManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationRoundnessManagerTest.java index 8ae7d52a5da5..ff30a4d6761d 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationRoundnessManagerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationRoundnessManagerTest.java @@ -29,7 +29,10 @@ import android.testing.TestableLooper; import android.testing.TestableLooper.RunWithLooper; import com.android.systemui.SysuiTestCase; +import com.android.systemui.statusbar.AmbientPulseManager; import com.android.systemui.statusbar.NotificationTestHelper; +import com.android.systemui.statusbar.notification.collection.NotificationEntry; +import com.android.systemui.statusbar.notification.row.ActivatableNotificationView; import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow; import com.android.systemui.statusbar.notification.row.ExpandableView; @@ -37,6 +40,8 @@ import org.junit.Assert; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; import java.util.HashSet; @@ -45,14 +50,18 @@ import java.util.HashSet; @RunWithLooper public class NotificationRoundnessManagerTest extends SysuiTestCase { - private NotificationRoundnessManager mRoundnessManager = new NotificationRoundnessManager(); + private NotificationRoundnessManager mRoundnessManager; private HashSet<ExpandableView> mAnimatedChildren = new HashSet<>(); private Runnable mRoundnessCallback = mock(Runnable.class); private ExpandableNotificationRow mFirst; private ExpandableNotificationRow mSecond; + @Mock + private AmbientPulseManager mAmbientPulseManager; @Before public void setUp() throws Exception { + MockitoAnnotations.initMocks(this); + mRoundnessManager = new NotificationRoundnessManager(mAmbientPulseManager); com.android.systemui.util.Assert.sMainLooper = TestableLooper.get(this).getLooper(); NotificationTestHelper testHelper = new NotificationTestHelper(getContext()); mFirst = testHelper.createRow(); @@ -127,6 +136,27 @@ public class NotificationRoundnessManagerTest extends SysuiTestCase { } @Test + public void testRoundnessPulsing() throws Exception { + // Let's create a notification that's neither the first or last item of the stack, + // this way we'll ensure that it won't have any rounded corners by default. + mRoundnessManager.updateRoundedChildren(new NotificationSection[]{ + createSection(mFirst, mSecond), + createSection(null, null) + }); + ExpandableNotificationRow row = new NotificationTestHelper(getContext()).createRow(); + NotificationEntry entry = mock(NotificationEntry.class); + when(entry.getRow()).thenReturn(row); + + mRoundnessManager.onAmbientStateChanged(entry, true); + Assert.assertEquals(1f, row.getCurrentBottomRoundness(), 0.0f); + Assert.assertEquals(1f, row.getCurrentTopRoundness(), 0.0f); + + mRoundnessManager.onAmbientStateChanged(entry, false); + Assert.assertEquals(0f, row.getCurrentBottomRoundness(), 0.0f); + Assert.assertEquals(0f, row.getCurrentTopRoundness(), 0.0f); + } + + @Test public void testRoundnessSetOnSecondSectionLast() { mRoundnessManager.updateRoundedChildren(new NotificationSection[]{ createSection(mFirst, mFirst), diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java index c140ba25859a..736f3840b91a 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java @@ -24,6 +24,7 @@ import static org.junit.Assert.assertTrue; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyBoolean; import static org.mockito.ArgumentMatchers.anyInt; +import static org.mockito.ArgumentMatchers.argThat; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.RETURNS_DEEP_STUBS; import static org.mockito.Mockito.atLeastOnce; @@ -35,17 +36,21 @@ import static org.mockito.Mockito.spy; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; +import android.metrics.LogMaker; import android.provider.Settings; import android.support.test.annotation.UiThreadTest; import android.support.test.filters.SmallTest; import android.support.test.runner.AndroidJUnit4; import android.view.View; +import com.android.internal.logging.MetricsLogger; +import com.android.internal.logging.nano.MetricsProto; import com.android.systemui.Dependency; import com.android.systemui.ExpandHelper; import com.android.systemui.InitController; import com.android.systemui.R; import com.android.systemui.SysuiTestCase; +import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin; import com.android.systemui.statusbar.EmptyShadeView; import com.android.systemui.statusbar.NotificationPresenter; import com.android.systemui.statusbar.NotificationRemoteInputManager; @@ -73,6 +78,7 @@ import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.ArgumentCaptor; +import org.mockito.ArgumentMatcher; import org.mockito.Mock; import org.mockito.junit.MockitoJUnit; import org.mockito.junit.MockitoRule; @@ -86,7 +92,8 @@ import java.util.ArrayList; @RunWith(AndroidJUnit4.class) public class NotificationStackScrollLayoutTest extends SysuiTestCase { - private NotificationStackScrollLayout mStackScroller; + private NotificationStackScrollLayout mStackScroller; // Normally test this + private NotificationStackScrollLayout mStackScrollerInternal; // See explanation below @Rule public MockitoRule mockito = MockitoJUnit.rule(); @Mock private StatusBar mBar; @@ -99,9 +106,12 @@ public class NotificationStackScrollLayoutTest extends SysuiTestCase { @Mock private NotificationData mNotificationData; @Mock private NotificationRemoteInputManager mRemoteInputManager; @Mock private RemoteInputController mRemoteInputController; + @Mock private MetricsLogger mMetricsLogger; + @Mock private NotificationRoundnessManager mNotificationRoundnessManager; private TestableNotificationEntryManager mEntryManager; private int mOriginalInterruptionModelSetting; + @Before @UiThreadTest public void setUp() throws Exception { @@ -110,6 +120,7 @@ public class NotificationStackScrollLayoutTest extends SysuiTestCase { NotificationBlockingHelperManager.class, mBlockingHelperManager); mDependency.injectTestDependency(StatusBarStateController.class, mBarState); + mDependency.injectTestDependency(MetricsLogger.class, mMetricsLogger); mDependency.injectTestDependency(NotificationRemoteInputManager.class, mRemoteInputManager); mDependency.injectMockDependency(ShadeController.class); @@ -123,8 +134,15 @@ public class NotificationStackScrollLayoutTest extends SysuiTestCase { NotificationShelf notificationShelf = mock(NotificationShelf.class); - mStackScroller = spy(new NotificationStackScrollLayout(getContext(), null, - true /* allowLongPress */)); + + // The actual class under test. You may need to work with this class directly when + // testing anonymous class members of mStackScroller, like mMenuEventListener, + // which refer to members of NotificationStackScrollLayout. The spy + // holds a copy of the CUT's instances of these classes, so they still refer to the CUT's + // member variables, not the spy's member variables. + mStackScrollerInternal = new NotificationStackScrollLayout(getContext(), null, + true /* allowLongPress */, mNotificationRoundnessManager); + mStackScroller = spy(mStackScrollerInternal); mStackScroller.setShelf(notificationShelf); mStackScroller.setStatusBar(mBar); mStackScroller.setScrimController(mock(ScrimController.class)); @@ -422,6 +440,63 @@ public class NotificationStackScrollLayoutTest extends SysuiTestCase { assertNull(swipeActionHelper.getExposedMenuView()); } + class LogMatcher implements ArgumentMatcher<LogMaker> { + private int mCategory, mType; + + LogMatcher(int category, int type) { + mCategory = category; + mType = type; + } + public boolean matches(LogMaker l) { + return (l.getCategory() == mCategory) + && (l.getType() == mType); + } + + public String toString() { + return String.format("LogMaker(%d, %d)", mCategory, mType); + } + } + + private LogMaker logMatcher(int category, int type) { + return argThat(new LogMatcher(category, type)); + } + + @Test + @UiThreadTest + public void testOnMenuClickedLogging() { + // Set up the object under test to have a valid mLongPressListener. We're testing an + // anonymous-class member, mMenuEventListener, so we need to modify the state of the + // class itself, not the Mockito spy copied from it. See notes in setup. + mStackScrollerInternal.setLongPressListener( + mock(ExpandableNotificationRow.LongPressListener.class)); + + ExpandableNotificationRow row = mock(ExpandableNotificationRow.class, RETURNS_DEEP_STUBS); + when(row.getStatusBarNotification().getLogMaker()).thenReturn(new LogMaker( + MetricsProto.MetricsEvent.VIEW_UNKNOWN)); + + mStackScroller.mMenuEventListener.onMenuClicked(row, 0, 0, mock( + NotificationMenuRowPlugin.MenuItem.class)); + verify(row.getStatusBarNotification()).getLogMaker(); // This writes most of the log data + verify(mMetricsLogger).write(logMatcher(MetricsProto.MetricsEvent.ACTION_TOUCH_GEAR, + MetricsProto.MetricsEvent.TYPE_ACTION)); + } + + @Test + @UiThreadTest + public void testOnMenuShownLogging() { + // Set up the object under test to have a valid mHeadsUpManager. See notes in setup. + mStackScrollerInternal.setHeadsUpManager(mHeadsUpManager); + + ExpandableNotificationRow row = mock(ExpandableNotificationRow.class, RETURNS_DEEP_STUBS); + when(row.getStatusBarNotification().getLogMaker()).thenReturn(new LogMaker( + MetricsProto.MetricsEvent.VIEW_UNKNOWN)); + + mStackScroller.mMenuEventListener.onMenuShown(row); + verify(row.getStatusBarNotification()).getLogMaker(); // This writes most of the log data + verify(mMetricsLogger).write(logMatcher(MetricsProto.MetricsEvent.ACTION_REVEAL_GEAR, + MetricsProto.MetricsEvent.TYPE_ACTION)); + } + private void setBarStateForTest(int state) { // Can't inject this through the listener or we end up on the actual implementation // rather than the mock because the spy just coppied the anonymous inner /shruggie. diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithmTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithmTest.java index 27ed9c5a14c8..cd52e8792cfd 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithmTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithmTest.java @@ -47,7 +47,6 @@ public class KeyguardClockPositionAlgorithmTest extends SysuiTestCase { private float mPanelExpansion; private int mKeyguardStatusHeight; private float mDark; - private boolean mPulsing; @Before public void setUp() { @@ -208,20 +207,6 @@ public class KeyguardClockPositionAlgorithmTest extends SysuiTestCase { } @Test - public void notifPositionWhilePulsingOnAOD() { - // GIVEN on AOD and pulsing - givenAOD(); - mNotificationStackHeight = EMPTY_HEIGHT; - mKeyguardStatusHeight = EMPTY_HEIGHT; - mPulsing = true; - mClockPositionAlgorithm.setPulsingPadding(200); - // WHEN the clock position algorithm is run - positionClock(); - // THEN the notif padding doesn't adjust for pulsing. - assertThat(mClockPosition.stackScrollerPadding).isEqualTo(1000); - } - - @Test public void notifPositionMiddleOfScreenOnLockScreen() { // GIVEN on lock screen and both stack scroll and clock have 0 height givenLockScreen(); @@ -307,20 +292,6 @@ public class KeyguardClockPositionAlgorithmTest extends SysuiTestCase { assertThat(mClockPosition.stackScrollerPadding).isEqualTo(0); } - @Test - public void notifPositionWhilePulsingOnLockScreen() { - // GIVEN on lock screen and pulsing - givenLockScreen(); - mNotificationStackHeight = EMPTY_HEIGHT; - mKeyguardStatusHeight = EMPTY_HEIGHT; - mPulsing = true; - mClockPositionAlgorithm.setPulsingPadding(200); - // WHEN the clock position algorithm is run - positionClock(); - // THEN the notif padding adjusts for pulsing. - assertThat(mClockPosition.stackScrollerPadding).isEqualTo(1200); - } - private void givenAOD() { mPanelExpansion = 1.f; mDark = 1.f; @@ -334,7 +305,7 @@ public class KeyguardClockPositionAlgorithmTest extends SysuiTestCase { private void positionClock() { mClockPositionAlgorithm.setup(EMPTY_MARGIN, SCREEN_HEIGHT, mNotificationStackHeight, mPanelExpansion, SCREEN_HEIGHT, mKeyguardStatusHeight, mDark, SECURE_LOCKED, - mPulsing, ZERO_DRAG); + ZERO_DRAG); mClockPositionAlgorithm.run(mClockPosition); } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ScrimControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ScrimControllerTest.java index 8eb42c4b088c..c20d37f123b1 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ScrimControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ScrimControllerTest.java @@ -45,6 +45,7 @@ import android.view.View; import com.android.internal.colorextraction.ColorExtractor.GradientColors; import com.android.internal.util.function.TriConsumer; import com.android.systemui.SysuiTestCase; +import com.android.systemui.doze.DozeLog; import com.android.systemui.statusbar.ScrimView; import com.android.systemui.util.wakelock.WakeLock; import com.android.systemui.utils.os.FakeHandler; @@ -133,7 +134,8 @@ public class ScrimControllerTest extends SysuiTestCase { // Back scrim should be transparent assertScrimVisibility(VISIBILITY_FULLY_TRANSPARENT, VISIBILITY_FULLY_TRANSPARENT); - // Move on to PULSING and check if the back scrim is still transparent + // Pulsing notification should conserve AOD wallpaper. + mScrimController.setPulseReason(DozeLog.PULSE_REASON_NOTIFICATION); mScrimController.transitionTo(ScrimState.PULSING); mScrimController.finishAnimationsImmediately(); assertScrimVisibility(VISIBILITY_FULLY_TRANSPARENT, VISIBILITY_FULLY_TRANSPARENT); @@ -218,13 +220,14 @@ public class ScrimControllerTest extends SysuiTestCase { mScrimController.finishAnimationsImmediately(); assertScrimVisibility(VISIBILITY_FULLY_TRANSPARENT, VISIBILITY_FULLY_OPAQUE); + mScrimController.setPulseReason(DozeLog.PULSE_REASON_SENSOR_WAKE_LOCK_SCREEN); mScrimController.transitionTo(ScrimState.PULSING); mScrimController.finishAnimationsImmediately(); // Front scrim should be transparent // Back scrim should be semi-transparent so the user can see the wallpaper // Pulse callback should have been invoked assertScrimVisibility(VISIBILITY_FULLY_TRANSPARENT, VISIBILITY_SEMI_TRANSPARENT); - assertScrimTint(mScrimBehind, true /* tinted */); + assertScrimTint(mScrimBehind, false /* tinted */); } @Test @@ -477,12 +480,8 @@ public class ScrimControllerTest extends SysuiTestCase { @Test public void testHoldsPulsingWallpaperAnimationLock() { // Pre-conditions - mScrimController.transitionTo(ScrimState.PULSING, new ScrimController.Callback() { - @Override - public boolean isFadeOutWallpaper() { - return true; - } - }); + mScrimController.setPulseReason(DozeLog.PULSE_REASON_NOTIFICATION); + mScrimController.transitionTo(ScrimState.PULSING); mScrimController.finishAnimationsImmediately(); reset(mWakeLock); @@ -491,7 +490,6 @@ public class ScrimControllerTest extends SysuiTestCase { verify(mWakeLock, never()).release(); mScrimController.finishAnimationsImmediately(); verify(mWakeLock).release(); - assertScrimVisibility(VISIBILITY_FULLY_TRANSPARENT, VISIBILITY_FULLY_OPAQUE); } @Test @@ -504,31 +502,27 @@ public class ScrimControllerTest extends SysuiTestCase { } @Test - public void testWillHidePulsingWallpaper_withRequestFadeOut() { - mScrimController.setWallpaperSupportsAmbientMode(true); - mScrimController.transitionTo(ScrimState.PULSING, new ScrimController.Callback() { - @Override - public boolean isFadeOutWallpaper() { - return true; - } - }); - verify(mAlarmManager).setExact(anyInt(), anyLong(), any(), any(), any()); - mScrimController.transitionTo(ScrimState.KEYGUARD); - verify(mAlarmManager).cancel(any(AlarmManager.OnAlarmListener.class)); - } - - @Test - public void testDoesNotHidePulsingWallpaper_withoutRequestFadeOut() { - mScrimController.setWallpaperSupportsAmbientMode(true); - mScrimController.transitionTo(ScrimState.PULSING, new ScrimController.Callback() {}); - verify(mAlarmManager, never()).setExact(anyInt(), anyLong(), any(), any(), any()); + public void testWillHidePulsingWallpaper_whenNotification() { + mScrimController.setWallpaperSupportsAmbientMode(false); + mScrimController.transitionTo(ScrimState.AOD); + mScrimController.finishAnimationsImmediately(); + mScrimController.setPulseReason(DozeLog.PULSE_REASON_NOTIFICATION); + mScrimController.transitionTo(ScrimState.PULSING); + mScrimController.finishAnimationsImmediately(); + assertScrimVisibility(VISIBILITY_FULLY_TRANSPARENT, VISIBILITY_FULLY_OPAQUE); + assertScrimTint(mScrimBehind, true); } @Test - public void testDoesNotHidePulsingWallpaper_withoutCallback() { - mScrimController.setWallpaperSupportsAmbientMode(true); + public void testWillHidePulsingWallpaper_whenDocking() { + mScrimController.setWallpaperSupportsAmbientMode(false); + mScrimController.transitionTo(ScrimState.AOD); + mScrimController.finishAnimationsImmediately(); + mScrimController.setPulseReason(DozeLog.PULSE_REASON_DOCKING); mScrimController.transitionTo(ScrimState.PULSING); - verify(mAlarmManager, never()).setExact(anyInt(), anyLong(), any(), any(), any()); + mScrimController.finishAnimationsImmediately(); + assertScrimVisibility(VISIBILITY_FULLY_TRANSPARENT, VISIBILITY_FULLY_OPAQUE); + assertScrimTint(mScrimBehind, true); } @Test @@ -560,34 +554,6 @@ public class ScrimControllerTest extends SysuiTestCase { Assert.assertTrue(mScrimController.wasAnimationJustCancelled()); } - /** - * Number of visible notifications affects scrim opacity. - */ - @Test - public void testNotificationDensity() { - mScrimController.transitionTo(ScrimState.KEYGUARD); - mScrimController.finishAnimationsImmediately(); - - mScrimController.setNotificationCount(0); - mScrimController.finishAnimationsImmediately(); - Assert.assertEquals("lower density when no notifications", - ScrimController.GRADIENT_SCRIM_ALPHA, mScrimBehind.getViewAlpha(), 0.01f); - - mScrimController.setNotificationCount(3); - mScrimController.finishAnimationsImmediately(); - Assert.assertEquals("stronger density when notifications are visible", - ScrimController.GRADIENT_SCRIM_ALPHA_BUSY, mScrimBehind.getViewAlpha(), 0.01f); - } - - /** - * Moving from/to states conserves old notification density. - */ - @Test - public void testConservesNotificationDensity() { - testConservesNotificationDensity(0 /* count */, ScrimController.GRADIENT_SCRIM_ALPHA); - testConservesNotificationDensity(3 /* count */, ScrimController.GRADIENT_SCRIM_ALPHA_BUSY); - } - @Test public void testScrimFocus() { mScrimController.transitionTo(ScrimState.AOD); @@ -662,24 +628,6 @@ public class ScrimControllerTest extends SysuiTestCase { mScrimBehind.getDefaultFocusHighlightEnabled()); } - /** - * Conserves old notification density after leaving state and coming back. - * - * @param count How many notification. - * @param expectedAlpha Expected alpha. - */ - private void testConservesNotificationDensity(int count, float expectedAlpha) { - mScrimController.setNotificationCount(count); - mScrimController.transitionTo(ScrimState.UNLOCKED); - mScrimController.finishAnimationsImmediately(); - - mScrimController.transitionTo(ScrimState.KEYGUARD); - mScrimController.finishAnimationsImmediately(); - - Assert.assertEquals("Doesn't respect notification busyness after transition", - expectedAlpha, mScrimBehind.getViewAlpha(), 0.01f); - } - private void assertScrimTint(ScrimView scrimView, boolean tinted) { final boolean viewIsTinted = scrimView.getTint() != Color.TRANSPARENT; final String name = scrimView == mScrimInFront ? "front" : "back"; diff --git a/proto/src/metrics_constants/metrics_constants.proto b/proto/src/metrics_constants/metrics_constants.proto index bb5d288f11e7..8261fe89f778 100644 --- a/proto/src/metrics_constants/metrics_constants.proto +++ b/proto/src/metrics_constants/metrics_constants.proto @@ -6801,7 +6801,6 @@ message MetricsEvent { // ACTION: Tap & Pay -> Default Application Setting -> Use Default // OS: Q ACTION_NFC_PAYMENT_ALWAYS_SETTING = 1623; - // ---- End Q Constants, all Q constants go above this line ---- // OPEN: Settings > System > Input & Gesture > Skip song gesture // OS: Q @@ -6811,6 +6810,16 @@ message MetricsEvent { // OS: Q SETTINGS_GESTURE_SILENCE = 1625; + // OPEN: Settings > System > Input & Gesture > Tap screen gesture + // OS: Q + SETTINGS_GESTURE_TAP_SCREEN = 1626; + + // OPEN: Settings > Network & internet > Click Mobile network to land on a page with a list of + // SIM/eSIM subscriptions. + // CATEGORY: SETTINGS + // OS: Q + MOBILE_NETWORK_LIST = 1627; + // ---- End Q Constants, all Q constants go above this line ---- // Add new aosp constants above this line. // END OF AOSP CONSTANTS diff --git a/proto/src/wifi.proto b/proto/src/wifi.proto index e9ce737eb5a5..bcc43a763599 100644 --- a/proto/src/wifi.proto +++ b/proto/src/wifi.proto @@ -485,6 +485,9 @@ message WifiLog { // Multiple lists of timestamped link layer stats with labels to represent whether wifi is usable repeated WifiUsabilityStats wifi_usability_stats_list = 126; + + // Counts the occurrences of each Wifi usability score provided by external app + repeated WifiUsabilityScoreCount wifi_usability_score_count = 127; } // Information that gets logged for every WiFi connection. @@ -670,6 +673,15 @@ message WifiScoreCount { optional int32 count = 2; } +// Counts the number of instances of a specific Wifi Usability Score +message WifiUsabilityScoreCount { + // Wifi Usability Score + optional int32 score = 1; + + // Number of Wifi score reports with this score + optional int32 count = 2; +} + // Number of occurrences of a specific link speed (Mbps) // and sum of rssi (dBm) and rssi^2 (dBm^2) message LinkSpeedCount { @@ -826,6 +838,10 @@ message StaEvent { // Wifi is turned off TYPE_WIFI_DISABLED = 19; + + // The NetworkAgent Wifi usability score has changed in a way that may + // impact connectivity + TYPE_WIFI_USABILITY_SCORE_BREACH = 20; } enum FrameworkDisconnectReason { @@ -940,6 +956,9 @@ message StaEvent { // NetworkAgent score of connected wifi optional int32 last_score = 14 [default = -1]; + + // NetworkAgent Wifi usability score of connected wifi + optional int32 last_wifi_usability_score = 15 [default = -1]; } // Wi-Fi Aware metrics @@ -1653,6 +1672,10 @@ message WifiIsUnusableEvent { // Firmware alert code. Only valid when the event was triggered by a firmware alert, otherwise -1. optional int32 firmware_alert_code = 10 [default = -1]; + + // NetworkAgent wifi usability score of connected wifi. + // Defaults to -1 if the score was never set. + optional int32 last_wifi_usability_score = 11 [default = -1]; } message PasspointProfileTypeCount { @@ -1765,6 +1788,15 @@ message WifiUsabilityStatsEntry { // The total time spent on hotspot2.0 scans and GAS exchange in ms counted from the last radio // chip reset optional int64 total_hotspot_2_scan_time_ms = 16; + + // Internal framework Wifi score + optional int32 wifi_score = 17; + + // Wifi usability score provided by external system app + optional int32 wifi_usability_score = 18; + + // Sequence number from external system app to framework + optional int32 seq_num_to_framework = 19; } message WifiUsabilityStats { diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java index 36ca52a6e600..763c16f771d0 100644 --- a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java +++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java @@ -16,6 +16,11 @@ package com.android.server.accessibility; +import static android.accessibilityservice.AccessibilityService.SHOW_MODE_AUTO; +import static android.accessibilityservice.AccessibilityService.SHOW_MODE_HARD_KEYBOARD_ORIGINAL_VALUE; +import static android.accessibilityservice.AccessibilityService.SHOW_MODE_HARD_KEYBOARD_OVERRIDDEN; +import static android.accessibilityservice.AccessibilityService.SHOW_MODE_HIDDEN; +import static android.accessibilityservice.AccessibilityService.SHOW_MODE_IGNORE_HARD_KEYBOARD; import static android.accessibilityservice.AccessibilityService.SHOW_MODE_MASK; import static android.view.WindowManager.LayoutParams.TYPE_ACCESSIBILITY_OVERLAY; import static android.view.accessibility.AccessibilityEvent.WINDOWS_CHANGE_ACCESSIBILITY_FOCUSED; @@ -23,13 +28,9 @@ import static android.view.accessibility.AccessibilityNodeInfo.ACTION_ACCESSIBIL import static android.view.accessibility.AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS; import static android.view.accessibility.AccessibilityNodeInfo.ACTION_CLICK; import static android.view.accessibility.AccessibilityNodeInfo.ACTION_LONG_CLICK; + import static com.android.internal.util.FunctionalUtils.ignoreRemoteException; import static com.android.internal.util.function.pooled.PooledLambda.obtainMessage; -import static android.accessibilityservice.AccessibilityService.SHOW_MODE_AUTO; -import static android.accessibilityservice.AccessibilityService.SHOW_MODE_HIDDEN; -import static android.accessibilityservice.AccessibilityService.SHOW_MODE_IGNORE_HARD_KEYBOARD; -import static android.accessibilityservice.AccessibilityService.SHOW_MODE_HARD_KEYBOARD_ORIGINAL_VALUE; -import static android.accessibilityservice.AccessibilityService.SHOW_MODE_HARD_KEYBOARD_OVERRIDDEN; import android.Manifest; import android.accessibilityservice.AccessibilityService; @@ -121,6 +122,8 @@ import com.android.server.SystemService; import com.android.server.wm.ActivityTaskManagerInternal; import com.android.server.wm.WindowManagerInternal; +import libcore.util.EmptyArray; + import org.xmlpull.v1.XmlPullParserException; import java.io.FileDescriptor; @@ -139,8 +142,6 @@ import java.util.Set; import java.util.function.Consumer; import java.util.function.IntSupplier; -import libcore.util.EmptyArray; - /** * This class is instantiated by the system as a system level service and can be * accessed only by the system. The task of this service is to be a centralized @@ -1827,8 +1828,6 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub updateFilterKeyEventsLocked(userState); updateTouchExplorationLocked(userState); updatePerformGesturesLocked(userState); - updateDisplayDaltonizerLocked(userState); - updateDisplayInversionLocked(userState); updateMagnificationLocked(userState); scheduleUpdateFingerprintGestureHandling(userState); scheduleUpdateInputFilter(userState); @@ -2187,14 +2186,6 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub return false; } - private void updateDisplayDaltonizerLocked(UserState userState) { - DisplayAdjustmentUtils.applyDaltonizerSetting(mContext, userState.mUserId); - } - - private void updateDisplayInversionLocked(UserState userState) { - DisplayAdjustmentUtils.applyInversionSetting(mContext, userState.mUserId); - } - private void updateMagnificationLocked(UserState userState) { if (userState.mUserId != mCurrentUserId) { return; @@ -4104,15 +4095,6 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub private final Uri mTouchExplorationGrantedAccessibilityServicesUri = Settings.Secure .getUriFor(Settings.Secure.TOUCH_EXPLORATION_GRANTED_ACCESSIBILITY_SERVICES); - private final Uri mDisplayInversionEnabledUri = Settings.Secure.getUriFor( - Settings.Secure.ACCESSIBILITY_DISPLAY_INVERSION_ENABLED); - - private final Uri mDisplayDaltonizerEnabledUri = Settings.Secure.getUriFor( - Settings.Secure.ACCESSIBILITY_DISPLAY_DALTONIZER_ENABLED); - - private final Uri mDisplayDaltonizerUri = Settings.Secure.getUriFor( - Settings.Secure.ACCESSIBILITY_DISPLAY_DALTONIZER); - private final Uri mHighTextContrastUri = Settings.Secure.getUriFor( Settings.Secure.ACCESSIBILITY_HIGH_TEXT_CONTRAST_ENABLED); @@ -4153,12 +4135,6 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub mTouchExplorationGrantedAccessibilityServicesUri, false, this, UserHandle.USER_ALL); contentResolver.registerContentObserver( - mDisplayInversionEnabledUri, false, this, UserHandle.USER_ALL); - contentResolver.registerContentObserver( - mDisplayDaltonizerEnabledUri, false, this, UserHandle.USER_ALL); - contentResolver.registerContentObserver( - mDisplayDaltonizerUri, false, this, UserHandle.USER_ALL); - contentResolver.registerContentObserver( mHighTextContrastUri, false, this, UserHandle.USER_ALL); contentResolver.registerContentObserver( mAccessibilitySoftKeyboardModeUri, false, this, UserHandle.USER_ALL); @@ -4202,11 +4178,6 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub if (readTouchExplorationGrantedAccessibilityServicesLocked(userState)) { onUserStateChangedLocked(userState); } - } else if (mDisplayDaltonizerEnabledUri.equals(uri) - || mDisplayDaltonizerUri.equals(uri)) { - updateDisplayDaltonizerLocked(userState); - } else if (mDisplayInversionEnabledUri.equals(uri)) { - updateDisplayInversionLocked(userState); } else if (mHighTextContrastUri.equals(uri)) { if (readHighTextContrastEnabledSettingLocked(userState)) { onUserStateChangedLocked(userState); diff --git a/services/accessibility/java/com/android/server/accessibility/DisplayAdjustmentUtils.java b/services/accessibility/java/com/android/server/accessibility/DisplayAdjustmentUtils.java deleted file mode 100644 index c81a876fe39e..000000000000 --- a/services/accessibility/java/com/android/server/accessibility/DisplayAdjustmentUtils.java +++ /dev/null @@ -1,102 +0,0 @@ -/* - * Copyright (C) 2013 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT 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.accessibility; - -import android.content.ContentResolver; -import android.content.Context; -import android.os.Binder; -import android.provider.Settings.Secure; -import android.view.accessibility.AccessibilityManager; - -import com.android.server.LocalServices; -import com.android.server.display.DisplayTransformManager; - -/** - * Utility methods for performing accessibility display adjustments. - */ -class DisplayAdjustmentUtils { - - /** Default inversion mode for display color correction. */ - private static final int DEFAULT_DISPLAY_DALTONIZER = - AccessibilityManager.DALTONIZER_CORRECT_DEUTERANOMALY; - - /** Matrix and offset used for converting color to gray-scale. */ - private static final float[] MATRIX_GRAYSCALE = new float[] { - .2126f, .2126f, .2126f, 0, - .7152f, .7152f, .7152f, 0, - .0722f, .0722f, .0722f, 0, - 0, 0, 0, 1 - }; - - /** - * Matrix and offset used for luminance inversion. Represents a transform - * from RGB to YIQ color space, rotation around the Y axis by 180 degrees, - * transform back to RGB color space, and subtraction from 1. The last row - * represents a non-multiplied addition, see surfaceflinger's ProgramCache - * for full implementation details. - */ - private static final float[] MATRIX_INVERT_COLOR = new float[] { - 0.402f, -0.598f, -0.599f, 0, - -1.174f, -0.174f, -1.175f, 0, - -0.228f, -0.228f, 0.772f, 0, - 1, 1, 1, 1 - }; - - public static void applyDaltonizerSetting(Context context, int userId) { - final ContentResolver cr = context.getContentResolver(); - final DisplayTransformManager dtm = LocalServices.getService(DisplayTransformManager.class); - - int daltonizerMode = AccessibilityManager.DALTONIZER_DISABLED; - long identity = Binder.clearCallingIdentity(); - try { - if (Secure.getIntForUser(cr, - Secure.ACCESSIBILITY_DISPLAY_DALTONIZER_ENABLED, 0, userId) != 0) { - daltonizerMode = Secure.getIntForUser(cr, - Secure.ACCESSIBILITY_DISPLAY_DALTONIZER, DEFAULT_DISPLAY_DALTONIZER, userId); - } - } finally { - Binder.restoreCallingIdentity(identity); - } - - float[] grayscaleMatrix = null; - if (daltonizerMode == AccessibilityManager.DALTONIZER_SIMULATE_MONOCHROMACY) { - // Monochromacy isn't supported by the native Daltonizer. - grayscaleMatrix = MATRIX_GRAYSCALE; - daltonizerMode = AccessibilityManager.DALTONIZER_DISABLED; - } - dtm.setColorMatrix(DisplayTransformManager.LEVEL_COLOR_MATRIX_GRAYSCALE, grayscaleMatrix); - dtm.setDaltonizerMode(daltonizerMode); - } - - /** - * Applies the specified user's display color adjustments. - */ - public static void applyInversionSetting(Context context, int userId) { - final ContentResolver cr = context.getContentResolver(); - final DisplayTransformManager dtm = LocalServices.getService(DisplayTransformManager.class); - - long identity = Binder.clearCallingIdentity(); - try { - final boolean invertColors = Secure.getIntForUser(cr, - Secure.ACCESSIBILITY_DISPLAY_INVERSION_ENABLED, 0, userId) != 0; - dtm.setColorMatrix(DisplayTransformManager.LEVEL_COLOR_MATRIX_INVERT_COLOR, - invertColors ? MATRIX_INVERT_COLOR : null); - } finally { - Binder.restoreCallingIdentity(identity); - } - } -} diff --git a/services/accessibility/java/com/android/server/accessibility/TouchExplorer.java b/services/accessibility/java/com/android/server/accessibility/TouchExplorer.java index cf9f233b8fe2..8ffaddefd3ef 100644 --- a/services/accessibility/java/com/android/server/accessibility/TouchExplorer.java +++ b/services/accessibility/java/com/android/server/accessibility/TouchExplorer.java @@ -462,7 +462,7 @@ class TouchExplorer extends BaseEventStreamTransformation return false; } - endGestureDetection(); + endGestureDetection(true); mAms.onGesture(gestureId); @@ -472,7 +472,7 @@ class TouchExplorer extends BaseEventStreamTransformation @Override public boolean onGestureCancelled(MotionEvent event, int policyFlags) { if (mCurrentState == STATE_GESTURE_DETECTING) { - endGestureDetection(); + endGestureDetection(event.getActionMasked() == MotionEvent.ACTION_UP); return true; } else if (mCurrentState == STATE_TOUCH_EXPLORING) { // If the finger is still moving, pass the event on. @@ -804,13 +804,19 @@ class TouchExplorer extends BaseEventStreamTransformation } } - private void endGestureDetection() { + private void endGestureDetection(boolean interactionEnd) { mAms.onTouchInteractionEnd(); // Announce the end of the gesture recognition. sendAccessibilityEvent(AccessibilityEvent.TYPE_GESTURE_DETECTION_END); - // Announce the end of a the touch interaction. - sendAccessibilityEvent(AccessibilityEvent.TYPE_TOUCH_INTERACTION_END); + if (interactionEnd) { + // Announce the end of a the touch interaction. + sendAccessibilityEvent(AccessibilityEvent.TYPE_TOUCH_INTERACTION_END); + } else { + // If gesture detection is end, but user doesn't release the finger, announce the + // transition to exploration state. + sendAccessibilityEvent(AccessibilityEvent.TYPE_TOUCH_EXPLORATION_GESTURE_START); + } mExitGestureDetectionModeDelayed.cancel(); mCurrentState = STATE_TOUCH_EXPLORING; @@ -889,7 +895,6 @@ class TouchExplorer extends BaseEventStreamTransformation MotionEvent event = mInjectedPointerTracker.getLastInjectedHoverEvent(); if (event != null && event.getActionMasked() == MotionEvent.ACTION_HOVER_EXIT) { final int pointerIdBits = event.getPointerIdBits(); - sendAccessibilityEvent(AccessibilityEvent.TYPE_TOUCH_EXPLORATION_GESTURE_START); sendMotionEvent(event, MotionEvent.ACTION_HOVER_ENTER, pointerIdBits, policyFlags); } } @@ -1148,8 +1153,8 @@ class TouchExplorer extends BaseEventStreamTransformation sendAccessibilityEvent(AccessibilityEvent.TYPE_GESTURE_DETECTION_END); // Clearing puts is in touch exploration state with a finger already // down, so announce the transition to exploration state. - sendAccessibilityEvent(AccessibilityEvent.TYPE_TOUCH_EXPLORATION_GESTURE_START); clear(); + sendAccessibilityEvent(AccessibilityEvent.TYPE_TOUCH_EXPLORATION_GESTURE_START); } } diff --git a/services/autofill/java/com/android/server/autofill/AutofillManagerService.java b/services/autofill/java/com/android/server/autofill/AutofillManagerService.java index ec6d20dd5c6a..c992da43fc07 100644 --- a/services/autofill/java/com/android/server/autofill/AutofillManagerService.java +++ b/services/autofill/java/com/android/server/autofill/AutofillManagerService.java @@ -252,9 +252,8 @@ public final class AutofillManagerService @Override // from AbstractMasterSystemService protected AutofillManagerServiceImpl newServiceLocked(@UserIdInt int resolvedUserId, boolean disabled) { - return new AutofillManagerServiceImpl(this, mLock, mRequestsHistory, - mUiLatencyHistory, mWtfHistory, resolvedUserId, mUi, mAutofillCompatState, - disabled); + return new AutofillManagerServiceImpl(this, mLock, mUiLatencyHistory, + mWtfHistory, resolvedUserId, mUi, mAutofillCompatState, disabled); } @Override // AbstractMasterSystemService @@ -291,6 +290,13 @@ public final class AutofillManagerService return mSupportedSmartSuggestionModes; } + /** + * Logs a request so it's dumped later... + */ + void logRequestLocked(@NonNull String historyItem) { + mRequestsHistory.log(historyItem); + } + // Called by AutofillManagerServiceImpl, doesn't need to check permission boolean isInstantServiceAllowed() { return mAllowInstantService; diff --git a/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java b/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java index d037b081cd4d..954b67e4e2dc 100644 --- a/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java +++ b/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java @@ -108,7 +108,6 @@ final class AutofillManagerServiceImpl private static final Random sRandom = new Random(); - private final LocalLog mRequestsHistory; private final LocalLog mUiLatencyHistory; private final LocalLog mWtfHistory; private final FieldClassificationStrategy mFieldClassificationStrategy; @@ -166,12 +165,12 @@ final class AutofillManagerServiceImpl @Nullable private RemoteAugmentedAutofillService mRemoteAugmentedAutofillService; - AutofillManagerServiceImpl(AutofillManagerService master, Object lock, LocalLog requestsHistory, + AutofillManagerServiceImpl(AutofillManagerService master, Object lock, LocalLog uiLatencyHistory, LocalLog wtfHistory, int userId, AutoFillUI ui, - AutofillCompatState autofillCompatState, boolean disabled) { + AutofillCompatState autofillCompatState, + boolean disabled) { super(master, lock, userId); - mRequestsHistory = requestsHistory; mUiLatencyHistory = uiLatencyHistory; mWtfHistory = wtfHistory; mUi = ui; @@ -310,7 +309,7 @@ final class AutofillManagerServiceImpl + " s=" + mInfo.getServiceInfo().packageName + " u=" + mUserId + " i=" + autofillId + " b=" + virtualBounds + " hc=" + hasCallback + " f=" + flags; - mRequestsHistory.log(historyItem); + mMaster.logRequestLocked(historyItem); newSession.updateLocked(autofillId, virtualBounds, value, ACTION_START_SESSION, flags); diff --git a/services/autofill/java/com/android/server/autofill/Session.java b/services/autofill/java/com/android/server/autofill/Session.java index a5ef21afc23e..7dfd8fef13c2 100644 --- a/services/autofill/java/com/android/server/autofill/Session.java +++ b/services/autofill/java/com/android/server/autofill/Session.java @@ -2610,6 +2610,13 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState + " when server returned null for session " + this.id); } + final String historyItem = + "aug:id=" + id + " u=" + uid + " m=" + mode + + " a=" + ComponentName.flattenToShortString(mComponentName) + + " f=" + mCurrentViewId + + " s=" + remoteService.getComponentName(); + mService.getMaster().logRequestLocked(historyItem); + final AutofillValue currentValue = mViewStates.get(mCurrentViewId).getCurrentValue(); // TODO(b/111330312): we might need to add a new state in the AutofillManager to optimize diff --git a/services/backup/java/com/android/server/backup/UserBackupManagerService.java b/services/backup/java/com/android/server/backup/UserBackupManagerService.java index e0e81ffb6b48..79f8a7e4e9ae 100644 --- a/services/backup/java/com/android/server/backup/UserBackupManagerService.java +++ b/services/backup/java/com/android/server/backup/UserBackupManagerService.java @@ -494,20 +494,18 @@ public class UserBackupManagerService { mUserId); mBaseStateDir = checkNotNull(baseStateDir, "baseStateDir cannot be null"); - mBaseStateDir.mkdirs(); - if (!SELinux.restoreconRecursive(mBaseStateDir)) { - Slog.w(TAG, "SELinux restorecon failed on " + mBaseStateDir); + // TODO (b/120424138): Remove once the system user is migrated to use the per-user CE + // directory. Per-user CE directories are managed by vold. + if (userId == UserHandle.USER_SYSTEM) { + mBaseStateDir.mkdirs(); + if (!SELinux.restorecon(mBaseStateDir)) { + Slog.w(TAG, "SELinux restorecon failed on " + mBaseStateDir); + } } + // TODO (b/120424138): The system user currently uses the cache which is managed by init.rc + // Initialization and restorecon is managed by vold for per-user CE directories. mDataDir = checkNotNull(dataDir, "dataDir cannot be null"); - // TODO(b/120424138): Remove when the system user moves out of the cache dir. The cache dir - // is managed by init.rc so we don't have to create it below. - if (userId != UserHandle.USER_SYSTEM) { - mDataDir.mkdirs(); - if (!SELinux.restoreconRecursive(mDataDir)) { - Slog.w(TAG, "SELinux restorecon failed on " + mDataDir); - } - } mBackupPasswordManager = new BackupPasswordManager(mContext, mBaseStateDir, mRng); // Receivers for scheduled backups and transport initialization operations. diff --git a/services/backup/java/com/android/server/backup/keyvalue/KeyValueBackupTask.java b/services/backup/java/com/android/server/backup/keyvalue/KeyValueBackupTask.java index 862ca711e694..cfc129e11c6e 100644 --- a/services/backup/java/com/android/server/backup/keyvalue/KeyValueBackupTask.java +++ b/services/backup/java/com/android/server/backup/keyvalue/KeyValueBackupTask.java @@ -45,6 +45,7 @@ import android.os.ParcelFileDescriptor; import android.os.Process; import android.os.RemoteException; import android.os.SELinux; +import android.os.UserHandle; import android.os.WorkSource; import com.android.internal.annotations.GuardedBy; @@ -686,8 +687,12 @@ public class KeyValueBackupTask implements BackupRestoreTask, Runnable { ParcelFileDescriptor.open( mNewStateFile, MODE_READ_WRITE | MODE_CREATE | MODE_TRUNCATE); - if (!SELinux.restorecon(mBackupDataFile)) { - mReporter.onRestoreconFailed(mBackupDataFile); + // TODO (b/120424138): Remove once the system user is migrated to use the per-user CE + // directory. Per-user CE directories are managed by vold. + if (mUserId == UserHandle.USER_SYSTEM) { + if (!SELinux.restorecon(mBackupDataFile)) { + mReporter.onRestoreconFailed(mBackupDataFile); + } } IBackupTransport transport = mTransportClient.connectOrThrow("KVBT.extractAgentData()"); diff --git a/services/contentcapture/java/com/android/server/contentcapture/ContentCaptureManagerService.java b/services/contentcapture/java/com/android/server/contentcapture/ContentCaptureManagerService.java index dc0f6028b0f8..e4bbcd67d4df 100644 --- a/services/contentcapture/java/com/android/server/contentcapture/ContentCaptureManagerService.java +++ b/services/contentcapture/java/com/android/server/contentcapture/ContentCaptureManagerService.java @@ -32,6 +32,7 @@ import android.os.ResultReceiver; import android.os.ShellCallback; import android.os.UserHandle; import android.os.UserManager; +import android.util.LocalLog; import android.util.Slog; import android.view.contentcapture.IContentCaptureManager; @@ -69,6 +70,8 @@ public final class ContentCaptureManagerService extends private final LocalService mLocalService = new LocalService(); + private final LocalLog mRequestsHistory = new LocalLog(20); + public ContentCaptureManagerService(@NonNull Context context) { super(context, new FrameworkResourcesServiceNameResolver(context, com.android.internal.R.string.config_defaultContentCaptureService), @@ -154,6 +157,13 @@ public final class ContentCaptureManagerService extends } } + /** + * Logs a request so it's dumped later... + */ + void logRequestLocked(@NonNull String historyItem) { + mRequestsHistory.log(historyItem); + } + private ActivityManagerInternal getAmInternal() { synchronized (mLock) { if (mAm == null) { @@ -217,9 +227,29 @@ public final class ContentCaptureManagerService extends public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { if (!DumpUtils.checkDumpPermission(getContext(), TAG, pw)) return; + boolean showHistory = true; + if (args != null) { + for (String arg : args) { + switch(arg) { + case "--no-history": + showHistory = false; + break; + case "--help": + pw.println("Usage: dumpsys content_capture [--no-history]"); + return; + default: + Slog.w(TAG, "Ignoring invalid dump arg: " + arg); + } + } + } + synchronized (mLock) { dumpLocked("", pw); } + if (showHistory) { + pw.println(); pw.println("Requests history:"); pw.println(); + mRequestsHistory.reverseDump(fd, pw, args); + } } @Override diff --git a/services/contentcapture/java/com/android/server/contentcapture/ContentCapturePerUserService.java b/services/contentcapture/java/com/android/server/contentcapture/ContentCapturePerUserService.java index 1dae2ceae7d9..8d2c79bd9923 100644 --- a/services/contentcapture/java/com/android/server/contentcapture/ContentCapturePerUserService.java +++ b/services/contentcapture/java/com/android/server/contentcapture/ContentCapturePerUserService.java @@ -85,7 +85,6 @@ final class ContentCapturePerUserService ContentCapturePerUserService(@NonNull ContentCaptureManagerService master, @NonNull Object lock, boolean disabled, @UserIdInt int userId) { super(master, lock, userId); - updateRemoteServiceLocked(disabled); } @@ -170,14 +169,24 @@ final class ContentCapturePerUserService @NonNull ComponentName componentName, int taskId, int displayId, @NonNull String sessionId, int uid, int flags, @NonNull IResultReceiver clientReceiver) { - if (!isEnabledLocked()) { + + final ComponentName serviceComponentName = getServiceComponentName(); + final boolean enabled = isEnabledLocked(); + final String historyItem = + "id=" + sessionId + " uid=" + uid + + " a=" + ComponentName.flattenToShortString(componentName) + + " t=" + taskId + " d=" + displayId + + " s=" + ComponentName.flattenToShortString(serviceComponentName) + + " u=" + mUserId + " f=" + flags + (enabled ? "" : " (disabled)"); + mMaster.logRequestLocked(historyItem); + + if (!enabled) { // TODO: it would be better to split in differet reasons, like // STATE_DISABLED_NO_SERVICE and STATE_DISABLED_BY_DEVICE_POLICY setClientState(clientReceiver, STATE_DISABLED | STATE_NO_SERVICE, /* binder= */ null); return; } - final ComponentName serviceComponentName = getServiceComponentName(); if (serviceComponentName == null) { // TODO(b/111276913): this happens when the system service is starting, we should // probably handle it in a more elegant way (like waiting for boot_complete or diff --git a/services/contentcapture/java/com/android/server/contentcapture/ContentCaptureServerSession.java b/services/contentcapture/java/com/android/server/contentcapture/ContentCaptureServerSession.java index ebe0083b398e..3c52e17ce1e8 100644 --- a/services/contentcapture/java/com/android/server/contentcapture/ContentCaptureServerSession.java +++ b/services/contentcapture/java/com/android/server/contentcapture/ContentCaptureServerSession.java @@ -83,6 +83,8 @@ final class ContentCaptureServerSession { */ @GuardedBy("mLock") public void sendActivitySnapshotLocked(@NonNull SnapshotData snapshotData) { + mService.getMaster().logRequestLocked("snapshot: id=" + mId); + mRemoteService.onActivitySnapshotRequest(mId, snapshotData); } diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java index d6f3e2ba4835..00550d9c660e 100644 --- a/services/core/java/com/android/server/ConnectivityService.java +++ b/services/core/java/com/android/server/ConnectivityService.java @@ -1494,6 +1494,9 @@ public class ConnectivityService extends IConnectivityManager.Stub newNc.setUids(null); newNc.setSSID(null); } + if (newNc.getNetworkSpecifier() != null) { + newNc.setNetworkSpecifier(newNc.getNetworkSpecifier().redact()); + } return newNc; } @@ -5358,7 +5361,8 @@ public class ConnectivityService extends IConnectivityManager.Stub } switch (notificationType) { case ConnectivityManager.CALLBACK_AVAILABLE: { - putParcelable(bundle, new NetworkCapabilities(networkAgent.networkCapabilities)); + putParcelable(bundle, networkCapabilitiesRestrictedForCallerPermissions( + networkAgent.networkCapabilities, nri.mPid, nri.mUid)); putParcelable(bundle, new LinkProperties(networkAgent.linkProperties)); // For this notification, arg1 contains the blocked status. msg.arg1 = arg1; diff --git a/services/core/java/com/android/server/LocationManagerService.java b/services/core/java/com/android/server/LocationManagerService.java index 0b4c01ef90bd..add5e5feaa8a 100644 --- a/services/core/java/com/android/server/LocationManagerService.java +++ b/services/core/java/com/android/server/LocationManagerService.java @@ -46,7 +46,6 @@ import android.content.pm.ResolveInfo; import android.content.pm.Signature; import android.content.res.Resources; import android.database.ContentObserver; -import android.hardware.location.ActivityRecognitionHardware; import android.location.Address; import android.location.Criteria; import android.location.GeocoderParams; @@ -93,7 +92,6 @@ import com.android.internal.util.ArrayUtils; import com.android.internal.util.DumpUtils; import com.android.internal.util.Preconditions; import com.android.server.location.AbstractLocationProvider; -import com.android.server.location.ActivityRecognitionProxy; import com.android.server.location.GeocoderProxy; import com.android.server.location.GeofenceManager; import com.android.server.location.GeofenceProxy; @@ -738,25 +736,6 @@ public class LocationManagerService extends ILocationManager.Stub { Slog.d(TAG, "Unable to bind FLP Geofence proxy."); } - // bind to hardware activity recognition - boolean activityRecognitionHardwareIsSupported = ActivityRecognitionHardware.isSupported(); - ActivityRecognitionHardware activityRecognitionHardware = null; - if (activityRecognitionHardwareIsSupported) { - activityRecognitionHardware = ActivityRecognitionHardware.getInstance(mContext); - } else { - Slog.d(TAG, "Hardware Activity-Recognition not supported."); - } - ActivityRecognitionProxy proxy = ActivityRecognitionProxy.createAndBind( - mContext, - activityRecognitionHardwareIsSupported, - activityRecognitionHardware, - com.android.internal.R.bool.config_enableActivityRecognitionHardwareOverlay, - com.android.internal.R.string.config_activityRecognitionHardwarePackageName, - com.android.internal.R.array.config_locationProviderPackageNames); - if (proxy == null) { - Slog.d(TAG, "Unable to bind ActivityRecognitionProxy."); - } - String[] testProviderStrings = resources.getStringArray( com.android.internal.R.array.config_testLocationProviders); for (String testProviderString : testProviderStrings) { diff --git a/services/core/java/com/android/server/StorageManagerService.java b/services/core/java/com/android/server/StorageManagerService.java index 2a806447d605..25e107642d04 100644 --- a/services/core/java/com/android/server/StorageManagerService.java +++ b/services/core/java/com/android/server/StorageManagerService.java @@ -780,6 +780,13 @@ class StorageManagerService extends IStorageManager.Stub }); refreshZramSettings(); + // Schedule zram writeback unless zram is disabled by persist.sys.zram_enabled + String zramPropValue = SystemProperties.get(ZRAM_ENABLED_PROPERTY); + if (!zramPropValue.equals("0") + && mContext.getResources().getBoolean( + com.android.internal.R.bool.config_zramWriteback)) { + ZramWriteback.scheduleZramWriteback(mContext); + } // Toggle isolated-enable system property in response to settings mContext.getContentResolver().registerContentObserver( Settings.Global.getUriFor(Settings.Global.ISOLATED_STORAGE_REMOTE), @@ -813,6 +820,12 @@ class StorageManagerService extends IStorageManager.Stub // changing the property value. There's no race: we're the // sole writer. SystemProperties.set(ZRAM_ENABLED_PROPERTY, desiredPropertyValue); + // Schedule writeback only if zram is being enabled. + if (desiredPropertyValue.equals("1") + && mContext.getResources().getBoolean( + com.android.internal.R.bool.config_zramWriteback)) { + ZramWriteback.scheduleZramWriteback(mContext); + } } } @@ -3656,6 +3669,8 @@ class StorageManagerService extends IStorageManager.Stub == PERMISSION_GRANTED || mIAppOpsService.checkOperation( OP_REQUEST_INSTALL_PACKAGES, uid, packageName) == MODE_ALLOWED) { return Zygote.MOUNT_EXTERNAL_INSTALLER; + } else if (mPmInternal.isInstantApp(packageName, UserHandle.getUserId(uid))) { + return Zygote.MOUNT_EXTERNAL_NONE; } else { return Zygote.MOUNT_EXTERNAL_WRITE; } diff --git a/services/core/java/com/android/server/TelephonyRegistry.java b/services/core/java/com/android/server/TelephonyRegistry.java index cbf6d04c9975..aa2389056c13 100644 --- a/services/core/java/com/android/server/TelephonyRegistry.java +++ b/services/core/java/com/android/server/TelephonyRegistry.java @@ -32,6 +32,8 @@ import android.os.IBinder; import android.os.Message; import android.os.RemoteException; import android.os.UserHandle; +import android.telephony.CallAttributes; +import android.telephony.CallQuality; import android.telephony.CellInfo; import android.telephony.CellLocation; import android.telephony.DataFailCause; @@ -173,6 +175,8 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { private ServiceState[] mServiceState; + private int[] mNetworkType; + private int[] mVoiceActivationState; private int[] mDataActivationState; @@ -202,6 +206,10 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { private Map<Integer, List<EmergencyNumber>> mEmergencyNumberList; + private CallQuality mCallQuality; + + private CallAttributes mCallAttributes; + private int[] mSrvccState; private int mDefaultSubId = SubscriptionManager.INVALID_SUBSCRIPTION_ID; @@ -358,6 +366,7 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { mDataConnectionNetworkType = new int[numPhones]; mCallIncomingNumber = new String[numPhones]; mServiceState = new ServiceState[numPhones]; + mNetworkType = new int[numPhones]; mVoiceActivationState = new int[numPhones]; mDataActivationState = new int[numPhones]; mUserMobileDataState = new boolean[numPhones]; @@ -377,6 +386,7 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { mDataActivationState[i] = TelephonyManager.SIM_ACTIVATION_STATE_UNKNOWN; mCallIncomingNumber[i] = ""; mServiceState[i] = new ServiceState(); + mNetworkType[i] = mServiceState[i].getVoiceNetworkType(); mSignalStrength[i] = new SignalStrength(); mUserMobileDataState[i] = false; mMessageWaiting[i] = false; @@ -807,6 +817,13 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { remove(r.binder); } } + if ((events & PhoneStateListener.LISTEN_CALL_ATTRIBUTES_CHANGED) != 0) { + try { + r.callback.onCallAttributesChanged(mCallAttributes); + } catch (RemoteException ex) { + remove(r.binder); + } + } } } } else { @@ -957,6 +974,21 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { if (validatePhoneId(phoneId)) { mServiceState[phoneId] = state; + boolean notifyCallAttributes = true; + if (mNetworkType[phoneId] != mServiceState[phoneId].getVoiceNetworkType()) { + mNetworkType[phoneId] = state.getVoiceNetworkType(); + mCallAttributes = new CallAttributes(mPreciseCallState, mNetworkType[phoneId], + mCallQuality); + } else { + // No change to network type, so no need to notify call attributes + notifyCallAttributes = false; + } + + if (mCallQuality == null) { + // No call quality reported yet, so no need to notify call attributes + notifyCallAttributes = false; + } + for (Record r : mRecords) { if (VDBG) { log("notifyServiceStateForSubscriber: r=" + r + " subId=" + subId @@ -975,6 +1007,14 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { mRemoveList.add(r.binder); } } + if (notifyCallAttributes && r.matchPhoneStateListenerEvent( + PhoneStateListener.LISTEN_CALL_ATTRIBUTES_CHANGED)) { + try { + r.callback.onCallAttributesChanged(mCallAttributes); + } catch (RemoteException ex) { + mRemoveList.add(r.binder); + } + } } } else { log("notifyServiceStateForSubscriber: INVALID phoneId=" + phoneId); @@ -1484,7 +1524,7 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { } public void notifyPreciseCallState(int ringingCallState, int foregroundCallState, - int backgroundCallState) { + int backgroundCallState, int phoneId) { if (!checkNotifyPermission("notifyPreciseCallState()")) { return; } @@ -1496,6 +1536,15 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { backgroundCallState, DisconnectCause.NOT_VALID, PreciseDisconnectCause.NOT_VALID); + boolean notifyCallAttributes = true; + if (mCallQuality == null) { + log("notifyPreciseCallState: mCallQuality is null, skipping call attributes"); + notifyCallAttributes = false; + } else { + mCallAttributes = new CallAttributes(mPreciseCallState, mNetworkType[phoneId], + mCallQuality); + } + for (Record r : mRecords) { if (r.matchPhoneStateListenerEvent(PhoneStateListener.LISTEN_PRECISE_CALL_STATE)) { try { @@ -1504,6 +1553,14 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { mRemoveList.add(r.binder); } } + if (notifyCallAttributes && r.matchPhoneStateListenerEvent( + PhoneStateListener.LISTEN_CALL_ATTRIBUTES_CHANGED)) { + try { + r.callback.onCallAttributesChanged(mCallAttributes); + } catch (RemoteException ex) { + mRemoveList.add(r.binder); + } + } } handleRemoveListLocked(); } @@ -1721,6 +1778,36 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { } } + @Override + public void notifyCallQualityChanged(CallQuality callQuality, int phoneId) { + if (!checkNotifyPermission("notifyCallQualityChanged()")) { + return; + } + + // merge CallQuality with PreciseCallState and network type + mCallQuality = callQuality; + mCallAttributes = new CallAttributes(mPreciseCallState, + mNetworkType[phoneId], + callQuality); + + synchronized (mRecords) { + TelephonyManager tm = (TelephonyManager) mContext.getSystemService( + Context.TELEPHONY_SERVICE); + + for (Record r : mRecords) { + if (r.matchPhoneStateListenerEvent( + PhoneStateListener.LISTEN_CALL_ATTRIBUTES_CHANGED)) { + try { + r.callback.onCallAttributesChanged(mCallAttributes); + } catch (RemoteException ex) { + mRemoveList.add(r.binder); + } + } + } + handleRemoveListLocked(); + } + } + @Override public void dump(FileDescriptor fd, PrintWriter writer, String[] args) { @@ -1738,6 +1825,7 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { pw.println("mCallState=" + mCallState[i]); pw.println("mCallIncomingNumber=" + mCallIncomingNumber[i]); pw.println("mServiceState=" + mServiceState[i]); + pw.println("mNetworkType=" + mNetworkType[i]); pw.println("mVoiceActivationState= " + mVoiceActivationState[i]); pw.println("mDataActivationState= " + mDataActivationState[i]); pw.println("mUserMobileDataState= " + mUserMobileDataState[i]); @@ -1763,6 +1851,8 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { pw.println("mPreferredDataSubId=" + mPreferredDataSubId); pw.println("mRadioPowerState=" + mRadioPowerState); pw.println("mEmergencyNumberList=" + mEmergencyNumberList); + pw.println("mCallQuality=" + mCallQuality); + pw.println("mCallAttributes=" + mCallAttributes); pw.decreaseIndent(); @@ -2020,6 +2110,11 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { android.Manifest.permission.READ_PRECISE_PHONE_STATE, null); } + if ((events & PhoneStateListener.LISTEN_CALL_ATTRIBUTES_CHANGED) != 0) { + mContext.enforceCallingOrSelfPermission( + android.Manifest.permission.READ_PRECISE_PHONE_STATE, null); + } + return true; } diff --git a/services/core/java/com/android/server/ZramWriteback.java b/services/core/java/com/android/server/ZramWriteback.java new file mode 100644 index 000000000000..3a4aff2ea9aa --- /dev/null +++ b/services/core/java/com/android/server/ZramWriteback.java @@ -0,0 +1,187 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.server; + +import android.app.job.JobInfo; +import android.app.job.JobParameters; +import android.app.job.JobScheduler; +import android.app.job.JobService; +import android.content.ComponentName; +import android.content.Context; +import android.os.FileUtils; +import android.os.SystemProperties; +import android.util.Slog; + +import java.io.File; +import java.io.IOException; +import java.util.concurrent.TimeUnit; + +/** + * Schedules jobs for triggering zram writeback. + */ +public final class ZramWriteback extends JobService { + private static final String TAG = "ZramWriteback"; + private static final boolean DEBUG = false; + + private static final ComponentName sZramWriteback = + new ComponentName("android", ZramWriteback.class.getName()); + + private static final int MARK_IDLE_JOB_ID = 811; + private static final int WRITEBACK_IDLE_JOB_ID = 812; + + private static final int MAX_ZRAM_DEVICES = 256; + private static int sZramDeviceId = 0; + + private static final String IDLE_SYS = "/sys/block/zram%d/idle"; + private static final String IDLE_SYS_ALL_PAGES = "all"; + + private static final String WB_SYS = "/sys/block/zram%d/writeback"; + private static final String WB_SYS_IDLE_PAGES = "idle"; + + private static final String WB_STATS_SYS = "/sys/block/zram%d/bd_stat"; + private static final int WB_STATS_MAX_FILE_SIZE = 128; + + private static final String BDEV_SYS = "/sys/block/zram%d/backing_dev"; + + private static final String MARK_IDLE_DELAY_PROP = "ro.zram.mark_idle_delay_mins"; + private static final String FIRST_WB_DELAY_PROP = "ro.zram.first_wb_delay_mins"; + private static final String PERIODIC_WB_DELAY_PROP = "ro.zram.periodic_wb_delay_hours"; + + private void markPagesAsIdle() { + String idlePath = String.format(IDLE_SYS, sZramDeviceId); + try { + FileUtils.stringToFile(new File(idlePath), IDLE_SYS_ALL_PAGES); + } catch (IOException e) { + Slog.e(TAG, "Failed to write to " + idlePath); + } + } + + private void flushIdlePages() { + if (DEBUG) Slog.d(TAG, "Start writing back idle pages to disk"); + String wbPath = String.format(WB_SYS, sZramDeviceId); + try { + FileUtils.stringToFile(new File(wbPath), WB_SYS_IDLE_PAGES); + } catch (IOException e) { + Slog.e(TAG, "Failed to write to " + wbPath); + } + if (DEBUG) Slog.d(TAG, "Finished writeback back idle pages"); + } + + private int getWrittenPageCount() { + String wbStatsPath = String.format(WB_STATS_SYS, sZramDeviceId); + try { + String wbStats = FileUtils + .readTextFile(new File(wbStatsPath), WB_STATS_MAX_FILE_SIZE, ""); + return Integer.parseInt(wbStats.trim().split("\\s+")[2], 10); + } catch (IOException e) { + Slog.e(TAG, "Failed to read writeback stats from " + wbStatsPath); + } + + return -1; + } + + private void markAndFlushPages() { + int pageCount = getWrittenPageCount(); + + flushIdlePages(); + markPagesAsIdle(); + + if (pageCount != -1) { + Slog.i(TAG, "Total pages written to disk is " + (getWrittenPageCount() - pageCount)); + } + } + + private static boolean isWritebackEnabled() { + try { + String backingDev = FileUtils + .readTextFile(new File(String.format(BDEV_SYS, sZramDeviceId)), 128, ""); + if (!"none".equals(backingDev.trim())) { + return true; + } else { + Slog.w(TAG, "Writeback device is not set"); + } + } catch (IOException e) { + Slog.w(TAG, "Writeback is not enabled on zram"); + } + return false; + } + + private static void schedNextWriteback(Context context) { + int nextWbDelay = SystemProperties.getInt(PERIODIC_WB_DELAY_PROP, 24); + JobScheduler js = (JobScheduler) context.getSystemService(Context.JOB_SCHEDULER_SERVICE); + + js.schedule(new JobInfo.Builder(WRITEBACK_IDLE_JOB_ID, sZramWriteback) + .setMinimumLatency(TimeUnit.HOURS.toMillis(nextWbDelay)) + .setRequiresDeviceIdle(true) + .build()); + } + + @Override + public boolean onStartJob(JobParameters params) { + + if (!isWritebackEnabled()) { + jobFinished(params, false); + return false; + } + + if (params.getJobId() == MARK_IDLE_JOB_ID) { + markPagesAsIdle(); + jobFinished(params, false); + return false; + } else { + new Thread("ZramWriteback_WritebackIdlePages") { + @Override + public void run() { + markAndFlushPages(); + schedNextWriteback(ZramWriteback.this); + jobFinished(params, false); + } + }.start(); + } + return true; + } + + @Override + public boolean onStopJob(JobParameters params) { + // The thread that triggers the writeback is non-interruptible + return false; + } + + /** + * Schedule the zram writeback job to trigger a writeback when idle + */ + public static void scheduleZramWriteback(Context context) { + int markIdleDelay = SystemProperties.getInt(MARK_IDLE_DELAY_PROP, 20); + int firstWbDelay = SystemProperties.getInt(FIRST_WB_DELAY_PROP, 180); + + JobScheduler js = (JobScheduler) context.getSystemService(Context.JOB_SCHEDULER_SERVICE); + + // Schedule a one time job to mark pages as idle. These pages will be written + // back at later point if they remain untouched. + js.schedule(new JobInfo.Builder(MARK_IDLE_JOB_ID, sZramWriteback) + .setMinimumLatency(TimeUnit.MINUTES.toMillis(markIdleDelay)) + .build()); + + // Schedule a one time job to flush idle pages to disk. + // After the initial writeback, subsequent writebacks are done at interval set + // by ro.zram.periodic_wb_delay_hours. + js.schedule(new JobInfo.Builder(WRITEBACK_IDLE_JOB_ID, sZramWriteback) + .setMinimumLatency(TimeUnit.MINUTES.toMillis(firstWbDelay)) + .setRequiresDeviceIdle(true) + .build()); + } +} diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java index 43deb1176fe6..089847d1ff7f 100644 --- a/services/core/java/com/android/server/am/ActivityManagerService.java +++ b/services/core/java/com/android/server/am/ActivityManagerService.java @@ -17867,6 +17867,15 @@ public class ActivityManagerService extends IActivityManager.Stub public void clearPendingBackup(int userId) { ActivityManagerService.this.clearPendingBackup(userId); } + + /** + * When power button is very long pressed, call this interface to do some pre-shutdown work + * like persisting database etc. + */ + @Override + public void prepareForPossibleShutdown() { + ActivityManagerService.this.prepareForPossibleShutdown(); + } } long inputDispatchingTimedOut(int pid, final boolean aboveSystem, String reason) { @@ -18123,6 +18132,18 @@ public class ActivityManagerService extends IActivityManager.Stub } } + /** + * When power button is very long pressed, call this interface to do some pre-shutdown work + * like persisting database etc. + */ + public void prepareForPossibleShutdown() { + synchronized (this) { + if (mUsageStatsService != null) { + mUsageStatsService.prepareForPossibleShutdown(); + } + } + } + @VisibleForTesting public static class Injector { private NetworkManagementInternal mNmi; diff --git a/services/core/java/com/android/server/am/CoreSettingsObserver.java b/services/core/java/com/android/server/am/CoreSettingsObserver.java index d7cb2bd36bde..d3953b58296c 100644 --- a/services/core/java/com/android/server/am/CoreSettingsObserver.java +++ b/services/core/java/com/android/server/am/CoreSettingsObserver.java @@ -67,9 +67,10 @@ final class CoreSettingsObserver extends ContentObserver { sGlobalSettingToTypeMap.put(Settings.Global.GPU_DEBUG_LAYERS_GLES, String.class); sGlobalSettingToTypeMap.put(Settings.Global.GPU_DEBUG_LAYER_APP, String.class); sGlobalSettingToTypeMap.put(Settings.Global.SMS_ACCESS_RESTRICTION_ENABLED, int.class); + sGlobalSettingToTypeMap.put(Settings.Global.GUP_DEV_ALL_APPS, int.class); sGlobalSettingToTypeMap.put(Settings.Global.GUP_DEV_OPT_IN_APPS, String.class); sGlobalSettingToTypeMap.put(Settings.Global.GUP_DEV_OPT_OUT_APPS, String.class); - sGlobalSettingToTypeMap.put(Settings.Global.GUP_BLACK_LIST, String.class); + sGlobalSettingToTypeMap.put(Settings.Global.GUP_BLACKLIST, String.class); // add other global settings here... } diff --git a/services/core/java/com/android/server/am/OomAdjuster.java b/services/core/java/com/android/server/am/OomAdjuster.java index 1f9362e246b7..dc033691eea5 100644 --- a/services/core/java/com/android/server/am/OomAdjuster.java +++ b/services/core/java/com/android/server/am/OomAdjuster.java @@ -132,8 +132,11 @@ public final class OomAdjuster { mActiveUids = activeUids; mLocalPowerManager = LocalServices.getService(PowerManagerInternal.class); - mAppCompact = new AppCompactor(mService); mConstants = mService.mConstants; + // mConstants can be null under test, which causes AppCompactor to crash + if (mConstants != null) { + mAppCompact = new AppCompactor(mService); + } } /** diff --git a/services/core/java/com/android/server/am/PendingIntentRecord.java b/services/core/java/com/android/server/am/PendingIntentRecord.java index 98c9ad66bc5c..55cca950a213 100644 --- a/services/core/java/com/android/server/am/PendingIntentRecord.java +++ b/services/core/java/com/android/server/am/PendingIntentRecord.java @@ -389,8 +389,9 @@ public final class PendingIntentRecord extends IIntentSender.Stub { if (key.allIntents != null && key.allIntents.length > 1) { res = controller.mAtmInternal.startActivitiesInPackage( - uid, key.packageName, allIntents, allResolvedTypes, resultTo, - mergedOptions, userId, false /* validateIncomingUser */, + uid, callingPid, callingUid, key.packageName, allIntents, + allResolvedTypes, resultTo, mergedOptions, userId, + false /* validateIncomingUser */, this /* originatingPendingIntent */, mAllowBgActivityStartsForActivitySender.contains(whitelistToken)); } else { diff --git a/services/core/java/com/android/server/am/ProcessList.java b/services/core/java/com/android/server/am/ProcessList.java index 5bc88450c376..c1be3872e031 100644 --- a/services/core/java/com/android/server/am/ProcessList.java +++ b/services/core/java/com/android/server/am/ProcessList.java @@ -1678,12 +1678,14 @@ public final class ProcessList { AppZygote appZygote = mAppZygotes.get(app.info.processName, app.info.uid); final ArrayList<ProcessRecord> zygoteProcessList; if (appZygote == null) { - final int userId = UserHandle.getUserId(app.info.uid); final IsolatedUidRange uidRange = mAppIsolatedUidRangeAllocator.getIsolatedUidRangeLocked(app.info); - // Allocate an isolated UID out of this range for the Zygote itself - final int zygoteIsolatedUid = uidRange.allocateIsolatedUidLocked(userId); - appZygote = new AppZygote(app.info, zygoteIsolatedUid); + final int userId = UserHandle.getUserId(app.info.uid); + // Create the app-zygote and provide it with the UID-range it's allowed + // to setresuid/setresgid to. + final int firstUid = UserHandle.getUid(userId, uidRange.mFirstUid); + final int lastUid = UserHandle.getUid(userId, uidRange.mLastUid); + appZygote = new AppZygote(app.info, app.info.uid, firstUid, lastUid); mAppZygotes.put(app.info.processName, app.info.uid, appZygote); zygoteProcessList = new ArrayList<ProcessRecord>(); mAppZygoteProcesses.put(appZygote, zygoteProcessList); diff --git a/services/core/java/com/android/server/attention/AttentionManagerService.java b/services/core/java/com/android/server/attention/AttentionManagerService.java new file mode 100644 index 000000000000..f60d6b06f451 --- /dev/null +++ b/services/core/java/com/android/server/attention/AttentionManagerService.java @@ -0,0 +1,548 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.server.attention; + +import android.Manifest; +import android.annotation.Nullable; +import android.annotation.UserIdInt; +import android.app.ActivityManager; +import android.attention.AttentionManagerInternal; +import android.attention.AttentionManagerInternal.AttentionCallbackInternal; +import android.content.BroadcastReceiver; +import android.content.ComponentName; +import android.content.Context; +import android.content.Intent; +import android.content.IntentFilter; +import android.content.ServiceConnection; +import android.content.pm.PackageManager; +import android.content.pm.ResolveInfo; +import android.content.pm.ServiceInfo; +import android.os.Binder; +import android.os.Handler; +import android.os.IBinder; +import android.os.Looper; +import android.os.Message; +import android.os.PowerManager; +import android.os.RemoteException; +import android.os.SystemClock; +import android.os.UserHandle; +import android.service.attention.AttentionService; +import android.service.attention.AttentionService.AttentionFailureCodes; +import android.service.attention.IAttentionCallback; +import android.service.attention.IAttentionService; +import android.text.TextUtils; +import android.util.Slog; +import android.util.SparseArray; + +import com.android.internal.R; +import com.android.internal.annotations.GuardedBy; +import com.android.internal.util.DumpUtils; +import com.android.internal.util.IndentingPrintWriter; +import com.android.internal.util.Preconditions; +import com.android.server.SystemService; + +import java.io.PrintWriter; + +/** + * An attention service implementation that runs in System Server process. + * This service publishes a LocalService and reroutes calls to a {@link AttentionService} that it + * manages. + */ +public class AttentionManagerService extends SystemService { + private static final String LOG_TAG = "AttentionManagerService"; + + /** Service will unbind if connection is not used for that amount of time. */ + private static final long CONNECTION_TTL_MILLIS = 60_000; + + /** If the check attention called within that period - cached value will be returned. */ + private static final long STALE_AFTER_MILLIS = 5_000; + + private final Context mContext; + private final PowerManager mPowerManager; + private final ActivityManager mActivityManager; + private final Object mLock; + @GuardedBy("mLock") + private final SparseArray<UserState> mUserStates = new SparseArray<>(); + private final AttentionHandler mAttentionHandler; + + private ComponentName mComponentName; + + public AttentionManagerService(Context context) { + super(context); + mContext = Preconditions.checkNotNull(context); + mPowerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE); + mActivityManager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE); + mLock = new Object(); + mAttentionHandler = new AttentionHandler(); + } + + @Override + public void onStart() { + publishLocalService(AttentionManagerInternal.class, new LocalService()); + } + + @Override + public void onStopUser(int userId) { + cancelAndUnbindLocked(peekUserStateLocked(userId), + AttentionService.ATTENTION_FAILURE_UNKNOWN); + } + + @Override + public void onBootPhase(int phase) { + super.onBootPhase(phase); + if (phase == SystemService.PHASE_THIRD_PARTY_APPS_CAN_START) { + mComponentName = resolveAttentionService(mContext); + if (mComponentName != null) { + // If the service is supported we want to keep receiving the screen off events. + mContext.registerReceiver(new ScreenStateReceiver(), + new IntentFilter(Intent.ACTION_SCREEN_OFF)); + } + } + } + + /** + * Returns {@code true} if attention service is supported on this device. + */ + public boolean isAttentionServiceSupported() { + return mComponentName != null; + } + + /** + * Checks whether user attention is at the screen and calls in the provided callback. + * + * @return {@code true} if the framework was able to send the provided callback to the service + */ + public boolean checkAttention(int requestCode, long timeout, + AttentionCallbackInternal callback) { + Preconditions.checkNotNull(callback); + + if (!isAttentionServiceSupported()) { + Slog.w(LOG_TAG, "Trying to call checkAttention() on an unsupported device."); + return false; + } + + // don't allow attention check in screen off state + if (!mPowerManager.isInteractive()) { + return false; + } + + synchronized (mLock) { + unbindAfterTimeoutLocked(); + + final UserState userState = getOrCreateCurrentUserStateLocked(); + // lazily start the service, which should be very lightweight to start + if (!userState.bindLocked()) { + return false; + } + + if (userState.mService == null) { + // make sure every callback is called back + if (userState.mPendingAttentionCheck != null) { + userState.mPendingAttentionCheck.cancel( + AttentionService.ATTENTION_FAILURE_UNKNOWN); + } + userState.mPendingAttentionCheck = new PendingAttentionCheck(requestCode, + callback, () -> checkAttention(requestCode, timeout, callback)); + } else { + try { + // throttle frequent requests + final AttentionCheckCache attentionCheckCache = userState.mAttentionCheckCache; + if (attentionCheckCache != null && SystemClock.uptimeMillis() + < attentionCheckCache.mLastComputed + STALE_AFTER_MILLIS) { + callback.onSuccess(requestCode, attentionCheckCache.mResult, + attentionCheckCache.mTimestamp); + return true; + } + + cancelAfterTimeoutLocked(timeout); + + userState.mCurrentAttentionCheckRequestCode = requestCode; + userState.mService.checkAttention(requestCode, new IAttentionCallback.Stub() { + @Override + public void onSuccess(int requestCode, int result, long timestamp) { + callback.onSuccess(requestCode, result, timestamp); + userState.mAttentionCheckCache = new AttentionCheckCache( + SystemClock.uptimeMillis(), result, + timestamp); + } + + @Override + public void onFailure(int requestCode, int error) { + callback.onFailure(requestCode, error); + } + + @Override + public IBinder asBinder() { + return null; + } + }); + } catch (RemoteException e) { + Slog.e(LOG_TAG, "Cannot call into the AttentionService"); + return false; + } + } + return true; + } + } + + /** Cancels the specified attention check. */ + public void cancelAttentionCheck(int requestCode) { + final UserState userState = getOrCreateCurrentUserStateLocked(); + try { + userState.mService.cancelAttentionCheck(requestCode); + } catch (RemoteException e) { + Slog.e(LOG_TAG, "Cannot call into the AttentionService"); + } + } + + @GuardedBy("mLock") + private void unbindAfterTimeoutLocked() { + mAttentionHandler.sendEmptyMessageDelayed(AttentionHandler.CONNECTION_EXPIRED, + CONNECTION_TTL_MILLIS); + } + + @GuardedBy("mLock") + private void cancelAfterTimeoutLocked(long timeout) { + mAttentionHandler.sendEmptyMessageDelayed(AttentionHandler.ATTENTION_CHECK_TIMEOUT, + timeout); + } + + + @GuardedBy("mLock") + private UserState getOrCreateCurrentUserStateLocked() { + return getOrCreateUserStateLocked(mActivityManager.getCurrentUser()); + } + + @GuardedBy("mLock") + private UserState getOrCreateUserStateLocked(int userId) { + UserState result = mUserStates.get(userId); + if (result == null) { + result = new UserState(userId, mContext, mLock); + mUserStates.put(userId, result); + } + return result; + } + + @GuardedBy("mLock") + UserState peekCurrentUserStateLocked() { + return peekUserStateLocked(mActivityManager.getCurrentUser()); + } + + @GuardedBy("mLock") + UserState peekUserStateLocked(int userId) { + return mUserStates.get(userId); + } + + /** + * Provides attention service component name at runtime, making sure it's provided by the + * system. + */ + private static ComponentName resolveAttentionService(Context context) { + // TODO(b/111939367): add a flag to turn on/off. + final String componentNameString = context.getString( + R.string.config_defaultAttentionService); + + if (TextUtils.isEmpty(componentNameString)) { + return null; + } + + final ComponentName componentName = ComponentName.unflattenFromString(componentNameString); + if (componentName == null) { + return null; + } + + final Intent intent = new Intent(AttentionService.SERVICE_INTERFACE).setPackage( + componentName.getPackageName()); + + // Make sure that only system apps can declare the AttentionService. + final ResolveInfo resolveInfo = context.getPackageManager().resolveService(intent, + PackageManager.MATCH_SYSTEM_ONLY); + if (resolveInfo == null || resolveInfo.serviceInfo == null) { + Slog.wtf(LOG_TAG, String.format("Service %s not found in package %s", + AttentionService.SERVICE_INTERFACE, componentName + )); + return null; + } + + final ServiceInfo serviceInfo = resolveInfo.serviceInfo; + final String permission = serviceInfo.permission; + if (Manifest.permission.BIND_ATTENTION_SERVICE.equals(permission)) { + return serviceInfo.getComponentName(); + } + Slog.e(LOG_TAG, String.format( + "Service %s should require %s permission. Found %s permission", + serviceInfo.getComponentName(), + Manifest.permission.BIND_ATTENTION_SERVICE, + serviceInfo.permission)); + return null; + } + + private void dumpInternal(PrintWriter pw) { + if (!DumpUtils.checkDumpPermission(mContext, LOG_TAG, pw)) return; + IndentingPrintWriter ipw = new IndentingPrintWriter(pw, " "); + ipw.println("Attention Manager Service (dumpsys attention)\n"); + + ipw.printPair("context", mContext); + pw.println(); + synchronized (mLock) { + int size = mUserStates.size(); + ipw.print("Number user states: "); + pw.println(size); + if (size > 0) { + ipw.increaseIndent(); + for (int i = 0; i < size; i++) { + UserState userState = mUserStates.valueAt(i); + ipw.print(i); + ipw.print(":"); + userState.dump(ipw); + ipw.println(); + } + ipw.decreaseIndent(); + } + } + } + + private final class LocalService extends AttentionManagerInternal { + @Override + public boolean isAttentionServiceSupported() { + return AttentionManagerService.this.isAttentionServiceSupported(); + } + + @Override + public boolean checkAttention(int requestCode, long timeout, + AttentionCallbackInternal callback) { + return AttentionManagerService.this.checkAttention(requestCode, timeout, callback); + } + + @Override + public void cancelAttentionCheck(int requestCode) { + AttentionManagerService.this.cancelAttentionCheck(requestCode); + } + } + + private static final class AttentionCheckCache { + private final long mLastComputed; + private final int mResult; + private final long mTimestamp; + + AttentionCheckCache(long lastComputed, @AttentionService.AttentionSuccessCodes int result, + long timestamp) { + mLastComputed = lastComputed; + mResult = result; + mTimestamp = timestamp; + } + } + + private static final class PendingAttentionCheck { + private final int mRequestCode; + private final AttentionCallbackInternal mCallback; + private final Runnable mRunnable; + + PendingAttentionCheck(int requestCode, AttentionCallbackInternal callback, + Runnable runnable) { + mRequestCode = requestCode; + mCallback = callback; + mRunnable = runnable; + } + + void cancel(@AttentionFailureCodes int failureCode) { + mCallback.onFailure(mRequestCode, failureCode); + } + + void run() { + mRunnable.run(); + } + } + + private static final class UserState { + final AttentionServiceConnection mConnection = new AttentionServiceConnection(); + + @GuardedBy("mLock") + IAttentionService mService; + @GuardedBy("mLock") + boolean mBinding; + @GuardedBy("mLock") + int mCurrentAttentionCheckRequestCode; + @GuardedBy("mLock") + PendingAttentionCheck mPendingAttentionCheck; + + @GuardedBy("mLock") + AttentionCheckCache mAttentionCheckCache; + + @UserIdInt + final int mUserId; + final Context mContext; + final Object mLock; + + private UserState(int userId, Context context, Object lock) { + mUserId = userId; + mContext = Preconditions.checkNotNull(context); + mLock = Preconditions.checkNotNull(lock); + } + + + @GuardedBy("mLock") + private void handlePendingCallbackLocked() { + if (mService != null && mPendingAttentionCheck != null) { + mPendingAttentionCheck.run(); + mPendingAttentionCheck = null; + } + } + + /** Binds to the system's AttentionService which provides an actual implementation. */ + @GuardedBy("mLock") + private boolean bindLocked() { + // No need to bind if service is binding or has already been bound. + if (mBinding || mService != null) { + return true; + } + + final boolean willBind; + final long identity = Binder.clearCallingIdentity(); + + try { + final ComponentName componentName = + resolveAttentionService(mContext); + if (componentName == null) { + // Might happen if the storage is encrypted and the user is not unlocked + return false; + } + final Intent mServiceIntent = new Intent( + AttentionService.SERVICE_INTERFACE).setComponent( + componentName); + willBind = mContext.bindServiceAsUser(mServiceIntent, mConnection, + Context.BIND_AUTO_CREATE, UserHandle.CURRENT); + mBinding = willBind; + } finally { + Binder.restoreCallingIdentity(identity); + } + return willBind; + } + + private void dump(IndentingPrintWriter pw) { + pw.printPair("context", mContext); + pw.printPair("userId", mUserId); + synchronized (mLock) { + pw.printPair("binding", mBinding); + pw.printPair("isAttentionCheckPending", mPendingAttentionCheck != null); + } + } + + private final class AttentionServiceConnection implements ServiceConnection { + @Override + public void onServiceConnected(ComponentName name, IBinder service) { + init(IAttentionService.Stub.asInterface(service)); + } + + @Override + public void onServiceDisconnected(ComponentName name) { + cleanupService(); + } + + @Override + public void onBindingDied(ComponentName name) { + cleanupService(); + } + + @Override + public void onNullBinding(ComponentName name) { + cleanupService(); + } + + void cleanupService() { + init(null); + } + + private void init(@Nullable IAttentionService service) { + synchronized (mLock) { + mService = service; + mBinding = false; + handlePendingCallbackLocked(); + } + } + } + } + + private class AttentionHandler extends Handler { + private static final int CONNECTION_EXPIRED = 1; + private static final int ATTENTION_CHECK_TIMEOUT = 2; + + AttentionHandler() { + super(Looper.myLooper()); + } + + public void handleMessage(Message msg) { + switch (msg.what) { + // Do not occupy resources when not in use - unbind proactively. + case CONNECTION_EXPIRED: { + for (int i = 0; i < mUserStates.size(); i++) { + cancelAndUnbindLocked(mUserStates.valueAt(i), + AttentionService.ATTENTION_FAILURE_UNKNOWN); + } + + } + break; + + // Callee is no longer interested in the attention check result - cancel. + case ATTENTION_CHECK_TIMEOUT: { + cancelAndUnbindLocked(peekCurrentUserStateLocked(), + AttentionService.ATTENTION_FAILURE_TIMED_OUT); + } + break; + + default: + break; + } + } + } + + @GuardedBy("mLock") + private void cancelAndUnbindLocked(UserState userState, + @AttentionFailureCodes int failureCode) { + synchronized (mLock) { + if (userState != null && userState.mService != null) { + try { + userState.mService.cancelAttentionCheck( + userState.mCurrentAttentionCheckRequestCode); + } catch (RemoteException e) { + Slog.e(LOG_TAG, "Unable to cancel attention check"); + } + + if (userState.mPendingAttentionCheck != null) { + userState.mPendingAttentionCheck.cancel(failureCode); + } + mContext.unbindService(userState.mConnection); + userState.mConnection.cleanupService(); + mUserStates.remove(userState.mUserId); + } + } + } + + /** + * Unbinds and stops the service when the screen off intent is received. + * Attention service only makes sense when screen is ON; disconnect and stop service otherwise. + */ + private final class ScreenStateReceiver extends BroadcastReceiver { + @Override + public void onReceive(Context context, Intent intent) { + if (Intent.ACTION_SCREEN_OFF.equals(intent.getAction())) { + cancelAndUnbindLocked(peekCurrentUserStateLocked(), + AttentionService.ATTENTION_FAILURE_UNKNOWN); + } + } + } +} diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java index 9a4ca1f954d0..d9fcf9ed8a7f 100644 --- a/services/core/java/com/android/server/audio/AudioService.java +++ b/services/core/java/com/android/server/audio/AudioService.java @@ -1614,7 +1614,9 @@ public class AudioService extends IAudioService.Stub // For notifications/ring, show the ui before making any adjustments // Don't suppress mute/unmute requests - if (mVolumeController.suppressAdjustment(resolvedStream, flags, isMute)) { + // Don't suppress adjustments for single volume device + if (mVolumeController.suppressAdjustment(resolvedStream, flags, isMute) + && !mIsSingleVolume) { direction = 0; flags &= ~AudioManager.FLAG_PLAY_SOUND; flags &= ~AudioManager.FLAG_VIBRATE; diff --git a/services/core/java/com/android/server/biometrics/BiometricServiceBase.java b/services/core/java/com/android/server/biometrics/BiometricServiceBase.java index ecc3d2da8226..174ecfa12ee6 100644 --- a/services/core/java/com/android/server/biometrics/BiometricServiceBase.java +++ b/services/core/java/com/android/server/biometrics/BiometricServiceBase.java @@ -116,6 +116,7 @@ public abstract class BiometricServiceBase extends SystemService protected HashMap<Integer, PerformanceStats> mPerformanceMap = new HashMap<>(); // Transactions that make use of CryptoObjects are tracked by mCryptoPerformaceMap. protected HashMap<Integer, PerformanceStats> mCryptoPerformanceMap = new HashMap<>(); + protected int mHALDeathCount; protected class PerformanceStats { public int accept; // number of accepted biometrics @@ -596,6 +597,7 @@ public abstract class BiometricServiceBase extends SystemService public void serviceDied(long cookie) { Slog.e(getTag(), "HAL died"); mMetricsLogger.count(getMetrics().tagHalDied(), 1); + mHALDeathCount++; handleError(getHalDeviceId(), BiometricConstants.BIOMETRIC_ERROR_HW_UNAVAILABLE, 0 /*vendorCode */); } diff --git a/services/core/java/com/android/server/biometrics/face/FaceService.java b/services/core/java/com/android/server/biometrics/face/FaceService.java index 5a9c1aca081a..a2aacdde4d9f 100644 --- a/services/core/java/com/android/server/biometrics/face/FaceService.java +++ b/services/core/java/com/android/server/biometrics/face/FaceService.java @@ -675,6 +675,12 @@ public class FaceService extends BiometricServiceBase { } @Override + public void serviceDied(long cookie) { + super.serviceDied(cookie); + mDaemon = null; + } + + @Override protected void updateActiveGroup(int userId, String clientPackage) { IBiometricsFace daemon = getFaceDaemon(); @@ -864,6 +870,8 @@ public class FaceService extends BiometricServiceBase { Slog.e(TAG, "dump formatting failure", e); } pw.println(dump); + pw.println("HAL Deaths: " + mHALDeathCount); + mHALDeathCount = 0; } private void dumpProto(FileDescriptor fd) { diff --git a/services/core/java/com/android/server/biometrics/fingerprint/FingerprintService.java b/services/core/java/com/android/server/biometrics/fingerprint/FingerprintService.java index 1613dc97225b..3db6a74a1c6c 100644 --- a/services/core/java/com/android/server/biometrics/fingerprint/FingerprintService.java +++ b/services/core/java/com/android/server/biometrics/fingerprint/FingerprintService.java @@ -777,6 +777,12 @@ public class FingerprintService extends BiometricServiceBase { } @Override + public void serviceDied(long cookie) { + super.serviceDied(cookie); + mDaemon = null; + } + + @Override protected void updateActiveGroup(int userId, String clientPackage) { IBiometricsFingerprint daemon = getFingerprintDaemon(); @@ -1074,6 +1080,8 @@ public class FingerprintService extends BiometricServiceBase { Slog.e(TAG, "dump formatting failure", e); } pw.println(dump); + pw.println("HAL Deaths: " + mHALDeathCount); + mHALDeathCount = 0; } private void dumpProto(FileDescriptor fd) { diff --git a/services/core/java/com/android/server/connectivity/PacManager.java b/services/core/java/com/android/server/connectivity/PacManager.java index 3ea9810f2d76..97896889f243 100644 --- a/services/core/java/com/android/server/connectivity/PacManager.java +++ b/services/core/java/com/android/server/connectivity/PacManager.java @@ -282,6 +282,7 @@ public class PacManager { private void setCurrentProxyScript(String script) { if (mProxyService == null) { Log.e(TAG, "setCurrentProxyScript: no proxy service"); + return; } try { mProxyService.setPacFile(script); diff --git a/services/core/java/com/android/server/display/AppSaturationController.java b/services/core/java/com/android/server/display/AppSaturationController.java new file mode 100644 index 000000000000..5d5e4f70ea7f --- /dev/null +++ b/services/core/java/com/android/server/display/AppSaturationController.java @@ -0,0 +1,213 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.server.display; + +import android.annotation.UserIdInt; +import android.util.SparseArray; + +import com.android.internal.annotations.GuardedBy; +import com.android.internal.annotations.VisibleForTesting; +import com.android.server.display.ColorDisplayService.ColorTransformController; + +import java.io.PrintWriter; +import java.lang.ref.WeakReference; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +class AppSaturationController { + + private final Object mLock = new Object(); + + /** + * A package name has one or more userIds it is running under. Each userId has zero or one + * saturation level, and zero or more ColorTransformControllers. + */ + @GuardedBy("mLock") + private final Map<String, SparseArray<SaturationController>> mAppsMap = new HashMap<>(); + + @VisibleForTesting + static final float[] TRANSLATION_VECTOR = {0f, 0f, 0f}; + + /** + * Add an {@link WeakReference<ColorTransformController>} for a given package and userId. + */ + boolean addColorTransformController(String packageName, @UserIdInt int userId, + WeakReference<ColorTransformController> controller) { + synchronized (mLock) { + return getSaturationControllerLocked(packageName, userId) + .addColorTransformController(controller); + } + } + + /** + * Set the saturation level ({@code ColorDisplayManager#SaturationLevel} constant for a given + * package name and userId. + */ + public boolean setSaturationLevel(String packageName, @UserIdInt int userId, + int saturationLevel) { + synchronized (mLock) { + return getSaturationControllerLocked(packageName, userId) + .setSaturationLevel(saturationLevel); + } + } + + /** + * Dump state information. + */ + public void dump(PrintWriter pw) { + synchronized (mLock) { + pw.println("App Saturation: "); + if (mAppsMap.size() == 0) { + pw.println(" No packages"); + return; + } + final List<String> packageNames = new ArrayList<>(mAppsMap.keySet()); + Collections.sort(packageNames); + for (String packageName : packageNames) { + pw.println(" " + packageName + ":"); + final SparseArray<SaturationController> appUserIdMap = mAppsMap.get(packageName); + for (int i = 0; i < appUserIdMap.size(); i++) { + pw.println(" " + appUserIdMap.keyAt(i) + ":"); + appUserIdMap.valueAt(i).dump(pw); + } + } + } + } + + /** + * Retrieve the SaturationController for a given package and userId, creating all intermediate + * connections as needed. + */ + private SaturationController getSaturationControllerLocked(String packageName, + @UserIdInt int userId) { + return getOrCreateSaturationControllerLocked(getOrCreateUserIdMapLocked(packageName), + userId); + } + + /** + * Retrieve or create the mapping between the app's given package name and its userIds (and + * their SaturationControllers). + */ + private SparseArray<SaturationController> getOrCreateUserIdMapLocked(String packageName) { + if (mAppsMap.get(packageName) != null) { + return mAppsMap.get(packageName); + } + + final SparseArray<SaturationController> appUserIdMap = new SparseArray<>(); + mAppsMap.put(packageName, appUserIdMap); + return appUserIdMap; + } + + /** + * Retrieve or create the mapping between an app's given userId and SaturationController. + */ + private SaturationController getOrCreateSaturationControllerLocked( + SparseArray<SaturationController> appUserIdMap, @UserIdInt int userId) { + if (appUserIdMap.get(userId) != null) { + return appUserIdMap.get(userId); + } + + final SaturationController saturationController = new SaturationController(); + appUserIdMap.put(userId, saturationController); + return saturationController; + } + + @VisibleForTesting + static void computeGrayscaleTransformMatrix(float saturation, float[] matrix) { + float desaturation = 1.0f - saturation; + float[] luminance = {0.231f * desaturation, 0.715f * desaturation, + 0.072f * desaturation}; + matrix[0] = luminance[0] + saturation; + matrix[1] = luminance[0]; + matrix[2] = luminance[0]; + matrix[3] = luminance[1]; + matrix[4] = luminance[1] + saturation; + matrix[5] = luminance[1]; + matrix[6] = luminance[2]; + matrix[7] = luminance[2]; + matrix[8] = luminance[2] + saturation; + } + + private static class SaturationController { + + private final List<WeakReference<ColorTransformController>> mControllerRefs = + new ArrayList<>(); + private int mSaturationLevel = 100; + private float[] mTransformMatrix = new float[9]; + + private boolean setSaturationLevel(int saturationLevel) { + mSaturationLevel = saturationLevel; + if (!mControllerRefs.isEmpty()) { + return updateState(); + } + return false; + } + + private boolean addColorTransformController( + WeakReference<ColorTransformController> controller) { + mControllerRefs.add(controller); + if (mSaturationLevel != 100) { + return updateState(); + } else { + clearExpiredReferences(); + } + return false; + } + + private boolean updateState() { + computeGrayscaleTransformMatrix(mSaturationLevel / 100f, mTransformMatrix); + + boolean updated = false; + final Iterator<WeakReference<ColorTransformController>> iterator = mControllerRefs + .iterator(); + while (iterator.hasNext()) { + WeakReference<ColorTransformController> controllerRef = iterator.next(); + final ColorTransformController controller = controllerRef.get(); + if (controller != null) { + controller.applyAppSaturation(mTransformMatrix, TRANSLATION_VECTOR); + updated = true; + } else { + // Purge cleared refs lazily to avoid accumulating a lot of dead windows + iterator.remove(); + } + } + return updated; + + } + + private void clearExpiredReferences() { + final Iterator<WeakReference<ColorTransformController>> iterator = mControllerRefs + .iterator(); + while (iterator.hasNext()) { + WeakReference<ColorTransformController> controllerRef = iterator.next(); + final ColorTransformController controller = controllerRef.get(); + if (controller == null) { + iterator.remove(); + } + } + } + + private void dump(PrintWriter pw) { + pw.println(" mSaturationLevel: " + mSaturationLevel); + pw.println(" mControllerRefs count: " + mControllerRefs.size()); + } + } +} diff --git a/services/core/java/com/android/server/display/ColorDisplayService.java b/services/core/java/com/android/server/display/ColorDisplayService.java index 2fe17d8f3c98..9223739406ee 100644 --- a/services/core/java/com/android/server/display/ColorDisplayService.java +++ b/services/core/java/com/android/server/display/ColorDisplayService.java @@ -27,6 +27,7 @@ import android.animation.TypeEvaluator; import android.animation.ValueAnimator; import android.annotation.NonNull; import android.annotation.Nullable; +import android.annotation.Size; import android.app.AlarmManager; import android.content.BroadcastReceiver; import android.content.ContentResolver; @@ -36,8 +37,8 @@ import android.content.IntentFilter; import android.content.pm.PackageManager; import android.content.res.Resources; import android.database.ContentObserver; -import android.hardware.display.ColorDisplayManager; import android.graphics.ColorSpace; +import android.hardware.display.ColorDisplayManager; import android.hardware.display.IColorDisplayManager; import android.net.Uri; import android.opengl.Matrix; @@ -50,18 +51,22 @@ import android.provider.Settings.Secure; import android.provider.Settings.System; import android.util.MathUtils; import android.util.Slog; +import android.view.accessibility.AccessibilityManager; import android.view.animation.AnimationUtils; import com.android.internal.R; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.app.ColorDisplayController; +import com.android.internal.util.DumpUtils; import com.android.server.DisplayThread; import com.android.server.SystemService; import com.android.server.twilight.TwilightListener; import com.android.server.twilight.TwilightManager; import com.android.server.twilight.TwilightState; +import java.io.FileDescriptor; import java.io.PrintWriter; +import java.lang.ref.WeakReference; import java.time.DateTimeException; import java.time.Instant; import java.time.LocalDateTime; @@ -398,8 +403,33 @@ public final class ColorDisplayService extends SystemService { } }; + /** + * Matrix and offset used for converting color to grayscale. + */ + private static final float[] MATRIX_GRAYSCALE = new float[]{ + .2126f, .2126f, .2126f, 0f, + .7152f, .7152f, .7152f, 0f, + .0722f, .0722f, .0722f, 0f, + 0f, 0f, 0f, 1f + }; + + /** + * Matrix and offset used for luminance inversion. Represents a transform from RGB to YIQ color + * space, rotation around the Y axis by 180 degrees, transform back to RGB color space, and + * subtraction from 1. The last row represents a non-multiplied addition, see surfaceflinger's + * ProgramCache for full implementation details. + */ + private static final float[] MATRIX_INVERT_COLOR = new float[] { + 0.402f, -0.598f, -0.599f, 0f, + -1.174f, -0.174f, -1.175f, 0f, + -0.228f, -0.228f, 0.772f, 0f, + 1f, 1f, 1f, 1f + }; + private final Handler mHandler; + private final AppSaturationController mAppSaturationController = new AppSaturationController(); + private int mCurrentUser = UserHandle.USER_NULL; private ContentObserver mUserSetupObserver; private boolean mBootCompleted; @@ -537,9 +567,16 @@ public final class ColorDisplayService extends SystemService { case System.DISPLAY_COLOR_MODE: onDisplayColorModeChanged(mNightDisplayController.getColorMode()); break; - case Secure.ACCESSIBILITY_DISPLAY_DALTONIZER_ENABLED: case Secure.ACCESSIBILITY_DISPLAY_INVERSION_ENABLED: - onAccessibilityTransformChanged(); + onAccessibilityInversionChanged(); + onAccessibilityActivated(); + break; + case Secure.ACCESSIBILITY_DISPLAY_DALTONIZER_ENABLED: + onAccessibilityDaltonizerChanged(); + onAccessibilityActivated(); + break; + case Secure.ACCESSIBILITY_DISPLAY_DALTONIZER: + onAccessibilityDaltonizerChanged(); break; case Secure.DISPLAY_WHITE_BALANCE_ENABLED: updateDisplayWhiteBalanceStatus(); @@ -568,6 +605,9 @@ public final class ColorDisplayService extends SystemService { cr.registerContentObserver( Secure.getUriFor(Secure.ACCESSIBILITY_DISPLAY_DALTONIZER_ENABLED), false /* notifyForDescendants */, mContentObserver, mCurrentUser); + cr.registerContentObserver( + Secure.getUriFor(Secure.ACCESSIBILITY_DISPLAY_DALTONIZER), + false /* notifyForDescendants */, mContentObserver, mCurrentUser); cr.registerContentObserver(Secure.getUriFor(Secure.DISPLAY_WHITE_BALANCE_ENABLED), false /* notifyForDescendants */, mContentObserver, mCurrentUser); @@ -698,10 +738,43 @@ public final class ColorDisplayService extends SystemService { dtm.setColorMode(mode, mNightDisplayTintController.getMatrix()); } - private void onAccessibilityTransformChanged() { + private void onAccessibilityActivated() { onDisplayColorModeChanged(mNightDisplayController.getColorMode()); } + /** + * Apply the accessibility daltonizer transform based on the settings value. + */ + private void onAccessibilityDaltonizerChanged() { + final boolean enabled = Secure.getIntForUser(getContext().getContentResolver(), + Secure.ACCESSIBILITY_DISPLAY_DALTONIZER_ENABLED, 0, mCurrentUser) != 0; + final int daltonizerMode = enabled ? Secure.getIntForUser(getContext().getContentResolver(), + Secure.ACCESSIBILITY_DISPLAY_DALTONIZER, + AccessibilityManager.DALTONIZER_CORRECT_DEUTERANOMALY, mCurrentUser) + : AccessibilityManager.DALTONIZER_DISABLED; + + final DisplayTransformManager dtm = getLocalService(DisplayTransformManager.class); + if (daltonizerMode == AccessibilityManager.DALTONIZER_SIMULATE_MONOCHROMACY) { + // Monochromacy isn't supported by the native Daltonizer implementation; use grayscale. + dtm.setColorMatrix(DisplayTransformManager.LEVEL_COLOR_MATRIX_GRAYSCALE, + MATRIX_GRAYSCALE); + dtm.setDaltonizerMode(AccessibilityManager.DALTONIZER_DISABLED); + } else { + dtm.setColorMatrix(DisplayTransformManager.LEVEL_COLOR_MATRIX_GRAYSCALE, null); + dtm.setDaltonizerMode(daltonizerMode); + } + } + + /** + * Apply the accessibility inversion transform based on the settings value. + */ + private void onAccessibilityInversionChanged() { + final boolean enabled = Secure.getIntForUser(getContext().getContentResolver(), + Secure.ACCESSIBILITY_DISPLAY_INVERSION_ENABLED, 0, mCurrentUser) != 0; + final DisplayTransformManager dtm = getLocalService(DisplayTransformManager.class); + dtm.setColorMatrix(DisplayTransformManager.LEVEL_COLOR_MATRIX_INVERT_COLOR, + enabled ? MATRIX_INVERT_COLOR : null); + } /** * Applies current color temperature matrix, or removes it if deactivated. @@ -829,6 +902,22 @@ public final class ColorDisplayService extends SystemService { return LocalDateTime.MIN; } + private boolean setAppSaturationLevelInternal(String packageName, int saturationLevel) { + return mAppSaturationController + .setSaturationLevel(packageName, mCurrentUser, saturationLevel); + } + + private void dumpInternal(PrintWriter pw) { + pw.println("COLOR DISPLAY MANAGER dumpsys (color_display)"); + pw.println("Night Display:"); + if (ColorDisplayManager.isNightDisplayAvailable(getContext())) { + pw.println(" Activated: " + mNightDisplayTintController.isActivated()); + } else { + pw.println(" Not available"); + } + mAppSaturationController.dump(pw); + } + private abstract class NightDisplayAutoMode { public abstract void onActivated(boolean activated); @@ -1132,6 +1221,16 @@ public final class ColorDisplayService extends SystemService { public void dump(PrintWriter pw) { mDisplayWhiteBalanceTintController.dump(pw); } + + /** + * Adds a {@link WeakReference<ColorTransformController>} for a newly started activity, and + * invokes {@link ColorTransformController#applyAppSaturation(float[], float[])} if needed. + */ + public boolean attachColorTransformController(String packageName, int uid, + WeakReference<ColorTransformController> controller) { + return mAppSaturationController + .addColorTransformController(packageName, uid, controller); + } } /** @@ -1163,6 +1262,15 @@ public final class ColorDisplayService extends SystemService { } } + /** + * Interface for applying transforms to a given AppWindow. + */ + public interface ColorTransformController { + + /** Apply the given saturation (grayscale) matrix to the associated AppWindow. */ + void applyAppSaturation(@Size(9) float[] matrix, @Size(3) float[] translation); + } + private final class BinderService extends IColorDisplayManager.Stub { @Override @@ -1196,5 +1304,30 @@ public final class ColorDisplayService extends SystemService { } return true; } + + @Override + public boolean setAppSaturationLevel(String packageName, int level) { + getContext().enforceCallingPermission( + Manifest.permission.CONTROL_DISPLAY_COLOR_TRANSFORMS, + "Permission required to set display saturation level"); + final long token = Binder.clearCallingIdentity(); + try { + return setAppSaturationLevelInternal(packageName, level); + } finally { + Binder.restoreCallingIdentity(token); + } + } + + @Override + public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { + if (!DumpUtils.checkDumpPermission(getContext(), TAG, pw)) return; + + final long token = Binder.clearCallingIdentity(); + try { + dumpInternal(pw); + } finally { + Binder.restoreCallingIdentity(token); + } + } } } diff --git a/services/core/java/com/android/server/hdmi/HdmiCecLocalDevice.java b/services/core/java/com/android/server/hdmi/HdmiCecLocalDevice.java index eb4e662b2c82..414f6bbfb995 100755 --- a/services/core/java/com/android/server/hdmi/HdmiCecLocalDevice.java +++ b/services/core/java/com/android/server/hdmi/HdmiCecLocalDevice.java @@ -56,11 +56,6 @@ abstract class HdmiCecLocalDevice { // Within the timer, a received <User Control Pressed> will start "Press and Hold" behavior. // When it expires, we can assume <User Control Release> is received. private static final int FOLLOWER_SAFETY_TIMEOUT = 550; - /** - * Return value of {@link #getLocalPortFromPhysicalAddress(int)} - */ - private static final int TARGET_NOT_UNDER_LOCAL_DEVICE = -1; - private static final int TARGET_SAME_PHYSICAL_ADDRESS = 0; protected final HdmiControlService mService; protected final int mDeviceType; @@ -1061,47 +1056,6 @@ abstract class HdmiCecLocalDevice { pw.println(String.format("mActiveRoutingPath: 0x%04x", mActiveRoutingPath)); } - /** - * Method to parse target physical address to the port number on the current device. - * - * <p>This check assumes target address is valid. - * @param targetPhysicalAddress is the physical address of the target device - * @return - * If the target device is under the current device, return the port number of current device - * that the target device is connected to. - * - * <p>If the target device has the same physical address as the current device, return - * {@link #TARGET_SAME_PHYSICAL_ADDRESS}. - * - * <p>If the target device is not under the current device, return - * {@link #TARGET_NOT_UNDER_LOCAL_DEVICE}. - */ - protected int getLocalPortFromPhysicalAddress(int targetPhysicalAddress) { - int myPhysicalAddress = mService.getPhysicalAddress(); - if (myPhysicalAddress == targetPhysicalAddress) { - return TARGET_SAME_PHYSICAL_ADDRESS; - } - int finalMask = 0xF000; - int mask; - int port = 0; - for (mask = 0x0F00; mask > 0x000F; mask >>= 4) { - if ((myPhysicalAddress & mask) == 0) { - port = mask & targetPhysicalAddress; - break; - } else { - finalMask |= mask; - } - } - if (finalMask != 0xFFFF && (finalMask & targetPhysicalAddress) == myPhysicalAddress) { - while (mask != 0x000F) { - mask >>= 4; - port >>= 4; - } - return port; - } - return TARGET_NOT_UNDER_LOCAL_DEVICE; - } - /** Calculates the physical address for {@code activePortId}. * * <p>This method assumes current device physical address is valid. diff --git a/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceAudioSystem.java b/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceAudioSystem.java index 71075f3d71ce..63214ed651b9 100644 --- a/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceAudioSystem.java +++ b/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceAudioSystem.java @@ -41,7 +41,15 @@ import com.android.internal.util.IndentingPrintWriter; import com.android.server.hdmi.Constants.AudioCodec; import com.android.server.hdmi.DeviceDiscoveryAction.DeviceDiscoveryCallback; import com.android.server.hdmi.HdmiAnnotations.ServiceThreadOnly; +import com.android.server.hdmi.HdmiUtils.CodecSad; +import com.android.server.hdmi.HdmiUtils.DeviceConfig; +import org.xmlpull.v1.XmlPullParserException; + +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; import java.io.UnsupportedEncodingException; import java.util.ArrayList; import java.util.Arrays; @@ -105,6 +113,8 @@ public class HdmiCecLocalDeviceAudioSystem extends HdmiCecLocalDeviceSource { mTvInputs.put(1, "com.droidlogic.tvinput/.services.Hdmi3InputService/HW7"); } + private static final String SHORT_AUDIO_DESCRIPTOR_CONFIG_PATH = "/vendor/etc/sadConfig.xml"; + /** * Called when a device is newly added or a new device is detected or * an existing device is updated. @@ -258,7 +268,7 @@ public class HdmiCecLocalDeviceAudioSystem extends HdmiCecLocalDeviceSource { mTvSystemAudioModeSupport = false; // Record the last state of System Audio Control before going to standby synchronized (mLock) { - SystemProperties.set( + mService.writeStringSetting( Constants.PROPERTY_LAST_SYSTEM_AUDIO_CONTROL, mSystemAudioActivated ? "true" : "false"); } @@ -320,7 +330,7 @@ public class HdmiCecLocalDeviceAudioSystem extends HdmiCecLocalDeviceSource { @ServiceThreadOnly protected void setPreferredAddress(int addr) { assertRunOnServiceThread(); - SystemProperties.set( + mService.writeStringSetting( Constants.PROPERTY_PREFERRED_ADDRESS_AUDIO_SYSTEM, String.valueOf(addr)); } @@ -459,7 +469,7 @@ public class HdmiCecLocalDeviceAudioSystem extends HdmiCecLocalDeviceSource { protected boolean handleRequestArcInitiate(HdmiCecMessage message) { assertRunOnServiceThread(); removeAction(ArcInitiationActionFromAvr.class); - if (!SystemProperties.getBoolean(Constants.PROPERTY_ARC_SUPPORT, true)) { + if (!mService.readBooleanSetting(Constants.PROPERTY_ARC_SUPPORT, true)) { mService.maySendFeatureAbortCommand(message, Constants.ABORT_UNRECOGNIZED_OPCODE); } else if (!isDirectConnectToTv()) { HdmiLogger.debug("AVR device is not directly connected with TV"); @@ -498,13 +508,35 @@ public class HdmiCecLocalDeviceAudioSystem extends HdmiCecLocalDeviceSource { mService.maySendFeatureAbortCommand(message, Constants.ABORT_NOT_IN_CORRECT_MODE); return true; } - AudioDeviceInfo deviceInfo = getSystemAudioDeviceInfo(); - if (deviceInfo == null) { - mService.maySendFeatureAbortCommand(message, Constants.ABORT_UNABLE_TO_DETERMINE); - return true; + + List<DeviceConfig> config = null; + File file = new File(SHORT_AUDIO_DESCRIPTOR_CONFIG_PATH); + if (file.exists()) { + try { + InputStream in = new FileInputStream(file); + config = HdmiUtils.ShortAudioDescriptorXmlParser.parse(in); + in.close(); + } catch (IOException e) { + Slog.e(TAG, "Error reading file: " + file, e); + } catch (XmlPullParserException e) { + Slog.e(TAG, "Unable to parse file: " + file, e); + } } + @AudioCodec int[] audioFormatCodes = parseAudioFormatCodes(message.getParams()); - byte[] sadBytes = getSupportedShortAudioDescriptors(deviceInfo, audioFormatCodes); + byte[] sadBytes; + if (config != null && config.size() > 0) { + sadBytes = getSupportedShortAudioDescriptorsFromConfig(config, audioFormatCodes); + } else { + AudioDeviceInfo deviceInfo = getSystemAudioDeviceInfo(); + if (deviceInfo == null) { + mService.maySendFeatureAbortCommand(message, Constants.ABORT_UNABLE_TO_DETERMINE); + return true; + } + + sadBytes = getSupportedShortAudioDescriptors(deviceInfo, audioFormatCodes); + } + if (sadBytes.length == 0) { mService.maySendFeatureAbortCommand(message, Constants.ABORT_INVALID_OPERAND); } else { @@ -531,6 +563,42 @@ public class HdmiCecLocalDeviceAudioSystem extends HdmiCecLocalDeviceSource { } } } + return getShortAudioDescriptorBytes(sads); + } + + private byte[] getSupportedShortAudioDescriptorsFromConfig( + List<DeviceConfig> deviceConfig, @AudioCodec int[] audioFormatCodes) { + DeviceConfig deviceConfigToUse = null; + for (DeviceConfig device : deviceConfig) { + // TODO(amyjojo) use PROPERTY_SYSTEM_AUDIO_MODE_AUDIO_PORT to get the audio device name + if (device.name.equals("VX_AUDIO_DEVICE_IN_HDMI_ARC")) { + deviceConfigToUse = device; + break; + } + } + if (deviceConfigToUse == null) { + // TODO(amyjojo) use PROPERTY_SYSTEM_AUDIO_MODE_AUDIO_PORT to get the audio device name + Slog.w(TAG, "sadConfig.xml does not have required device info for " + + "VX_AUDIO_DEVICE_IN_HDMI_ARC"); + return new byte[0]; + } + HashMap<Integer, byte[]> map = new HashMap<>(); + ArrayList<byte[]> sads = new ArrayList<>(audioFormatCodes.length); + for (CodecSad codecSad : deviceConfigToUse.supportedCodecs) { + map.put(codecSad.audioCodec, codecSad.sad); + } + for (int i = 0; i < audioFormatCodes.length; i++) { + if (map.containsKey(audioFormatCodes[i])) { + byte[] sad = map.get(audioFormatCodes[i]); + if (sad != null && sad.length == 3) { + sads.add(sad); + } + } + } + return getShortAudioDescriptorBytes(sads); + } + + private byte[] getShortAudioDescriptorBytes(ArrayList<byte[]> sads) { // Short Audio Descriptors are always 3 bytes long. byte[] bytes = new byte[sads.size() * 3]; int index = 0; @@ -761,7 +829,7 @@ public class HdmiCecLocalDeviceAudioSystem extends HdmiCecLocalDeviceSource { boolean currentMuteStatus = mService.getAudioManager().isStreamMute(AudioManager.STREAM_MUSIC); if (currentMuteStatus == newSystemAudioMode) { - if (SystemProperties.getBoolean( + if (mService.readBooleanSetting( Constants.PROPERTY_SYSTEM_AUDIO_MODE_MUTING_ENABLE, true) || newSystemAudioMode) { mService.getAudioManager() diff --git a/services/core/java/com/android/server/hdmi/HdmiCecLocalDevicePlayback.java b/services/core/java/com/android/server/hdmi/HdmiCecLocalDevicePlayback.java index 32288de15a00..7a0c27906122 100644 --- a/services/core/java/com/android/server/hdmi/HdmiCecLocalDevicePlayback.java +++ b/services/core/java/com/android/server/hdmi/HdmiCecLocalDevicePlayback.java @@ -100,7 +100,7 @@ public class HdmiCecLocalDevicePlayback extends HdmiCecLocalDeviceSource { @ServiceThreadOnly protected void setPreferredAddress(int addr) { assertRunOnServiceThread(); - SystemProperties.set(Constants.PROPERTY_PREFERRED_ADDRESS_PLAYBACK, + mService.writeStringSetting(Constants.PROPERTY_PREFERRED_ADDRESS_PLAYBACK, String.valueOf(addr)); } diff --git a/services/core/java/com/android/server/hdmi/HdmiControlService.java b/services/core/java/com/android/server/hdmi/HdmiControlService.java index 486faf3e9fa5..46219d5cbe8a 100644 --- a/services/core/java/com/android/server/hdmi/HdmiControlService.java +++ b/services/core/java/com/android/server/hdmi/HdmiControlService.java @@ -646,6 +646,7 @@ public class HdmiControlService extends SystemService { return enabled ? ENABLED : DISABLED; } + @VisibleForTesting boolean readBooleanSetting(String key, boolean defVal) { ContentResolver cr = getContext().getContentResolver(); return Global.getInt(cr, key, toInt(defVal)) == ENABLED; @@ -656,6 +657,11 @@ public class HdmiControlService extends SystemService { Global.putInt(cr, key, toInt(value)); } + void writeStringSetting(String key, String value) { + ContentResolver cr = getContext().getContentResolver(); + Global.putString(cr, key, value); + } + private void initializeCec(int initiatedBy) { mAddressAllocated = false; mCecController.setOption(OptionKey.SYSTEM_CEC_CONTROL, true); diff --git a/services/core/java/com/android/server/hdmi/HdmiUtils.java b/services/core/java/com/android/server/hdmi/HdmiUtils.java index 11e557c024ce..e44f1d1522ec 100644 --- a/services/core/java/com/android/server/hdmi/HdmiUtils.java +++ b/services/core/java/com/android/server/hdmi/HdmiUtils.java @@ -16,23 +16,35 @@ package com.android.server.hdmi; +import android.annotation.Nullable; import android.hardware.hdmi.HdmiDeviceInfo; import android.util.Slog; import android.util.SparseArray; +import android.util.Xml; +import com.android.internal.util.HexDump; import com.android.internal.util.IndentingPrintWriter; +import com.android.server.hdmi.Constants.AudioCodec; +import org.xmlpull.v1.XmlPullParser; +import org.xmlpull.v1.XmlPullParserException; + +import java.io.IOException; +import java.io.InputStream; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collections; import java.util.List; import java.util.Map; - +import java.util.Objects; /** * Various utilities to handle HDMI CEC messages. */ final class HdmiUtils { + private static final String TAG = "HdmiUtils"; + private static final int[] ADDRESS_TO_TYPE = { HdmiDeviceInfo.DEVICE_TV, // ADDR_TV HdmiDeviceInfo.DEVICE_RECORDER, // ADDR_RECORDER_1 @@ -69,6 +81,12 @@ final class HdmiUtils { "Secondary_TV", }; + /** + * Return value of {@link #getLocalPortFromPhysicalAddress(int, int)} + */ + static final int TARGET_NOT_UNDER_LOCAL_DEVICE = -1; + static final int TARGET_SAME_PHYSICAL_ADDRESS = 0; + private HdmiUtils() { /* cannot be instantiated */ } /** @@ -392,6 +410,203 @@ final class HdmiUtils { pw.decreaseIndent(); } + /** + * Method to parse target physical address to the port number on the current device. + * + * <p>This check assumes target address is valid. + * + * @param targetPhysicalAddress is the physical address of the target device + * @param myPhysicalAddress is the physical address of the current device + * @return + * If the target device is under the current device, return the port number of current device + * that the target device is connected to. This also applies to the devices that are indirectly + * connected to the current device. + * + * <p>If the target device has the same physical address as the current device, return + * {@link #TARGET_SAME_PHYSICAL_ADDRESS}. + * + * <p>If the target device is not under the current device, return + * {@link #TARGET_NOT_UNDER_LOCAL_DEVICE}. + */ + public static int getLocalPortFromPhysicalAddress( + int targetPhysicalAddress, int myPhysicalAddress) { + if (myPhysicalAddress == targetPhysicalAddress) { + return TARGET_SAME_PHYSICAL_ADDRESS; + } + + int mask = 0xF000; + int finalMask = 0xF000; + int maskedAddress = myPhysicalAddress; + + while (maskedAddress != 0) { + maskedAddress = myPhysicalAddress & mask; + finalMask |= mask; + mask >>= 4; + } + + int portAddress = targetPhysicalAddress & finalMask; + if ((portAddress & (finalMask << 4)) != myPhysicalAddress) { + return TARGET_NOT_UNDER_LOCAL_DEVICE; + } + + mask <<= 4; + int port = portAddress & mask; + while ((port >> 4) != 0) { + port >>= 4; + } + return port; + } + + public static class ShortAudioDescriptorXmlParser { + // We don't use namespaces + private static final String NS = null; + + // return a list of devices config + public static List<DeviceConfig> parse(InputStream in) + throws XmlPullParserException, IOException { + XmlPullParser parser = Xml.newPullParser(); + parser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, false); + parser.setInput(in, null); + parser.nextTag(); + return readDevices(parser); + } + + private static void skip(XmlPullParser parser) throws XmlPullParserException, IOException { + if (parser.getEventType() != XmlPullParser.START_TAG) { + throw new IllegalStateException(); + } + int depth = 1; + while (depth != 0) { + switch (parser.next()) { + case XmlPullParser.END_TAG: + depth--; + break; + case XmlPullParser.START_TAG: + depth++; + break; + } + } + } + + private static List<DeviceConfig> readDevices(XmlPullParser parser) + throws XmlPullParserException, IOException { + List<DeviceConfig> devices = new ArrayList<>(); + + parser.require(XmlPullParser.START_TAG, NS, "config"); + while (parser.next() != XmlPullParser.END_TAG) { + if (parser.getEventType() != XmlPullParser.START_TAG) { + continue; + } + String name = parser.getName(); + // Starts by looking for the device tag + if (name.equals("device")) { + String deviceType = parser.getAttributeValue(null, "type"); + DeviceConfig config = null; + if (deviceType != null) { + config = readDeviceConfig(parser, deviceType); + } + if (config != null) { + devices.add(config); + } + } else { + skip(parser); + } + } + return devices; + } + + // Processes device tags in the config. + @Nullable + private static DeviceConfig readDeviceConfig(XmlPullParser parser, String deviceType) + throws XmlPullParserException, IOException { + List<CodecSad> codecSads = new ArrayList<>(); + int format; + byte[] descriptor; + + parser.require(XmlPullParser.START_TAG, NS, "device"); + while (parser.next() != XmlPullParser.END_TAG) { + if (parser.getEventType() != XmlPullParser.START_TAG) { + continue; + } + String tagName = parser.getName(); + + // Starts by looking for the supportedFormat tag + if (tagName.equals("supportedFormat")) { + String codecAttriValue = parser.getAttributeValue(null, "format"); + String sadAttriValue = parser.getAttributeValue(null, "descriptor"); + format = (codecAttriValue) == null + ? Constants.AUDIO_CODEC_NONE : formatNameToNum(codecAttriValue); + descriptor = readSad(sadAttriValue); + if (format != Constants.AUDIO_CODEC_NONE && descriptor != null) { + codecSads.add(new CodecSad(format, descriptor)); + } + parser.nextTag(); + parser.require(XmlPullParser.END_TAG, NS, "supportedFormat"); + } else { + skip(parser); + } + } + if (codecSads.size() == 0) { + return null; + } + return new DeviceConfig(deviceType, codecSads); + } + + // Processes sad attribute in the supportedFormat. + @Nullable + private static byte[] readSad(String sad) { + if (sad == null || sad.length() == 0) { + return null; + } + byte[] sadBytes = HexDump.hexStringToByteArray(sad); + if (sadBytes.length != 3) { + Slog.w(TAG, "SAD byte array length is not 3. Length = " + sadBytes.length); + return null; + } + return sadBytes; + } + + @AudioCodec + private static int formatNameToNum(String codecAttriValue) { + switch (codecAttriValue) { + case "AUDIO_FORMAT_NONE": + return Constants.AUDIO_CODEC_NONE; + case "AUDIO_FORMAT_LPCM": + return Constants.AUDIO_CODEC_LPCM; + case "AUDIO_FORMAT_DD": + return Constants.AUDIO_CODEC_DD; + case "AUDIO_FORMAT_MPEG1": + return Constants.AUDIO_CODEC_MPEG1; + case "AUDIO_FORMAT_MP3": + return Constants.AUDIO_CODEC_MP3; + case "AUDIO_FORMAT_MPEG2": + return Constants.AUDIO_CODEC_MPEG2; + case "AUDIO_FORMAT_AAC": + return Constants.AUDIO_CODEC_AAC; + case "AUDIO_FORMAT_DTS": + return Constants.AUDIO_CODEC_DTS; + case "AUDIO_FORMAT_ATRAC": + return Constants.AUDIO_CODEC_ATRAC; + case "AUDIO_FORMAT_ONEBITAUDIO": + return Constants.AUDIO_CODEC_ONEBITAUDIO; + case "AUDIO_FORMAT_DDP": + return Constants.AUDIO_CODEC_DDP; + case "AUDIO_FORMAT_DTSHD": + return Constants.AUDIO_CODEC_DTSHD; + case "AUDIO_FORMAT_TRUEHD": + return Constants.AUDIO_CODEC_TRUEHD; + case "AUDIO_FORMAT_DST": + return Constants.AUDIO_CODEC_DST; + case "AUDIO_FORMAT_WMAPRO": + return Constants.AUDIO_CODEC_WMAPRO; + case "AUDIO_FORMAT_MAX": + return Constants.AUDIO_CODEC_MAX; + default: + return Constants.AUDIO_CODEC_NONE; + } + } + } + // Device configuration of its supported Codecs and their Short Audio Descriptors. public static class DeviceConfig { /** Name of the device. Should be {@link Constants.AudioDevice}. **/ @@ -399,10 +614,27 @@ final class HdmiUtils { /** List of a {@link CodecSad}. **/ public final List<CodecSad> supportedCodecs; - private DeviceConfig(String name, List<CodecSad> supportedCodecs) { + public DeviceConfig(String name, List<CodecSad> supportedCodecs) { this.name = name; this.supportedCodecs = supportedCodecs; } + + @Override + public boolean equals(Object obj) { + if (obj instanceof DeviceConfig) { + DeviceConfig that = (DeviceConfig) obj; + return that.name.equals(this.name) + && that.supportedCodecs.equals(this.supportedCodecs); + } + return false; + } + + @Override + public int hashCode() { + return Objects.hash( + name, + supportedCodecs.hashCode()); + } } // Short Audio Descriptor of a specific Codec @@ -419,5 +651,27 @@ final class HdmiUtils { this.audioCodec = audioCodec; this.sad = sad; } + + public CodecSad(int audioCodec, String sad) { + this.audioCodec = audioCodec; + this.sad = HexDump.hexStringToByteArray(sad); + } + + @Override + public boolean equals(Object obj) { + if (obj instanceof CodecSad) { + CodecSad that = (CodecSad) obj; + return that.audioCodec == this.audioCodec + && Arrays.equals(that.sad, this.sad); + } + return false; + } + + @Override + public int hashCode() { + return Objects.hash( + audioCodec, + Arrays.hashCode(sad)); + } } } diff --git a/services/core/java/com/android/server/input/InputManagerService.java b/services/core/java/com/android/server/input/InputManagerService.java index 979de66f1dc8..669ff2b7bad5 100644 --- a/services/core/java/com/android/server/input/InputManagerService.java +++ b/services/core/java/com/android/server/input/InputManagerService.java @@ -138,6 +138,9 @@ public class InputManagerService extends IInputManager.Stub private final Context mContext; private final InputManagerHandler mHandler; + // Context cache used for loading pointer resources. + private Context mDisplayContext; + private final File mDoubleTouchGestureEnableFile; private WindowManagerCallbacks mWindowManagerCallbacks; @@ -1923,8 +1926,25 @@ public class InputManagerService extends IInputManager.Stub } // Native callback. - private PointerIcon getPointerIcon() { - return PointerIcon.getDefaultIcon(mContext); + private PointerIcon getPointerIcon(int displayId) { + return PointerIcon.getDefaultIcon(getContextForDisplay(displayId)); + } + + private Context getContextForDisplay(int displayId) { + if (mDisplayContext != null && mDisplayContext.getDisplay().getDisplayId() == displayId) { + return mDisplayContext; + } + + if (mContext.getDisplay().getDisplayId() == displayId) { + mDisplayContext = mContext; + return mDisplayContext; + } + + // Create and cache context for non-default display. + final DisplayManager displayManager = mContext.getSystemService(DisplayManager.class); + final Display display = displayManager.getDisplay(displayId); + mDisplayContext = mContext.createDisplayContext(display); + return mDisplayContext; } // Native callback. diff --git a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java index 7ff6a2fc5574..7788d268f5c9 100644 --- a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java +++ b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java @@ -2903,7 +2903,23 @@ public class InputMethodManagerService extends IInputMethodManager.Stub @SoftInputModeFlags int softInputMode, int windowFlags, EditorInfo attribute, IInputContext inputContext, @MissingMethodFlags int missingMethods, int unverifiedTargetSdkVersion) { - final int userId = UserHandle.getUserId(Binder.getCallingUid()); + final int callingUserId = UserHandle.getCallingUserId(); + final int userId; + if (PER_PROFILE_IME_ENABLED && attribute != null && attribute.targetInputMethodUser != null + && attribute.targetInputMethodUser.getIdentifier() != callingUserId) { + mContext.enforceCallingPermission(Manifest.permission.INTERACT_ACROSS_USERS_FULL, + "Using EditorInfo.user requires INTERACT_ACROSS_USERS_FULL."); + userId = attribute.targetInputMethodUser.getIdentifier(); + if (!mUserManagerInternal.isUserRunning(userId)) { + // There is a chance that we hit here because of race condition. Let's just return + // an error code instead of crashing the caller process, which at least has + // INTERACT_ACROSS_USERS_FULL permission thus is likely to be an important process. + Slog.e(TAG, "User #" + userId + " is not running."); + return InputBindResult.INVALID_USER; + } + } else { + userId = callingUserId; + } InputBindResult res = null; synchronized (mMethodMap) { // Needs to check the validity before clearing calling identity diff --git a/services/core/java/com/android/server/job/JobConcurrencyManager.java b/services/core/java/com/android/server/job/JobConcurrencyManager.java index 827c0f1df71a..4d9b5f5d01c6 100644 --- a/services/core/java/com/android/server/job/JobConcurrencyManager.java +++ b/services/core/java/com/android/server/job/JobConcurrencyManager.java @@ -18,16 +18,34 @@ package com.android.server.job; import android.app.ActivityManager; import android.app.job.JobInfo; +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.Intent; +import android.content.IntentFilter; +import android.os.Handler; +import android.os.PowerManager; import android.os.RemoteException; import android.util.Slog; +import android.util.TimeUtils; +import android.util.proto.ProtoOutputStream; +import com.android.internal.annotations.GuardedBy; +import com.android.internal.annotations.VisibleForTesting; import com.android.internal.app.procstats.ProcessStats; +import com.android.internal.os.BackgroundThread; +import com.android.internal.util.IndentingPrintWriter; +import com.android.internal.util.StatLogger; +import com.android.server.job.JobSchedulerService.Constants; import com.android.server.job.controllers.JobStatus; import com.android.server.job.controllers.StateController; import java.util.Iterator; import java.util.List; +/** + * This class decides, given the various configuration and the system status, how many more jobs + * can start. + */ class JobConcurrencyManager { private static final String TAG = JobSchedulerService.TAG; private static final boolean DEBUG = JobSchedulerService.DEBUG; @@ -35,6 +53,16 @@ class JobConcurrencyManager { private final Object mLock; private final JobSchedulerService mService; private final JobSchedulerService.Constants mConstants; + private final Context mContext; + private final Handler mHandler; + + private PowerManager mPowerManager; + + private boolean mCurrentInteractiveState; + private boolean mEffectiveInteractiveState; + + private long mLastScreenOnRealtime; + private long mLastScreenOffRealtime; private static final int MAX_JOB_CONTEXTS_COUNT = JobSchedulerService.MAX_JOB_CONTEXTS_COUNT; @@ -50,10 +78,193 @@ class JobConcurrencyManager { int[] mRecycledPreferredUidForContext = new int[MAX_JOB_CONTEXTS_COUNT]; + /** Max job counts according to the current system state. */ + private JobSchedulerService.MaxJobCounts mMaxJobCounts; + + private final JobCountTracker mJobCountTracker = new JobCountTracker(); + + /** Current memory trim level. */ + private int mLastMemoryTrimLevel; + + /** Used to throttle heavy API calls. */ + private long mNextSystemStateRefreshTime; + private static final int SYSTEM_STATE_REFRESH_MIN_INTERVAL = 1000; + + private final StatLogger mStatLogger = new StatLogger(new String[]{ + "assignJobsToContexts", + "refreshSystemState", + }); + + interface Stats { + int ASSIGN_JOBS_TO_CONTEXTS = 0; + int REFRESH_SYSTEM_STATE = 1; + + int COUNT = REFRESH_SYSTEM_STATE + 1; + } + JobConcurrencyManager(JobSchedulerService service) { mService = service; mLock = mService.mLock; mConstants = service.mConstants; + mContext = service.getContext(); + + mHandler = BackgroundThread.getHandler(); + } + + public void onSystemReady() { + mPowerManager = mContext.getSystemService(PowerManager.class); + + final IntentFilter filter = new IntentFilter(Intent.ACTION_SCREEN_ON); + filter.addAction(Intent.ACTION_SCREEN_OFF); + mContext.registerReceiver(mReceiver, filter); + + onInteractiveStateChanged(mPowerManager.isInteractive()); + } + + private final BroadcastReceiver mReceiver = new BroadcastReceiver() { + @Override + public void onReceive(Context context, Intent intent) { + switch (intent.getAction()) { + case Intent.ACTION_SCREEN_ON: + onInteractiveStateChanged(true); + break; + case Intent.ACTION_SCREEN_OFF: + onInteractiveStateChanged(false); + break; + } + } + }; + + /** + * Called when the screen turns on / off. + */ + private void onInteractiveStateChanged(boolean interactive) { + synchronized (mLock) { + if (mCurrentInteractiveState == interactive) { + return; + } + mCurrentInteractiveState = interactive; + if (DEBUG) { + Slog.d(TAG, "Interactive: " + interactive); + } + + final long now = JobSchedulerService.sElapsedRealtimeClock.millis(); + if (interactive) { + mLastScreenOnRealtime = now; + mEffectiveInteractiveState = true; + + mHandler.removeCallbacks(mRampUpForScreenOff); + } else { + mLastScreenOffRealtime = now; + + // Set mEffectiveInteractiveState to false after the delay, when we may increase + // the concurrency. + // We don't need a wakeup alarm here. When there's a pending job, there should + // also be jobs running too, meaning the device should be awake. + + // Note: we can't directly do postDelayed(this::rampUpForScreenOn), because + // we need the exact same instance for removeCallbacks(). + mHandler.postDelayed(mRampUpForScreenOff, + mConstants.SCREEN_OFF_JOB_CONCURRENCY_INCREASE_DELAY_MS.getValue()); + } + } + } + + private final Runnable mRampUpForScreenOff = this::rampUpForScreenOff; + + /** + * Called in {@link Constants#SCREEN_OFF_JOB_CONCURRENCY_INCREASE_DELAY_MS} after + * the screen turns off, in order to increase concurrency. + */ + private void rampUpForScreenOff() { + synchronized (mLock) { + // Make sure the screen has really been off for the configured duration. + // (There could be a race.) + if (!mEffectiveInteractiveState) { + return; + } + if (mLastScreenOnRealtime > mLastScreenOffRealtime) { + return; + } + final long now = JobSchedulerService.sElapsedRealtimeClock.millis(); + if ((mLastScreenOffRealtime + + mConstants.SCREEN_OFF_JOB_CONCURRENCY_INCREASE_DELAY_MS.getValue()) + > now) { + return; + } + + mEffectiveInteractiveState = false; + + if (DEBUG) { + Slog.d(TAG, "Ramping up concurrency"); + } + + mService.maybeRunPendingJobsLocked(); + } + } + + private boolean isFgJob(JobStatus job) { + return job.lastEvaluatedPriority >= JobInfo.PRIORITY_TOP_APP; + } + + @GuardedBy("mLock") + private void refreshSystemStateLocked() { + final long nowUptime = JobSchedulerService.sUptimeMillisClock.millis(); + + // Only refresh the information every so often. + if (nowUptime < mNextSystemStateRefreshTime) { + return; + } + + final long start = mStatLogger.getTime(); + mNextSystemStateRefreshTime = nowUptime + SYSTEM_STATE_REFRESH_MIN_INTERVAL; + + mLastMemoryTrimLevel = ProcessStats.ADJ_MEM_FACTOR_NORMAL; + try { + mLastMemoryTrimLevel = ActivityManager.getService().getMemoryTrimLevel(); + } catch (RemoteException e) { + } + + mStatLogger.logDurationStat(Stats.REFRESH_SYSTEM_STATE, start); + } + + @GuardedBy("mLock") + private void updateMaxCountsLocked() { + refreshSystemStateLocked(); + + if (mEffectiveInteractiveState) { + // Screen on + switch (mLastMemoryTrimLevel) { + case ProcessStats.ADJ_MEM_FACTOR_MODERATE: + mMaxJobCounts = mConstants.MAX_JOB_COUNTS_ON_MODERATE; + break; + case ProcessStats.ADJ_MEM_FACTOR_LOW: + mMaxJobCounts = mConstants.MAX_JOB_COUNTS_ON_LOW; + break; + case ProcessStats.ADJ_MEM_FACTOR_CRITICAL: + mMaxJobCounts = mConstants.MAX_JOB_COUNTS_ON_CRITICAL; + break; + default: + mMaxJobCounts = mConstants.MAX_JOB_COUNTS_ON_NORMAL; + break; + } + } else { + // Screen off + switch (mLastMemoryTrimLevel) { + case ProcessStats.ADJ_MEM_FACTOR_MODERATE: + mMaxJobCounts = mConstants.MAX_JOB_COUNTS_OFF_MODERATE; + break; + case ProcessStats.ADJ_MEM_FACTOR_LOW: + mMaxJobCounts = mConstants.MAX_JOB_COUNTS_OFF_LOW; + break; + case ProcessStats.ADJ_MEM_FACTOR_CRITICAL: + mMaxJobCounts = mConstants.MAX_JOB_COUNTS_OFF_CRITICAL; + break; + default: + mMaxJobCounts = mConstants.MAX_JOB_COUNTS_OFF_NORMAL; + break; + } + } } /** @@ -62,7 +273,17 @@ class JobConcurrencyManager { * run higher priority ones. * Lock on mJobs before calling this function. */ + @GuardedBy("mLock") void assignJobsToContextsLocked() { + final long start = mStatLogger.getTime(); + + assignJobsToContextsInternalLocked(); + + mStatLogger.logDurationStat(Stats.ASSIGN_JOBS_TO_CONTEXTS, start); + } + + @GuardedBy("mLock") + private void assignJobsToContextsInternalLocked() { if (DEBUG) { Slog.d(TAG, printPendingQueueLocked()); } @@ -72,60 +293,63 @@ class JobConcurrencyManager { final List<JobServiceContext> activeServices = mService.mActiveServices; final List<StateController> controllers = mService.mControllers; - int memLevel; - try { - memLevel = ActivityManager.getService().getMemoryTrimLevel(); - } catch (RemoteException e) { - memLevel = ProcessStats.ADJ_MEM_FACTOR_NORMAL; - } - switch (memLevel) { - case ProcessStats.ADJ_MEM_FACTOR_MODERATE: - mService.mMaxActiveJobs = mConstants.BG_MODERATE_JOB_COUNT; - break; - case ProcessStats.ADJ_MEM_FACTOR_LOW: - mService.mMaxActiveJobs = mConstants.BG_LOW_JOB_COUNT; - break; - case ProcessStats.ADJ_MEM_FACTOR_CRITICAL: - mService.mMaxActiveJobs = mConstants.BG_CRITICAL_JOB_COUNT; - break; - default: - mService.mMaxActiveJobs = mConstants.BG_NORMAL_JOB_COUNT; - break; - } + updateMaxCountsLocked(); // To avoid GC churn, we recycle the arrays. JobStatus[] contextIdToJobMap = mRecycledAssignContextIdToJobMap; boolean[] slotChanged = mRecycledSlotChanged; int[] preferredUidForContext = mRecycledPreferredUidForContext; - int numTotalRunningJobs = 0; - int numForegroundJobs = 0; + + // Initialize the work variables and also count running jobs. + mJobCountTracker.reset( + mMaxJobCounts.getTotalMax(), + mMaxJobCounts.getMaxBg(), + mMaxJobCounts.getMinBg()); + for (int i=0; i<MAX_JOB_CONTEXTS_COUNT; i++) { final JobServiceContext js = mService.mActiveServices.get(i); final JobStatus status = js.getRunningJobLocked(); + if ((contextIdToJobMap[i] = status) != null) { - numTotalRunningJobs++; - if (status.lastEvaluatedPriority >= JobInfo.PRIORITY_TOP_APP) { - numForegroundJobs++; - } + mJobCountTracker.incrementRunningJobCount(isFgJob(status)); } + slotChanged[i] = false; preferredUidForContext[i] = js.getPreferredUid(); } if (DEBUG) { Slog.d(TAG, printContextIdToJobMap(contextIdToJobMap, "running jobs initial")); } - for (int i=0; i<pendingJobs.size(); i++) { - final JobStatus nextPending = pendingJobs.get(i); + + // Next, update the job priorities, and also count the pending FG / BG jobs. + for (int i = 0; i < pendingJobs.size(); i++) { + final JobStatus pending = pendingJobs.get(i); // If job is already running, go to next job. + int jobRunningContext = findJobContextIdFromMap(pending, contextIdToJobMap); + if (jobRunningContext != -1) { + continue; + } + + final int priority = mService.evaluateJobPriorityLocked(pending); + pending.lastEvaluatedPriority = priority; + + mJobCountTracker.incrementPendingJobCount(isFgJob(pending)); + } + + mJobCountTracker.onCountDone(); + + for (int i = 0; i < pendingJobs.size(); i++) { + final JobStatus nextPending = pendingJobs.get(i); + + // Unfortunately we need to repeat this relatively expensive check. int jobRunningContext = findJobContextIdFromMap(nextPending, contextIdToJobMap); if (jobRunningContext != -1) { continue; } - final int priority = mService.evaluateJobPriorityLocked(nextPending); - nextPending.lastEvaluatedPriority = priority; + final boolean isPendingFg = isFgJob(nextPending); // Find an available slot for nextPending. The context should be available OR // it should have lowest priority among all running jobs @@ -137,18 +361,10 @@ class JobConcurrencyManager { JobStatus job = contextIdToJobMap[j]; int preferredUid = preferredUidForContext[j]; if (job == null) { - final boolean totalCountOk = numTotalRunningJobs < mService.mMaxActiveJobs; - final boolean fgCountOk = (priority >= JobInfo.PRIORITY_TOP_APP) - && (numForegroundJobs < mConstants.FG_JOB_COUNT); final boolean preferredUidOkay = (preferredUid == nextPending.getUid()) || (preferredUid == JobServiceContext.NO_PREFERRED_UID); - // TODO: The following check is slightly wrong. - // Depending on how the pending jobs are sorted, we sometimes cap the total - // job count at mMaxActiveJobs (when all jobs are FG jobs), or - // at [mMaxActiveJobs + FG_JOB_COUNT] (when there are mMaxActiveJobs BG jobs - // and then FG_JOB_COUNT FG jobs.) - if ((totalCountOk || fgCountOk) && preferredUidOkay) { + if (preferredUidOkay && mJobCountTracker.canJobStart(isPendingFg)) { // This slot is free, and we haven't yet hit the limit on // concurrent jobs... we can just throw the job in to here. selectedContextId = j; @@ -183,16 +399,18 @@ class JobConcurrencyManager { } if (startingJob) { // Increase the counters when we're going to start a job. - numTotalRunningJobs++; - if (priority >= JobInfo.PRIORITY_TOP_APP) { - numForegroundJobs++; - } + mJobCountTracker.onStartingNewJob(isPendingFg); } } if (DEBUG) { Slog.d(TAG, printContextIdToJobMap(contextIdToJobMap, "running jobs final")); } - tracker.noteConcurrency(numTotalRunningJobs, numForegroundJobs); + + mJobCountTracker.logStatus(); + + tracker.noteConcurrency(mJobCountTracker.getTotalRunningJobCountToNote(), + mJobCountTracker.getFgRunningJobCountToNote()); + for (int i=0; i<MAX_JOB_CONTEXTS_COUNT; i++) { boolean preservePreferredUid = false; if (slotChanged[i]) { @@ -228,7 +446,7 @@ class JobConcurrencyManager { } } - int findJobContextIdFromMap(JobStatus jobStatus, JobStatus[] map) { + private static int findJobContextIdFromMap(JobStatus jobStatus, JobStatus[] map) { for (int i=0; i<map.length; i++) { if (map[i] != null && map[i].matches(jobStatus.getUid(), jobStatus.getJobId())) { return i; @@ -237,6 +455,7 @@ class JobConcurrencyManager { return -1; } + @GuardedBy("mLock") private String printPendingQueueLocked() { StringBuilder s = new StringBuilder("Pending queue: "); Iterator<JobStatus> it = mService.mPendingJobs.iterator(); @@ -251,7 +470,7 @@ class JobConcurrencyManager { return s.toString(); } - private String printContextIdToJobMap(JobStatus[] map, String initial) { + private static String printContextIdToJobMap(JobStatus[] map, String initial) { StringBuilder s = new StringBuilder(initial + ": "); for (int i=0; i<map.length; i++) { s.append("(") @@ -262,4 +481,222 @@ class JobConcurrencyManager { return s.toString(); } + + public void dumpLocked(IndentingPrintWriter pw) { + final long now = System.currentTimeMillis(); + final long nowRealtime = JobSchedulerService.sElapsedRealtimeClock.millis(); + + pw.println("Concurrency:"); + + pw.increaseIndent(); + try { + pw.print("Screen state: current "); + pw.print(mCurrentInteractiveState ? "ON" : "OFF"); + pw.print(" effective "); + pw.print(mEffectiveInteractiveState ? "ON" : "OFF"); + pw.println(); + + pw.print("Last screen ON : "); + TimeUtils.dumpTimeWithDelta(pw, now - nowRealtime + mLastScreenOnRealtime, now); + pw.println(); + + pw.print("Last screen OFF: "); + TimeUtils.dumpTimeWithDelta(pw, now - nowRealtime + mLastScreenOffRealtime, now); + pw.println(); + + pw.println(); + + pw.println("Current max jobs:"); + pw.println(" "); + pw.println(mJobCountTracker); + + pw.println(); + + pw.print("mLastMemoryTrimLevel: "); + pw.print(mLastMemoryTrimLevel); + pw.println(); + + mStatLogger.dump(pw); + } finally { + pw.decreaseIndent(); + } + } + + public void dumpProtoLocked(ProtoOutputStream proto) { + // TODO Implement it. + } + + /** + * This class decides, taking into account {@link #mMaxJobCounts} and how many jos are running / + * pending, how many more job can start. + * + * Extracted for testing and logging. + */ + @VisibleForTesting + static class JobCountTracker { + private int mConfigNumTotalMaxJobs; + private int mConfigNumMaxBgJobs; + private int mConfigNumMinBgJobs; + + private int mNumRunningFgJobs; + private int mNumRunningBgJobs; + + private int mNumPendingFgJobs; + private int mNumPendingBgJobs; + + private int mNumStartingFgJobs; + private int mNumStartingBgJobs; + + private int mNumReservedForBg; + private int mNumActualMaxFgJobs; + private int mNumActualMaxBgJobs; + + void reset(int numTotalMaxJobs, int numMaxBgJobs, int numMinBgJobs) { + mConfigNumTotalMaxJobs = numTotalMaxJobs; + mConfigNumMaxBgJobs = numMaxBgJobs; + mConfigNumMinBgJobs = numMinBgJobs; + + mNumRunningFgJobs = 0; + mNumRunningBgJobs = 0; + + mNumPendingFgJobs = 0; + mNumPendingBgJobs = 0; + + mNumStartingFgJobs = 0; + mNumStartingBgJobs = 0; + + mNumReservedForBg = 0; + mNumActualMaxFgJobs = 0; + mNumActualMaxBgJobs = 0; + } + + void incrementRunningJobCount(boolean isFg) { + if (isFg) { + mNumRunningFgJobs++; + } else { + mNumRunningBgJobs++; + } + } + + void incrementPendingJobCount(boolean isFg) { + if (isFg) { + mNumPendingFgJobs++; + } else { + mNumPendingBgJobs++; + } + } + + void onStartingNewJob(boolean isFg) { + if (isFg) { + mNumStartingFgJobs++; + } else { + mNumStartingBgJobs++; + } + } + + void onCountDone() { + // Note some variables are used only here but are made class members in order to have + // them on logcat / dumpsys. + + // How many slots should we allocate to BG jobs at least? + // That's basically "getMinBg()", but if there are less jobs, decrease it. + // (e.g. even if min-bg is 2, if there's only 1 running+pending job, this has to be 1.) + final int reservedForBg = Math.min( + mConfigNumMinBgJobs, + mNumRunningBgJobs + mNumPendingBgJobs); + + // However, if there are FG jobs already running, we have to adjust it. + mNumReservedForBg = Math.min(reservedForBg, + mConfigNumTotalMaxJobs - mNumRunningFgJobs); + + // Max FG is [total - [number needed for BG jobs]] + // [number needed for BG jobs] is the bigger one of [running BG] or [reserved BG] + final int maxFg = + mConfigNumTotalMaxJobs - Math.max(mNumRunningBgJobs, mNumReservedForBg); + + // The above maxFg is the theoretical max. If there are less FG jobs, the actual + // max FG will be lower accordingly. + mNumActualMaxFgJobs = Math.min( + maxFg, + mNumRunningFgJobs + mNumPendingFgJobs); + + // Max BG is [total - actual max FG], but cap at [config max BG]. + final int maxBg = Math.min( + mConfigNumMaxBgJobs, + mConfigNumTotalMaxJobs - mNumActualMaxFgJobs); + + // If there are less BG jobs than maxBg, then reduce the actual max BG accordingly. + // This isn't needed for the logic to work, but this will give consistent output + // on logcat and dumpsys. + mNumActualMaxBgJobs = Math.min( + maxBg, + mNumRunningBgJobs + mNumPendingBgJobs); + } + + boolean canJobStart(boolean isFg) { + if (isFg) { + return mNumRunningFgJobs + mNumStartingFgJobs < mNumActualMaxFgJobs; + } else { + return mNumRunningBgJobs + mNumStartingBgJobs < mNumActualMaxBgJobs; + } + } + + public int getNumStartingFgJobs() { + return mNumStartingFgJobs; + } + + public int getNumStartingBgJobs() { + return mNumStartingBgJobs; + } + + int getTotalRunningJobCountToNote() { + return mNumRunningFgJobs + mNumRunningBgJobs + + mNumStartingFgJobs + mNumStartingBgJobs; + } + + int getFgRunningJobCountToNote() { + return mNumRunningFgJobs + mNumStartingFgJobs; + } + + void logStatus() { + if (DEBUG) { + Slog.d(TAG, "assignJobsToContexts: " + this); + } + } + + public String toString() { + final int totalFg = mNumRunningFgJobs + mNumStartingFgJobs; + final int totalBg = mNumRunningBgJobs + mNumStartingBgJobs; + return String.format( + "Config={tot=%d bg min/max=%d/%d}" + + " Running: %d / %d (%d)" + + " Pending: %d / %d (%d)" + + " Actual max: %d%s / %d%s (%d%s)" + + " Starting: %d / %d (%d)" + + " Total: %d%s / %d%s (%d%s)", + mConfigNumTotalMaxJobs, + mConfigNumMinBgJobs, + mConfigNumMaxBgJobs, + + mNumRunningFgJobs, mNumRunningBgJobs, + mNumRunningFgJobs + mNumRunningBgJobs, + + mNumPendingFgJobs, mNumPendingBgJobs, + mNumPendingFgJobs + mNumPendingBgJobs, + + mNumActualMaxFgJobs, (totalFg <= mConfigNumTotalMaxJobs) ? "" : "*", + mNumActualMaxBgJobs, (totalBg <= mConfigNumMaxBgJobs) ? "" : "*", + + mNumActualMaxFgJobs + mNumActualMaxBgJobs, + (mNumActualMaxFgJobs + mNumActualMaxBgJobs <= mConfigNumTotalMaxJobs) + ? "" : "*", + + mNumStartingFgJobs, mNumStartingBgJobs, mNumStartingFgJobs + mNumStartingBgJobs, + + totalFg, (totalFg <= mNumActualMaxFgJobs) ? "" : "*", + totalBg, (totalBg <= mNumActualMaxBgJobs) ? "" : "*", + totalFg + totalBg, (totalFg + totalBg <= mConfigNumTotalMaxJobs) ? "" : "*" + ); + } + } } diff --git a/services/core/java/com/android/server/job/JobSchedulerService.java b/services/core/java/com/android/server/job/JobSchedulerService.java index 2464ca782b6e..cc0ac9a7e0a9 100644 --- a/services/core/java/com/android/server/job/JobSchedulerService.java +++ b/services/core/java/com/android/server/job/JobSchedulerService.java @@ -224,12 +224,6 @@ public class JobSchedulerService extends com.android.server.SystemService volatile boolean mInParole; /** - * Current limit on the number of concurrent JobServiceContext entries we want to - * keep actively running a job. - */ - int mMaxActiveJobs = 1; - - /** * A mapping of which uids are currently in the foreground to their effective priority. */ final SparseIntArray mUidPriorityOverride = new SparseIntArray(); @@ -332,41 +326,68 @@ public class JobSchedulerService extends com.android.server.SystemService } } - private static class MaxJobCounts { + static class MaxJobCounts { private final KeyValueListParser.IntValue mTotal; - private final KeyValueListParser.IntValue mBg; + private final KeyValueListParser.IntValue mMaxBg; + private final KeyValueListParser.IntValue mMinBg; - private MaxJobCounts(int totalDefault, String totalKey, int bgDefault, String bgKey) { + MaxJobCounts(int totalDefault, String totalKey, + int maxBgDefault, String maxBgKey, int minBgDefault, String minBgKey) { mTotal = new KeyValueListParser.IntValue(totalKey, totalDefault); - mBg = new KeyValueListParser.IntValue(bgKey, bgDefault); + mMaxBg = new KeyValueListParser.IntValue(maxBgKey, maxBgDefault); + mMinBg = new KeyValueListParser.IntValue(minBgKey, minBgDefault); } public void parse(KeyValueListParser parser) { mTotal.parse(parser); - mBg.parse(parser); + mMaxBg.parse(parser); + mMinBg.parse(parser); - if (mBg.getValue() > mTotal.getValue()) { - mBg.setValue(mTotal.getValue()); + if (mTotal.getValue() < 1) { + mTotal.setValue(1); + } else if (mTotal.getValue() > MAX_JOB_CONTEXTS_COUNT) { + mTotal.setValue(MAX_JOB_CONTEXTS_COUNT); } + if (mMaxBg.getValue() < 1) { + mMaxBg.setValue(1); + } else if (mMaxBg.getValue() > mTotal.getValue()) { + mMaxBg.setValue(mTotal.getValue()); + } + if (mMinBg.getValue() < 0) { + mMinBg.setValue(0); + } else { + if (mMinBg.getValue() > mMaxBg.getValue()) { + mMinBg.setValue(mMaxBg.getValue()); + } + if (mMinBg.getValue() >= mTotal.getValue()) { + mMinBg.setValue(mTotal.getValue() - 1); + } + } } public int getTotalMax() { return mTotal.getValue(); } - public int getBgMax() { - return mBg.getValue(); + public int getMaxBg() { + return mMaxBg.getValue(); + } + + public int getMinBg() { + return mMinBg.getValue(); } public void dump(PrintWriter pw, String prefix) { mTotal.dump(pw, prefix); - mBg.dump(pw, prefix); + mMaxBg.dump(pw, prefix); + mMinBg.dump(pw, prefix); } public void dumpProto(ProtoOutputStream proto, long tagTotal, long tagBg) { mTotal.dumpProto(proto, tagTotal); - mBg.dumpProto(proto, tagBg); + mMaxBg.dumpProto(proto, tagBg); + mMinBg.dumpProto(proto, tagBg); } } @@ -386,11 +407,14 @@ public class JobSchedulerService extends com.android.server.SystemService private static final String KEY_MIN_READY_JOBS_COUNT = "min_ready_jobs_count"; private static final String KEY_HEAVY_USE_FACTOR = "heavy_use_factor"; private static final String KEY_MODERATE_USE_FACTOR = "moderate_use_factor"; - private static final String KEY_FG_JOB_COUNT = "fg_job_count"; - private static final String KEY_BG_NORMAL_JOB_COUNT = "bg_normal_job_count"; - private static final String KEY_BG_MODERATE_JOB_COUNT = "bg_moderate_job_count"; - private static final String KEY_BG_LOW_JOB_COUNT = "bg_low_job_count"; - private static final String KEY_BG_CRITICAL_JOB_COUNT = "bg_critical_job_count"; + + // The following values used to be used on P and below. Do not reuse them. + private static final String DEPRECATED_KEY_FG_JOB_COUNT = "fg_job_count"; + private static final String DEPRECATED_KEY_BG_NORMAL_JOB_COUNT = "bg_normal_job_count"; + private static final String DEPRECATED_KEY_BG_MODERATE_JOB_COUNT = "bg_moderate_job_count"; + private static final String DEPRECATED_KEY_BG_LOW_JOB_COUNT = "bg_low_job_count"; + private static final String DEPRECATED_KEY_BG_CRITICAL_JOB_COUNT = "bg_critical_job_count"; + private static final String KEY_MAX_STANDARD_RESCHEDULE_COUNT = "max_standard_reschedule_count"; private static final String KEY_MAX_WORK_RESCHEDULE_COUNT = "max_work_reschedule_count"; @@ -429,11 +453,6 @@ public class JobSchedulerService extends com.android.server.SystemService private static final int DEFAULT_MIN_READY_JOBS_COUNT = 1; private static final float DEFAULT_HEAVY_USE_FACTOR = .9f; private static final float DEFAULT_MODERATE_USE_FACTOR = .5f; - private static final int DEFAULT_FG_JOB_COUNT = 4; - private static final int DEFAULT_BG_NORMAL_JOB_COUNT = 6; - private static final int DEFAULT_BG_MODERATE_JOB_COUNT = 4; - private static final int DEFAULT_BG_LOW_JOB_COUNT = 1; - private static final int DEFAULT_BG_CRITICAL_JOB_COUNT = 1; private static final int DEFAULT_MAX_STANDARD_RESCHEDULE_COUNT = Integer.MAX_VALUE; private static final int DEFAULT_MAX_WORK_RESCHEDULE_COUNT = Integer.MAX_VALUE; private static final long DEFAULT_MIN_LINEAR_BACKOFF_TIME = JobInfo.MIN_BACKOFF_MILLIS; @@ -506,66 +525,52 @@ public class JobSchedulerService extends com.android.server.SystemService * This is the job execution factor that is considered to be moderate use of the system. */ float MODERATE_USE_FACTOR = DEFAULT_MODERATE_USE_FACTOR; - /** - * The number of MAX_JOB_CONTEXTS_COUNT we reserve for the foreground app. - */ - int FG_JOB_COUNT = DEFAULT_FG_JOB_COUNT; - /** - * The maximum number of background jobs we allow when the system is in a normal - * memory state. - */ - int BG_NORMAL_JOB_COUNT = DEFAULT_BG_NORMAL_JOB_COUNT; - /** - * The maximum number of background jobs we allow when the system is in a moderate - * memory state. - */ - int BG_MODERATE_JOB_COUNT = DEFAULT_BG_MODERATE_JOB_COUNT; - /** - * The maximum number of background jobs we allow when the system is in a low - * memory state. - */ - int BG_LOW_JOB_COUNT = DEFAULT_BG_LOW_JOB_COUNT; - /** - * The maximum number of background jobs we allow when the system is in a critical - * memory state. - */ - int BG_CRITICAL_JOB_COUNT = DEFAULT_BG_CRITICAL_JOB_COUNT; // Max job counts for screen on / off, for each memory trim level. - // TODO Remove the old configs such as FG_JOB_COUNT and BG_*_COUNT, once the code switches - // to the below configs. - final MaxJobCounts MAX_JOB_COUNTS_ON_NORMAL = new MaxJobCounts( - 4, "max_job_total_on_normal", - 2, "max_job_bg_on_normal"); + 8, "max_job_total_on_normal", + 6, "max_job_max_bg_on_normal", + 2, "max_job_min_bg_on_normal"); final MaxJobCounts MAX_JOB_COUNTS_ON_MODERATE = new MaxJobCounts( - 4, "max_job_total_on_moderate", - 1, "max_job_bg_on_moderate"); + 8, "max_job_total_on_moderate", + 4, "max_job_max_bg_on_moderate", + 2, "max_job_min_bg_on_moderate"); final MaxJobCounts MAX_JOB_COUNTS_ON_LOW = new MaxJobCounts( - 4, "max_job_total_on_low", - 1, "max_job_bg_on_low"); + 5, "max_job_total_on_low", + 1, "max_job_max_bg_on_low", + 1, "max_job_min_bg_on_low"); final MaxJobCounts MAX_JOB_COUNTS_ON_CRITICAL = new MaxJobCounts( - 2, "max_job_total_on_critical", - 1, "max_job_bg_on_critical"); + 5, "max_job_total_on_critical", + 1, "max_job_max_bg_on_critical", + 1, "max_job_min_bg_on_critical"); final MaxJobCounts MAX_JOB_COUNTS_OFF_NORMAL = new MaxJobCounts( - 8, "max_job_total_off_normal", - 4, "max_job_bg_off_normal"); + 10, "max_job_total_off_normal", + 6, "max_job_max_bg_off_normal", + 2, "max_job_min_bg_off_normal"); final MaxJobCounts MAX_JOB_COUNTS_OFF_MODERATE = new MaxJobCounts( - 6, "max_job_total_off_moderate", - 4, "max_job_bg_off_moderate"); + 10, "max_job_total_off_moderate", + 4, "max_job_max_bg_off_moderate", + 2, "max_job_min_bg_off_moderate"); final MaxJobCounts MAX_JOB_COUNTS_OFF_LOW = new MaxJobCounts( - 4, "max_job_total_off_low", - 1, "max_job_bg_off_low"); + 5, "max_job_total_off_low", + 1, "max_job_max_bg_off_low", + 1, "max_job_min_bg_off_low"); final MaxJobCounts MAX_JOB_COUNTS_OFF_CRITICAL = new MaxJobCounts( - 2, "max_job_total_off_critical", - 1, "max_job_bg_off_critical"); + 5, "max_job_total_off_critical", + 1, "max_job_max_bg_off_critical", + 1, "max_job_min_bg_off_critical"); + + /** Wait for this long after screen off before increasing the job concurrency. */ + final KeyValueListParser.IntValue SCREEN_OFF_JOB_CONCURRENCY_INCREASE_DELAY_MS = + new KeyValueListParser.IntValue( + "screen_off_job_concurrency_increase_delay_ms", 30_000); /** * The maximum number of times we allow a job to have itself rescheduled before @@ -706,28 +711,6 @@ public class JobSchedulerService extends com.android.server.SystemService DEFAULT_HEAVY_USE_FACTOR); MODERATE_USE_FACTOR = mParser.getFloat(KEY_MODERATE_USE_FACTOR, DEFAULT_MODERATE_USE_FACTOR); - FG_JOB_COUNT = mParser.getInt(KEY_FG_JOB_COUNT, - DEFAULT_FG_JOB_COUNT); - BG_NORMAL_JOB_COUNT = mParser.getInt(KEY_BG_NORMAL_JOB_COUNT, - DEFAULT_BG_NORMAL_JOB_COUNT); - if ((FG_JOB_COUNT+BG_NORMAL_JOB_COUNT) > MAX_JOB_CONTEXTS_COUNT) { - BG_NORMAL_JOB_COUNT = MAX_JOB_CONTEXTS_COUNT - FG_JOB_COUNT; - } - BG_MODERATE_JOB_COUNT = mParser.getInt(KEY_BG_MODERATE_JOB_COUNT, - DEFAULT_BG_MODERATE_JOB_COUNT); - if ((FG_JOB_COUNT+BG_MODERATE_JOB_COUNT) > MAX_JOB_CONTEXTS_COUNT) { - BG_MODERATE_JOB_COUNT = MAX_JOB_CONTEXTS_COUNT - FG_JOB_COUNT; - } - BG_LOW_JOB_COUNT = mParser.getInt(KEY_BG_LOW_JOB_COUNT, - DEFAULT_BG_LOW_JOB_COUNT); - if ((FG_JOB_COUNT+BG_LOW_JOB_COUNT) > MAX_JOB_CONTEXTS_COUNT) { - BG_LOW_JOB_COUNT = MAX_JOB_CONTEXTS_COUNT - FG_JOB_COUNT; - } - BG_CRITICAL_JOB_COUNT = mParser.getInt(KEY_BG_CRITICAL_JOB_COUNT, - DEFAULT_BG_CRITICAL_JOB_COUNT); - if ((FG_JOB_COUNT+BG_CRITICAL_JOB_COUNT) > MAX_JOB_CONTEXTS_COUNT) { - BG_CRITICAL_JOB_COUNT = MAX_JOB_CONTEXTS_COUNT - FG_JOB_COUNT; - } MAX_JOB_COUNTS_ON_NORMAL.parse(mParser); MAX_JOB_COUNTS_ON_MODERATE.parse(mParser); @@ -798,11 +781,6 @@ public class JobSchedulerService extends com.android.server.SystemService pw.printPair(KEY_MIN_READY_JOBS_COUNT, MIN_READY_JOBS_COUNT).println(); pw.printPair(KEY_HEAVY_USE_FACTOR, HEAVY_USE_FACTOR).println(); pw.printPair(KEY_MODERATE_USE_FACTOR, MODERATE_USE_FACTOR).println(); - pw.printPair(KEY_FG_JOB_COUNT, FG_JOB_COUNT).println(); - pw.printPair(KEY_BG_NORMAL_JOB_COUNT, BG_NORMAL_JOB_COUNT).println(); - pw.printPair(KEY_BG_MODERATE_JOB_COUNT, BG_MODERATE_JOB_COUNT).println(); - pw.printPair(KEY_BG_LOW_JOB_COUNT, BG_LOW_JOB_COUNT).println(); - pw.printPair(KEY_BG_CRITICAL_JOB_COUNT, BG_CRITICAL_JOB_COUNT).println(); MAX_JOB_COUNTS_ON_NORMAL.dump(pw, ""); MAX_JOB_COUNTS_ON_MODERATE.dump(pw, ""); @@ -859,11 +837,6 @@ public class JobSchedulerService extends com.android.server.SystemService proto.write(ConstantsProto.MIN_READY_JOBS_COUNT, MIN_READY_JOBS_COUNT); proto.write(ConstantsProto.HEAVY_USE_FACTOR, HEAVY_USE_FACTOR); proto.write(ConstantsProto.MODERATE_USE_FACTOR, MODERATE_USE_FACTOR); - proto.write(ConstantsProto.FG_JOB_COUNT, FG_JOB_COUNT); - proto.write(ConstantsProto.BG_NORMAL_JOB_COUNT, BG_NORMAL_JOB_COUNT); - proto.write(ConstantsProto.BG_MODERATE_JOB_COUNT, BG_MODERATE_JOB_COUNT); - proto.write(ConstantsProto.BG_LOW_JOB_COUNT, BG_LOW_JOB_COUNT); - proto.write(ConstantsProto.BG_CRITICAL_JOB_COUNT, BG_CRITICAL_JOB_COUNT); // TODO Dump max job counts. @@ -1558,6 +1531,9 @@ public class JobSchedulerService extends com.android.server.SystemService } catch (RemoteException e) { // ignored; both services live in system_server } + + mConcurrencyManager.onSystemReady(); + // Remove any jobs that are not associated with any of the current users. cancelJobsForNonExistentUsers(); // Register thermal callback @@ -1685,7 +1661,7 @@ public class JobSchedulerService extends com.android.server.SystemService * Reschedules the given job based on the job's backoff policy. It doesn't make sense to * specify an override deadline on a failed job (the failed job will run even though it's not * ready), so we reschedule it with {@link JobStatus#NO_LATEST_RUNTIME}, but specify that any - * ready job with {@link JobStatus#numFailures} > 0 will be executed. + * ready job with {@link JobStatus#getNumFailures()} > 0 will be executed. * * @param failureToReschedule Provided job status that we will reschedule. * @return A newly instantiated JobStatus with the same constraints as the last job except @@ -2467,7 +2443,7 @@ public class JobSchedulerService extends com.android.server.SystemService * A controller can force a job into the pending queue even if it's already running, but * here is where we decide whether to actually execute it. */ - private void maybeRunPendingJobsLocked() { + void maybeRunPendingJobsLocked() { if (DEBUG) { Slog.d(TAG, "pending queue: " + mPendingJobs.size() + " jobs."); } @@ -3480,9 +3456,12 @@ public class JobSchedulerService extends com.android.server.SystemService pw.println(); pw.print("mReadyToRock="); pw.println(mReadyToRock); pw.print("mReportedActive="); pw.println(mReportedActive); - pw.print("mMaxActiveJobs="); pw.println(mMaxActiveJobs); } pw.println(); + + mConcurrencyManager.dumpLocked(pw); + + pw.println(); pw.print("PersistStats: "); pw.println(mJobs.getPersistStats()); } @@ -3634,8 +3613,8 @@ public class JobSchedulerService extends com.android.server.SystemService if (filterUid == -1) { proto.write(JobSchedulerServiceDumpProto.IS_READY_TO_ROCK, mReadyToRock); proto.write(JobSchedulerServiceDumpProto.REPORTED_ACTIVE, mReportedActive); - proto.write(JobSchedulerServiceDumpProto.MAX_ACTIVE_JOBS, mMaxActiveJobs); } + mConcurrencyManager.dumpProtoLocked(proto); } proto.flush(); diff --git a/services/core/java/com/android/server/location/ActivityRecognitionProxy.java b/services/core/java/com/android/server/location/ActivityRecognitionProxy.java deleted file mode 100644 index 22fabb2cdd3e..000000000000 --- a/services/core/java/com/android/server/location/ActivityRecognitionProxy.java +++ /dev/null @@ -1,118 +0,0 @@ -/* - * Copyright (C) 2014 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT 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.location; - -import android.content.Context; -import android.hardware.location.ActivityRecognitionHardware; -import android.hardware.location.IActivityRecognitionHardwareClient; -import android.hardware.location.IActivityRecognitionHardwareWatcher; -import android.os.IBinder; -import android.os.RemoteException; -import android.util.Log; - -import com.android.internal.os.BackgroundThread; -import com.android.server.ServiceWatcher; - -/** - * Proxy class to bind GmsCore to the ActivityRecognitionHardware. - * - * @hide - */ -public class ActivityRecognitionProxy { - - private static final String TAG = "ActivityRecognitionProxy"; - - /** - * Creates an instance of the proxy and binds it to the appropriate FusedProvider. - * - * @return An instance of the proxy if it could be bound, null otherwise. - */ - public static ActivityRecognitionProxy createAndBind( - Context context, - boolean activityRecognitionHardwareIsSupported, - ActivityRecognitionHardware activityRecognitionHardware, - int overlaySwitchResId, - int defaultServicePackageNameResId, - int initialPackageNameResId) { - ActivityRecognitionProxy activityRecognitionProxy = new ActivityRecognitionProxy( - context, - activityRecognitionHardwareIsSupported, - activityRecognitionHardware, - overlaySwitchResId, - defaultServicePackageNameResId, - initialPackageNameResId); - - if (activityRecognitionProxy.mServiceWatcher.start()) { - return activityRecognitionProxy; - } else { - return null; - } - } - - private final ServiceWatcher mServiceWatcher; - private final boolean mIsSupported; - private final ActivityRecognitionHardware mInstance; - - private ActivityRecognitionProxy( - Context context, - boolean activityRecognitionHardwareIsSupported, - ActivityRecognitionHardware activityRecognitionHardware, - int overlaySwitchResId, - int defaultServicePackageNameResId, - int initialPackageNameResId) { - mIsSupported = activityRecognitionHardwareIsSupported; - mInstance = activityRecognitionHardware; - - mServiceWatcher = new ServiceWatcher( - context, - TAG, - "com.android.location.service.ActivityRecognitionProvider", - overlaySwitchResId, - defaultServicePackageNameResId, - initialPackageNameResId, - BackgroundThread.getHandler()) { - @Override - protected void onBind() { - runOnBinder(ActivityRecognitionProxy.this::initializeService); - } - }; - } - - private void initializeService(IBinder binder) { - try { - String descriptor = binder.getInterfaceDescriptor(); - - if (IActivityRecognitionHardwareWatcher.class.getCanonicalName().equals( - descriptor)) { - IActivityRecognitionHardwareWatcher watcher = - IActivityRecognitionHardwareWatcher.Stub.asInterface(binder); - if (mInstance != null) { - watcher.onInstanceChanged(mInstance); - } - } else if (IActivityRecognitionHardwareClient.class.getCanonicalName() - .equals(descriptor)) { - IActivityRecognitionHardwareClient client = - IActivityRecognitionHardwareClient.Stub.asInterface(binder); - client.onAvailabilityChanged(mIsSupported, mInstance); - } else { - Log.e(TAG, "Invalid descriptor found on connection: " + descriptor); - } - } catch (RemoteException e) { - Log.w(TAG, e); - } - } -} diff --git a/services/core/java/com/android/server/location/GeofenceProxy.java b/services/core/java/com/android/server/location/GeofenceProxy.java index ca4f7fee494a..38c7d491f706 100644 --- a/services/core/java/com/android/server/location/GeofenceProxy.java +++ b/services/core/java/com/android/server/location/GeofenceProxy.java @@ -113,8 +113,12 @@ public final class GeofenceProxy { IGeofenceHardware geofenceHardware = IGeofenceHardware.Stub.asInterface(service); try { - geofenceHardware.setGpsGeofenceHardware(mGpsGeofenceHardware); - geofenceHardware.setFusedGeofenceHardware(mFusedGeofenceHardware); + if (mGpsGeofenceHardware != null) { + geofenceHardware.setGpsGeofenceHardware(mGpsGeofenceHardware); + } + if (mFusedGeofenceHardware != null) { + geofenceHardware.setFusedGeofenceHardware(mFusedGeofenceHardware); + } mGeofenceHardware = geofenceHardware; mServiceWatcher.runOnBinder(mUpdateGeofenceHardware); diff --git a/services/core/java/com/android/server/location/GnssConfiguration.java b/services/core/java/com/android/server/location/GnssConfiguration.java index 9e339430da12..72259268aa81 100644 --- a/services/core/java/com/android/server/location/GnssConfiguration.java +++ b/services/core/java/com/android/server/location/GnssConfiguration.java @@ -23,6 +23,7 @@ import android.telephony.CarrierConfigManager; import android.telephony.SubscriptionManager; import android.text.TextUtils; import android.util.Log; +import android.util.StatsLog; import libcore.io.IoUtils; @@ -231,6 +232,8 @@ class GnssConfiguration { mEsExtensionSec = getRangeCheckedConfigEsExtensionSec(); + logConfigurations(); + final HalInterfaceVersion gnssConfigurationIfaceVersion = native_get_gnss_configuration_version(); if (gnssConfigurationIfaceVersion != null) { @@ -282,6 +285,23 @@ class GnssConfiguration { } } + private void logConfigurations() { + StatsLog.write(StatsLog.GNSS_CONFIGURATION_REPORTED, + getSuplHost(), + getSuplPort(0), + getC2KHost(), + getC2KPort(0), + getIntConfig(CONFIG_SUPL_VER, 0), + getSuplMode(0), + getSuplEs(0) == 1, + getIntConfig(CONFIG_LPP_PROFILE, 0), + getIntConfig(CONFIG_A_GLONASS_POS_PROTOCOL_SELECT, 0), + getIntConfig(CONFIG_USE_EMERGENCY_PDN_FOR_EMERGENCY_SUPL, 0) == 1, + getIntConfig(CONFIG_GPS_LOCK, 0), + getEsExtensionSec(), + mProperties.getProperty(CONFIG_NFW_PROXY_APPS)); + } + /** * Loads GNSS properties from carrier config file. */ diff --git a/services/core/java/com/android/server/location/GnssVisibilityControl.java b/services/core/java/com/android/server/location/GnssVisibilityControl.java index 845aa9dfacd6..591889dde5de 100644 --- a/services/core/java/com/android/server/location/GnssVisibilityControl.java +++ b/services/core/java/com/android/server/location/GnssVisibilityControl.java @@ -28,6 +28,7 @@ import android.os.PowerManager; import android.os.UserHandle; import android.text.TextUtils; import android.util.Log; +import android.util.StatsLog; import java.util.Arrays; import java.util.HashMap; @@ -278,14 +279,24 @@ class GnssVisibilityControl { if (DEBUG) Log.d(TAG, nfwNotification.toString()); final String proxyAppPackageName = nfwNotification.mProxyAppPackageName; + Boolean isLocationPermissionEnabled = mProxyAppToLocationPermissions.get( + proxyAppPackageName); + boolean isLocationRequestAccepted = + nfwNotification.mResponseType != NfwNotification.NFW_RESPONSE_TYPE_REJECTED; + boolean isPermissionMismatched; + if (isLocationPermissionEnabled == null) { + isPermissionMismatched = isLocationRequestAccepted; + } else { + isPermissionMismatched = (isLocationPermissionEnabled != isLocationRequestAccepted); + } + logEvent(nfwNotification, isPermissionMismatched); + if (TextUtils.isEmpty(proxyAppPackageName)) { Log.e(TAG, "ProxyAppPackageName field is not set. Not sending intent to proxy app for " + nfwNotification); return; } - Boolean isLocationPermissionEnabled = mProxyAppToLocationPermissions.get( - proxyAppPackageName); if (isLocationPermissionEnabled == null) { // App is not in the configured list. Log.e(TAG, "Could not find proxy app with name: " + proxyAppPackageName + " in the " @@ -317,9 +328,7 @@ class GnssVisibilityControl { mAppOps.noteOpNoThrow(AppOpsManager.OP_FINE_LOCATION, clsAppUid, proxyAppPackageName); // Log proxy app permission mismatch between framework and GNSS HAL. - boolean isLocationRequestAccepted = - nfwNotification.mResponseType != NfwNotification.NFW_RESPONSE_TYPE_REJECTED; - if (isLocationPermissionEnabled != isLocationRequestAccepted) { + if (isPermissionMismatched) { Log.w(TAG, "Permission mismatch. Framework proxy app " + proxyAppPackageName + " location permission is set to " + isLocationPermissionEnabled + " but GNSS non-framework location access response type is " @@ -338,6 +347,19 @@ class GnssVisibilityControl { } } + private void logEvent(NfwNotification notification, boolean isPermissionMismatched) { + StatsLog.write(StatsLog.GNSS_NFW_NOTIFICATION_REPORTED, + notification.mProxyAppPackageName, + notification.mProtocolStack, + notification.mOtherProtocolStackName, + notification.mRequestor, + notification.mRequestorId, + notification.mResponseType, + notification.mInEmergencyMode, + notification.mIsCachedLocation, + isPermissionMismatched); + } + private void postEvent(Runnable event) { // Hold a wake lock until this message is delivered. // Note that this assumes the message will not be removed from the queue before diff --git a/services/core/java/com/android/server/locksettings/LockSettingsService.java b/services/core/java/com/android/server/locksettings/LockSettingsService.java index ea8c7922d831..8734ceb614a9 100644 --- a/services/core/java/com/android/server/locksettings/LockSettingsService.java +++ b/services/core/java/com/android/server/locksettings/LockSettingsService.java @@ -21,10 +21,10 @@ import static android.Manifest.permission.READ_CONTACTS; import static android.content.Context.KEYGUARD_SERVICE; import static android.content.pm.PackageManager.PERMISSION_GRANTED; -import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_BOOT; -import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_LOCKOUT; import static com.android.internal.widget.LockPatternUtils.SYNTHETIC_PASSWORD_ENABLED_KEY; import static com.android.internal.widget.LockPatternUtils.SYNTHETIC_PASSWORD_HANDLE_KEY; +import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_BOOT; +import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_LOCKOUT; import static com.android.internal.widget.LockPatternUtils.USER_FRP; import static com.android.internal.widget.LockPatternUtils.frpCredentialEnabled; import static com.android.internal.widget.LockPatternUtils.userOwnsFrpCredential; @@ -81,9 +81,9 @@ import android.security.keystore.KeyProperties; import android.security.keystore.KeyProtection; import android.security.keystore.UserNotAuthenticatedException; import android.security.keystore.recovery.KeyChainProtectionParams; +import android.security.keystore.recovery.KeyChainSnapshot; import android.security.keystore.recovery.RecoveryCertPath; import android.security.keystore.recovery.WrappedApplicationKey; -import android.security.keystore.recovery.KeyChainSnapshot; import android.service.gatekeeper.GateKeeperResponse; import android.service.gatekeeper.IGateKeeperService; import android.text.TextUtils; @@ -109,9 +109,9 @@ import com.android.server.LocalServices; import com.android.server.SystemService; import com.android.server.locksettings.LockSettingsStorage.CredentialHash; import com.android.server.locksettings.LockSettingsStorage.PersistentData; -import com.android.server.locksettings.recoverablekeystore.RecoverableKeyStoreManager; import com.android.server.locksettings.SyntheticPasswordManager.AuthenticationResult; import com.android.server.locksettings.SyntheticPasswordManager.AuthenticationToken; +import com.android.server.locksettings.recoverablekeystore.RecoverableKeyStoreManager; import com.android.server.wm.WindowManagerInternal; import libcore.util.HexEncoding; @@ -130,8 +130,8 @@ import java.security.NoSuchAlgorithmException; import java.security.SecureRandom; import java.security.UnrecoverableKeyException; import java.security.cert.CertificateException; -import java.util.Arrays; import java.util.ArrayList; +import java.util.Arrays; import java.util.List; import java.util.Map; import java.util.NoSuchElementException; @@ -2103,11 +2103,24 @@ public class LockSettingsService extends ILockSettings.Stub { } @Override - public @Nullable String importKey(@NonNull String alias, byte[] keyBytes) throws RemoteException { + public @Nullable String generateKeyWithMetadata( + @NonNull String alias, @Nullable byte[] metadata) throws RemoteException { + return mRecoverableKeyStoreManager.generateKeyWithMetadata(alias, metadata); + } + + @Override + public @Nullable String importKey(@NonNull String alias, @NonNull byte[] keyBytes) + throws RemoteException { return mRecoverableKeyStoreManager.importKey(alias, keyBytes); } @Override + public @Nullable String importKeyWithMetadata(@NonNull String alias, @NonNull byte[] keyBytes, + @Nullable byte[] metadata) throws RemoteException { + return mRecoverableKeyStoreManager.importKeyWithMetadata(alias, keyBytes, metadata); + } + + @Override public @Nullable String getKey(@NonNull String alias) throws RemoteException { return mRecoverableKeyStoreManager.getKey(alias); } diff --git a/services/core/java/com/android/server/locksettings/recoverablekeystore/KeySyncTask.java b/services/core/java/com/android/server/locksettings/recoverablekeystore/KeySyncTask.java index f1951b1e31b1..1f9b027be030 100644 --- a/services/core/java/com/android/server/locksettings/recoverablekeystore/KeySyncTask.java +++ b/services/core/java/com/android/server/locksettings/recoverablekeystore/KeySyncTask.java @@ -26,6 +26,7 @@ import android.security.keystore.recovery.KeyChainSnapshot; import android.security.keystore.recovery.KeyDerivationParams; import android.security.keystore.recovery.WrappedApplicationKey; import android.util.Log; +import android.util.Pair; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.util.ArrayUtils; @@ -258,9 +259,9 @@ public class KeySyncTask implements Runnable { localLskfHash = hashCredentialsBySaltedSha256(salt, mCredential); } - Map<String, SecretKey> rawKeys; + Map<String, Pair<SecretKey, byte[]>> rawKeysWithMetadata; try { - rawKeys = getKeysToSync(recoveryAgentUid); + rawKeysWithMetadata = getKeysToSync(recoveryAgentUid); } catch (GeneralSecurityException e) { Log.e(TAG, "Failed to load recoverable keys for sync", e); return; @@ -278,7 +279,9 @@ public class KeySyncTask implements Runnable { } // Only include insecure key material for test if (mTestOnlyInsecureCertificateHelper.isTestOnlyCertificateAlias(rootCertAlias)) { - rawKeys = mTestOnlyInsecureCertificateHelper.keepOnlyWhitelistedInsecureKeys(rawKeys); + rawKeysWithMetadata = + mTestOnlyInsecureCertificateHelper.keepOnlyWhitelistedInsecureKeys( + rawKeysWithMetadata); } SecretKey recoveryKey; @@ -292,7 +295,7 @@ public class KeySyncTask implements Runnable { Map<String, byte[]> encryptedApplicationKeys; try { encryptedApplicationKeys = KeySyncUtils.encryptKeysWithRecoveryKey( - recoveryKey, rawKeys); + recoveryKey, rawKeysWithMetadata); } catch (InvalidKeyException | NoSuchAlgorithmException e) { Log.wtf(TAG, "Should be impossible: could not encrypt application keys with random key", @@ -356,7 +359,8 @@ public class KeySyncTask implements Runnable { .setCounterId(counterId) .setServerParams(vaultHandle) .setKeyChainProtectionParams(metadataList) - .setWrappedApplicationKeys(createApplicationKeyEntries(encryptedApplicationKeys)) + .setWrappedApplicationKeys( + createApplicationKeyEntries(encryptedApplicationKeys, rawKeysWithMetadata)) .setEncryptedRecoveryKeyBlob(encryptedRecoveryKey); try { keyChainSnapshotBuilder.setTrustedHardwareCertPath(certPath); @@ -405,7 +409,7 @@ public class KeySyncTask implements Runnable { /** * Returns all of the recoverable keys for the user. */ - private Map<String, SecretKey> getKeysToSync(int recoveryAgentUid) + private Map<String, Pair<SecretKey, byte[]>> getKeysToSync(int recoveryAgentUid) throws InsecureUserException, KeyStoreException, UnrecoverableKeyException, NoSuchAlgorithmException, NoSuchPaddingException, BadPlatformKeyException, InvalidKeyException, InvalidAlgorithmParameterException, IOException { @@ -521,12 +525,14 @@ public class KeySyncTask implements Runnable { } private static List<WrappedApplicationKey> createApplicationKeyEntries( - Map<String, byte[]> encryptedApplicationKeys) { + Map<String, byte[]> encryptedApplicationKeys, + Map<String, Pair<SecretKey, byte[]>> originalKeysWithMetadata) { ArrayList<WrappedApplicationKey> keyEntries = new ArrayList<>(); for (String alias : encryptedApplicationKeys.keySet()) { keyEntries.add(new WrappedApplicationKey.Builder() .setAlias(alias) .setEncryptedKeyMaterial(encryptedApplicationKeys.get(alias)) + .setMetadata(originalKeysWithMetadata.get(alias).second) .build()); } return keyEntries; diff --git a/services/core/java/com/android/server/locksettings/recoverablekeystore/KeySyncUtils.java b/services/core/java/com/android/server/locksettings/recoverablekeystore/KeySyncUtils.java index 8e6f9cbbb260..24d575e27bdd 100644 --- a/services/core/java/com/android/server/locksettings/recoverablekeystore/KeySyncUtils.java +++ b/services/core/java/com/android/server/locksettings/recoverablekeystore/KeySyncUtils.java @@ -16,6 +16,9 @@ package com.android.server.locksettings.recoverablekeystore; +import android.annotation.Nullable; +import android.util.Pair; + import com.android.internal.annotations.VisibleForTesting; import java.nio.ByteBuffer; @@ -152,15 +155,28 @@ public class KeySyncUtils { * @hide */ public static Map<String, byte[]> encryptKeysWithRecoveryKey( - SecretKey recoveryKey, Map<String, SecretKey> keys) + SecretKey recoveryKey, Map<String, Pair<SecretKey, byte[]>> keys) throws NoSuchAlgorithmException, InvalidKeyException { HashMap<String, byte[]> encryptedKeys = new HashMap<>(); for (String alias : keys.keySet()) { - SecretKey key = keys.get(alias); + SecretKey key = keys.get(alias).first; + byte[] metadata = keys.get(alias).second; + byte[] header; + if (metadata == null) { + header = ENCRYPTED_APPLICATION_KEY_HEADER; + } else { + // The provided metadata, if non-empty, will be bound to the authenticated + // encryption process of the key material. As a result, the ciphertext cannot be + // decrypted if a wrong metadata is provided during the recovery/decryption process. + // Note that Android P devices do not have the API to provide the optional metadata, + // so all the keys with non-empty metadata stored on Android Q+ devices cannot be + // recovered on Android P devices. + header = concat(ENCRYPTED_APPLICATION_KEY_HEADER, metadata); + } byte[] encryptedKey = SecureBox.encrypt( /*theirPublicKey=*/ null, /*sharedSecret=*/ recoveryKey.getEncoded(), - /*header=*/ ENCRYPTED_APPLICATION_KEY_HEADER, + /*header=*/ header, /*payload=*/ key.getEncoded()); encryptedKeys.put(alias, encryptedKey); } @@ -257,12 +273,19 @@ public class KeySyncUtils { * @throws AEADBadTagException if the message has been tampered with or was encrypted with a * different key. */ - public static byte[] decryptApplicationKey(byte[] recoveryKey, byte[] encryptedApplicationKey) + public static byte[] decryptApplicationKey(byte[] recoveryKey, byte[] encryptedApplicationKey, + @Nullable byte[] applicationKeyMetadata) throws NoSuchAlgorithmException, InvalidKeyException, AEADBadTagException { + byte[] header; + if (applicationKeyMetadata == null) { + header = ENCRYPTED_APPLICATION_KEY_HEADER; + } else { + header = concat(ENCRYPTED_APPLICATION_KEY_HEADER, applicationKeyMetadata); + } return SecureBox.decrypt( /*ourPrivateKey=*/ null, /*sharedSecret=*/ recoveryKey, - /*header=*/ ENCRYPTED_APPLICATION_KEY_HEADER, + /*header=*/ header, /*encryptedPayload=*/ encryptedApplicationKey); } diff --git a/services/core/java/com/android/server/locksettings/recoverablekeystore/RecoverableKeyGenerator.java b/services/core/java/com/android/server/locksettings/recoverablekeystore/RecoverableKeyGenerator.java index c249468a80a7..1692e5cb9842 100644 --- a/services/core/java/com/android/server/locksettings/recoverablekeystore/RecoverableKeyGenerator.java +++ b/services/core/java/com/android/server/locksettings/recoverablekeystore/RecoverableKeyGenerator.java @@ -17,6 +17,8 @@ package com.android.server.locksettings.recoverablekeystore; import android.annotation.NonNull; +import android.annotation.Nullable; +import android.util.Log; import com.android.server.locksettings.recoverablekeystore.storage.RecoverableKeyStoreDb; @@ -24,7 +26,6 @@ import java.security.InvalidKeyException; import java.security.KeyStoreException; import java.security.NoSuchAlgorithmException; import java.util.Locale; -import android.util.Log; import javax.crypto.KeyGenerator; import javax.crypto.SecretKey; @@ -84,6 +85,8 @@ public class RecoverableKeyGenerator { * @param userId The user ID of the profile to which the calling app belongs. * @param uid The uid of the application that will own the key. * @param alias The alias by which the key will be known in the recoverable key store. + * @param metadata The optional metadata that will be authenticated (but unencrypted) together + * with the key material when the key is uploaded to cloud. * @throws RecoverableKeyStorageException if there is some error persisting the key either to * the database. * @throws KeyStoreException if there is a KeyStore error wrapping the generated key. @@ -92,12 +95,13 @@ public class RecoverableKeyGenerator { * @hide */ public byte[] generateAndStoreKey( - PlatformEncryptionKey platformKey, int userId, int uid, String alias) + PlatformEncryptionKey platformKey, int userId, int uid, String alias, + @Nullable byte[] metadata) throws RecoverableKeyStorageException, KeyStoreException, InvalidKeyException { mKeyGenerator.init(KEY_SIZE_BITS); SecretKey key = mKeyGenerator.generateKey(); - WrappedKey wrappedKey = WrappedKey.fromSecretKey(platformKey, key); + WrappedKey wrappedKey = WrappedKey.fromSecretKey(platformKey, key, metadata); long result = mDatabase.insertKey(userId, uid, alias, wrappedKey); if (result == RESULT_CANNOT_INSERT_ROW) { @@ -126,6 +130,8 @@ public class RecoverableKeyGenerator { * @param uid The uid of the application that will own the key. * @param alias The alias by which the key will be known in the recoverable key store. * @param keyBytes The raw bytes of the AES key to be imported. + * @param metadata The optional metadata that will be authenticated (but unencrypted) together + * with the key material when the key is uploaded to cloud. * @throws RecoverableKeyStorageException if there is some error persisting the key either to * the database. * @throws KeyStoreException if there is a KeyStore error wrapping the generated key. @@ -135,11 +141,11 @@ public class RecoverableKeyGenerator { */ public void importKey( @NonNull PlatformEncryptionKey platformKey, int userId, int uid, @NonNull String alias, - @NonNull byte[] keyBytes) + @NonNull byte[] keyBytes, @Nullable byte[] metadata) throws RecoverableKeyStorageException, KeyStoreException, InvalidKeyException { SecretKey key = new SecretKeySpec(keyBytes, SECRET_KEY_ALGORITHM); - WrappedKey wrappedKey = WrappedKey.fromSecretKey(platformKey, key); + WrappedKey wrappedKey = WrappedKey.fromSecretKey(platformKey, key, metadata); long result = mDatabase.insertKey(userId, uid, alias, wrappedKey); if (result == RESULT_CANNOT_INSERT_ROW) { diff --git a/services/core/java/com/android/server/locksettings/recoverablekeystore/RecoverableKeyStoreManager.java b/services/core/java/com/android/server/locksettings/recoverablekeystore/RecoverableKeyStoreManager.java index fc5184d1438f..ed864c0221c9 100644 --- a/services/core/java/com/android/server/locksettings/recoverablekeystore/RecoverableKeyStoreManager.java +++ b/services/core/java/com/android/server/locksettings/recoverablekeystore/RecoverableKeyStoreManager.java @@ -20,8 +20,8 @@ import static android.security.keystore.recovery.RecoveryController.ERROR_BAD_CE import static android.security.keystore.recovery.RecoveryController.ERROR_DECRYPTION_FAILED; import static android.security.keystore.recovery.RecoveryController.ERROR_DOWNGRADE_CERTIFICATE; import static android.security.keystore.recovery.RecoveryController.ERROR_INSECURE_USER; -import static android.security.keystore.recovery.RecoveryController.ERROR_INVALID_KEY_FORMAT; import static android.security.keystore.recovery.RecoveryController.ERROR_INVALID_CERTIFICATE; +import static android.security.keystore.recovery.RecoveryController.ERROR_INVALID_KEY_FORMAT; import static android.security.keystore.recovery.RecoveryController.ERROR_NO_SNAPSHOT_PENDING; import static android.security.keystore.recovery.RecoveryController.ERROR_SERVICE_INTERNAL_ERROR; import static android.security.keystore.recovery.RecoveryController.ERROR_SESSION_EXPIRED; @@ -35,12 +35,12 @@ import android.os.Binder; import android.os.RemoteException; import android.os.ServiceSpecificException; import android.os.UserHandle; +import android.security.KeyStore; import android.security.keystore.recovery.KeyChainProtectionParams; import android.security.keystore.recovery.KeyChainSnapshot; import android.security.keystore.recovery.RecoveryCertPath; import android.security.keystore.recovery.RecoveryController; import android.security.keystore.recovery.WrappedApplicationKey; -import android.security.KeyStore; import android.util.ArrayMap; import android.util.Log; @@ -59,7 +59,6 @@ import com.android.server.locksettings.recoverablekeystore.storage.RecoverySnaps import java.io.IOException; import java.security.InvalidKeyException; -import java.security.KeyFactory; import java.security.KeyStoreException; import java.security.NoSuchAlgorithmException; import java.security.PublicKey; @@ -70,7 +69,6 @@ import java.security.cert.CertificateEncodingException; import java.security.cert.CertificateException; import java.security.cert.X509Certificate; import java.security.spec.InvalidKeySpecException; -import java.security.spec.X509EncodedKeySpec; import java.util.Arrays; import java.util.HashMap; import java.util.List; @@ -606,7 +604,8 @@ public class RecoverableKeyStoreManager { try { byte[] recoveryKey = decryptRecoveryKey(sessionEntry, encryptedRecoveryKey); - Map<String, byte[]> keysByAlias = recoverApplicationKeys(recoveryKey, applicationKeys); + Map<String, byte[]> keysByAlias = recoverApplicationKeys(recoveryKey, + applicationKeys); return importKeyMaterials(userId, uid, keysByAlias); } catch (KeyStoreException e) { throw new ServiceSpecificException(ERROR_SERVICE_INTERNAL_ERROR, e.getMessage()); @@ -625,7 +624,8 @@ public class RecoverableKeyStoreManager { * @throws KeyStoreException if an error occurs importing the key or getting the grant. */ private @NonNull Map<String, String> importKeyMaterials( - int userId, int uid, Map<String, byte[]> keysByAlias) throws KeyStoreException { + int userId, int uid, Map<String, byte[]> keysByAlias) + throws KeyStoreException { ArrayMap<String, String> grantAliasesByAlias = new ArrayMap<>(keysByAlias.size()); for (String alias : keysByAlias.keySet()) { mApplicationKeyStorage.setSymmetricKeyEntry(userId, uid, alias, keysByAlias.get(alias)); @@ -674,9 +674,29 @@ public class RecoverableKeyStoreManager { * Generates a key named {@code alias} in caller's namespace. * The key is stored in system service keystore namespace. * + * @param alias the alias provided by caller as a reference to the key. * @return grant alias, which caller can use to access the key. + * @throws RemoteException if certain internal errors occur. + * + * @deprecated Use {@link #generateKeyWithMetadata(String, byte[])} instead. */ + @Deprecated public String generateKey(@NonNull String alias) throws RemoteException { + return generateKeyWithMetadata(alias, /*metadata=*/ null); + } + + /** + * Generates a key named {@code alias} with the {@code metadata} in caller's namespace. + * The key is stored in system service keystore namespace. + * + * @param alias the alias provided by caller as a reference to the key. + * @param metadata the optional metadata blob that will authenticated (but unencrypted) together + * with the key material when the key is uploaded to cloud. + * @return grant alias, which caller can use to access the key. + * @throws RemoteException if certain internal errors occur. + */ + public String generateKeyWithMetadata(@NonNull String alias, @Nullable byte[] metadata) + throws RemoteException { checkRecoverKeyStorePermission(); Preconditions.checkNotNull(alias, "alias is null"); int uid = Binder.getCallingUid(); @@ -695,8 +715,8 @@ public class RecoverableKeyStoreManager { } try { - byte[] secretKey = - mRecoverableKeyGenerator.generateAndStoreKey(encryptionKey, userId, uid, alias); + byte[] secretKey = mRecoverableKeyGenerator.generateAndStoreKey(encryptionKey, userId, + uid, alias, metadata); mApplicationKeyStorage.setSymmetricKeyEntry(userId, uid, alias, secretKey); return getAlias(userId, uid, alias); } catch (KeyStoreException | InvalidKeyException | RecoverableKeyStorageException e) { @@ -713,10 +733,30 @@ public class RecoverableKeyStoreManager { * @return grant alias, which caller can use to access the key. * @throws RemoteException if the given key is invalid or some internal errors occur. * + * @deprecated Use {{@link #importKeyWithMetadata(String, byte[], byte[])}} instead. + * * @hide */ + @Deprecated public @Nullable String importKey(@NonNull String alias, @NonNull byte[] keyBytes) throws RemoteException { + return importKeyWithMetadata(alias, keyBytes, /*metadata=*/ null); + } + + /** + * Imports a 256-bit AES-GCM key named {@code alias} with the given {@code metadata}. The key is + * stored in system service keystore namespace. + * + * @param alias the alias provided by caller as a reference to the key. + * @param keyBytes the raw bytes of the 256-bit AES key. + * @param metadata the metadata to be authenticated (but unencrypted) together with the key. + * @return grant alias, which caller can use to access the key. + * @throws RemoteException if the given key is invalid or some internal errors occur. + * + * @hide + */ + public @Nullable String importKeyWithMetadata(@NonNull String alias, @NonNull byte[] keyBytes, + @Nullable byte[] metadata) throws RemoteException { checkRecoverKeyStorePermission(); Preconditions.checkNotNull(alias, "alias is null"); Preconditions.checkNotNull(keyBytes, "keyBytes is null"); @@ -745,7 +785,8 @@ public class RecoverableKeyStoreManager { try { // Wrap the key by the platform key and store the wrapped key locally - mRecoverableKeyGenerator.importKey(encryptionKey, userId, uid, alias, keyBytes); + mRecoverableKeyGenerator.importKey(encryptionKey, userId, uid, alias, keyBytes, + metadata); // Import the key to Android KeyStore and get grant mApplicationKeyStorage.setSymmetricKeyEntry(userId, uid, alias, keyBytes); @@ -812,17 +853,17 @@ public class RecoverableKeyStoreManager { * @return Map from alias to raw key material. * @throws RemoteException if an error occurred decrypting the keys. */ - private @NonNull Map<String, byte[]> recoverApplicationKeys( - @NonNull byte[] recoveryKey, + private @NonNull Map<String, byte[]> recoverApplicationKeys(@NonNull byte[] recoveryKey, @NonNull List<WrappedApplicationKey> applicationKeys) throws RemoteException { HashMap<String, byte[]> keyMaterialByAlias = new HashMap<>(); for (WrappedApplicationKey applicationKey : applicationKeys) { String alias = applicationKey.getAlias(); byte[] encryptedKeyMaterial = applicationKey.getEncryptedKeyMaterial(); + byte[] keyMetadata = applicationKey.getMetadata(); try { - byte[] keyMaterial = - KeySyncUtils.decryptApplicationKey(recoveryKey, encryptedKeyMaterial); + byte[] keyMaterial = KeySyncUtils.decryptApplicationKey(recoveryKey, + encryptedKeyMaterial, keyMetadata); keyMaterialByAlias.put(alias, keyMaterial); } catch (NoSuchAlgorithmException e) { Log.wtf(TAG, "Missing SecureBox algorithm. AOSP required to support this.", e); diff --git a/services/core/java/com/android/server/locksettings/recoverablekeystore/TestOnlyInsecureCertificateHelper.java b/services/core/java/com/android/server/locksettings/recoverablekeystore/TestOnlyInsecureCertificateHelper.java index 5ba3cceec6d0..057429c3e7d4 100644 --- a/services/core/java/com/android/server/locksettings/recoverablekeystore/TestOnlyInsecureCertificateHelper.java +++ b/services/core/java/com/android/server/locksettings/recoverablekeystore/TestOnlyInsecureCertificateHelper.java @@ -18,17 +18,20 @@ package com.android.server.locksettings.recoverablekeystore; import static android.security.keystore.recovery.RecoveryController.ERROR_INVALID_CERTIFICATE; -import com.android.internal.widget.LockPatternUtils; import android.annotation.NonNull; import android.annotation.Nullable; import android.os.RemoteException; import android.os.ServiceSpecificException; import android.security.keystore.recovery.TrustedRootCertificates; import android.util.Log; +import android.util.Pair; + +import com.android.internal.widget.LockPatternUtils; -import java.util.HashMap; import java.security.cert.X509Certificate; +import java.util.HashMap; import java.util.Map; + import javax.crypto.SecretKey; /** @@ -90,16 +93,18 @@ public class TestOnlyInsecureCertificateHelper { && credential.startsWith(TrustedRootCertificates.INSECURE_PASSWORD_PREFIX); } - public Map<String, SecretKey> keepOnlyWhitelistedInsecureKeys(Map<String, SecretKey> rawKeys) { + public Map<String, Pair<SecretKey, byte[]>> keepOnlyWhitelistedInsecureKeys( + Map<String, Pair<SecretKey, byte[]>> rawKeys) { if (rawKeys == null) { return null; } - Map<String, SecretKey> filteredKeys = new HashMap<>(); - for (Map.Entry<String, SecretKey> entry : rawKeys.entrySet()) { + Map<String, Pair<SecretKey, byte[]>> filteredKeys = new HashMap<>(); + for (Map.Entry<String, Pair<SecretKey, byte[]>> entry : rawKeys.entrySet()) { String alias = entry.getKey(); if (alias != null && alias.startsWith(TrustedRootCertificates.INSECURE_KEY_ALIAS_PREFIX)) { - filteredKeys.put(entry.getKey(), entry.getValue()); + filteredKeys.put(entry.getKey(), + Pair.create(entry.getValue().first, entry.getValue().second)); Log.d(TAG, "adding key with insecure alias " + alias + " to the recovery snapshot"); } } diff --git a/services/core/java/com/android/server/locksettings/recoverablekeystore/WrappedKey.java b/services/core/java/com/android/server/locksettings/recoverablekeystore/WrappedKey.java index 0077242b412a..09d7541102b5 100644 --- a/services/core/java/com/android/server/locksettings/recoverablekeystore/WrappedKey.java +++ b/services/core/java/com/android/server/locksettings/recoverablekeystore/WrappedKey.java @@ -16,8 +16,10 @@ package com.android.server.locksettings.recoverablekeystore; +import android.annotation.Nullable; import android.security.keystore.recovery.RecoveryController; import android.util.Log; +import android.util.Pair; import java.security.InvalidAlgorithmParameterException; import java.security.InvalidKeyException; @@ -49,6 +51,7 @@ public class WrappedKey { private final int mRecoveryStatus; private final byte[] mNonce; private final byte[] mKeyMaterial; + private final byte[] mKeyMetadata; /** * Returns a wrapped form of {@code key}, using {@code wrappingKey} to encrypt the key material. @@ -58,7 +61,8 @@ public class WrappedKey { * {@link android.security.keystore.AndroidKeyStoreKey} for an example of a key that does * not expose its key material. */ - public static WrappedKey fromSecretKey(PlatformEncryptionKey wrappingKey, SecretKey key) + public static WrappedKey fromSecretKey(PlatformEncryptionKey wrappingKey, SecretKey key, + @Nullable byte[] metadata) throws InvalidKeyException, KeyStoreException { if (key.getEncoded() == null) { throw new InvalidKeyException( @@ -96,6 +100,7 @@ public class WrappedKey { return new WrappedKey( /*nonce=*/ cipher.getIV(), /*keyMaterial=*/ encryptedKeyMaterial, + /*keyMetadata=*/ metadata, /*platformKeyGenerationId=*/ wrappingKey.getGenerationId(), RecoveryController.RECOVERY_STATUS_SYNC_IN_PROGRESS); } @@ -110,11 +115,10 @@ public class WrappedKey { * @see RecoveryController#RECOVERY_STATUS_SYNC_IN_PROGRESS * @hide */ - public WrappedKey(byte[] nonce, byte[] keyMaterial, int platformKeyGenerationId) { - mNonce = nonce; - mKeyMaterial = keyMaterial; - mPlatformKeyGenerationId = platformKeyGenerationId; - mRecoveryStatus = RecoveryController.RECOVERY_STATUS_SYNC_IN_PROGRESS; + public WrappedKey(byte[] nonce, byte[] keyMaterial, @Nullable byte[] keyMetadata, + int platformKeyGenerationId) { + this(nonce, keyMaterial, keyMetadata, platformKeyGenerationId, + RecoveryController.RECOVERY_STATUS_SYNC_IN_PROGRESS); } /** @@ -122,15 +126,18 @@ public class WrappedKey { * * @param nonce The nonce with which the key material was encrypted. * @param keyMaterial The encrypted bytes of the key material. + * @param keyMetadata The metadata that will be authenticated (but unencrypted) together with + * the key material when the key is uploaded to cloud. * @param platformKeyGenerationId The generation ID of the key used to wrap this key. * @param recoveryStatus recovery status of the key. * * @hide */ - public WrappedKey(byte[] nonce, byte[] keyMaterial, int platformKeyGenerationId, - int recoveryStatus) { + public WrappedKey(byte[] nonce, byte[] keyMaterial, @Nullable byte[] keyMetadata, + int platformKeyGenerationId, int recoveryStatus) { mNonce = nonce; mKeyMaterial = keyMaterial; + mKeyMetadata = keyMetadata; mPlatformKeyGenerationId = platformKeyGenerationId; mRecoveryStatus = recoveryStatus; } @@ -154,6 +161,15 @@ public class WrappedKey { } /** + * Returns the key metadata. + * + * @hide + */ + public @Nullable byte[] getKeyMetadata() { + return mKeyMetadata; + } + + /** * Returns the generation ID of the platform key, with which this key was wrapped. * * @hide @@ -181,12 +197,12 @@ public class WrappedKey { * * @hide */ - public static Map<String, SecretKey> unwrapKeys( + public static Map<String, Pair<SecretKey, byte[]>> unwrapKeys( PlatformDecryptionKey platformKey, Map<String, WrappedKey> wrappedKeys) throws NoSuchAlgorithmException, NoSuchPaddingException, BadPlatformKeyException, InvalidKeyException, InvalidAlgorithmParameterException { - HashMap<String, SecretKey> unwrappedKeys = new HashMap<>(); + HashMap<String, Pair<SecretKey, byte[]>> unwrappedKeys = new HashMap<>(); Cipher cipher = Cipher.getInstance(KEY_WRAP_CIPHER_ALGORITHM); int platformKeyGenerationId = platformKey.getGenerationId(); @@ -219,7 +235,7 @@ public class WrappedKey { e); continue; } - unwrappedKeys.put(alias, key); + unwrappedKeys.put(alias, Pair.create(key, wrappedKey.getKeyMetadata())); } return unwrappedKeys; diff --git a/services/core/java/com/android/server/locksettings/recoverablekeystore/serialization/KeyChainSnapshotDeserializer.java b/services/core/java/com/android/server/locksettings/recoverablekeystore/serialization/KeyChainSnapshotDeserializer.java index b486834235dc..8a19d62de0b9 100644 --- a/services/core/java/com/android/server/locksettings/recoverablekeystore/serialization/KeyChainSnapshotDeserializer.java +++ b/services/core/java/com/android/server/locksettings/recoverablekeystore/serialization/KeyChainSnapshotDeserializer.java @@ -23,19 +23,18 @@ import static com.android.server.locksettings.recoverablekeystore.serialization. import static com.android.server.locksettings.recoverablekeystore.serialization.KeyChainSnapshotSchema.TAG_ALIAS; import static com.android.server.locksettings.recoverablekeystore.serialization.KeyChainSnapshotSchema.TAG_APPLICATION_KEY; import static com.android.server.locksettings.recoverablekeystore.serialization.KeyChainSnapshotSchema.TAG_APPLICATION_KEYS; - -import static com.android.server.locksettings.recoverablekeystore.serialization - .KeyChainSnapshotSchema.TAG_BACKEND_PUBLIC_KEY; +import static com.android.server.locksettings.recoverablekeystore.serialization.KeyChainSnapshotSchema.TAG_BACKEND_PUBLIC_KEY; import static com.android.server.locksettings.recoverablekeystore.serialization.KeyChainSnapshotSchema.TAG_COUNTER_ID; -import static com.android.server.locksettings.recoverablekeystore.serialization.KeyChainSnapshotSchema.TAG_RECOVERY_KEY_MATERIAL; import static com.android.server.locksettings.recoverablekeystore.serialization.KeyChainSnapshotSchema.TAG_KEY_CHAIN_PROTECTION_PARAMS; import static com.android.server.locksettings.recoverablekeystore.serialization.KeyChainSnapshotSchema.TAG_KEY_CHAIN_PROTECTION_PARAMS_LIST; import static com.android.server.locksettings.recoverablekeystore.serialization.KeyChainSnapshotSchema.TAG_KEY_CHAIN_SNAPSHOT; import static com.android.server.locksettings.recoverablekeystore.serialization.KeyChainSnapshotSchema.TAG_KEY_DERIVATION_PARAMS; import static com.android.server.locksettings.recoverablekeystore.serialization.KeyChainSnapshotSchema.TAG_KEY_MATERIAL; +import static com.android.server.locksettings.recoverablekeystore.serialization.KeyChainSnapshotSchema.TAG_KEY_METADATA; import static com.android.server.locksettings.recoverablekeystore.serialization.KeyChainSnapshotSchema.TAG_LOCK_SCREEN_UI_TYPE; import static com.android.server.locksettings.recoverablekeystore.serialization.KeyChainSnapshotSchema.TAG_MAX_ATTEMPTS; import static com.android.server.locksettings.recoverablekeystore.serialization.KeyChainSnapshotSchema.TAG_MEMORY_DIFFICULTY; +import static com.android.server.locksettings.recoverablekeystore.serialization.KeyChainSnapshotSchema.TAG_RECOVERY_KEY_MATERIAL; import static com.android.server.locksettings.recoverablekeystore.serialization.KeyChainSnapshotSchema.TAG_SALT; import static com.android.server.locksettings.recoverablekeystore.serialization.KeyChainSnapshotSchema.TAG_SERVER_PARAMS; import static com.android.server.locksettings.recoverablekeystore.serialization.KeyChainSnapshotSchema.TAG_SNAPSHOT_VERSION; @@ -49,6 +48,9 @@ import android.security.keystore.recovery.WrappedApplicationKey; import android.util.Base64; import android.util.Xml; +import org.xmlpull.v1.XmlPullParser; +import org.xmlpull.v1.XmlPullParserException; + import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStream; @@ -59,9 +61,6 @@ import java.util.ArrayList; import java.util.List; import java.util.Locale; -import org.xmlpull.v1.XmlPullParser; -import org.xmlpull.v1.XmlPullParserException; - /** * Deserializes a {@link android.security.keystore.recovery.KeyChainSnapshot} instance from XML. */ @@ -191,6 +190,10 @@ public class KeyChainSnapshotDeserializer { builder.setEncryptedKeyMaterial(readBlobTag(parser, TAG_KEY_MATERIAL)); break; + case TAG_KEY_METADATA: + builder.setMetadata(readBlobTag(parser, TAG_KEY_METADATA)); + break; + default: throw new KeyChainSnapshotParserException(String.format( Locale.US, "Unexpected tag %s in wrappedApplicationKey", name)); diff --git a/services/core/java/com/android/server/locksettings/recoverablekeystore/serialization/KeyChainSnapshotSchema.java b/services/core/java/com/android/server/locksettings/recoverablekeystore/serialization/KeyChainSnapshotSchema.java index 0f2c2fc6c959..8f85a27d4690 100644 --- a/services/core/java/com/android/server/locksettings/recoverablekeystore/serialization/KeyChainSnapshotSchema.java +++ b/services/core/java/com/android/server/locksettings/recoverablekeystore/serialization/KeyChainSnapshotSchema.java @@ -52,6 +52,7 @@ class KeyChainSnapshotSchema { static final String TAG_APPLICATION_KEY = "applicationKey"; static final String TAG_ALIAS = "alias"; static final String TAG_KEY_MATERIAL = "keyMaterial"; + static final String TAG_KEY_METADATA = "keyMetadata"; // Statics only private KeyChainSnapshotSchema() {} diff --git a/services/core/java/com/android/server/locksettings/recoverablekeystore/serialization/KeyChainSnapshotSerializer.java b/services/core/java/com/android/server/locksettings/recoverablekeystore/serialization/KeyChainSnapshotSerializer.java index 235df698a674..527e879a198b 100644 --- a/services/core/java/com/android/server/locksettings/recoverablekeystore/serialization/KeyChainSnapshotSerializer.java +++ b/services/core/java/com/android/server/locksettings/recoverablekeystore/serialization/KeyChainSnapshotSerializer.java @@ -24,25 +24,24 @@ import static com.android.server.locksettings.recoverablekeystore.serialization. import static com.android.server.locksettings.recoverablekeystore.serialization.KeyChainSnapshotSchema.TAG_ALIAS; import static com.android.server.locksettings.recoverablekeystore.serialization.KeyChainSnapshotSchema.TAG_APPLICATION_KEY; import static com.android.server.locksettings.recoverablekeystore.serialization.KeyChainSnapshotSchema.TAG_APPLICATION_KEYS; - -import static com.android.server.locksettings.recoverablekeystore.serialization - .KeyChainSnapshotSchema.TAG_BACKEND_PUBLIC_KEY; import static com.android.server.locksettings.recoverablekeystore.serialization.KeyChainSnapshotSchema.TAG_COUNTER_ID; -import static com.android.server.locksettings.recoverablekeystore.serialization.KeyChainSnapshotSchema.TAG_RECOVERY_KEY_MATERIAL; import static com.android.server.locksettings.recoverablekeystore.serialization.KeyChainSnapshotSchema.TAG_KEY_CHAIN_PROTECTION_PARAMS; import static com.android.server.locksettings.recoverablekeystore.serialization.KeyChainSnapshotSchema.TAG_KEY_CHAIN_PROTECTION_PARAMS_LIST; import static com.android.server.locksettings.recoverablekeystore.serialization.KeyChainSnapshotSchema.TAG_KEY_CHAIN_SNAPSHOT; import static com.android.server.locksettings.recoverablekeystore.serialization.KeyChainSnapshotSchema.TAG_KEY_DERIVATION_PARAMS; import static com.android.server.locksettings.recoverablekeystore.serialization.KeyChainSnapshotSchema.TAG_KEY_MATERIAL; +import static com.android.server.locksettings.recoverablekeystore.serialization.KeyChainSnapshotSchema.TAG_KEY_METADATA; import static com.android.server.locksettings.recoverablekeystore.serialization.KeyChainSnapshotSchema.TAG_LOCK_SCREEN_UI_TYPE; import static com.android.server.locksettings.recoverablekeystore.serialization.KeyChainSnapshotSchema.TAG_MAX_ATTEMPTS; import static com.android.server.locksettings.recoverablekeystore.serialization.KeyChainSnapshotSchema.TAG_MEMORY_DIFFICULTY; +import static com.android.server.locksettings.recoverablekeystore.serialization.KeyChainSnapshotSchema.TAG_RECOVERY_KEY_MATERIAL; import static com.android.server.locksettings.recoverablekeystore.serialization.KeyChainSnapshotSchema.TAG_SALT; import static com.android.server.locksettings.recoverablekeystore.serialization.KeyChainSnapshotSchema.TAG_SERVER_PARAMS; import static com.android.server.locksettings.recoverablekeystore.serialization.KeyChainSnapshotSchema.TAG_SNAPSHOT_VERSION; import static com.android.server.locksettings.recoverablekeystore.serialization.KeyChainSnapshotSchema.TAG_TRUSTED_HARDWARE_CERT_PATH; import static com.android.server.locksettings.recoverablekeystore.serialization.KeyChainSnapshotSchema.TAG_USER_SECRET_TYPE; +import android.annotation.Nullable; import android.security.keystore.recovery.KeyChainProtectionParams; import android.security.keystore.recovery.KeyChainSnapshot; import android.security.keystore.recovery.KeyDerivationParams; @@ -103,6 +102,7 @@ public class KeyChainSnapshotSerializer { XmlSerializer xmlSerializer, WrappedApplicationKey applicationKey) throws IOException { writePropertyTag(xmlSerializer, TAG_ALIAS, applicationKey.getAlias()); writePropertyTag(xmlSerializer, TAG_KEY_MATERIAL, applicationKey.getEncryptedKeyMaterial()); + writePropertyTag(xmlSerializer, TAG_KEY_METADATA, applicationKey.getMetadata()); } private static void writeKeyChainProtectionParams( @@ -181,8 +181,11 @@ public class KeyChainSnapshotSerializer { } private static void writePropertyTag( - XmlSerializer xmlSerializer, String propertyName, byte[] propertyValue) + XmlSerializer xmlSerializer, String propertyName, @Nullable byte[] propertyValue) throws IOException { + if (propertyValue == null) { + return; + } xmlSerializer.startTag(NAMESPACE, propertyName); xmlSerializer.text(Base64.encodeToString(propertyValue, /*flags=*/ Base64.DEFAULT)); xmlSerializer.endTag(NAMESPACE, propertyName); diff --git a/services/core/java/com/android/server/locksettings/recoverablekeystore/storage/RecoverableKeyStoreDb.java b/services/core/java/com/android/server/locksettings/recoverablekeystore/storage/RecoverableKeyStoreDb.java index e69f73df0184..dffaffe677ad 100644 --- a/services/core/java/com/android/server/locksettings/recoverablekeystore/storage/RecoverableKeyStoreDb.java +++ b/services/core/java/com/android/server/locksettings/recoverablekeystore/storage/RecoverableKeyStoreDb.java @@ -104,6 +104,12 @@ public class RecoverableKeyStoreDb { values.put(KeysEntry.COLUMN_NAME_LAST_SYNCED_AT, LAST_SYNCED_AT_UNSYNCED); values.put(KeysEntry.COLUMN_NAME_GENERATION_ID, wrappedKey.getPlatformKeyGenerationId()); values.put(KeysEntry.COLUMN_NAME_RECOVERY_STATUS, wrappedKey.getRecoveryStatus()); + byte[] keyMetadata = wrappedKey.getKeyMetadata(); + if (keyMetadata == null) { + values.putNull(KeysEntry.COLUMN_NAME_KEY_METADATA); + } else { + values.put(KeysEntry.COLUMN_NAME_KEY_METADATA, keyMetadata); + } return db.replace(KeysEntry.TABLE_NAME, /*nullColumnHack=*/ null, values); } @@ -119,7 +125,8 @@ public class RecoverableKeyStoreDb { KeysEntry.COLUMN_NAME_NONCE, KeysEntry.COLUMN_NAME_WRAPPED_KEY, KeysEntry.COLUMN_NAME_GENERATION_ID, - KeysEntry.COLUMN_NAME_RECOVERY_STATUS}; + KeysEntry.COLUMN_NAME_RECOVERY_STATUS, + KeysEntry.COLUMN_NAME_KEY_METADATA}; String selection = KeysEntry.COLUMN_NAME_UID + " = ? AND " + KeysEntry.COLUMN_NAME_ALIAS + " = ?"; @@ -155,7 +162,17 @@ public class RecoverableKeyStoreDb { cursor.getColumnIndexOrThrow(KeysEntry.COLUMN_NAME_GENERATION_ID)); int recoveryStatus = cursor.getInt( cursor.getColumnIndexOrThrow(KeysEntry.COLUMN_NAME_RECOVERY_STATUS)); - return new WrappedKey(nonce, keyMaterial, generationId, recoveryStatus); + + // Retrieve the metadata associated with the key + byte[] keyMetadata; + int metadataIdx = cursor.getColumnIndexOrThrow(KeysEntry.COLUMN_NAME_KEY_METADATA); + if (cursor.isNull(metadataIdx)) { + keyMetadata = null; + } else { + keyMetadata = cursor.getBlob(metadataIdx); + } + + return new WrappedKey(nonce, keyMaterial, keyMetadata, generationId, recoveryStatus); } } @@ -252,7 +269,8 @@ public class RecoverableKeyStoreDb { KeysEntry.COLUMN_NAME_NONCE, KeysEntry.COLUMN_NAME_WRAPPED_KEY, KeysEntry.COLUMN_NAME_ALIAS, - KeysEntry.COLUMN_NAME_RECOVERY_STATUS}; + KeysEntry.COLUMN_NAME_RECOVERY_STATUS, + KeysEntry.COLUMN_NAME_KEY_METADATA}; String selection = KeysEntry.COLUMN_NAME_USER_ID + " = ? AND " + KeysEntry.COLUMN_NAME_UID + " = ? AND " @@ -283,8 +301,18 @@ public class RecoverableKeyStoreDb { cursor.getColumnIndexOrThrow(KeysEntry.COLUMN_NAME_ALIAS)); int recoveryStatus = cursor.getInt( cursor.getColumnIndexOrThrow(KeysEntry.COLUMN_NAME_RECOVERY_STATUS)); - keys.put(alias, new WrappedKey(nonce, keyMaterial, platformKeyGenerationId, - recoveryStatus)); + + // Retrieve the metadata associated with the key + byte[] keyMetadata; + int metadataIdx = cursor.getColumnIndexOrThrow(KeysEntry.COLUMN_NAME_KEY_METADATA); + if (cursor.isNull(metadataIdx)) { + keyMetadata = null; + } else { + keyMetadata = cursor.getBlob(metadataIdx); + } + + keys.put(alias, new WrappedKey(nonce, keyMaterial, keyMetadata, + platformKeyGenerationId, recoveryStatus)); } return keys; } diff --git a/services/core/java/com/android/server/locksettings/recoverablekeystore/storage/RecoverableKeyStoreDbContract.java b/services/core/java/com/android/server/locksettings/recoverablekeystore/storage/RecoverableKeyStoreDbContract.java index 22e77cc79831..b58ee4bc9d74 100644 --- a/services/core/java/com/android/server/locksettings/recoverablekeystore/storage/RecoverableKeyStoreDbContract.java +++ b/services/core/java/com/android/server/locksettings/recoverablekeystore/storage/RecoverableKeyStoreDbContract.java @@ -67,6 +67,12 @@ class RecoverableKeyStoreDbContract { * Status of the key sync {@code RecoveryController#setRecoveryStatus} */ static final String COLUMN_NAME_RECOVERY_STATUS = "recovery_status"; + + /** + * Data blob that will be authenticated (but encrypted) together with the key when the key + * is uploaded to cloud. + */ + static final String COLUMN_NAME_KEY_METADATA = "key_metadata"; } /** diff --git a/services/core/java/com/android/server/locksettings/recoverablekeystore/storage/RecoverableKeyStoreDbHelper.java b/services/core/java/com/android/server/locksettings/recoverablekeystore/storage/RecoverableKeyStoreDbHelper.java index 43efe9cc0cbb..b0613da35d28 100644 --- a/services/core/java/com/android/server/locksettings/recoverablekeystore/storage/RecoverableKeyStoreDbHelper.java +++ b/services/core/java/com/android/server/locksettings/recoverablekeystore/storage/RecoverableKeyStoreDbHelper.java @@ -32,7 +32,7 @@ import com.android.server.locksettings.recoverablekeystore.storage.RecoverableKe class RecoverableKeyStoreDbHelper extends SQLiteOpenHelper { private static final String TAG = "RecoverableKeyStoreDbHp"; - static final int DATABASE_VERSION = 4; + static final int DATABASE_VERSION = 5; private static final String DATABASE_NAME = "recoverablekeystore.db"; private static final String SQL_CREATE_KEYS_ENTRY = @@ -46,6 +46,7 @@ class RecoverableKeyStoreDbHelper extends SQLiteOpenHelper { + KeysEntry.COLUMN_NAME_GENERATION_ID + " INTEGER," + KeysEntry.COLUMN_NAME_LAST_SYNCED_AT + " INTEGER," + KeysEntry.COLUMN_NAME_RECOVERY_STATUS + " INTEGER," + + KeysEntry.COLUMN_NAME_KEY_METADATA + " BLOB," + "UNIQUE(" + KeysEntry.COLUMN_NAME_UID + "," + KeysEntry.COLUMN_NAME_ALIAS + "))"; @@ -135,6 +136,11 @@ class RecoverableKeyStoreDbHelper extends SQLiteOpenHelper { oldVersion = 4; } + if (oldVersion < 5 && newVersion >= 5) { + upgradeDbForVersion5(db); + oldVersion = 5; + } + if (oldVersion != newVersion) { Log.e(TAG, "Failed to update recoverablekeystore database to the most recent version"); } @@ -166,6 +172,13 @@ class RecoverableKeyStoreDbHelper extends SQLiteOpenHelper { /*defaultStr=*/ null); } + private void upgradeDbForVersion5(SQLiteDatabase db) { + Log.d(TAG, "Updating recoverable keystore database to version 5"); + // adds a column to store the metadata for application keys + addColumnToTable(db, KeysEntry.TABLE_NAME, + KeysEntry.COLUMN_NAME_KEY_METADATA, "BLOB", /*defaultStr=*/ null); + } + private static void addColumnToTable( SQLiteDatabase db, String tableName, String column, String columnType, String defaultStr) { diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java index 7323e93ebf84..1798617a9fce 100644 --- a/services/core/java/com/android/server/notification/NotificationManagerService.java +++ b/services/core/java/com/android/server/notification/NotificationManagerService.java @@ -3509,7 +3509,7 @@ public class NotificationManagerService extends SystemService { getContext().sendBroadcastAsUser(new Intent( NotificationManager.ACTION_NOTIFICATION_POLICY_ACCESS_GRANTED_CHANGED) .setPackage(pkg) - .addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY), + .addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT), UserHandle.of(userId), null); handleSavePolicyFile(); } diff --git a/services/core/java/com/android/server/om/IdmapManager.java b/services/core/java/com/android/server/om/IdmapManager.java index 16143d3ae9e0..74fbea1544bd 100644 --- a/services/core/java/com/android/server/om/IdmapManager.java +++ b/services/core/java/com/android/server/om/IdmapManager.java @@ -24,11 +24,14 @@ import static com.android.server.om.OverlayManagerService.TAG; import android.annotation.NonNull; import android.content.om.OverlayInfo; +import android.content.pm.ApplicationInfo; import android.content.pm.PackageInfo; +import android.os.Build.VERSION_CODES; import android.os.IBinder; import android.os.IIdmap2; import android.os.RemoteException; import android.os.ServiceManager; +import android.os.SystemProperties; import android.os.UserHandle; import android.util.Slog; @@ -51,6 +54,13 @@ class IdmapManager { private final Installer mInstaller; private IIdmap2 mIdmap2Service; + private static final boolean VENDOR_IS_Q_OR_LATER; + static { + // STOPSHIP(b/119390857): Check api version once Q sdk version is finalized + final String value = SystemProperties.get("ro.vndk.version", "Q"); + VENDOR_IS_Q_OR_LATER = value.equals("Q") || value.equals("q"); + } + IdmapManager(final Installer installer) { mInstaller = installer; if (FEATURE_FLAG_IDMAP2) { @@ -69,10 +79,13 @@ class IdmapManager { final String overlayPath = overlayPackage.applicationInfo.getBaseCodePath(); try { if (FEATURE_FLAG_IDMAP2) { - if (mIdmap2Service.verifyIdmap(overlayPath, userId)) { + int policies = determineFulfilledPolicies(overlayPackage); + boolean enforce = enforceOverlayable(overlayPackage); + if (mIdmap2Service.verifyIdmap(overlayPath, policies, enforce, userId)) { return true; } - return mIdmap2Service.createIdmap(targetPath, overlayPath, userId) != null; + return mIdmap2Service.createIdmap(targetPath, overlayPath, policies, enforce, + userId) != null; } else { mInstaller.idmap(targetPath, overlayPath, sharedGid); return true; @@ -156,4 +169,71 @@ class IdmapManager { }, SECOND_IN_MILLIS); } } + + /** + * Checks if overlayable and policies should be enforced on the specified overlay for backwards + * compatibility with pre-Q overlays. + */ + private boolean enforceOverlayable(@NonNull final PackageInfo overlayPackage) { + final ApplicationInfo ai = overlayPackage.applicationInfo; + if (ai.targetSdkVersion >= VERSION_CODES.Q) { + // Always enforce policies for overlays targeting Q+. + return true; + } + + if (ai.isVendor() && !VENDOR_IS_Q_OR_LATER) { + // If the overlay is on a pre-Q vendor partition, do not enforce overlayable + // restrictions on this overlay because the pre-Q platform has no understanding of + // overlayable. + return false; + } + + // Do not enforce overlayable restrictions on pre-Q overlays signed with the + // platform signature. + return !ai.isSignedWithPlatformKey(); + } + + /** + * Retrieves a bitmask for idmap2 that represents the policies the specified overlay fulfills. + * @throws SecurityException if the overlay is not allowed to overlay any resource + */ + private int determineFulfilledPolicies(@NonNull final PackageInfo overlayPackage) + throws SecurityException { + final ApplicationInfo ai = overlayPackage.applicationInfo; + final boolean overlayIsQOrLater = ai.targetSdkVersion >= VERSION_CODES.Q; + + int fulfilledPolicies = 0; + + // TODO(b/119402606) : Add signature policy + + // Vendor partition (/vendor) + if (ai.isVendor()) { + if (overlayIsQOrLater) { + fulfilledPolicies |= IIdmap2.POLICY_VENDOR_PARTITION; + } else if (VENDOR_IS_Q_OR_LATER) { + throw new SecurityException("Overlay must target Q sdk or higher"); + } + } + + // Product partition (/product) + if (ai.isProduct()) { + if (overlayIsQOrLater) { + fulfilledPolicies |= IIdmap2.POLICY_PRODUCT_PARTITION; + } else { + throw new SecurityException("Overlay must target Q sdk or higher"); + } + } + + // System partition (/system) + if (ai.isSystemApp()) { + if (overlayIsQOrLater) { + fulfilledPolicies |= IIdmap2.POLICY_SYSTEM_PARTITION; + } else { + throw new SecurityException("Overlay must target Q sdk or higher"); + } + } + + // All overlays can overlay resources with the public policy + return fulfilledPolicies | IIdmap2.POLICY_PUBLIC; + } } diff --git a/services/core/java/com/android/server/om/OverlayManagerServiceImpl.java b/services/core/java/com/android/server/om/OverlayManagerServiceImpl.java index b0d2704196a6..1cbf0bfac05c 100644 --- a/services/core/java/com/android/server/om/OverlayManagerServiceImpl.java +++ b/services/core/java/com/android/server/om/OverlayManagerServiceImpl.java @@ -270,7 +270,9 @@ final class OverlayManagerServiceImpl { Slog.d(TAG, "onTargetPackageUpgraded packageName=" + packageName + " userId=" + userId); } - updateAllOverlaysForTarget(packageName, userId, 0); + if (updateAllOverlaysForTarget(packageName, userId, 0)) { + mListener.onOverlaysChanged(packageName, userId); + } } void onTargetPackageRemoved(@NonNull final String packageName, final int userId) { diff --git a/services/core/java/com/android/server/os/BugreportManagerServiceImpl.java b/services/core/java/com/android/server/os/BugreportManagerServiceImpl.java index faa4714a8697..1178cc18f828 100644 --- a/services/core/java/com/android/server/os/BugreportManagerServiceImpl.java +++ b/services/core/java/com/android/server/os/BugreportManagerServiceImpl.java @@ -17,7 +17,9 @@ package com.android.server.os; import android.annotation.RequiresPermission; +import android.app.AppOpsManager; import android.content.Context; +import android.os.Binder; import android.os.BugreportParams; import android.os.IDumpstate; import android.os.IDumpstateListener; @@ -46,9 +48,11 @@ class BugreportManagerServiceImpl extends IDumpstate.Stub { private IDumpstate mDs = null; private final Context mContext; + private final AppOpsManager mAppOps; BugreportManagerServiceImpl(Context context) { mContext = context; + mAppOps = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE); } @Override @@ -60,21 +64,24 @@ class BugreportManagerServiceImpl extends IDumpstate.Stub { throw new UnsupportedOperationException("setListener is not allowed on this service"); } - @Override @RequiresPermission(android.Manifest.permission.DUMP) - public void startBugreport(FileDescriptor bugreportFd, FileDescriptor screenshotFd, + public void startBugreport(int callingUidUnused, String callingPackage, + FileDescriptor bugreportFd, FileDescriptor screenshotFd, int bugreportMode, IDumpstateListener listener) throws RemoteException { - + int callingUid = Binder.getCallingUid(); + // TODO(b/111441001): validate all arguments & ensure primary user validate(bugreportMode); + mAppOps.checkPackage(callingUid, callingPackage); mDs = getDumpstateService(); if (mDs == null) { Slog.w(TAG, "Unable to get bugreport service"); // TODO(b/111441001): pass error on listener return; } - mDs.startBugreport(bugreportFd, screenshotFd, bugreportMode, listener); + mDs.startBugreport(callingUid, callingPackage, + bugreportFd, screenshotFd, bugreportMode, listener); } private boolean validate(@BugreportParams.BugreportMode int mode) { diff --git a/services/core/java/com/android/server/pm/BackgroundDexOptService.java b/services/core/java/com/android/server/pm/BackgroundDexOptService.java index d6ab5f717568..65fc9824c76e 100644 --- a/services/core/java/com/android/server/pm/BackgroundDexOptService.java +++ b/services/core/java/com/android/server/pm/BackgroundDexOptService.java @@ -27,24 +27,29 @@ import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; +import android.content.pm.PackageInfo; import android.os.BatteryManager; import android.os.Environment; import android.os.ServiceManager; import android.os.SystemProperties; +import android.os.UserHandle; import android.os.storage.StorageManager; import android.util.ArraySet; import android.util.Log; +import android.util.StatsLog; -import com.android.server.pm.dex.DexManager; +import com.android.internal.util.ArrayUtils; import com.android.server.LocalServices; import com.android.server.PinnerService; +import com.android.server.pm.dex.DexManager; import com.android.server.pm.dex.DexoptOptions; import java.io.File; +import java.nio.file.Paths; import java.util.List; import java.util.Set; -import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicBoolean; /** * {@hide} @@ -289,6 +294,50 @@ public class BackgroundDexOptService extends JobService { return result; } + /** + * Get the size of the directory. It uses recursion to go over all files. + * @param f + * @return + */ + private long getDirectorySize(File f) { + long size = 0; + if (f.isDirectory()) { + for (File file: f.listFiles()) { + size += getDirectorySize(file); + } + } else { + size = f.length(); + } + return size; + } + + /** + * Get the size of a package. + * @param pkg + */ + private long getPackageSize(PackageManagerService pm, String pkg) { + PackageInfo info = pm.getPackageInfo(pkg, 0, UserHandle.USER_SYSTEM); + long size = 0; + if (info != null && info.applicationInfo != null) { + File path = Paths.get(info.applicationInfo.sourceDir).toFile(); + if (path.isFile()) { + path = path.getParentFile(); + } + size += getDirectorySize(path); + if (!ArrayUtils.isEmpty(info.applicationInfo.splitSourceDirs)) { + for (String splitSourceDir : info.applicationInfo.splitSourceDirs) { + path = Paths.get(splitSourceDir).toFile(); + if (path.isFile()) { + path = path.getParentFile(); + } + size += getDirectorySize(path); + } + } + return size; + } + return 0; + } + private int optimizePackages(PackageManagerService pm, ArraySet<String> pkgs, long lowStorageThreshold, boolean is_for_primary_dex, ArraySet<String> failedPackageNames) { @@ -315,8 +364,10 @@ public class BackgroundDexOptService extends JobService { int reason; boolean downgrade; + long package_size_before = 0; //used when the app is downgraded // Downgrade unused packages. if (unusedPackages.contains(pkg) && shouldDowngrade) { + package_size_before = getPackageSize(pm, pkg); // This applies for system apps or if packages location is not a directory, i.e. // monolithic install. if (is_for_primary_dex && !pm.canHaveOatDir(pkg)) { @@ -366,6 +417,10 @@ public class BackgroundDexOptService extends JobService { synchronized (failedPackageNames) { failedPackageNames.remove(pkg); } + if (downgrade) { + StatsLog.write(StatsLog.APP_DOWNGRADED, pkg, package_size_before, + getPackageSize(pm, pkg), /*aggressive=*/ false); + } } } notifyPinService(updatedPackages); diff --git a/services/core/java/com/android/server/pm/Installer.java b/services/core/java/com/android/server/pm/Installer.java index a5c083e1d03c..8a6105cb7fa9 100644 --- a/services/core/java/com/android/server/pm/Installer.java +++ b/services/core/java/com/android/server/pm/Installer.java @@ -621,6 +621,14 @@ public class Installer extends SystemService { throw new InstallerException("Invalid instruction set: " + instructionSet); } + public boolean compileLayouts(String apkPath, String packageName, String outDexFile, int uid) { + try { + return mInstalld.compileLayouts(apkPath, packageName, outDexFile, uid); + } catch (RemoteException e) { + return false; + } + } + public static class InstallerException extends Exception { public InstallerException(String detailMessage) { super(detailMessage); diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java index 6baf12ce3b44..55e12cdf208a 100644 --- a/services/core/java/com/android/server/pm/PackageManagerService.java +++ b/services/core/java/com/android/server/pm/PackageManagerService.java @@ -311,6 +311,7 @@ import com.android.server.pm.dex.ArtManagerService; import com.android.server.pm.dex.DexManager; import com.android.server.pm.dex.DexoptOptions; import com.android.server.pm.dex.PackageDexUsage; +import com.android.server.pm.dex.ViewCompiler; import com.android.server.pm.permission.BasePermission; import com.android.server.pm.permission.DefaultPermissionGrantPolicy; import com.android.server.pm.permission.DefaultPermissionGrantPolicy.DefaultPermissionGrantedCallback; @@ -446,6 +447,9 @@ public class PackageManagerService extends IPackageManager.Stub private static final long BACKUP_TIMEOUT_MILLIS = TimeUnit.SECONDS.toMillis(60); + private static final boolean PRECOMPILED_LAYOUT_ENABLED = + SystemProperties.getBoolean("view.precompiled_layout_enabled", false); + private static final int RADIO_UID = Process.PHONE_UID; private static final int LOG_UID = Process.LOG_UID; private static final int NFC_UID = Process.NFC_UID; @@ -888,6 +892,8 @@ public class PackageManagerService extends IPackageManager.Stub // is used by other apps). private final DexManager mDexManager; + private final ViewCompiler mViewCompiler; + private AtomicInteger mNextMoveId = new AtomicInteger(); private final MoveCallbacks mMoveCallbacks; @@ -1342,6 +1348,8 @@ public class PackageManagerService extends IPackageManager.Stub final @Nullable String mSystemTextClassifierPackage; final @Nullable String mWellbeingPackage; final @Nullable String mDocumenterPackage; + final @Nullable String mConfiguratorPackage; + final @Nullable String mAppPredictionServicePackage; final @NonNull String mServicesSystemSharedLibraryPackageName; final @NonNull String mSharedSystemSharedLibraryPackageName; @@ -1458,8 +1466,9 @@ public class PackageManagerService extends IPackageManager.Stub Trace.asyncTraceEnd(TRACE_TAG_PACKAGE_MANAGER, args.traceMethod, args.traceCookie); } - } else { - Slog.e(TAG, "Bogus post-install token " + msg.arg1); + } else if (DEBUG_INSTALL) { + // No post-install when we run restore from installExistingPackageForUser + Slog.i(TAG, "Nothing to do for post-install token " + msg.arg1); } Trace.asyncTraceEnd(TRACE_TAG_PACKAGE_MANAGER, "postInstall", msg.arg1); @@ -2259,6 +2268,8 @@ public class PackageManagerService extends IPackageManager.Stub mArtManagerService = new ArtManagerService(mContext, this, installer, mInstallLock); mMoveCallbacks = new MoveCallbacks(FgThread.get().getLooper()); + mViewCompiler = new ViewCompiler(mInstallLock, mInstaller); + mOnPermissionChangeListeners = new OnPermissionChangeListeners( FgThread.get().getLooper()); @@ -2865,6 +2876,9 @@ public class PackageManagerService extends IPackageManager.Stub mWellbeingPackage = getWellbeingPackageName(); mDocumenterPackage = getDocumenterPackageName(); + mConfiguratorPackage = + mContext.getString(R.string.config_deviceConfiguratorPackageName); + mAppPredictionServicePackage = getAppPredictionServicePackageName(); // Now that we know all of the shared libraries, update all clients to have // the correct library paths. @@ -3747,7 +3761,7 @@ public class PackageManagerService extends IPackageManager.Stub /** * Returns whether or not a full application can see an instant application. * <p> - * Currently, there are three cases in which this can occur: + * Currently, there are four cases in which this can occur: * <ol> * <li>The calling application is a "special" process. Special processes * are those with a UID < {@link Process#FIRST_APPLICATION_UID}.</li> @@ -3755,6 +3769,7 @@ public class PackageManagerService extends IPackageManager.Stub * {@link android.Manifest.permission#ACCESS_INSTANT_APPS}.</li> * <li>The calling application is the default launcher on the * system partition.</li> + * <li>The calling application is the default app prediction service.</li> * </ol> */ private boolean canViewInstantApps(int callingUid, int userId) { @@ -3772,6 +3787,11 @@ public class PackageManagerService extends IPackageManager.Stub && isCallerSameApp(homeComponent.getPackageName(), callingUid)) { return true; } + // TODO(b/122900055) Change/Remove this and replace with new permission role. + if (mAppPredictionServicePackage != null + && isCallerSameApp(mAppPredictionServicePackage, callingUid)) { + return true; + } } return false; } @@ -5487,13 +5507,13 @@ public class PackageManagerService extends IPackageManager.Stub final int callingUserId = UserHandle.getUserId(callingUid); final boolean isCallerInstantApp = getInstantAppPackageName(callingUid) != null; // Map to base uids. - uid1 = UserHandle.getAppId(uid1); - uid2 = UserHandle.getAppId(uid2); + final int appId1 = UserHandle.getAppId(uid1); + final int appId2 = UserHandle.getAppId(uid2); // reader synchronized (mPackages) { Signature[] s1; Signature[] s2; - Object obj = mSettings.getSettingLPr(uid1); + Object obj = mSettings.getSettingLPr(appId1); if (obj != null) { if (obj instanceof SharedUserSetting) { if (isCallerInstantApp) { @@ -5512,7 +5532,7 @@ public class PackageManagerService extends IPackageManager.Stub } else { return PackageManager.SIGNATURE_UNKNOWN_PACKAGE; } - obj = mSettings.getSettingLPr(uid2); + obj = mSettings.getSettingLPr(appId2); if (obj != null) { if (obj instanceof SharedUserSetting) { if (isCallerInstantApp) { @@ -5567,11 +5587,11 @@ public class PackageManagerService extends IPackageManager.Stub final int callingUid = Binder.getCallingUid(); final int callingUserId = UserHandle.getUserId(callingUid); // Map to base uids. - uid = UserHandle.getAppId(uid); + final int appId = UserHandle.getAppId(uid); // reader synchronized (mPackages) { final PackageParser.SigningDetails signingDetails; - final Object obj = mSettings.getSettingLPr(uid); + final Object obj = mSettings.getSettingLPr(appId); if (obj != null) { if (obj instanceof SharedUserSetting) { final boolean isCallerInstantApp = getInstantAppPackageName(callingUid) != null; @@ -5687,10 +5707,10 @@ public class PackageManagerService extends IPackageManager.Stub final int callingUid = Binder.getCallingUid(); final boolean isCallerInstantApp = getInstantAppPackageName(callingUid) != null; final int userId = UserHandle.getUserId(uid); - uid = UserHandle.getAppId(uid); + final int appId = UserHandle.getAppId(uid); // reader synchronized (mPackages) { - Object obj = mSettings.getSettingLPr(uid); + final Object obj = mSettings.getSettingLPr(appId); if (obj instanceof SharedUserSetting) { if (isCallerInstantApp) { return null; @@ -5725,8 +5745,9 @@ public class PackageManagerService extends IPackageManager.Stub if (getInstantAppPackageName(callingUid) != null) { return null; } + final int appId = UserHandle.getAppId(uid); synchronized (mPackages) { - Object obj = mSettings.getSettingLPr(UserHandle.getAppId(uid)); + final Object obj = mSettings.getSettingLPr(appId); if (obj instanceof SharedUserSetting) { final SharedUserSetting sus = (SharedUserSetting) obj; return sus.name + ":" + sus.userId; @@ -5753,8 +5774,8 @@ public class PackageManagerService extends IPackageManager.Stub final String[] names = new String[uids.length]; synchronized (mPackages) { for (int i = uids.length - 1; i >= 0; i--) { - final int uid = uids[i]; - Object obj = mSettings.getSettingLPr(UserHandle.getAppId(uid)); + final int appId = UserHandle.getAppId(uids[i]); + final Object obj = mSettings.getSettingLPr(appId); if (obj instanceof SharedUserSetting) { final SharedUserSetting sus = (SharedUserSetting) obj; names[i] = "shared:" + sus.name; @@ -5802,8 +5823,9 @@ public class PackageManagerService extends IPackageManager.Stub if (getInstantAppPackageName(callingUid) != null) { return 0; } + final int appId = UserHandle.getAppId(uid); synchronized (mPackages) { - Object obj = mSettings.getSettingLPr(UserHandle.getAppId(uid)); + final Object obj = mSettings.getSettingLPr(appId); if (obj instanceof SharedUserSetting) { final SharedUserSetting sus = (SharedUserSetting) obj; return sus.pkgFlags; @@ -5824,8 +5846,9 @@ public class PackageManagerService extends IPackageManager.Stub if (getInstantAppPackageName(callingUid) != null) { return 0; } + final int appId = UserHandle.getAppId(uid); synchronized (mPackages) { - Object obj = mSettings.getSettingLPr(UserHandle.getAppId(uid)); + final Object obj = mSettings.getSettingLPr(appId); if (obj instanceof SharedUserSetting) { final SharedUserSetting sus = (SharedUserSetting) obj; return sus.pkgPrivateFlags; @@ -5845,10 +5868,10 @@ public class PackageManagerService extends IPackageManager.Stub if (getInstantAppPackageName(Binder.getCallingUid()) != null) { return false; } - uid = UserHandle.getAppId(uid); + final int appId = UserHandle.getAppId(uid); // reader synchronized (mPackages) { - Object obj = mSettings.getSettingLPr(uid); + final Object obj = mSettings.getSettingLPr(appId); if (obj instanceof SharedUserSetting) { final SharedUserSetting sus = (SharedUserSetting) obj; final Iterator<PackageSetting> it = sus.packages.iterator(); @@ -9089,6 +9112,10 @@ public class PackageManagerService extends IPackageManager.Stub pkgCompilationReason = PackageManagerService.REASON_BACKGROUND_DEXOPT; } + if (PRECOMPILED_LAYOUT_ENABLED) { + mArtManagerService.compileLayouts(pkg); + } + // 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 @@ -9233,6 +9260,21 @@ public class PackageManagerService extends IPackageManager.Stub return performDexOpt(new DexoptOptions(packageName, compilerFilter, flags)); } + /** + * Ask the package manager to compile layouts in the given package. + */ + @Override + public boolean compileLayouts(String packageName) { + PackageParser.Package pkg; + synchronized (mPackages) { + pkg = mPackages.get(packageName); + if (pkg == null) { + return false; + } + } + return mViewCompiler.compileLayouts(pkg); + } + /*package*/ boolean performDexOpt(DexoptOptions options) { if (getInstantAppPackageName(Binder.getCallingUid()) != null) { return false; @@ -12723,6 +12765,11 @@ public class PackageManagerService extends IPackageManager.Stub @Override public int installExistingPackageAsUser(String packageName, int userId, int installFlags, int installReason) { + if (DEBUG_INSTALL) { + Log.v(TAG, "installExistingPackageAsUser package=" + packageName + " userId=" + userId + + " installFlags=" + installFlags + " installReason=" + installReason); + } + final int callingUid = Binder.getCallingUid(); if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.INSTALL_PACKAGES) != PackageManager.PERMISSION_GRANTED @@ -12793,6 +12840,11 @@ public class PackageManagerService extends IPackageManager.Stub synchronized (mPackages) { updateSequenceNumberLP(pkgSetting, new int[]{ userId }); } + // start async restore with no post-install since we finish install here + PackageInstalledInfo res = + createPackageInstalledInfo(PackageManager.INSTALL_SUCCEEDED); + res.pkg = pkgSetting.pkg; + restoreAndPostInstall(userId, res, null); } } finally { Binder.restoreCallingIdentity(callingId); @@ -13732,8 +13784,8 @@ public class PackageManagerService extends IPackageManager.Stub } } for (InstallRequest request : installRequests) { - resolvePackageInstalledInfo(request.args, - request.installResult); + restoreAndPostInstall(request.args.user.getIdentifier(), request.installResult, + new PostInstallData(request.args, request.installResult)); } }); } @@ -13748,7 +13800,14 @@ public class PackageManagerService extends IPackageManager.Stub return res; } - private void resolvePackageInstalledInfo(InstallArgs args, PackageInstalledInfo res) { + /** @param data Post-install is performed only if this is non-null. */ + private void restoreAndPostInstall( + int userId, PackageInstalledInfo res, @Nullable PostInstallData data) { + if (DEBUG_INSTALL) { + Log.v(TAG, "restoreAndPostInstall userId=" + userId + " package=" + + res.pkg.packageName); + } + // A restore should be performed at this point if (a) the install // succeeded, (b) the operation is not an update, and (c) the new // package has not opted out of backup participation. @@ -13764,9 +13823,12 @@ public class PackageManagerService extends IPackageManager.Stub int token; if (mNextInstallToken < 0) mNextInstallToken = 1; token = mNextInstallToken++; + if (data != null) { + mRunningInstalls.put(token, data); + } else if (DEBUG_INSTALL) { + Log.v(TAG, "No post-install required for " + token); + } - PostInstallData data = new PostInstallData(args, res); - mRunningInstalls.put(token, data); if (DEBUG_INSTALL) Log.v(TAG, "+ starting restore round-trip " + token); if (res.returnCode == PackageManager.INSTALL_SUCCEEDED && doRestore) { @@ -13777,7 +13839,11 @@ public class PackageManagerService extends IPackageManager.Stub IBackupManager bm = IBackupManager.Stub.asInterface( ServiceManager.getService(Context.BACKUP_SERVICE)); if (bm != null) { - int userId = args.user.getIdentifier(); + // For backwards compatibility as USER_ALL previously routed directly to USER_SYSTEM + // in the BackupManager. USER_ALL is used in compatibility tests. + if (userId == UserHandle.USER_ALL) { + userId = UserHandle.USER_SYSTEM; + } if (DEBUG_INSTALL) { Log.v(TAG, "token " + token + " to BM for possible restore for user " + userId); } @@ -16104,6 +16170,13 @@ public class PackageManagerService extends IPackageManager.Stub && ((pkg.applicationInfo.flags & ApplicationInfo.FLAG_DEBUGGABLE) == 0); if (performDexopt) { + // Compile the layout resources. + if (PRECOMPILED_LAYOUT_ENABLED) { + Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "compileLayouts"); + mViewCompiler.compileLayouts(pkg); + Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER); + } + Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "dexopt"); // Do not run PackageDexOptimizer through the local performDexOpt // method because `pkg` may not be in `mPackages` yet. @@ -18944,7 +19017,8 @@ public class PackageManagerService extends IPackageManager.Stub @GuardedBy("mPackages") private int getUidTargetSdkVersionLockedLPr(int uid) { - Object obj = mSettings.getSettingLPr(uid); + final int appId = UserHandle.getAppId(uid); + final Object obj = mSettings.getSettingLPr(appId); if (obj instanceof SharedUserSetting) { final SharedUserSetting sus = (SharedUserSetting) obj; int vers = Build.VERSION_CODES.CUR_DEVELOPMENT; @@ -19135,7 +19209,7 @@ public class PackageManagerService extends IPackageManager.Stub // writer synchronized (mPackages) { PackageParser.Package pkg = mPackages.get(packageName); - if (pkg == null || pkg.applicationInfo.uid != callingUid) { + if (pkg == null || !isCallerSameApp(packageName, callingUid)) { if (mContext.checkCallingOrSelfPermission( android.Manifest.permission.SET_PREFERRED_APPLICATIONS) != PackageManager.PERMISSION_GRANTED) { @@ -19808,6 +19882,14 @@ public class PackageManagerService extends IPackageManager.Stub .setPackage(launcherComponent.getPackageName()); mContext.sendBroadcastAsUser(launcherIntent, UserHandle.of(launcherUid)); } + // TODO(b/122900055) Change/Remove this and replace with new permission role. + if (mAppPredictionServicePackage != null) { + Intent predictorIntent = new Intent(PackageInstaller.ACTION_SESSION_COMMITTED) + .putExtra(PackageInstaller.EXTRA_SESSION, sessionInfo) + .putExtra(Intent.EXTRA_USER, UserHandle.of(userId)) + .setPackage(mAppPredictionServicePackage); + mContext.sendBroadcastAsUser(predictorIntent, UserHandle.of(launcherUid)); + } } } @@ -19960,6 +20042,20 @@ public class PackageManagerService extends IPackageManager.Stub return mContext.getString(R.string.config_defaultWellbeingPackage); } + private String getAppPredictionServicePackageName() { + String flattenedAppPredictionServiceComponentName = + mContext.getString(R.string.config_defaultAppPredictionService); + if (flattenedAppPredictionServiceComponentName == null) { + return null; + } + ComponentName appPredictionServiceComponentName = + ComponentName.unflattenFromString(flattenedAppPredictionServiceComponentName); + if (appPredictionServiceComponentName == null) { + return null; + } + return appPredictionServiceComponentName.getPackageName(); + } + @Override public void setApplicationEnabledSetting(String appPackageName, int newState, int flags, int userId, String callingPackage) { @@ -23122,6 +23218,8 @@ public class PackageManagerService extends IPackageManager.Stub return mWellbeingPackage; case PackageManagerInternal.PACKAGE_DOCUMENTER: return mDocumenterPackage; + case PackageManagerInternal.PACKAGE_CONFIGURATOR: + return mConfiguratorPackage; } return null; } @@ -23673,6 +23771,21 @@ public class PackageManagerService extends IPackageManager.Stub public void setEnableRollbackCode(int token, int enableRollbackCode) { PackageManagerService.this.setEnableRollbackCode(token, enableRollbackCode); } + + /** + * Ask the package manager to compile layouts in the given package. + */ + @Override + public boolean compileLayouts(String packageName) { + PackageParser.Package pkg; + synchronized (mPackages) { + pkg = mPackages.get(packageName); + if (pkg == null) { + return false; + } + } + return mArtManagerService.compileLayouts(pkg); + } } @GuardedBy("mPackages") diff --git a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java index c9d298cc28c2..022c1aad8113 100644 --- a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java +++ b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java @@ -40,6 +40,7 @@ import android.content.pm.InstrumentationInfo; import android.content.pm.PackageInfo; import android.content.pm.PackageInstaller; import android.content.pm.PackageInstaller.SessionParams; +import android.content.pm.PackageManagerInternal; import android.content.pm.PackageItemInfo; import android.content.pm.PackageManager; import android.content.pm.PackageManager.NameNotFoundException; @@ -1170,6 +1171,7 @@ class PackageManagerShellCommand extends ShellCommand { String checkProfilesRaw = null; boolean secondaryDex = false; String split = null; + boolean compileLayouts = false; String opt; while ((opt = getNextOption()) != null) { @@ -1189,6 +1191,9 @@ class PackageManagerShellCommand extends ShellCommand { case "-r": compilationReason = getNextArgRequired(); break; + case "--compile-layouts": + compileLayouts = true; + break; case "--check-prof": checkProfilesRaw = getNextArgRequired(); break; @@ -1220,14 +1225,16 @@ class PackageManagerShellCommand extends ShellCommand { } } - if (compilerFilter != null && compilationReason != null) { - pw.println("Cannot use compilation filter (\"-m\") and compilation reason (\"-r\") " + - "at the same time"); - return 1; - } - if (compilerFilter == null && compilationReason == null) { - pw.println("Cannot run without any of compilation filter (\"-m\") and compilation " + - "reason (\"-r\") at the same time"); + final boolean compilerFilterGiven = compilerFilter != null; + final boolean compilationReasonGiven = compilationReason != null; + // Make sure exactly one of -m, -r, or --compile-layouts is given. + if ((!compilerFilterGiven && !compilationReasonGiven && !compileLayouts) + || (!compilerFilterGiven && compilationReasonGiven && compileLayouts) + || (compilerFilterGiven && !compilationReasonGiven && compileLayouts) + || (compilerFilterGiven && compilationReasonGiven && !compileLayouts) + || (compilerFilterGiven && compilationReasonGiven && compileLayouts)) { + pw.println("Must specify exactly one of compilation filter (\"-m\"), compilation " + + "reason (\"-r\"), or compile layouts (\"--compile-layouts\")"); return 1; } @@ -1241,15 +1248,16 @@ class PackageManagerShellCommand extends ShellCommand { return 1; } - String targetCompilerFilter; - if (compilerFilter != null) { + String targetCompilerFilter = null; + if (compilerFilterGiven) { if (!DexFile.isValidCompilerFilter(compilerFilter)) { pw.println("Error: \"" + compilerFilter + "\" is not a valid compilation filter."); return 1; } targetCompilerFilter = compilerFilter; - } else { + } + if (compilationReasonGiven) { int reason = -1; for (int i = 0; i < PackageManagerServiceCompilerMapping.REASON_STRINGS.length; i++) { if (PackageManagerServiceCompilerMapping.REASON_STRINGS[i].equals( @@ -1291,12 +1299,19 @@ class PackageManagerShellCommand extends ShellCommand { pw.flush(); } - boolean result = secondaryDex + boolean result = true; + if (compileLayouts) { + PackageManagerInternal internal = LocalServices.getService( + PackageManagerInternal.class); + result = internal.compileLayouts(packageName); + } else { + result = secondaryDex ? mInterface.performDexOptSecondary(packageName, targetCompilerFilter, forceCompilation) : mInterface.performDexOptMode(packageName, checkProfiles, targetCompilerFilter, forceCompilation, true /* bootComplete */, split); + } if (!result) { failedPackages.add(packageName); } @@ -3004,6 +3019,7 @@ class PackageManagerShellCommand extends ShellCommand { pw.println(" --check-prof (true | false): look at profiles when doing dexopt?"); pw.println(" --secondary-dex: compile app secondary dex files"); pw.println(" --split SPLIT: compile only the given split name"); + pw.println(" --compile-layouts: compile layout resources for faster inflation"); pw.println(""); pw.println(" force-dex-opt PACKAGE"); pw.println(" Force immediate execution of dex opt for the given PACKAGE."); diff --git a/services/core/java/com/android/server/pm/Settings.java b/services/core/java/com/android/server/pm/Settings.java index 95da2091828d..b0f232607d88 100644 --- a/services/core/java/com/android/server/pm/Settings.java +++ b/services/core/java/com/android/server/pm/Settings.java @@ -2790,13 +2790,13 @@ public final class Settings { // dataPath - path to package's data path // seinfo - seinfo label for the app (assigned at install time) // gids - supplementary gids this app launches with + // profileableFromShellFlag - 0 or 1 if the package is profileable from shell. // // NOTE: We prefer not to expose all ApplicationInfo flags for now. // // DO NOT MODIFY THIS FORMAT UNLESS YOU CAN ALSO MODIFY ITS USERS // FROM NATIVE CODE. AT THE MOMENT, LOOK AT THE FOLLOWING SOURCES: - // frameworks/base/libs/packagelistparser - // system/core/run-as/run-as.c + // system/core/libpackagelistparser // sb.setLength(0); sb.append(ai.packageName); @@ -2816,6 +2816,8 @@ public final class Settings { } else { sb.append("none"); } + sb.append(" "); + sb.append(ai.isProfileableByShell() ? "1" : "0"); sb.append("\n"); writer.append(sb); } diff --git a/services/core/java/com/android/server/pm/ShortcutPackage.java b/services/core/java/com/android/server/pm/ShortcutPackage.java index 83f0fde066ec..563fd7f90c4b 100644 --- a/services/core/java/com/android/server/pm/ShortcutPackage.java +++ b/services/core/java/com/android/server/pm/ShortcutPackage.java @@ -20,8 +20,10 @@ import android.annotation.Nullable; import android.annotation.UserIdInt; import android.content.ComponentName; import android.content.Intent; +import android.content.IntentFilter; import android.content.pm.PackageInfo; import android.content.pm.ShortcutInfo; +import android.content.pm.ShortcutManager; import android.content.res.Resources; import android.os.PersistableBundle; import android.text.format.Formatter; @@ -640,6 +642,55 @@ class ShortcutPackage extends ShortcutPackageItem { } /** + * Returns a list of ShortcutInfos that match the given intent filter and the category of + * available ShareTarget definitions in this package. + */ + public List<ShortcutManager.ShareShortcutInfo> getMatchingShareTargets( + @NonNull IntentFilter filter) { + final List<ShareTargetInfo> matchedTargets = new ArrayList<>(); + for (int i = 0; i < mShareTargets.size(); i++) { + final ShareTargetInfo target = mShareTargets.get(i); + for (ShareTargetInfo.TargetData data : target.mTargetData) { + if (filter.hasDataType(data.mMimeType)) { + // Matched at least with one data type + matchedTargets.add(target); + break; + } + } + } + + if (matchedTargets.isEmpty()) { + return new ArrayList<>(); + } + + // Get the list of all dynamic shortcuts in this package + final ArrayList<ShortcutInfo> shortcuts = new ArrayList<>(); + findAll(shortcuts, ShortcutInfo::isDynamicVisible, ShortcutInfo.CLONE_REMOVE_FOR_LAUNCHER); + + final List<ShortcutManager.ShareShortcutInfo> result = new ArrayList<>(); + for (int i = 0; i < shortcuts.size(); i++) { + final ShortcutInfo si = shortcuts.get(i); + for (int j = 0; j < matchedTargets.size(); j++) { + // Shortcut must have all of share target categories + boolean hasAllCategories = true; + final ShareTargetInfo target = matchedTargets.get(j); + for (int q = 0; q < target.mCategories.length; q++) { + if (!si.getCategories().contains(target.mCategories[q])) { + hasAllCategories = false; + break; + } + } + if (hasAllCategories) { + result.add(new ShortcutManager.ShareShortcutInfo(si, new ComponentName( + getPackageName(), target.mTargetClass))); + break; + } + } + } + return result; + } + + /** * Return the filenames (excluding path names) of icon bitmap files from this package. */ public ArraySet<String> getUsedBitmapFiles() { diff --git a/services/core/java/com/android/server/pm/ShortcutService.java b/services/core/java/com/android/server/pm/ShortcutService.java index 2b773f47e3e9..fdbaba24966b 100644 --- a/services/core/java/com/android/server/pm/ShortcutService.java +++ b/services/core/java/com/android/server/pm/ShortcutService.java @@ -46,6 +46,7 @@ import android.content.pm.PackageManagerInternal; import android.content.pm.ParceledListSlice; import android.content.pm.ResolveInfo; import android.content.pm.ShortcutInfo; +import android.content.pm.ShortcutManager; import android.content.pm.ShortcutServiceInternal; import android.content.pm.ShortcutServiceInternal.ShortcutChangeListener; import android.content.res.Resources; @@ -2149,6 +2150,23 @@ public class ShortcutService extends IShortcutService.Stub { } } + @Override + public ParceledListSlice<ShortcutManager.ShareShortcutInfo> getShareTargets(String packageName, + IntentFilter filter, @UserIdInt int userId) { + verifyCaller(packageName, userId); + + synchronized (mLock) { + throwIfUserLockedL(userId); + + final List<ShortcutManager.ShareShortcutInfo> shortcutInfoList = new ArrayList<>(); + + final ShortcutUser user = getUserShortcutsLocked(userId); + user.forAllPackages(p -> shortcutInfoList.addAll(p.getMatchingShareTargets(filter))); + + return new ParceledListSlice<>(shortcutInfoList); + } + } + @GuardedBy("mLock") private ParceledListSlice<ShortcutInfo> getShortcutsWithQueryLocked(@NonNull String packageName, @UserIdInt int userId, int cloneFlags, @NonNull Predicate<ShortcutInfo> query) { diff --git a/services/core/java/com/android/server/pm/StagingManager.java b/services/core/java/com/android/server/pm/StagingManager.java index bd14223c962c..7bab0bbc7964 100644 --- a/services/core/java/com/android/server/pm/StagingManager.java +++ b/services/core/java/com/android/server/pm/StagingManager.java @@ -19,6 +19,7 @@ package com.android.server.pm; import android.annotation.NonNull; import android.apex.ApexInfo; import android.apex.ApexInfoList; +import android.apex.ApexSessionInfo; import android.apex.IApexService; import android.content.pm.PackageInstaller; import android.content.pm.PackageInstaller.SessionInfo; @@ -138,7 +139,7 @@ public class StagingManager { return success; } - void preRebootVerification(@NonNull PackageInstallerSession session) { + private void preRebootVerification(@NonNull PackageInstallerSession session) { boolean success = true; if ((session.params.installFlags & PackageManager.INSTALL_APEX) != 0) { @@ -170,6 +171,30 @@ public class StagingManager { } } + private void resumeSession(@NonNull PackageInstallerSession session) { + // Check with apexservice whether the apex + // packages have been activated. + final IApexService apex = IApexService.Stub.asInterface( + ServiceManager.getService("apexservice")); + ApexSessionInfo apexSessionInfo; + try { + apexSessionInfo = apex.getStagedSessionInfo(session.sessionId); + } catch (RemoteException re) { + Slog.e(TAG, "Unable to contact apexservice", re); + // TODO should we retry here? Mark the session as failed? + return; + } + if (apexSessionInfo.isActivationFailed || apexSessionInfo.isUnknown) { + session.setStagedSessionFailed(SessionInfo.ACTIVATION_FAILED); + } + if (apexSessionInfo.isActivated) { + session.setStagedSessionApplied(); + // TODO(b/118865310) if multi-package proceed with the installation of APKs. + } + // TODO(b/118865310) if (apexSessionInfo.isVerified) { /* mark this as staged in apexd */ } + // In every other case apexd will retry to apply the session at next boot. + } + void commitSession(@NonNull PackageInstallerSession session) { updateStoredSession(session); mBgHandler.post(() -> preRebootVerification(session)); @@ -190,8 +215,19 @@ public class StagingManager { void restoreSession(@NonNull PackageInstallerSession session) { updateStoredSession(session); - // TODO(b/118865310): This method is called when PackageInstaller is re-instantiated, e.g. - // at reboot. Staging manager should at this point recover state from apexd and decide what - // to do with the session. + // Check the state of the session and decide what to do next. + if (session.isStagedSessionFailed() || session.isStagedSessionApplied()) { + // Final states, nothing to do. + return; + } + if (!session.isStagedSessionReady()) { + // The framework got restarted before the pre-reboot verification could complete, + // restart the verification. + mBgHandler.post(() -> preRebootVerification(session)); + } else { + // Session had already being marked ready. Start the checks to verify if there is any + // follow-up work. + mBgHandler.post(() -> resumeSession(session)); + } } } diff --git a/services/core/java/com/android/server/pm/dex/ArtManagerService.java b/services/core/java/com/android/server/pm/dex/ArtManagerService.java index 1f05dc966555..863bfd5ea391 100644 --- a/services/core/java/com/android/server/pm/dex/ArtManagerService.java +++ b/services/core/java/com/android/server/pm/dex/ArtManagerService.java @@ -472,6 +472,33 @@ public class ArtManagerService extends android.content.pm.dex.IArtManager.Stub { } /** + * Compile layout resources in a given package. + */ + public boolean compileLayouts(PackageParser.Package pkg) { + try { + final String packageName = pkg.packageName; + final String apkPath = pkg.baseCodePath; + final ApplicationInfo appInfo = pkg.applicationInfo; + final String outDexFile = appInfo.dataDir + "/code_cache/compiled_view.dex"; + Log.i("PackageManager", "Compiling layouts in " + packageName + " (" + apkPath + + ") to " + outDexFile); + long callingId = Binder.clearCallingIdentity(); + try { + synchronized (mInstallLock) { + return mInstaller.compileLayouts(apkPath, packageName, outDexFile, + appInfo.uid); + } + } finally { + Binder.restoreCallingIdentity(callingId); + } + } + catch (Throwable e) { + Log.e("PackageManager", "Failed to compile layouts", e); + return false; + } + } + + /** * Build the profiles names for all the package code paths (excluding resource only paths). * Return the map [code path -> profile name]. */ diff --git a/services/core/java/com/android/server/pm/dex/ViewCompiler.java b/services/core/java/com/android/server/pm/dex/ViewCompiler.java new file mode 100644 index 000000000000..8d8e17e92b3d --- /dev/null +++ b/services/core/java/com/android/server/pm/dex/ViewCompiler.java @@ -0,0 +1,58 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License + */ + +package com.android.server.pm.dex; + +import android.content.pm.ApplicationInfo; +import android.content.pm.PackageParser; +import android.os.Binder; +import android.util.Log; +import com.android.internal.annotations.GuardedBy; +import com.android.server.pm.Installer; + +public class ViewCompiler { + private final Object mInstallLock; + @GuardedBy("mInstallLock") + private final Installer mInstaller; + + public ViewCompiler(Object installLock, Installer installer) { + mInstallLock = installLock; + mInstaller = installer; + } + + public boolean compileLayouts(PackageParser.Package pkg) { + try { + final String packageName = pkg.packageName; + final String apkPath = pkg.baseCodePath; + final ApplicationInfo appInfo = pkg.applicationInfo; + final String outDexFile = appInfo.dataDir + "/code_cache/compiled_view.dex"; + Log.i("PackageManager", "Compiling layouts in " + packageName + " (" + apkPath + + ") to " + outDexFile); + long callingId = Binder.clearCallingIdentity(); + try { + synchronized (mInstallLock) { + return mInstaller.compileLayouts(apkPath, packageName, outDexFile, + appInfo.uid); + } + } finally { + Binder.restoreCallingIdentity(callingId); + } + } catch (Throwable e) { + Log.e("PackageManager", "Failed to compile layouts", e); + return false; + } + } +} diff --git a/services/core/java/com/android/server/pm/permission/BasePermission.java b/services/core/java/com/android/server/pm/permission/BasePermission.java index 3a49412357d8..17f83479a3b1 100644 --- a/services/core/java/com/android/server/pm/permission/BasePermission.java +++ b/services/core/java/com/android/server/pm/permission/BasePermission.java @@ -247,6 +247,10 @@ public final class BasePermission { public boolean isDocumenter() { return (protectionLevel & PermissionInfo.PROTECTION_FLAG_DOCUMENTER) != 0; } + public boolean isConfigurator() { + return (protectionLevel & PermissionInfo.PROTECTION_FLAG_CONFIGURATOR) + != 0; + } public void transfer(@NonNull String origPackageName, @NonNull String newPackageName) { if (!origPackageName.equals(sourcePackageName)) { diff --git a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java index 93964cb09ae6..30b5e49bc3fd 100644 --- a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java +++ b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java @@ -1640,6 +1640,13 @@ public class PermissionManagerService { // Special permissions for the system default text classifier. allowed = true; } + if (!allowed && bp.isConfigurator() + && pkg.packageName.equals(mPackageManagerInt.getKnownPackageName( + PackageManagerInternal.PACKAGE_CONFIGURATOR, + UserHandle.USER_SYSTEM))) { + // Special permissions for the device configurator. + allowed = true; + } if (!allowed && bp.isWellbeing() && pkg.packageName.equals(mPackageManagerInt.getKnownPackageName( PackageManagerInternal.PACKAGE_WELLBEING, UserHandle.USER_SYSTEM))) { diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java index 2060aef37044..41cab2d7ebd3 100644 --- a/services/core/java/com/android/server/policy/PhoneWindowManager.java +++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java @@ -84,8 +84,10 @@ import static android.view.WindowManagerGlobal.ADD_OKAY; import static android.view.WindowManagerGlobal.ADD_PERMISSION_DENIED; import static com.android.server.policy.WindowManagerPolicy.WindowManagerFuncs.CAMERA_LENS_COVERED; -import static com.android.server.policy.WindowManagerPolicy.WindowManagerFuncs.CAMERA_LENS_COVER_ABSENT; -import static com.android.server.policy.WindowManagerPolicy.WindowManagerFuncs.CAMERA_LENS_UNCOVERED; +import static com.android.server.policy.WindowManagerPolicy.WindowManagerFuncs + .CAMERA_LENS_COVER_ABSENT; +import static com.android.server.policy.WindowManagerPolicy.WindowManagerFuncs + .CAMERA_LENS_UNCOVERED; import static com.android.server.policy.WindowManagerPolicy.WindowManagerFuncs.LID_CLOSED; import static com.android.server.policy.WindowManagerPolicy.WindowManagerFuncs.LID_OPEN; import static com.android.server.wm.WindowManagerPolicyProto.KEYGUARD_DELEGATE; @@ -478,6 +480,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { int mShortPressOnSleepBehavior; int mShortPressOnWindowBehavior; boolean mHasSoftInput = false; + boolean mHapticTextHandleEnabled; boolean mUseTvRouting; int mVeryLongPressTimeout; boolean mAllowStartActivityForLongPressOnPowerDuringSetup; @@ -565,6 +568,10 @@ public class PhoneWindowManager implements WindowManagerPolicy { private boolean mScreenshotChordPowerKeyTriggered; private long mScreenshotChordPowerKeyTime; + private static final long MOVING_DISPLAY_TO_TOP_DURATION_MILLIS = 10; + private volatile boolean mMovingDisplayToTopKeyTriggered; + private volatile long mMovingDisplayToTopKeyTime; + // Ringer toggle should reuse timing and triggering from screenshot power and a11y vol up private int mRingerToggleChord = VOLUME_HUSH_OFF; @@ -604,7 +611,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { private boolean mAodShowing; private boolean mPerDisplayFocusEnabled = false; - private int mTopFocusedDisplayId = INVALID_DISPLAY; + private volatile int mTopFocusedDisplayId = INVALID_DISPLAY; private static final int MSG_ENABLE_POINTER_LOCATION = 1; private static final int MSG_DISABLE_POINTER_LOCATION = 2; @@ -632,6 +639,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { private static final int MSG_POWER_VERY_LONG_PRESS = 25; private static final int MSG_NOTIFY_USER_ACTIVITY = 26; private static final int MSG_RINGER_TOGGLE_CHORD = 27; + private static final int MSG_MOVE_DISPLAY_TO_TOP = 28; private class PolicyHandler extends Handler { @Override @@ -727,6 +735,10 @@ public class PhoneWindowManager implements WindowManagerPolicy { case MSG_RINGER_TOGGLE_CHORD: handleRingerChordGesture(); break; + case MSG_MOVE_DISPLAY_TO_TOP: + mWindowManagerFuncs.moveDisplayToTop(msg.arg1); + mMovingDisplayToTopKeyTriggered = false; + break; } } } @@ -808,6 +820,13 @@ public class PhoneWindowManager implements WindowManagerPolicy { } }; + private Runnable mPossibleVeryLongPressReboot = new Runnable() { + @Override + public void run() { + mActivityManagerInternal.prepareForPossibleShutdown(); + } + }; + private void handleRingerChordGesture() { if (mRingerToggleChord == VOLUME_HUSH_OFF) { return; @@ -953,6 +972,8 @@ public class PhoneWindowManager implements WindowManagerPolicy { // Inform the StatusBar; but do not allow it to consume the event. sendSystemKeyToStatusBarAsync(event.getKeyCode()); + schedulePossibleVeryLongPressReboot(); + // If the power key has still not yet been handled, then detect short // press, long press, or multi press and decide what to do. mPowerKeyHandled = hungUp || mScreenshotChordVolumeDownKeyTriggered @@ -1056,6 +1077,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { if (hasVeryLongPressOnPowerBehavior()) { mHandler.removeMessages(MSG_POWER_VERY_LONG_PRESS); } + cancelPossibleVeryLongPressReboot(); } private void cancelPendingBackKeyAction() { @@ -1815,6 +1837,9 @@ public class PhoneWindowManager implements WindowManagerPolicy { mAllowStartActivityForLongPressOnPowerDuringSetup = mContext.getResources().getBoolean( com.android.internal.R.bool.config_allowStartActivityForLongPressOnPowerInSetup); + mHapticTextHandleEnabled = mContext.getResources().getBoolean( + com.android.internal.R.bool.config_enableHapticTextHandle); + mUseTvRouting = AudioSystem.getPlatformType(mContext) == AudioSystem.PLATFORM_TELEVISION; mHandleVolumeKeysInWM = mContext.getResources().getBoolean( @@ -2270,9 +2295,8 @@ public class PhoneWindowManager implements WindowManagerPolicy { } final LayoutParams attrs = win.getAttrs(); - final boolean showImeOverKeyguard = imeTarget != null && imeTarget.isVisibleLw() && - ((imeTarget.getAttrs().flags & FLAG_SHOW_WHEN_LOCKED) != 0 - || !canBeHiddenByKeyguardLw(imeTarget)); + final boolean showImeOverKeyguard = imeTarget != null && imeTarget.isVisibleLw() + && (imeTarget.canShowWhenLocked() || !canBeHiddenByKeyguardLw(imeTarget)); // Show IME over the keyguard if the target allows it boolean allowWhenLocked = (win.isInputMethodWindow() || imeTarget == this) @@ -2280,7 +2304,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { if (isKeyguardLocked() && isKeyguardOccluded()) { // Show SHOW_WHEN_LOCKED windows if Keyguard is occluded. - allowWhenLocked |= (attrs.flags & FLAG_SHOW_WHEN_LOCKED) != 0 + allowWhenLocked |= win.canShowWhenLocked() // Show error dialogs over apps that are shown on lockscreen || (attrs.privateFlags & PRIVATE_FLAG_SYSTEM_ERROR) != 0; } @@ -2558,12 +2582,25 @@ public class PhoneWindowManager implements WindowManagerPolicy { final int eventDisplayId = event.getDisplayId(); if (result == 0 && !mPerDisplayFocusEnabled && eventDisplayId != INVALID_DISPLAY && eventDisplayId != mTopFocusedDisplayId) { - // Someone tries to send a key event to a display which doesn't have a focused window. - // We drop the event here, or it will cause ANR. - // TODO (b/121057974): The user may be confused about why the key doesn't work, so we - // may need to deal with this problem. - Slog.i(TAG, "Dropping this event targeting display #" + eventDisplayId - + " because the focus is on display #" + mTopFocusedDisplayId); + // An event is targeting a non-focused display. Try to move the display to top so that + // it can become the focused display to interact with the user. + final long eventDownTime = event.getDownTime(); + if (mMovingDisplayToTopKeyTime < eventDownTime) { + // We have not handled this event yet. Move the display to top, and then tell + // dispatcher to try again later. + mMovingDisplayToTopKeyTime = eventDownTime; + mMovingDisplayToTopKeyTriggered = true; + mHandler.sendMessage( + mHandler.obtainMessage(MSG_MOVE_DISPLAY_TO_TOP, eventDisplayId, 0)); + return MOVING_DISPLAY_TO_TOP_DURATION_MILLIS; + } else if (mMovingDisplayToTopKeyTriggered) { + // The message has not been handled yet. Tell dispatcher to try again later. + return MOVING_DISPLAY_TO_TOP_DURATION_MILLIS; + } + // The target display is still not the top focused display. Drop the event because the + // display may not contain any window which can receive keys. + Slog.w(TAG, "Dropping key targeting non-focused display #" + eventDisplayId + + " keyCode=" + KeyEvent.keyCodeToString(event.getKeyCode())); return -1; } return result; @@ -4901,6 +4938,15 @@ public class PhoneWindowManager implements WindowManagerPolicy { } } + private void schedulePossibleVeryLongPressReboot() { + mHandler.removeCallbacks(mPossibleVeryLongPressReboot); + mHandler.postDelayed(mPossibleVeryLongPressReboot, mVeryLongPressTimeout); + } + + private void cancelPossibleVeryLongPressReboot() { + mHandler.removeCallbacks(mPossibleVeryLongPressReboot); + } + // TODO (multidisplay): Support multiple displays in WindowManagerPolicy. private void updateScreenOffSleepToken(boolean acquire) { if (acquire) { @@ -5158,8 +5204,11 @@ public class PhoneWindowManager implements WindowManagerPolicy { case HapticFeedbackConstants.CLOCK_TICK: case HapticFeedbackConstants.CONTEXT_CLICK: return VibrationEffect.get(VibrationEffect.EFFECT_TICK); - case HapticFeedbackConstants.KEYBOARD_RELEASE: case HapticFeedbackConstants.TEXT_HANDLE_MOVE: + if (!mHapticTextHandleEnabled) { + return null; + } + case HapticFeedbackConstants.KEYBOARD_RELEASE: case HapticFeedbackConstants.VIRTUAL_KEY_RELEASE: case HapticFeedbackConstants.ENTRY_BUMP: case HapticFeedbackConstants.DRAG_CROSSING: @@ -5324,11 +5373,13 @@ public class PhoneWindowManager implements WindowManagerPolicy { pw.println(mAllowStartActivityForLongPressOnPowerDuringSetup); pw.print(prefix); pw.print("mHasSoftInput="); pw.print(mHasSoftInput); - pw.print(" mDismissImeOnBackKeyPressed="); pw.println(mDismissImeOnBackKeyPressed); + pw.print(" mHapticTextHandleEnabled="); pw.println(mHapticTextHandleEnabled); + pw.print(prefix); + pw.print("mDismissImeOnBackKeyPressed="); pw.print(mDismissImeOnBackKeyPressed); + pw.print(" mIncallPowerBehavior="); + pw.println(incallPowerBehaviorToString(mIncallPowerBehavior)); pw.print(prefix); - pw.print("mIncallPowerBehavior="); - pw.print(incallPowerBehaviorToString(mIncallPowerBehavior)); - pw.print(" mIncallBackBehavior="); + pw.print("mIncallBackBehavior="); pw.print(incallBackBehaviorToString(mIncallBackBehavior)); pw.print(" mEndcallBehavior="); pw.println(endcallBehaviorToString(mEndcallBehavior)); diff --git a/services/core/java/com/android/server/policy/WindowManagerPolicy.java b/services/core/java/com/android/server/policy/WindowManagerPolicy.java index 3da325c55b32..e1a911e8ada5 100644 --- a/services/core/java/com/android/server/policy/WindowManagerPolicy.java +++ b/services/core/java/com/android/server/policy/WindowManagerPolicy.java @@ -468,6 +468,9 @@ public interface WindowManagerPolicy extends WindowManagerPolicyConstants { /** @return true if this window desires key events. */ boolean canReceiveKeys(); + /** @return true if the window can show over keyguard. */ + boolean canShowWhenLocked(); + /** * Writes {@link com.android.server.wm.IdentifierProto} to stream. */ @@ -634,6 +637,12 @@ public interface WindowManagerPolicy extends WindowManagerPolicyConstants { * Notifies window manager that user is switched. */ void onUserSwitched(); + + /** + * Hint to window manager that the user is interacting with a display that should be treated + * as the top display. + */ + void moveDisplayToTop(int displayId); } /** diff --git a/services/core/java/com/android/server/policy/role/LegacyRoleResolutionPolicy.java b/services/core/java/com/android/server/policy/role/LegacyRoleResolutionPolicy.java index 45c975b26956..055c941f8b0a 100644 --- a/services/core/java/com/android/server/policy/role/LegacyRoleResolutionPolicy.java +++ b/services/core/java/com/android/server/policy/role/LegacyRoleResolutionPolicy.java @@ -62,6 +62,8 @@ public class LegacyRoleResolutionPolicy implements RoleManagerService.RoleHolder mContext.getContentResolver(), Settings.Secure.SMS_DEFAULT_APPLICATION, userId); + // TODO: STOPSHIP: Remove the following code once we remove default_sms_application + // and use the new config_defaultRoleHolders. if (result == null) { Collection<SmsApplication.SmsApplicationData> applications = SmsApplication.getApplicationCollectionAsUser(mContext, userId); diff --git a/services/core/java/com/android/server/role/RoleManagerService.java b/services/core/java/com/android/server/role/RoleManagerService.java index c0ec3672c665..5516b234925b 100644 --- a/services/core/java/com/android/server/role/RoleManagerService.java +++ b/services/core/java/com/android/server/role/RoleManagerService.java @@ -229,9 +229,12 @@ public class RoleManagerService extends SystemService implements RoleUserState.C // Any role for which we have a record are already migrated RoleUserState userState = getOrCreateUserState(userId); if (!userState.isRoleAvailable(role)) { - userState.addRoleName(role); List<String> roleHolders = mLegacyRoleResolver.getRoleHolders(role, userId); + if (roleHolders.isEmpty()) { + return; + } Slog.i(LOG_TAG, "Migrating " + role + ", legacy holders: " + roleHolders); + userState.addRoleName(role); int size = roleHolders.size(); for (int i = 0; i < size; i++) { userState.addRoleHolder(role, roleHolders.get(i)); diff --git a/services/core/java/com/android/server/storage/DeviceStorageMonitorService.java b/services/core/java/com/android/server/storage/DeviceStorageMonitorService.java index f7cc4432f9bc..2700f9ddc203 100644 --- a/services/core/java/com/android/server/storage/DeviceStorageMonitorService.java +++ b/services/core/java/com/android/server/storage/DeviceStorageMonitorService.java @@ -24,7 +24,6 @@ import android.app.PendingIntent; import android.content.Context; import android.content.Intent; import android.content.pm.PackageManager; -import android.net.TrafficStats; import android.os.Binder; import android.os.Environment; import android.os.FileObserver; @@ -42,13 +41,13 @@ import android.text.format.DateUtils; import android.util.ArrayMap; import android.util.DataUnit; import android.util.Slog; +import android.util.StatsLog; import com.android.internal.messages.nano.SystemMessageProto.SystemMessage; import com.android.internal.notification.SystemNotificationChannels; import com.android.internal.util.DumpUtils; import com.android.internal.util.IndentingPrintWriter; import com.android.server.EventLogTags; -import com.android.server.IoThread; import com.android.server.SystemService; import com.android.server.pm.InstructionSets; import com.android.server.pm.PackageManagerService; @@ -499,9 +498,15 @@ public class DeviceStorageMonitorService extends SystemService { notification.flags |= Notification.FLAG_NO_CLEAR; mNotifManager.notifyAsUser(uuid.toString(), SystemMessage.NOTE_LOW_STORAGE, notification, UserHandle.ALL); + StatsLog.write(StatsLog.LOW_STORAGE_STATE_CHANGED, + Objects.toString(vol.getDescription()), + StatsLog.LOW_STORAGE_STATE_CHANGED__STATE__ON); } else if (State.isLeaving(State.LEVEL_LOW, oldLevel, newLevel)) { mNotifManager.cancelAsUser(uuid.toString(), SystemMessage.NOTE_LOW_STORAGE, UserHandle.ALL); + StatsLog.write(StatsLog.LOW_STORAGE_STATE_CHANGED, + Objects.toString(vol.getDescription()), + StatsLog.LOW_STORAGE_STATE_CHANGED__STATE__OFF); } } diff --git a/services/core/java/com/android/server/textservices/TextServicesManagerService.java b/services/core/java/com/android/server/textservices/TextServicesManagerService.java index 7236d79c55ab..d4aa59d3ce85 100644 --- a/services/core/java/com/android/server/textservices/TextServicesManagerService.java +++ b/services/core/java/com/android/server/textservices/TextServicesManagerService.java @@ -16,6 +16,8 @@ package com.android.server.textservices; +import static android.Manifest.permission.INTERACT_ACROSS_USERS_FULL; + import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.UserIdInt; @@ -513,8 +515,8 @@ public class TextServicesManagerService extends ITextServicesManager.Stub { // TODO: Save SpellCheckerService by supported languages. Currently only one spell // checker is saved. @Override - public SpellCheckerInfo getCurrentSpellChecker(String locale) { - int userId = UserHandle.getCallingUserId(); + public SpellCheckerInfo getCurrentSpellChecker(@UserIdInt int userId, String locale) { + verifyUser(userId); synchronized (mLock) { final TextServicesData tsd = getDataFromCallingUserIdLocked(userId); if (tsd == null) return null; @@ -527,11 +529,12 @@ public class TextServicesManagerService extends ITextServicesManager.Stub { // TODO: Save SpellCheckerSubtype by supported languages by looking at "locale". @Override public SpellCheckerSubtype getCurrentSpellCheckerSubtype( - boolean allowImplicitlySelectedSubtype) { + @UserIdInt int userId, boolean allowImplicitlySelectedSubtype) { + verifyUser(userId); + final int subtypeHashCode; final SpellCheckerInfo sci; final Locale systemLocale; - final int userId = UserHandle.getCallingUserId(); synchronized (mLock) { final TextServicesData tsd = getDataFromCallingUserIdLocked(userId); @@ -591,17 +594,17 @@ public class TextServicesManagerService extends ITextServicesManager.Stub { } @Override - public void getSpellCheckerService(String sciId, String locale, + public void getSpellCheckerService(@UserIdInt int userId, String sciId, String locale, ITextServicesSessionListener tsListener, ISpellCheckerSessionListener scListener, Bundle bundle) { + verifyUser(userId); if (TextUtils.isEmpty(sciId) || tsListener == null || scListener == null) { Slog.e(TAG, "getSpellCheckerService: Invalid input."); return; } - int callingUserId = UserHandle.getCallingUserId(); synchronized (mLock) { - final TextServicesData tsd = getDataFromCallingUserIdLocked(callingUserId); + final TextServicesData tsd = getDataFromCallingUserIdLocked(userId); if (tsd == null) return; HashMap<String, SpellCheckerInfo> spellCheckerMap = tsd.mSpellCheckerMap; @@ -634,8 +637,8 @@ public class TextServicesManagerService extends ITextServicesManager.Stub { } @Override - public boolean isSpellCheckerEnabled() { - int userId = UserHandle.getCallingUserId(); + public boolean isSpellCheckerEnabled(@UserIdInt int userId) { + verifyUser(userId); synchronized (mLock) { final TextServicesData tsd = getDataFromCallingUserIdLocked(userId); @@ -671,11 +674,11 @@ public class TextServicesManagerService extends ITextServicesManager.Stub { } @Override - public SpellCheckerInfo[] getEnabledSpellCheckers() { - int callingUserId = UserHandle.getCallingUserId(); + public SpellCheckerInfo[] getEnabledSpellCheckers(@UserIdInt int userId) { + verifyUser(userId); synchronized (mLock) { - final TextServicesData tsd = getDataFromCallingUserIdLocked(callingUserId); + final TextServicesData tsd = getDataFromCallingUserIdLocked(userId); if (tsd == null) return null; ArrayList<SpellCheckerInfo> spellCheckerList = tsd.mSpellCheckerList; @@ -691,11 +694,12 @@ public class TextServicesManagerService extends ITextServicesManager.Stub { } @Override - public void finishSpellCheckerService(ISpellCheckerSessionListener listener) { + public void finishSpellCheckerService(@UserIdInt int userId, + ISpellCheckerSessionListener listener) { if (DBG) { Slog.d(TAG, "FinishSpellCheckerService"); } - int userId = UserHandle.getCallingUserId(); + verifyUser(userId); synchronized (mLock) { final TextServicesData tsd = getDataFromCallingUserIdLocked(userId); @@ -716,6 +720,15 @@ public class TextServicesManagerService extends ITextServicesManager.Stub { } } + private void verifyUser(@UserIdInt int userId) { + final int callingUserId = UserHandle.getCallingUserId(); + if (userId != callingUserId) { + mContext.enforceCallingPermission(INTERACT_ACROSS_USERS_FULL, + "Cross-user interaction requires INTERACT_ACROSS_USERS_FULL. userId=" + userId + + " callingUserId=" + callingUserId); + } + } + private void setCurrentSpellCheckerLocked(@Nullable SpellCheckerInfo sci, TextServicesData tsd) { final String sciId = (sci != null) ? sci.getId() : ""; if (DBG) { diff --git a/services/core/java/com/android/server/wm/ActivityDisplay.java b/services/core/java/com/android/server/wm/ActivityDisplay.java index 1f638c7f2e5d..e817dd47e756 100644 --- a/services/core/java/com/android/server/wm/ActivityDisplay.java +++ b/services/core/java/com/android/server/wm/ActivityDisplay.java @@ -278,12 +278,12 @@ class ActivityDisplay extends ConfigurationContainer<ActivityStack> } // Since positionChildAt() is called during the creation process of pinned stacks, - // ActivityStack#getWindowContainerController() can be null. In this special case, + // ActivityStack#getStack() can be null. In this special case, // since DisplayContest#positionStackAt() is called in TaskStack#onConfigurationChanged(), // we don't have to call WindowContainerController#positionChildAt() here. - if (stack.getWindowContainerController() != null && mDisplayContent != null) { + if (stack.getTaskStack() != null && mDisplayContent != null) { mDisplayContent.positionStackAt(insertPosition, - stack.getWindowContainerController().mContainer, includingParents); + stack.getTaskStack(), includingParents); } if (!wasContained) { stack.setParent(this); @@ -450,13 +450,12 @@ class ActivityDisplay extends ConfigurationContainer<ActivityStack> @VisibleForTesting <T extends ActivityStack> T createStackUnchecked(int windowingMode, int activityType, int stackId, boolean onTop) { - if (windowingMode == WINDOWING_MODE_PINNED) { - return (T) new PinnedActivityStack(this, stackId, - mRootActivityContainer.mStackSupervisor, onTop); + if (windowingMode == WINDOWING_MODE_PINNED && activityType != ACTIVITY_TYPE_STANDARD) { + throw new IllegalArgumentException("Stack with windowing mode cannot with non standard " + + "activity type."); } return (T) new ActivityStack(this, stackId, - mRootActivityContainer.mStackSupervisor, windowingMode, activityType, - onTop); + mRootActivityContainer.mStackSupervisor, windowingMode, activityType, onTop); } /** @@ -559,22 +558,26 @@ class ActivityDisplay extends ConfigurationContainer<ActivityStack> } /** - * Pause all activities in either all of the stacks or just the back stacks. + * Pause all activities in either all of the stacks or just the back stacks. This is done before + * resuming a new activity and to make sure that previously active activities are + * paused in stacks that are no longer visible or in pinned windowing mode. This does not + * pause activities in visible stacks, so if an activity is launched within the same stack/task, + * then we should explicitly pause that stack's top activity. * @param userLeaving Passed to pauseActivity() to indicate whether to call onUserLeaving(). * @param resuming The resuming activity. * @param dontWait The resuming activity isn't going to wait for all activities to be paused * before resuming. - * @return true if any activity was paused as a result of this call. + * @return {@code true} if any activity was paused as a result of this call. */ boolean pauseBackStacks(boolean userLeaving, ActivityRecord resuming, boolean dontWait) { boolean someActivityPaused = false; for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) { final ActivityStack stack = mStacks.get(stackNdx); - // TODO(b/111541062): Check if resumed activity on this display instead - if (!mRootActivityContainer.isTopDisplayFocusedStack(stack) - && stack.getResumedActivity() != null) { + final ActivityRecord resumedActivity = stack.getResumedActivity(); + if (resumedActivity != null + && (!stack.shouldBeVisible(resuming) || !stack.isFocusable())) { if (DEBUG_STATES) Slog.d(TAG_STATES, "pauseBackStacks: stack=" + stack + - " mResumedActivity=" + stack.getResumedActivity()); + " mResumedActivity=" + resumedActivity); someActivityPaused |= stack.startPausingLocked(userLeaving, false, resuming, dontWait); } @@ -626,6 +629,10 @@ class ActivityDisplay extends ConfigurationContainer<ActivityStack> return; } + // Collect the stacks that are necessary to be removed instead of performing the removal + // by looping mStacks, so that we don't miss any stacks after the stack size changed or + // stacks reordered. + final ArrayList<ActivityStack> stacks = new ArrayList<>(); for (int j = windowingModes.length - 1 ; j >= 0; --j) { final int windowingMode = windowingModes[j]; for (int i = mStacks.size() - 1; i >= 0; --i) { @@ -636,9 +643,13 @@ class ActivityDisplay extends ConfigurationContainer<ActivityStack> if (stack.getWindowingMode() != windowingMode) { continue; } - mRootActivityContainer.mStackSupervisor.removeStack(stack); + stacks.add(stack); } } + + for (int i = stacks.size() - 1; i >= 0; --i) { + mRootActivityContainer.mStackSupervisor.removeStack(stacks.get(i)); + } } void removeStacksWithActivityTypes(int... activityTypes) { @@ -646,15 +657,23 @@ class ActivityDisplay extends ConfigurationContainer<ActivityStack> return; } + // Collect the stacks that are necessary to be removed instead of performing the removal + // by looping mStacks, so that we don't miss any stacks after the stack size changed or + // stacks reordered. + final ArrayList<ActivityStack> stacks = new ArrayList<>(); for (int j = activityTypes.length - 1 ; j >= 0; --j) { final int activityType = activityTypes[j]; for (int i = mStacks.size() - 1; i >= 0; --i) { final ActivityStack stack = mStacks.get(i); if (stack.getActivityType() == activityType) { - mRootActivityContainer.mStackSupervisor.removeStack(stack); + stacks.add(stack); } } } + + for (int i = stacks.size() - 1; i >= 0; --i) { + mRootActivityContainer.mStackSupervisor.removeStack(stacks.get(i)); + } } void onStackWindowingModeChanged(ActivityStack stack) { @@ -1019,8 +1038,8 @@ class ActivityDisplay extends ConfigurationContainer<ActivityStack> return mSplitScreenPrimaryStack != null; } - PinnedActivityStack getPinnedStack() { - return (PinnedActivityStack) mPinnedStack; + ActivityStack getPinnedStack() { + return mPinnedStack; } boolean hasPinnedStack() { diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java index 9f8af5048da2..6213fa02cb9f 100644 --- a/services/core/java/com/android/server/wm/ActivityRecord.java +++ b/services/core/java/com/android/server/wm/ActivityRecord.java @@ -1946,30 +1946,84 @@ final class ActivityRecord extends ConfigurationContainer { try { mAtmService.getLifecycleManager().scheduleTransaction(app.getThread(), appToken, WindowVisibilityItem.obtain(true /* showWindow */)); - if (shouldPauseWhenBecomingVisible()) { - // An activity must be in the {@link PAUSING} state for the system to validate - // the move to {@link PAUSED}. - setState(PAUSING, "makeVisibleIfNeeded"); + makeActiveIfNeeded(null /* activeActivity*/); + } catch (Exception e) { + Slog.w(TAG, "Exception thrown sending visibility update: " + intent.getComponent(), e); + } + } + + /** + * Make activity resumed or paused if needed. + * @param activeActivity an activity that is resumed or just completed pause action. + * We won't change the state of this activity. + */ + boolean makeActiveIfNeeded(ActivityRecord activeActivity) { + if (shouldResumeActivity(activeActivity)) { + if (DEBUG_VISIBILITY) { + Slog.v("TAG_VISIBILITY", "Resume visible activity, " + this); + } + return getActivityStack().resumeTopActivityUncheckedLocked(activeActivity /* prev */, + null /* options */); + } else if (shouldPauseActivity(activeActivity)) { + if (DEBUG_VISIBILITY) { + Slog.v("TAG_VISIBILITY", "Pause visible activity, " + this); + } + // An activity must be in the {@link PAUSING} state for the system to validate + // the move to {@link PAUSED}. + setState(PAUSING, "makeVisibleIfNeeded"); + try { mAtmService.getLifecycleManager().scheduleTransaction(app.getThread(), appToken, PauseActivityItem.obtain(finishing, false /* userLeaving */, configChangeFlags, false /* dontReport */)); + } catch (Exception e) { + Slog.w(TAG, "Exception thrown sending pause: " + intent.getComponent(), e); } - } catch (Exception e) { - Slog.w(TAG, "Exception thrown sending visibility update: " + intent.getComponent(), e); } + return false; + } + + /** + * Check if activity should be moved to PAUSED state. The activity: + * - should be eligible to be made active (see {@link #shouldMakeActive(ActivityRecord)}) + * - should be non-focusable + * - should not be currently pausing or paused + * @param activeActivity the activity that is active or just completed pause action. We won't + * resume if this activity is active. + */ + private boolean shouldPauseActivity(ActivityRecord activeActivity) { + return shouldMakeActive(activeActivity) && !isFocusable() && !isState(PAUSING, PAUSED); + } + + /** + * Check if activity should be moved to RESUMED state. The activity: + * - should be eligible to be made active (see {@link #shouldMakeActive(ActivityRecord)}) + * - should be focusable + * @param activeActivity the activity that is active or just completed pause action. We won't + * resume if this activity is active. + */ + private boolean shouldResumeActivity(ActivityRecord activeActivity) { + return shouldMakeActive(activeActivity) && isFocusable() && !isState(RESUMED); } - /** Check if activity should be moved to PAUSED state when it becomes visible. */ - private boolean shouldPauseWhenBecomingVisible() { - // If the activity is stopped or stopping, cycle to the paused state. We avoid doing + /** + * Check if activity is eligible to be made active (resumed of paused). The activity: + * - should be paused, stopped or stopping + * - should not be the currently active one + * - should be either the topmost in task, or right below the top activity that is finishing + * If all of these conditions are not met at the same time, the activity cannot be made active. + */ + private boolean shouldMakeActive(ActivityRecord activeActivity) { + // If the activity is stopped, stopping, cycle to an active state. We avoid doing // this when there is an activity waiting to become translucent as the extra binder // calls will lead to noticeable jank. A later call to - // ActivityStack#ensureActivitiesVisibleLocked will bring the activity to the proper - // paused state. We also avoid doing this for the activity the stack supervisor - // considers the resumed activity, as normal means will bring the activity from STOPPED - // to RESUMED. Adding PAUSING in this scenario will lead to double lifecycles. - if (!isState(STOPPED, STOPPING) || getActivityStack().mTranslucentActivityWaiting != null - || isResumedActivityOnDisplay()) { + // ActivityStack#ensureActivitiesVisibleLocked will bring the activity to a proper + // active state. + if (!isState(RESUMED, PAUSED, STOPPED, STOPPING) + || getActivityStack().mTranslucentActivityWaiting != null) { + return false; + } + + if (this == activeActivity) { return false; } @@ -1979,14 +2033,14 @@ final class ActivityRecord extends ConfigurationContainer { throw new IllegalStateException("Activity not found in its task"); } if (positionInTask == task.mActivities.size() - 1) { - // It's the topmost activity in the task - should become paused now + // It's the topmost activity in the task - should become resumed now return true; } // Check if activity above is finishing now and this one becomes the topmost in task. final ActivityRecord activityAbove = task.mActivities.get(positionInTask + 1); if (activityAbove.finishing && results == null) { - // We will only allow pausing if activity above wasn't launched for result. Otherwise it - // will cause this activity to resume before getting result. + // We will only allow making active if activity above wasn't launched for result. + // Otherwise it will cause this activity to resume before getting result. return true; } return false; @@ -2508,6 +2562,13 @@ final class ActivityRecord extends ConfigurationContainer { final IBinder binder = (freezeScreenIfNeeded && appToken != null) ? appToken.asBinder() : null; mAppWindowToken.setOrientation(requestedOrientation, binder, this); + + // Push the new configuration to the requested app in case where it's not pushed, e.g. when + // the request is handled at task level with letterbox. + if (!getMergedOverrideConfiguration().equals( + mLastReportedConfiguration.getMergedConfiguration())) { + ensureActivityConfiguration(0 /* globalChanges */, false /* preserveWindow */); + } } int getOrientation() { diff --git a/services/core/java/com/android/server/wm/ActivityStack.java b/services/core/java/com/android/server/wm/ActivityStack.java index 4d7de9058105..3aef8e1f84bf 100644 --- a/services/core/java/com/android/server/wm/ActivityStack.java +++ b/services/core/java/com/android/server/wm/ActivityStack.java @@ -114,6 +114,7 @@ import android.app.ActivityManagerInternal; import android.app.ActivityOptions; import android.app.AppGlobals; import android.app.IActivityController; +import android.app.RemoteAction; import android.app.ResultInfo; import android.app.WindowConfiguration.ActivityType; import android.app.WindowConfiguration.WindowingMode; @@ -173,8 +174,7 @@ import java.util.Set; /** * State and management of a single stack of activities. */ -class ActivityStack<T extends StackWindowController> extends ConfigurationContainer - implements StackWindowListener { +class ActivityStack extends ConfigurationContainer { private static final String TAG = TAG_WITH_CLASS_NAME ? "ActivityStack" : TAG_ATM; private static final String TAG_ADD_REMOVE = TAG + POSTFIX_ADD_REMOVE; private static final String TAG_APP = TAG + POSTFIX_APP; @@ -297,8 +297,7 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai static final int REMOVE_TASK_MODE_MOVING_TO_TOP = 2; final ActivityTaskManagerService mService; - private final WindowManagerService mWindowManager; - T mWindowContainerController; + final WindowManagerService mWindowManager; /** * The back history of all previous (and possibly still @@ -358,6 +357,11 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai */ boolean mForceHidden = false; + /** + * Used to keep resumeTopActivityUncheckedLocked() from being entered recursively + */ + boolean mInResumeTopActivity = false; + private boolean mUpdateBoundsDeferred; private boolean mUpdateBoundsDeferredCalled; private boolean mUpdateDisplayedBoundsDeferredCalled; @@ -397,6 +401,9 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai static final int DESTROY_ACTIVITIES_MSG = FIRST_ACTIVITY_STACK_MSG + 5; static final int TRANSLUCENT_TIMEOUT_MSG = FIRST_ACTIVITY_STACK_MSG + 6; + // TODO: remove after unification. + TaskStack mTaskStack; + private static class ScheduleDestroyArgs { final WindowProcessController mOwner; final String mReason; @@ -495,21 +502,30 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai // stacks on a wrong display. mDisplayId = display.mDisplayId; setActivityType(activityType); - mWindowContainerController = createStackWindowController(display.mDisplayId, onTop, - mTmpRect2); + createTaskStack(display.mDisplayId, onTop, mTmpRect2); setWindowingMode(windowingMode, false /* animate */, false /* showRecents */, false /* enteringSplitScreenMode */, false /* deferEnsuringVisibility */, true /* creating */); display.addChild(this, onTop ? POSITION_TOP : POSITION_BOTTOM); } - T createStackWindowController(int displayId, boolean onTop, Rect outBounds) { - return (T) new StackWindowController(mStackId, this, displayId, onTop, outBounds, - mRootActivityContainer.mWindowManager); + void createTaskStack(int displayId, boolean onTop, Rect outBounds) { + final DisplayContent dc = mWindowManager.mRoot.getDisplayContent(displayId); + if (dc == null) { + throw new IllegalArgumentException("Trying to add stackId=" + mStackId + + " to unknown displayId=" + displayId); + } + mTaskStack = new TaskStack(mWindowManager, mStackId, this); + dc.setStackOnDisplay(mStackId, onTop, mTaskStack); + if (mTaskStack.matchParentBounds()) { + outBounds.setEmpty(); + } else { + mTaskStack.getRawBounds(outBounds); + } } - T getWindowContainerController() { - return mWindowContainerController; + TaskStack getTaskStack() { + return mTaskStack; } /** @@ -553,6 +569,9 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai if (display == null) { return; } + if (getTaskStack() == null) { + return; + } // Update bounds if applicable boolean hasNewOverrideBounds = false; @@ -560,8 +579,7 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai if (getRequestedOverrideWindowingMode() == WINDOWING_MODE_PINNED) { // Pinned calculation already includes rotation mTmpRect2.set(mTmpRect); - hasNewOverrideBounds = getWindowContainerController().mContainer - .calculatePinnedBoundsForConfigChange(mTmpRect2); + hasNewOverrideBounds = getTaskStack().calculatePinnedBoundsForConfigChange(mTmpRect2); } else { final int newRotation = getWindowConfiguration().getRotation(); if (!matchParentBounds()) { @@ -588,7 +606,7 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai || getRequestedOverrideWindowingMode() == WINDOWING_MODE_SPLIT_SCREEN_SECONDARY) { mTmpRect2.set(mTmpRect); - getWindowContainerController().mContainer + getTaskStack() .calculateDockedBoundsForConfigChange(newParentConfig, mTmpRect2); hasNewOverrideBounds = true; } @@ -786,7 +804,11 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai mTmpRect2.setEmpty(); if (windowingMode != WINDOWING_MODE_FULLSCREEN) { - mWindowContainerController.getRawBounds(mTmpRect2); + if (mTaskStack.matchParentBounds()) { + mTmpRect2.setEmpty(); + } else { + mTaskStack.getRawBounds(mTmpRect2); + } } if (!Objects.equals(getRequestedOverrideBounds(), mTmpRect2)) { @@ -843,7 +865,12 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai // Reparent the window container before we try to update the position when adding it to // the new display below mTmpRect2.setEmpty(); - mWindowContainerController.reparent(activityDisplay.mDisplayId, mTmpRect2, onTop); + if (mTaskStack == null) { + // TODO: Remove after unification. + Log.w(TAG, "Task stack is not valid when reparenting."); + } else { + mTaskStack.reparent(activityDisplay.mDisplayId, mTmpRect2, onTop); + } setBounds(mTmpRect2.isEmpty() ? null : mTmpRect2); activityDisplay.addChild(this, onTop ? POSITION_TOP : POSITION_BOTTOM); if (!displayRemoved) { @@ -876,8 +903,10 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai /** Removes the stack completely. Also calls WindowManager to do the same on its side. */ void remove() { removeFromDisplay(); - mWindowContainerController.removeContainer(); - mWindowContainerController = null; + if (mTaskStack != null) { + mTaskStack.removeIfPossible(); + mTaskStack = null; + } onParentChanged(); } @@ -890,26 +919,35 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai */ void getStackDockedModeBounds(Rect dockedBounds, Rect currentTempTaskBounds, Rect outStackBounds, Rect outTempTaskBounds) { - mWindowContainerController.getStackDockedModeBounds(getParent().getConfiguration(), - dockedBounds, currentTempTaskBounds, - outStackBounds, outTempTaskBounds); + if (mTaskStack != null) { + mTaskStack.getStackDockedModeBoundsLocked(getParent().getConfiguration(), dockedBounds, + currentTempTaskBounds, outStackBounds, outTempTaskBounds); + } else { + outStackBounds.setEmpty(); + outTempTaskBounds.setEmpty(); + } } void prepareFreezingTaskBounds() { - mWindowContainerController.prepareFreezingTaskBounds(); + if (mTaskStack != null) { + // TODO: This cannot be false after unification. + mTaskStack.prepareFreezingTaskBounds(); + } } void getWindowContainerBounds(Rect outBounds) { - if (mWindowContainerController != null) { - mWindowContainerController.getBounds(outBounds); + if (mTaskStack != null) { + mTaskStack.getBounds(outBounds); return; } outBounds.setEmpty(); } void positionChildWindowContainerAtTop(TaskRecord child) { - mWindowContainerController.positionChildAtTop(child.getTask(), - true /* includingParents */); + if (mTaskStack != null) { + // TODO: Remove after unification. This cannot be false after that. + mTaskStack.positionChildAtTop(child.getTask(), true /* includingParents */); + } } void positionChildWindowContainerAtBottom(TaskRecord child) { @@ -918,14 +956,27 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai // task to bottom, the next focusable stack on the same display should be focused. final ActivityStack nextFocusableStack = getDisplay().getNextFocusableStack( child.getStack(), true /* ignoreCurrent */); - mWindowContainerController.positionChildAtBottom(child.getTask(), - nextFocusableStack == null /* includingParents */); + if (mTaskStack != null) { + // TODO: Remove after unification. This cannot be false after that. + mTaskStack.positionChildAtBottom(child.getTask(), + nextFocusableStack == null /* includingParents */); + } } /** * Returns whether to defer the scheduling of the multi-window mode. */ boolean deferScheduleMultiWindowModeChanged() { + if (inPinnedWindowingMode()) { + // For the pinned stack, the deferring of the multi-window mode changed is tied to the + // transition animation into picture-in-picture, and is called once the animation + // completes, or is interrupted in a way that would leave the stack in a non-fullscreen + // state. + // @see BoundsAnimationController + // @see BoundsAnimationControllerTests + if (getTaskStack() == null) return false; + return getTaskStack().deferScheduleMultiWindowModeChanged(); + } return false; } @@ -1686,6 +1737,7 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai "Activity paused: token=" + token + ", timeout=" + timeout); final ActivityRecord r = isInStackLocked(token); + if (r != null) { mHandler.removeMessages(PAUSE_TIMEOUT_MSG, r); if (mPausingActivity == r) { @@ -2042,8 +2094,7 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai boolean aboveTop = top != null; final boolean stackShouldBeVisible = shouldBeVisible(starting); boolean behindFullscreenActivity = !stackShouldBeVisible; - boolean resumeNextActivity = mRootActivityContainer.isTopDisplayFocusedStack(this) - && (isInStackLocked(starting) == null); + boolean resumeNextActivity = isFocusable() && isInStackLocked(starting) == null; final boolean isTopNotPinnedStack = isAttached() && getDisplay().isTopNotPinnedStack(this); for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) { @@ -2104,6 +2155,10 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai if (r.handleAlreadyVisible()) { resumeNextActivity = false; } + + if (notifyClients) { + r.makeActiveIfNeeded(starting); + } } else { r.makeVisibleIfNeeded(starting, notifyClients); } @@ -2281,7 +2336,7 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai r.setVisible(true); } if (r != starting) { - mStackSupervisor.startSpecificActivityLocked(r, andResume, false); + mStackSupervisor.startSpecificActivityLocked(r, andResume, true /* checkConfig */); return true; } } @@ -2459,7 +2514,7 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai */ @GuardedBy("mService") boolean resumeTopActivityUncheckedLocked(ActivityRecord prev, ActivityOptions options) { - if (mStackSupervisor.inResumeTopActivity) { + if (mInResumeTopActivity) { // Don't even start recursing. return false; } @@ -2467,7 +2522,7 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai boolean result = false; try { // Protect against recursion. - mStackSupervisor.inResumeTopActivity = true; + mInResumeTopActivity = true; result = resumeTopActivityInnerLocked(prev, options); // When resuming the top activity, it may be necessary to pause the top activity (for @@ -2482,7 +2537,7 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai checkReadyForSleep(); } } finally { - mStackSupervisor.inResumeTopActivity = false; + mInResumeTopActivity = false; } return result; @@ -2515,7 +2570,7 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai // Find the next top-most activity to resume in this stack that is not finishing and is // focusable. If it is not focusable, we will fall into the case below to resume the // top activity in the next focusable task. - final ActivityRecord next = topRunningActivityLocked(true /* focusableOnly */); + ActivityRecord next = topRunningActivityLocked(true /* focusableOnly */); final boolean hasRunningActivity = next != null; @@ -2603,6 +2658,12 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai if (!mRootActivityContainer.allPausedActivitiesComplete()) { if (DEBUG_SWITCH || DEBUG_PAUSE || DEBUG_STATES) Slog.v(TAG_PAUSE, "resumeTopActivityLocked: Skip resume: some activity pausing."); + + // Adding previous activity to the waiting visible list, or it would be stopped + // before top activity being visible. + if (prev != null && !next.nowVisible) { + mStackSupervisor.mActivitiesWaitingForVisibleActivity.add(prev); + } return false; } @@ -2812,7 +2873,9 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai // the screen based on the new activity order. boolean notUpdated = true; - if (isFocusedStackOnDisplay()) { + // Activity should also be visible if set mLaunchTaskBehind to true (see + // ActivityRecord#shouldBeVisibleIgnoringKeyguard()). + if (shouldBeVisible(next)) { // We have special rotation behavior when here is some active activity that // requests specific orientation or Keyguard is locked. Make sure all activity // visibilities are set correctly as well as the transition is updated if needed @@ -2994,7 +3057,10 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai position = getAdjustedPositionForTask(task, position, null /* starting */); mTaskHistory.remove(task); mTaskHistory.add(position, task); - mWindowContainerController.positionChildAt(task.getTask(), position); + if (mTaskStack != null) { + // TODO: this could not be false after unification. + mTaskStack.positionChildAt(task.getTask(), position); + } updateTaskMovement(task, true); } @@ -4038,6 +4104,12 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai mStackSupervisor.mFinishingActivities.add(r); r.resumeKeyDispatchingLocked(); mRootActivityContainer.resumeFocusedStacksTopActivities(); + // If activity was not paused at this point - explicitly pause it to start finishing + // process. Finishing will be completed once it reports pause back. + if (r.isState(RESUMED) && mPausingActivity != null) { + startPausingLocked(false /* userLeaving */, false /* uiSleeping */, next /* resuming */, + false /* dontWait */); + } return r; } @@ -4909,8 +4981,7 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai } // TODO: Figure-out a way to consolidate with resize() method below. - @Override - public void requestResize(Rect bounds) { + void requestResize(Rect bounds) { mService.resizeStack(mStackId, bounds, true /* allowResizeInDockedMode */, false /* preserveWindows */, false /* animate */, -1 /* animationDuration */); @@ -4948,7 +5019,8 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai } void onPipAnimationEndResize() { - mWindowContainerController.onPipAnimationEndResize(); + if (mTaskStack == null) return; + mTaskStack.onPipAnimationEndResize(); } @@ -5494,6 +5566,65 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai } } + + Rect getDefaultPictureInPictureBounds(float aspectRatio) { + if (getTaskStack() == null) return null; + return getTaskStack().getPictureInPictureBounds(aspectRatio, null /* currentStackBounds */); + } + + void animateResizePinnedStack(Rect sourceHintBounds, Rect toBounds, int animationDuration, + boolean fromFullscreen) { + if (!inPinnedWindowingMode()) return; + if (skipResizeAnimation(toBounds == null /* toFullscreen */)) { + mService.moveTasksToFullscreenStack(mStackId, true /* onTop */); + } else { + if (getTaskStack() == null) return; + getTaskStack().animateResizePinnedStack(toBounds, sourceHintBounds, + animationDuration, fromFullscreen); + } + } + + private boolean skipResizeAnimation(boolean toFullscreen) { + if (!toFullscreen) { + return false; + } + final Configuration parentConfig = getParent().getConfiguration(); + final ActivityRecord top = topRunningNonOverlayTaskActivity(); + return top != null && !top.isConfigurationCompatible(parentConfig); + } + + void setPictureInPictureAspectRatio(float aspectRatio) { + if (getTaskStack() == null) return; + getTaskStack().setPictureInPictureAspectRatio(aspectRatio); + } + + void setPictureInPictureActions(List<RemoteAction> actions) { + if (getTaskStack() == null) return; + getTaskStack().setPictureInPictureActions(actions); + } + + boolean isAnimatingBoundsToFullscreen() { + if (getTaskStack() == null) return false; + return getTaskStack().isAnimatingBoundsToFullscreen(); + } + + public void updatePictureInPictureModeForPinnedStackAnimation(Rect targetStackBounds, + boolean forceUpdate) { + // It is guaranteed that the activities requiring the update will be in the pinned stack at + // this point (either reparented before the animation into PiP, or before reparenting after + // the animation out of PiP) + synchronized (mService.mGlobalLock) { + if (!isAttached()) { + return; + } + ArrayList<TaskRecord> tasks = getAllTasks(); + for (int i = 0; i < tasks.size(); i++) { + mStackSupervisor.updatePictureInPictureMode(tasks.get(i), targetStackBounds, + forceUpdate); + } + } + } + public int getStackId() { return mStackId; } diff --git a/services/core/java/com/android/server/wm/ActivityStackSupervisor.java b/services/core/java/com/android/server/wm/ActivityStackSupervisor.java index a50ae8431cb0..a83ef34f1cac 100644 --- a/services/core/java/com/android/server/wm/ActivityStackSupervisor.java +++ b/services/core/java/com/android/server/wm/ActivityStackSupervisor.java @@ -327,9 +327,6 @@ public class ActivityStackSupervisor implements RecentTasks.Callbacks { */ PowerManager.WakeLock mGoingToSleep; - /** Used to keep resumeTopActivityUncheckedLocked() from being entered recursively */ - boolean inResumeTopActivity; - /** * Temporary rect used during docked stack resize calculation so we don't need to create a new * object each time. @@ -1674,8 +1671,8 @@ public class ActivityStackSupervisor implements RecentTasks.Callbacks { } void resizePinnedStackLocked(Rect pinnedBounds, Rect tempPinnedTaskBounds) { - // TODO(multi-display): Pinned stack display should be passed in. - final PinnedActivityStack stack = + // TODO(multi-display): The display containing the stack should be passed in. + final ActivityStack stack = mRootActivityContainer.getDefaultDisplay().getPinnedStack(); if (stack == null) { Slog.w(TAG, "resizePinnedStackLocked: pinned stack not found"); @@ -1686,7 +1683,7 @@ public class ActivityStackSupervisor implements RecentTasks.Callbacks { // another AM call that is holding the AMS lock. In such a case, the pinnedBounds may be // incorrect if AMS.resizeStackWithBoundsFromWindowManager() is already called while waiting // for the AMS lock to be freed. So check and make sure these bounds are still good. - final PinnedStackWindowController stackController = stack.getWindowContainerController(); + final TaskStack stackController = stack.getTaskStack(); if (stackController.pinnedStackResizeDisallowed()) { return; } @@ -1730,15 +1727,14 @@ public class ActivityStackSupervisor implements RecentTasks.Callbacks { * invisible as well and added to the stopping list. After which we process the * stopping list by handling the idle. */ - final PinnedActivityStack pinnedStack = (PinnedActivityStack) stack; - pinnedStack.mForceHidden = true; - pinnedStack.ensureActivitiesVisibleLocked(null, 0, PRESERVE_WINDOWS); - pinnedStack.mForceHidden = false; + stack.mForceHidden = true; + stack.ensureActivitiesVisibleLocked(null, 0, PRESERVE_WINDOWS); + stack.mForceHidden = false; activityIdleInternalLocked(null, false /* fromTimeout */, true /* processPausingActivites */, null /* configuration */); // Move all the tasks to the bottom of the fullscreen stack - moveTasksToFullscreenStackLocked(pinnedStack, !ON_TOP); + moveTasksToFullscreenStackLocked(stack, !ON_TOP); } else { for (int i = tasks.size() - 1; i >= 0; i--) { removeTaskByIdLocked(tasks.get(i).taskId, true /* killProcess */, @@ -2642,6 +2638,9 @@ public class ActivityStackSupervisor implements RecentTasks.Callbacks { try { mService.moveTaskToFrontLocked(task.taskId, 0, options, true /* fromRecents */); + // Apply options to prevent pendingOptions be taken by client to make sure + // the override pending app transition will be applied immediately. + targetActivity.applyOptionsLocked(); } finally { mActivityMetricsLogger.notifyActivityLaunched(START_TASK_TO_FRONT, targetActivity); diff --git a/services/core/java/com/android/server/wm/ActivityStartController.java b/services/core/java/com/android/server/wm/ActivityStartController.java index 08596836ed4d..43c12064a3c1 100644 --- a/services/core/java/com/android/server/wm/ActivityStartController.java +++ b/services/core/java/com/android/server/wm/ActivityStartController.java @@ -179,7 +179,10 @@ public class ActivityStartController { .setActivityOptions(options.toBundle()) .execute(); mLastHomeActivityStartRecord = tmpOutRecord[0]; - if (mSupervisor.inResumeTopActivity) { + final ActivityDisplay display = + mService.mRootActivityContainer.getActivityDisplay(displayId); + final ActivityStack homeStack = display != null ? display.getHomeStack() : null; + if (homeStack != null && homeStack.mInResumeTopActivity) { // If we are in resume section already, home activity will be initialized, but not // resumed (to avoid recursive resume) and will stay that way until something pokes it // again. We need to schedule another resume. @@ -297,6 +300,29 @@ public class ActivityStartController { String[] resolvedTypes, IBinder resultTo, SafeActivityOptions options, int userId, boolean validateIncomingUser, PendingIntentRecord originatingPendingIntent, boolean allowBackgroundActivityStart) { + return startActivitiesInPackage(uid, 0 /* realCallingPid */, -1 /* realCallingUid */, + callingPackage, intents, resolvedTypes, resultTo, options, userId, validateIncomingUser, + originatingPendingIntent, allowBackgroundActivityStart); + } + + /** + * Start intents as a package. + * + * @param uid Make a call as if this UID did. + * @param realCallingPid PID of the real caller. + * @param realCallingUid UID of the real caller. + * @param callingPackage Make a call as if this package did. + * @param intents Intents to start. + * @param userId Start the intents on this user. + * @param validateIncomingUser Set true to skip checking {@code userId} with the calling UID. + * @param originatingPendingIntent PendingIntentRecord that originated this activity start or + * null if not originated by PendingIntent + */ + final int startActivitiesInPackage(int uid, int realCallingPid, int realCallingUid, + String callingPackage, Intent[] intents, String[] resolvedTypes, IBinder resultTo, + SafeActivityOptions options, int userId, boolean validateIncomingUser, + PendingIntentRecord originatingPendingIntent, + boolean allowBackgroundActivityStart) { final String reason = "startActivityInPackage"; @@ -304,12 +330,14 @@ public class ActivityStartController { Binder.getCallingUid(), reason); // TODO: Switch to user app stacks here. - return startActivities(null, uid, callingPackage, intents, resolvedTypes, resultTo, options, - userId, reason, originatingPendingIntent, allowBackgroundActivityStart); + return startActivities(null, uid, realCallingPid, realCallingUid, callingPackage, intents, + resolvedTypes, resultTo, options, userId, reason, originatingPendingIntent, + allowBackgroundActivityStart); } - int startActivities(IApplicationThread caller, int callingUid, String callingPackage, - Intent[] intents, String[] resolvedTypes, IBinder resultTo, SafeActivityOptions options, + int startActivities(IApplicationThread caller, int callingUid, int incomingRealCallingPid, + int incomingRealCallingUid, String callingPackage, Intent[] intents, + String[] resolvedTypes, IBinder resultTo, SafeActivityOptions options, int userId, String reason, PendingIntentRecord originatingPendingIntent, boolean allowBackgroundActivityStart) { if (intents == null) { @@ -322,8 +350,12 @@ public class ActivityStartController { throw new IllegalArgumentException("intents are length different than resolvedTypes"); } - final int realCallingPid = Binder.getCallingPid(); - final int realCallingUid = Binder.getCallingUid(); + final int realCallingPid = incomingRealCallingPid != 0 + ? incomingRealCallingPid + : Binder.getCallingPid(); + final int realCallingUid = incomingRealCallingUid != -1 + ? incomingRealCallingUid + : Binder.getCallingUid(); int callingPid; if (callingUid >= 0) { diff --git a/services/core/java/com/android/server/wm/ActivityStarter.java b/services/core/java/com/android/server/wm/ActivityStarter.java index 916baa08fcbc..4e2dffc2ba78 100644 --- a/services/core/java/com/android/server/wm/ActivityStarter.java +++ b/services/core/java/com/android/server/wm/ActivityStarter.java @@ -294,6 +294,8 @@ class ActivityStarter { private static class Request { private static final int DEFAULT_CALLING_UID = -1; private static final int DEFAULT_CALLING_PID = 0; + static final int DEFAULT_REAL_CALLING_UID = -1; + static final int DEFAULT_REAL_CALLING_PID = 0; IApplicationThread caller; Intent intent; @@ -306,11 +308,11 @@ class ActivityStarter { IBinder resultTo; String resultWho; int requestCode; - int callingPid = DEFAULT_CALLING_UID; - int callingUid = DEFAULT_CALLING_PID; + int callingPid = DEFAULT_CALLING_PID; + int callingUid = DEFAULT_CALLING_UID; String callingPackage; - int realCallingPid; - int realCallingUid; + int realCallingPid = DEFAULT_REAL_CALLING_PID; + int realCallingUid = DEFAULT_REAL_CALLING_UID; int startFlags; SafeActivityOptions activityOptions; boolean ignoreTargetSecurity; @@ -365,8 +367,8 @@ class ActivityStarter { callingPid = DEFAULT_CALLING_PID; callingUid = DEFAULT_CALLING_UID; callingPackage = null; - realCallingPid = 0; - realCallingUid = 0; + realCallingPid = DEFAULT_REAL_CALLING_PID; + realCallingUid = DEFAULT_REAL_CALLING_UID; startFlags = 0; activityOptions = null; ignoreTargetSecurity = false; @@ -502,7 +504,8 @@ class ActivityStarter { // for transactional diffs and preprocessing. if (mRequest.mayWait) { return startActivityMayWait(mRequest.caller, mRequest.callingUid, - mRequest.callingPackage, mRequest.intent, mRequest.resolvedType, + mRequest.callingPackage, mRequest.realCallingPid, mRequest.realCallingUid, + mRequest.intent, mRequest.resolvedType, mRequest.voiceSession, mRequest.voiceInteractor, mRequest.resultTo, mRequest.resultWho, mRequest.requestCode, mRequest.startFlags, mRequest.profilerInfo, mRequest.waitResult, mRequest.globalConfig, @@ -1092,10 +1095,10 @@ class ActivityStarter { } private int startActivityMayWait(IApplicationThread caller, int callingUid, - String callingPackage, Intent intent, String resolvedType, - IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor, - IBinder resultTo, String resultWho, int requestCode, int startFlags, - ProfilerInfo profilerInfo, WaitResult outResult, + String callingPackage, int requestRealCallingPid, int requestRealCallingUid, + Intent intent, String resolvedType, IVoiceInteractionSession voiceSession, + IVoiceInteractor voiceInteractor, IBinder resultTo, String resultWho, int requestCode, + int startFlags, ProfilerInfo profilerInfo, WaitResult outResult, Configuration globalConfig, SafeActivityOptions options, boolean ignoreTargetSecurity, int userId, TaskRecord inTask, String reason, boolean allowPendingRemoteAnimationRegistryLookup, @@ -1107,8 +1110,12 @@ class ActivityStarter { mSupervisor.getActivityMetricsLogger().notifyActivityLaunching(intent); boolean componentSpecified = intent.getComponent() != null; - final int realCallingPid = Binder.getCallingPid(); - final int realCallingUid = Binder.getCallingUid(); + final int realCallingPid = requestRealCallingPid != Request.DEFAULT_REAL_CALLING_PID + ? requestRealCallingPid + : Binder.getCallingPid(); + final int realCallingUid = requestRealCallingUid != Request.DEFAULT_REAL_CALLING_UID + ? requestRealCallingUid + : Binder.getCallingUid(); int callingPid; if (callingUid >= 0) { @@ -1622,7 +1629,7 @@ class ActivityStarter { // Also, we don't want to resume activities in a task that currently has an overlay // as the starting activity just needs to be in the visible paused state until the // over is removed. - mTargetStack.ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS); + mTargetStack.ensureActivitiesVisibleLocked(mStartActivity, 0, !PRESERVE_WINDOWS); // Go ahead and tell window manager to execute app transition for this activity // since the app transition will not be triggered through the resume channel. mTargetStack.getDisplay().mDisplayContent.executeAppTransition(); diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerInternal.java b/services/core/java/com/android/server/wm/ActivityTaskManagerInternal.java index d8644df3684c..67b00b2cfbf1 100644 --- a/services/core/java/com/android/server/wm/ActivityTaskManagerInternal.java +++ b/services/core/java/com/android/server/wm/ActivityTaskManagerInternal.java @@ -192,6 +192,8 @@ public abstract class ActivityTaskManagerInternal { * Start intents as a package. * * @param uid Make a call as if this UID did. + * @param realCallingPid PID of the real caller. + * @param realCallingUid UID of the real caller. * @param callingPackage Make a call as if this package did. * @param intents Intents to start. * @param userId Start the intents on this user. @@ -201,9 +203,10 @@ public abstract class ActivityTaskManagerInternal { * @param allowBackgroundActivityStart Whether the background activity start should be allowed * from originatingPendingIntent */ - public abstract int startActivitiesInPackage(int uid, String callingPackage, Intent[] intents, - String[] resolvedTypes, IBinder resultTo, SafeActivityOptions options, int userId, - boolean validateIncomingUser, PendingIntentRecord originatingPendingIntent, + public abstract int startActivitiesInPackage(int uid, int realCallingPid, int realCallingUid, + String callingPackage, Intent[] intents, String[] resolvedTypes, IBinder resultTo, + SafeActivityOptions options, int userId, boolean validateIncomingUser, + PendingIntentRecord originatingPendingIntent, boolean allowBackgroundActivityStart); public abstract int startActivityInPackage(int uid, int realCallingPid, int realCallingUid, diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java index 2cd4921a6672..61c4863c0bc9 100644 --- a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java +++ b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java @@ -82,13 +82,10 @@ import static com.android.server.am.ActivityManagerServiceDumpProcessesProto.HEA import static com.android.server.am.ActivityManagerServiceDumpProcessesProto.HOME_PROC; import static com.android.server.am.ActivityManagerServiceDumpProcessesProto.LAUNCHING_ACTIVITY; import static com.android.server.am.ActivityManagerServiceDumpProcessesProto.PREVIOUS_PROC; -import static com.android.server.am.ActivityManagerServiceDumpProcessesProto - .PREVIOUS_PROC_VISIBLE_TIME_MS; +import static com.android.server.am.ActivityManagerServiceDumpProcessesProto.PREVIOUS_PROC_VISIBLE_TIME_MS; import static com.android.server.am.ActivityManagerServiceDumpProcessesProto.SCREEN_COMPAT_PACKAGES; -import static com.android.server.am.ActivityManagerServiceDumpProcessesProto.ScreenCompatPackage - .MODE; -import static com.android.server.am.ActivityManagerServiceDumpProcessesProto.ScreenCompatPackage - .PACKAGE; +import static com.android.server.am.ActivityManagerServiceDumpProcessesProto.ScreenCompatPackage.MODE; +import static com.android.server.am.ActivityManagerServiceDumpProcessesProto.ScreenCompatPackage.PACKAGE; import static com.android.server.wm.ActivityStack.REMOVE_TASK_MODE_DESTROYING; import static com.android.server.wm.ActivityStackSupervisor.DEFER_RESUME; import static com.android.server.wm.ActivityStackSupervisor.ON_TOP; @@ -960,9 +957,10 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { enforceNotIsolatedCaller(reason); userId = handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(), userId, reason); // TODO: Switch to user app stacks here. - return getActivityStartController().startActivities(caller, -1, callingPackage, intents, - resolvedTypes, resultTo, SafeActivityOptions.fromBundle(bOptions), userId, reason, - null /* originatingPendingIntent */, false /* allowBackgroundActivityStart */); + return getActivityStartController().startActivities(caller, -1, 0, -1, callingPackage, + intents, resolvedTypes, resultTo, SafeActivityOptions.fromBundle(bOptions), userId, + reason, null /* originatingPendingIntent */, + false /* allowBackgroundActivityStart */); } @Override @@ -2408,7 +2406,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { try { synchronized (mGlobalLock) { if (animate) { - final PinnedActivityStack stack = mRootActivityContainer.getStack(stackId); + final ActivityStack stack = mRootActivityContainer.getStack(stackId); if (stack == null) { Slog.w(TAG, "resizeStack: stackId " + stackId + " not found."); return; @@ -3713,7 +3711,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { final long ident = Binder.clearCallingIdentity(); try { synchronized (mGlobalLock) { - final PinnedActivityStack stack = + final ActivityStack stack = mRootActivityContainer.getDefaultDisplay().getPinnedStack(); if (stack == null) { Slog.w(TAG, "dismissPip: pinned stack not found."); @@ -3835,9 +3833,8 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { // If we are animating to fullscreen then we have already dispatched the PIP mode // changed, so we should reflect that check here as well. - final PinnedActivityStack stack = r.getActivityStack(); - final PinnedStackWindowController windowController = stack.getWindowContainerController(); - return !windowController.mContainer.isAnimatingBoundsToFullscreen(); + final TaskStack taskStack = r.getActivityStack().getTaskStack(); + return !taskStack.isAnimatingBoundsToFullscreen(); } @Override @@ -3871,7 +3868,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { r.pictureInPictureArgs.getSourceRectHint()); mRootActivityContainer.moveActivityToPinnedStack( r, sourceBounds, aspectRatio, "enterPictureInPictureMode"); - final PinnedActivityStack stack = r.getActivityStack(); + final ActivityStack stack = r.getActivityStack(); stack.setPictureInPictureAspectRatio(aspectRatio); stack.setPictureInPictureActions(actions); MetricsLoggerWrapper.logPictureInPictureEnter(mContext, r.appInfo.uid, @@ -3915,7 +3912,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { // If the activity is already in picture-in-picture, update the pinned stack now // if it is not already expanding to fullscreen. Otherwise, the arguments will // be used the next time the activity enters PiP - final PinnedActivityStack stack = r.getActivityStack(); + final ActivityStack stack = r.getActivityStack(); if (!stack.isAnimatingBoundsToFullscreen()) { stack.setPictureInPictureAspectRatio( r.pictureInPictureArgs.getAspectRatio()); @@ -5831,14 +5828,16 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { } @Override - public int startActivitiesInPackage(int uid, String callingPackage, Intent[] intents, - String[] resolvedTypes, IBinder resultTo, SafeActivityOptions options, int userId, - boolean validateIncomingUser, PendingIntentRecord originatingPendingIntent, + public int startActivitiesInPackage(int uid, int realCallingPid, int realCallingUid, + String callingPackage, Intent[] intents, String[] resolvedTypes, IBinder resultTo, + SafeActivityOptions options, int userId, boolean validateIncomingUser, + PendingIntentRecord originatingPendingIntent, boolean allowBackgroundActivityStart) { synchronized (mGlobalLock) { - return getActivityStartController().startActivitiesInPackage(uid, callingPackage, - intents, resolvedTypes, resultTo, options, userId, validateIncomingUser, - originatingPendingIntent, allowBackgroundActivityStart); + return getActivityStartController().startActivitiesInPackage(uid, realCallingPid, + realCallingUid, callingPackage, intents, resolvedTypes, resultTo, options, + userId, validateIncomingUser, originatingPendingIntent, + allowBackgroundActivityStart); } } diff --git a/services/core/java/com/android/server/wm/AppTransition.java b/services/core/java/com/android/server/wm/AppTransition.java index 089640b32dd3..5f393ef59057 100644 --- a/services/core/java/com/android/server/wm/AppTransition.java +++ b/services/core/java/com/android/server/wm/AppTransition.java @@ -65,6 +65,8 @@ import static com.android.internal.R.styleable.WindowAnimation_wallpaperIntraOpe import static com.android.internal.R.styleable.WindowAnimation_wallpaperIntraOpenExitAnimation; import static com.android.internal.R.styleable.WindowAnimation_wallpaperOpenEnterAnimation; import static com.android.internal.R.styleable.WindowAnimation_wallpaperOpenExitAnimation; +import static com.android.server.wm.AppTransitionProto.APP_TRANSITION_STATE; +import static com.android.server.wm.AppTransitionProto.LAST_USED_APP_TRANSITION; import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ANIM; import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_APP_TRANSITIONS; import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME; @@ -73,8 +75,6 @@ import static com.android.server.wm.WindowManagerInternal.AppTransitionListener; import static com.android.server.wm.WindowStateAnimator.STACK_CLIP_AFTER_ANIM; import static com.android.server.wm.WindowStateAnimator.STACK_CLIP_BEFORE_ANIM; import static com.android.server.wm.WindowStateAnimator.STACK_CLIP_NONE; -import static com.android.server.wm.AppTransitionProto.APP_TRANSITION_STATE; -import static com.android.server.wm.AppTransitionProto.LAST_USED_APP_TRANSITION; import android.annotation.DrawableRes; import android.annotation.NonNull; @@ -84,6 +84,7 @@ import android.content.ComponentName; import android.content.Context; import android.content.res.Configuration; import android.content.res.ResourceId; +import android.content.res.Resources; import android.graphics.Bitmap; import android.graphics.Canvas; import android.graphics.Color; @@ -547,7 +548,7 @@ public class AppTransition implements Dump { } Animation loadAnimationAttr(LayoutParams lp, int animAttr, int transit) { - int resId = ResourceId.ID_NULL; + int resId = Resources.ID_NULL; Context context = mContext; if (animAttr >= 0) { AttributeCache.Entry ent = getCachedAnimations(lp); diff --git a/services/core/java/com/android/server/wm/AppWindowToken.java b/services/core/java/com/android/server/wm/AppWindowToken.java index 801c1e727483..780eda49faf4 100644 --- a/services/core/java/com/android/server/wm/AppWindowToken.java +++ b/services/core/java/com/android/server/wm/AppWindowToken.java @@ -82,6 +82,7 @@ import static com.android.server.wm.WindowManagerService.logWithStack; import static com.android.server.wm.WindowStateAnimator.STACK_CLIP_AFTER_ANIM; import android.annotation.CallSuper; +import android.annotation.Size; import android.app.Activity; import android.app.ActivityManager; import android.content.ComponentName; @@ -113,11 +114,14 @@ import com.android.internal.R; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.util.ToBooleanFunction; import com.android.server.AttributeCache; +import com.android.server.LocalServices; +import com.android.server.display.ColorDisplayService; import com.android.server.policy.WindowManagerPolicy; import com.android.server.policy.WindowManagerPolicy.StartingSurface; import com.android.server.wm.WindowManagerService.H; import java.io.PrintWriter; +import java.lang.ref.WeakReference; import java.util.ArrayDeque; import java.util.ArrayList; import java.util.function.Consumer; @@ -289,6 +293,20 @@ class AppWindowToken extends WindowToken implements WindowManagerService.AppFree private static final int STARTING_WINDOW_TYPE_SNAPSHOT = 1; private static final int STARTING_WINDOW_TYPE_SPLASH_SCREEN = 2; + private AppSaturationInfo mLastAppSaturationInfo; + + private final ColorDisplayService.ColorTransformController mColorTransformController = + (matrix, translation) -> mWmService.mH.post(() -> { + synchronized (mWmService.mGlobalLock) { + if (mLastAppSaturationInfo == null) { + mLastAppSaturationInfo = new AppSaturationInfo(); + } + + mLastAppSaturationInfo.setSaturation(matrix, translation); + updateColorTransform(); + } + }); + AppWindowToken(WindowManagerService service, IApplicationToken token, ComponentName activityComponent, boolean voiceInteraction, DisplayContent dc, long inputDispatchingTimeoutNanos, boolean fullscreen, boolean showForAllUsers, @@ -311,6 +329,11 @@ class AppWindowToken extends WindowToken implements WindowManagerService.AppFree // Application tokens start out hidden. setHidden(true); hiddenRequested = true; + + ColorDisplayService.ColorDisplayServiceInternal cds = LocalServices.getService( + ColorDisplayService.ColorDisplayServiceInternal.class); + cds.attachColorTransformController(activityRecord.packageName, activityRecord.mUserId, + new WeakReference<>(mColorTransformController)); } AppWindowToken(WindowManagerService service, IApplicationToken token, @@ -968,6 +991,8 @@ class AppWindowToken extends WindowToken implements WindowManagerService.AppFree : null; mLastParent = task; + + updateColorTransform(); } void postWindowRemoveStartingWindowCleanup(WindowState win) { @@ -2816,4 +2841,22 @@ class AppWindowToken extends WindowToken implements WindowManagerService.AppFree mDisplayContent.mClosingApps.remove(this); } } + + private void updateColorTransform() { + if (mSurfaceControl != null && mLastAppSaturationInfo != null) { + mPendingTransaction.setColorTransform(mSurfaceControl, mLastAppSaturationInfo.mMatrix, + mLastAppSaturationInfo.mTranslation); + mWmService.scheduleAnimationLocked(); + } + } + + private static class AppSaturationInfo { + float[] mMatrix = new float[9]; + float[] mTranslation = new float[3]; + + void setSaturation(@Size(9) float[] matrix, @Size(3) float[] translation) { + System.arraycopy(matrix, 0, mMatrix, 0, mMatrix.length); + System.arraycopy(translation, 0, mTranslation, 0, mTranslation.length); + } + } } diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java index 45bb94b1f43b..6527ca0e751d 100644 --- a/services/core/java/com/android/server/wm/DisplayContent.java +++ b/services/core/java/com/android/server/wm/DisplayContent.java @@ -328,14 +328,6 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo private int mLastOrientation = SCREEN_ORIENTATION_UNSPECIFIED; /** - * Flag indicating that the application is receiving an orientation that has different metrics - * than it expected. E.g. Portrait instead of Landscape. - * - * @see #updateRotationUnchecked() - */ - private boolean mAltOrientation = false; - - /** * Orientation forced by some window. If there is no visible window that specifies orientation * it is set to {@link android.content.pm.ActivityInfo#SCREEN_ORIENTATION_UNSPECIFIED}. * @@ -1085,10 +1077,6 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo return mLastOrientation; } - boolean getAltOrientation() { - return mAltOrientation; - } - int getLastWindowForcedOrientation() { return mLastWindowForcedOrientation; } @@ -1130,15 +1118,9 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo boolean rotationNeedsUpdate() { final int lastOrientation = getLastOrientation(); final int oldRotation = getRotation(); - final boolean oldAltOrientation = getAltOrientation(); final int rotation = mDisplayRotation.rotationForOrientation(lastOrientation, oldRotation); - final boolean altOrientation = !mDisplayRotation.rotationHasCompatibleMetrics( - lastOrientation, rotation); - if (oldRotation == rotation && oldAltOrientation == altOrientation) { - return false; - } - return true; + return oldRotation != rotation; } /** @@ -1336,7 +1318,6 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo final int oldRotation = mRotation; final int lastOrientation = mLastOrientation; - final boolean oldAltOrientation = mAltOrientation; final int rotation = mDisplayRotation.rotationForOrientation(lastOrientation, oldRotation); if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "Computed rotation=" + rotation + " for display id=" + mDisplayId + " based on lastOrientation=" + lastOrientation @@ -1368,35 +1349,26 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo } final boolean rotateSeamlessly = mayRotateSeamlessly; - // TODO: Implement forced rotation changes. - // Set mAltOrientation to indicate that the application is receiving - // an orientation that has different metrics than it expected. - // eg. Portrait instead of Landscape. - - final boolean altOrientation = !mDisplayRotation.rotationHasCompatibleMetrics( - lastOrientation, rotation); - if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "Display id=" + mDisplayId + " selected orientation " + lastOrientation + ", got rotation " + rotation + " which has " - + (altOrientation ? "incompatible" : "compatible") + " metrics"); + + " metrics"); - if (oldRotation == rotation && oldAltOrientation == altOrientation) { + if (oldRotation == rotation) { // No change. return false; } if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "Display id=" + mDisplayId + " rotation changed to " + rotation - + (altOrientation ? " (alt)" : "") + " from " + oldRotation - + (oldAltOrientation ? " (alt)" : "") + ", lastOrientation=" + lastOrientation); + + " from " + oldRotation + + ", lastOrientation=" + lastOrientation); if (DisplayContent.deltaRotation(rotation, oldRotation) != 2) { mWaitingForConfig = true; } mRotation = rotation; - mAltOrientation = altOrientation; mWmService.mWindowsFreezingScreen = WINDOWS_FREEZING_SCREENS_ACTIVE; mWmService.mH.sendNewMessageDelayed(WindowManagerService.H.WINDOW_FREEZE_TIMEOUT, @@ -1538,26 +1510,8 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo private DisplayInfo updateDisplayAndOrientation(int uiMode) { // Use the effective "visual" dimensions based on current rotation final boolean rotated = (mRotation == ROTATION_90 || mRotation == ROTATION_270); - final int realdw = rotated ? mBaseDisplayHeight : mBaseDisplayWidth; - final int realdh = rotated ? mBaseDisplayWidth : mBaseDisplayHeight; - int dw = realdw; - int dh = realdh; - - if (mAltOrientation) { - if (realdw > realdh) { - // Turn landscape into portrait. - int maxw = (int)(realdh/1.3f); - if (maxw < realdw) { - dw = maxw; - } - } else { - // Turn portrait into landscape. - int maxh = (int)(realdw/1.3f); - if (maxh < realdh) { - dh = maxh; - } - } - } + final int dw = rotated ? mBaseDisplayHeight : mBaseDisplayWidth; + final int dh = rotated ? mBaseDisplayWidth : mBaseDisplayHeight; // Update application display metrics. final WmDisplayCutout wmDisplayCutout = calculateDisplayCutoutForRotation(mRotation); @@ -2309,13 +2263,12 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo out.set(mDisplayFrames.mStable); } - TaskStack createStack(int stackId, boolean onTop, StackWindowController controller) { - if (DEBUG_STACK) Slog.d(TAG_WM, "Create new stackId=" + stackId + " on displayId=" - + mDisplayId); + void setStackOnDisplay(int stackId, boolean onTop, TaskStack stack) { + if (DEBUG_STACK) { + Slog.d(TAG_WM, "Create new stackId=" + stackId + " on displayId=" + mDisplayId); + } - final TaskStack stack = new TaskStack(mWmService, stackId, controller); mTaskStackContainers.addStackToDisplay(stack, onTop); - return stack; } void moveStackToDisplay(TaskStack stack, boolean onTop) { @@ -4017,7 +3970,6 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo /** * Adds the stack to this container. - * @see DisplayContent#createStack(int, boolean, StackWindowController) */ void addStackToDisplay(TaskStack stack, boolean onTop) { addStackReferenceIfNeeded(stack); diff --git a/services/core/java/com/android/server/wm/DisplayRotation.java b/services/core/java/com/android/server/wm/DisplayRotation.java index 7aabc15d9860..bc165dceb544 100644 --- a/services/core/java/com/android/server/wm/DisplayRotation.java +++ b/services/core/java/com/android/server/wm/DisplayRotation.java @@ -676,36 +676,6 @@ public class DisplayRotation { return rotation == mPortraitRotation || rotation == mUpsideDownRotation; } - /** - * Given an orientation constant and a rotation, returns true if the rotation - * has compatible metrics to the requested orientation. For example, if - * the application requested landscape and got seascape, then the rotation - * has compatible metrics; if the application requested portrait and got landscape, - * then the rotation has incompatible metrics; if the application did not specify - * a preference, then anything goes. - * - * @param orientation An orientation constant, such as - * {@link android.content.pm.ActivityInfo#SCREEN_ORIENTATION_LANDSCAPE}. - * @param rotation The rotation to check. - * @return True if the rotation is compatible with the requested orientation. - */ - boolean rotationHasCompatibleMetrics(int orientation, int rotation) { - switch (orientation) { - case ActivityInfo.SCREEN_ORIENTATION_PORTRAIT: - case ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT: - case ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT: - return isAnyPortrait(rotation); - - case ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE: - case ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE: - case ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE: - return isLandscapeOrSeascape(rotation); - - default: - return true; - } - } - private boolean isValidRotationChoice(final int preferredRotation) { // Determine if the given app orientation is compatible with the provided rotation choice. switch (mCurrentAppOrientation) { diff --git a/services/core/java/com/android/server/wm/LaunchParamsPersister.java b/services/core/java/com/android/server/wm/LaunchParamsPersister.java index 3062d34780b6..86dc66dbca3b 100644 --- a/services/core/java/com/android/server/wm/LaunchParamsPersister.java +++ b/services/core/java/com/android/server/wm/LaunchParamsPersister.java @@ -221,7 +221,7 @@ class LaunchParamsPersister { } private boolean saveTaskToLaunchParam(TaskRecord task, PersistableLaunchParams params) { - final ActivityStack<?> stack = task.getStack(); + final ActivityStack stack = task.getStack(); final int displayId = stack.mDisplayId; final ActivityDisplay display = mSupervisor.mRootActivityContainer.getActivityDisplay(displayId); diff --git a/services/core/java/com/android/server/wm/PinnedActivityStack.java b/services/core/java/com/android/server/wm/PinnedActivityStack.java deleted file mode 100644 index 2a05af4f473c..000000000000 --- a/services/core/java/com/android/server/wm/PinnedActivityStack.java +++ /dev/null @@ -1,111 +0,0 @@ -/* - * Copyright (C) 2017 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.server.wm; - -import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD; -import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED; - -import android.app.RemoteAction; -import android.content.res.Configuration; -import android.graphics.Rect; - -import java.util.ArrayList; -import java.util.List; - -/** - * State and management of the pinned stack of activities. - */ -class PinnedActivityStack extends ActivityStack<PinnedStackWindowController> - implements PinnedStackWindowListener { - - PinnedActivityStack(ActivityDisplay display, int stackId, ActivityStackSupervisor supervisor, - boolean onTop) { - super(display, stackId, supervisor, WINDOWING_MODE_PINNED, ACTIVITY_TYPE_STANDARD, onTop); - } - - @Override - PinnedStackWindowController createStackWindowController(int displayId, boolean onTop, - Rect outBounds) { - return new PinnedStackWindowController(mStackId, this, displayId, onTop, outBounds, - mRootActivityContainer.mWindowManager); - } - - Rect getDefaultPictureInPictureBounds(float aspectRatio) { - return getWindowContainerController().getPictureInPictureBounds(aspectRatio, - null /* currentStackBounds */); - } - - void animateResizePinnedStack(Rect sourceHintBounds, Rect toBounds, int animationDuration, - boolean fromFullscreen) { - if (skipResizeAnimation(toBounds == null /* toFullscreen */)) { - mService.moveTasksToFullscreenStack(mStackId, true /* onTop */); - } else { - getWindowContainerController().animateResizePinnedStack(toBounds, sourceHintBounds, - animationDuration, fromFullscreen); - } - } - - private boolean skipResizeAnimation(boolean toFullscreen) { - if (!toFullscreen) { - return false; - } - final Configuration parentConfig = getParent().getConfiguration(); - final ActivityRecord top = topRunningNonOverlayTaskActivity(); - return top != null && !top.isConfigurationCompatible(parentConfig); - } - - void setPictureInPictureAspectRatio(float aspectRatio) { - getWindowContainerController().setPictureInPictureAspectRatio(aspectRatio); - } - - void setPictureInPictureActions(List<RemoteAction> actions) { - getWindowContainerController().setPictureInPictureActions(actions); - } - - boolean isAnimatingBoundsToFullscreen() { - return getWindowContainerController().mContainer.isAnimatingBoundsToFullscreen(); - } - - /** - * Returns whether to defer the scheduling of the multi-window mode. - */ - boolean deferScheduleMultiWindowModeChanged() { - // For the pinned stack, the deferring of the multi-window mode changed is tied to the - // transition animation into picture-in-picture, and is called once the animation completes, - // or is interrupted in a way that would leave the stack in a non-fullscreen state. - // @see BoundsAnimationController - // @see BoundsAnimationControllerTests - return mWindowContainerController.deferScheduleMultiWindowModeChanged(); - } - - public void updatePictureInPictureModeForPinnedStackAnimation(Rect targetStackBounds, - boolean forceUpdate) { - // It is guaranteed that the activities requiring the update will be in the pinned stack at - // this point (either reparented before the animation into PiP, or before reparenting after - // the animation out of PiP) - synchronized (mService.mGlobalLock) { - if (!isAttached()) { - return; - } - ArrayList<TaskRecord> tasks = getAllTasks(); - for (int i = 0; i < tasks.size(); i++ ) { - mStackSupervisor.updatePictureInPictureMode(tasks.get(i), targetStackBounds, - forceUpdate); - } - } - } -} diff --git a/services/core/java/com/android/server/wm/PinnedStackWindowController.java b/services/core/java/com/android/server/wm/PinnedStackWindowController.java deleted file mode 100644 index 518e39ba9d58..000000000000 --- a/services/core/java/com/android/server/wm/PinnedStackWindowController.java +++ /dev/null @@ -1,205 +0,0 @@ -/* - * Copyright (C) 2017 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License - */ - -package com.android.server.wm; - -import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD; -import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN; - -import static com.android.server.wm.BoundsAnimationController.NO_PIP_MODE_CHANGED_CALLBACKS; -import static com.android.server.wm.BoundsAnimationController.SCHEDULE_PIP_MODE_CHANGED_ON_END; -import static com.android.server.wm.BoundsAnimationController.SCHEDULE_PIP_MODE_CHANGED_ON_START; -import static com.android.server.wm.BoundsAnimationController.SchedulePipModeChangedState; - -import android.app.RemoteAction; -import android.graphics.Rect; - -import java.util.List; - -/** - * Controller for the pinned stack container. See {@link StackWindowController}. - */ -public class PinnedStackWindowController extends StackWindowController { - - private Rect mTmpFromBounds = new Rect(); - private Rect mTmpToBounds = new Rect(); - - public PinnedStackWindowController(int stackId, PinnedStackWindowListener listener, - int displayId, boolean onTop, Rect outBounds, WindowManagerService service) { - super(stackId, listener, displayId, onTop, outBounds, service); - } - - /** - * @return the {@param currentStackBounds} transformed to the give {@param aspectRatio}. If - * {@param currentStackBounds} is null, then the {@param aspectRatio} is applied to the - * default bounds. - */ - public Rect getPictureInPictureBounds(float aspectRatio, Rect stackBounds) { - synchronized (mGlobalLock) { - if (!mService.mSupportsPictureInPicture || mContainer == null) { - return null; - } - - final DisplayContent displayContent = mContainer.getDisplayContent(); - if (displayContent == null) { - return null; - } - - final PinnedStackController pinnedStackController = - displayContent.getPinnedStackController(); - if (stackBounds == null) { - // Calculate the aspect ratio bounds from the default bounds - stackBounds = pinnedStackController.getDefaultOrLastSavedBounds(); - } - - if (pinnedStackController.isValidPictureInPictureAspectRatio(aspectRatio)) { - return pinnedStackController.transformBoundsToAspectRatio(stackBounds, aspectRatio, - true /* useCurrentMinEdgeSize */); - } else { - return stackBounds; - } - } - } - - /** - * Animates the pinned stack. - */ - public void animateResizePinnedStack(Rect toBounds, Rect sourceHintBounds, - int animationDuration, boolean fromFullscreen) { - synchronized (mGlobalLock) { - if (mContainer == null) { - throw new IllegalArgumentException("Pinned stack container not found :("); - } - - // Get the from-bounds - final Rect fromBounds = new Rect(); - mContainer.getBounds(fromBounds); - - // Get non-null fullscreen to-bounds for animating if the bounds are null - @SchedulePipModeChangedState int schedulePipModeChangedState = - NO_PIP_MODE_CHANGED_CALLBACKS; - final boolean toFullscreen = toBounds == null; - if (toFullscreen) { - if (fromFullscreen) { - throw new IllegalArgumentException("Should not defer scheduling PiP mode" - + " change on animation to fullscreen."); - } - schedulePipModeChangedState = SCHEDULE_PIP_MODE_CHANGED_ON_START; - - mService.getStackBounds( - WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, mTmpToBounds); - if (!mTmpToBounds.isEmpty()) { - // If there is a fullscreen bounds, use that - toBounds = new Rect(mTmpToBounds); - } else { - // Otherwise, use the display bounds - toBounds = new Rect(); - mContainer.getDisplayContent().getBounds(toBounds); - } - } else if (fromFullscreen) { - schedulePipModeChangedState = SCHEDULE_PIP_MODE_CHANGED_ON_END; - } - - mContainer.setAnimationFinalBounds(sourceHintBounds, toBounds, toFullscreen); - - final Rect finalToBounds = toBounds; - final @SchedulePipModeChangedState int finalSchedulePipModeChangedState = - schedulePipModeChangedState; - final DisplayContent displayContent = mContainer.getDisplayContent(); - displayContent.mBoundsAnimationController.getHandler().post(() -> { - if (mContainer == null) { - return; - } - displayContent.mBoundsAnimationController.animateBounds(mContainer, fromBounds, - finalToBounds, animationDuration, finalSchedulePipModeChangedState, - fromFullscreen, toFullscreen); - }); - } - } - - /** - * Sets the current picture-in-picture aspect ratio. - */ - public void setPictureInPictureAspectRatio(float aspectRatio) { - synchronized (mGlobalLock) { - if (!mService.mSupportsPictureInPicture || mContainer == null) { - return; - } - - final PinnedStackController pinnedStackController = - mContainer.getDisplayContent().getPinnedStackController(); - - if (Float.compare(aspectRatio, pinnedStackController.getAspectRatio()) != 0) { - mContainer.getAnimationOrCurrentBounds(mTmpFromBounds); - mTmpToBounds.set(mTmpFromBounds); - getPictureInPictureBounds(aspectRatio, mTmpToBounds); - if (!mTmpToBounds.equals(mTmpFromBounds)) { - animateResizePinnedStack(mTmpToBounds, null /* sourceHintBounds */, - -1 /* duration */, false /* fromFullscreen */); - } - pinnedStackController.setAspectRatio( - pinnedStackController.isValidPictureInPictureAspectRatio(aspectRatio) - ? aspectRatio : -1f); - } - } - } - - /** - * Sets the current picture-in-picture actions. - */ - public void setPictureInPictureActions(List<RemoteAction> actions) { - synchronized (mGlobalLock) { - if (!mService.mSupportsPictureInPicture || mContainer == null) { - return; - } - - mContainer.getDisplayContent().getPinnedStackController().setActions(actions); - } - } - - /** - * @return whether the multi-window mode change should be deferred as a part of a transition - * from fullscreen to non-fullscreen bounds. - */ - public boolean deferScheduleMultiWindowModeChanged() { - synchronized (mGlobalLock) { - return mContainer.deferScheduleMultiWindowModeChanged(); - } - } - - /** - * @return whether the stack can be resized from the bounds animation. - */ - public boolean pinnedStackResizeDisallowed() { - synchronized (mGlobalLock) { - return mContainer.pinnedStackResizeDisallowed(); - } - } - - /** - * The following calls are made from WM to AM. - */ - - /** Calls directly into activity manager so window manager lock shouldn't held. */ - public void updatePictureInPictureModeForPinnedStackAnimation(Rect targetStackBounds, - boolean forceUpdate) { - if (mListener != null) { - PinnedStackWindowListener listener = (PinnedStackWindowListener) mListener; - listener.updatePictureInPictureModeForPinnedStackAnimation(targetStackBounds, - forceUpdate); - } - } -} diff --git a/services/core/java/com/android/server/wm/PinnedStackWindowListener.java b/services/core/java/com/android/server/wm/PinnedStackWindowListener.java deleted file mode 100644 index 33e8a60329bf..000000000000 --- a/services/core/java/com/android/server/wm/PinnedStackWindowListener.java +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright (C) 2017 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License - */ - -package com.android.server.wm; - -import android.graphics.Rect; - -/** - * Interface used by the creator of {@link PinnedStackWindowController} to listen to changes with - * the stack container. - */ -public interface PinnedStackWindowListener extends StackWindowListener { - - /** - * Called when the stack container pinned stack animation will change the picture-in-picture - * mode. This is a direct call into ActivityManager. - */ - default void updatePictureInPictureModeForPinnedStackAnimation(Rect targetStackBounds, - boolean forceUpdate) {} -} diff --git a/services/core/java/com/android/server/wm/RootActivityContainer.java b/services/core/java/com/android/server/wm/RootActivityContainer.java index f55c7c96e325..c4a853dc3483 100644 --- a/services/core/java/com/android/server/wm/RootActivityContainer.java +++ b/services/core/java/com/android/server/wm/RootActivityContainer.java @@ -234,7 +234,7 @@ class RootActivityContainer extends ConfigurationContainer mWindowManager = wm; setWindowContainer(mWindowManager.mRoot); mDisplayManager = mService.mContext.getSystemService(DisplayManager.class); - mDisplayManager.registerDisplayListener(this, mService.mH); + mDisplayManager.registerDisplayListener(this, mService.mUiHandler); mDisplayManagerInternal = LocalServices.getService(DisplayManagerInternal.class); final Display[] displays = mDisplayManager.getDisplays(); @@ -955,7 +955,7 @@ class RootActivityContainer extends ConfigurationContainer mWindowManager.deferSurfaceLayout(); final ActivityDisplay display = r.getActivityStack().getDisplay(); - PinnedActivityStack stack = display.getPinnedStack(); + ActivityStack stack = display.getPinnedStack(); // This will clear the pinned stack by moving an existing task to the full screen stack, // ensuring only one task is present. @@ -1108,28 +1108,41 @@ class RootActivityContainer extends ConfigurationContainer return false; } + boolean result = false; if (targetStack != null && (targetStack.isTopStackOnDisplay() || getTopDisplayFocusedStack() == targetStack)) { - return targetStack.resumeTopActivityUncheckedLocked(target, targetOptions); + result = targetStack.resumeTopActivityUncheckedLocked(target, targetOptions); } - // Resume all top activities in focused stacks on all displays. for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) { + boolean resumedOnDisplay = false; final ActivityDisplay display = mActivityDisplays.get(displayNdx); - final ActivityStack focusedStack = display.getFocusedStack(); - if (focusedStack == null) { - continue; + for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) { + final ActivityStack stack = display.getChildAt(stackNdx); + final ActivityRecord topRunningActivity = stack.topRunningActivityLocked(); + if (!stack.isFocusableAndVisible() || topRunningActivity == null) { + continue; + } + if (topRunningActivity.isState(RESUMED)) { + // Kick off any lingering app transitions form the MoveTaskToFront operation. + stack.executeAppTransition(targetOptions); + } else { + resumedOnDisplay |= topRunningActivity.makeActiveIfNeeded(target); + } } - final ActivityRecord r = focusedStack.topRunningActivityLocked(); - if (r == null || !r.isState(RESUMED)) { - focusedStack.resumeTopActivityUncheckedLocked(null, null); - } else if (r.isState(RESUMED)) { - // Kick off any lingering app transitions form the MoveTaskToFront operation. - focusedStack.executeAppTransition(targetOptions); + if (!resumedOnDisplay) { + // In cases when there are no valid activities (e.g. device just booted or launcher + // crashed) it's possible that nothing was resumed on a display. Requesting resume + // of top activity in focused stack explicitly will make sure that at least home + // activity is started and resumed, and no recursion occurs. + final ActivityStack focusedStack = display.getFocusedStack(); + if (focusedStack != null) { + focusedStack.resumeTopActivityUncheckedLocked(target, targetOptions); + } } } - return false; + return result; } void applySleepTokens(boolean applyToStacks) { diff --git a/services/core/java/com/android/server/wm/Session.java b/services/core/java/com/android/server/wm/Session.java index 937c9d9fc809..58cf73a9a2bd 100644 --- a/services/core/java/com/android/server/wm/Session.java +++ b/services/core/java/com/android/server/wm/Session.java @@ -47,10 +47,9 @@ import android.view.IWindowId; import android.view.IWindowSession; import android.view.IWindowSessionCallback; import android.view.InputChannel; -import android.view.Surface; +import android.view.InsetsState; import android.view.SurfaceControl; import android.view.SurfaceSession; -import android.view.InsetsState; import android.view.WindowManager; import com.android.internal.os.logging.MetricsLoggerWrapper; @@ -432,7 +431,7 @@ class Session extends IWindowSession.Stub implements IBinder.DeathRecipient { @Override public void insetsModified(IWindow window, InsetsState state) { - synchronized (mService.mWindowMap) { + synchronized (mService.mGlobalLock) { final WindowState windowState = mService.windowForClientLocked(this, window, false /* throwOnError */); if (windowState != null) { diff --git a/services/core/java/com/android/server/wm/StackWindowController.java b/services/core/java/com/android/server/wm/StackWindowController.java deleted file mode 100644 index ada807b1ff3c..000000000000 --- a/services/core/java/com/android/server/wm/StackWindowController.java +++ /dev/null @@ -1,245 +0,0 @@ -/* - * Copyright (C) 2016 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License - */ - -package com.android.server.wm; - -import static com.android.server.wm.WindowContainer.POSITION_BOTTOM; -import static com.android.server.wm.WindowContainer.POSITION_TOP; -import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_STACK; -import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM; - -import android.content.res.Configuration; -import android.graphics.Rect; -import android.os.Handler; -import android.os.Looper; -import android.os.Message; -import android.util.Slog; -import android.util.SparseArray; - -import com.android.internal.annotations.VisibleForTesting; - -import java.lang.ref.WeakReference; - -/** - * Controller for the stack container. This is created by activity manager to link activity stacks - * to the stack container they use in window manager. - * - * Test class: {@link StackWindowControllerTests} - */ -public class StackWindowController - extends WindowContainerController<TaskStack, StackWindowListener> { - - private final int mStackId; - - private final H mHandler; - - final Rect mTmpBounds = new Rect(); - - public StackWindowController(int stackId, StackWindowListener listener, int displayId, - boolean onTop, Rect outBounds) { - this(stackId, listener, displayId, onTop, outBounds, WindowManagerService.getInstance()); - } - - @VisibleForTesting - public StackWindowController(int stackId, StackWindowListener listener, - int displayId, boolean onTop, Rect outBounds, WindowManagerService service) { - super(listener, service); - mStackId = stackId; - mHandler = new H(new WeakReference<>(this), service.mH.getLooper()); - - final DisplayContent dc = mRoot.getDisplayContent(displayId); - if (dc == null) { - throw new IllegalArgumentException("Trying to add stackId=" + stackId - + " to unknown displayId=" + displayId); - } - - dc.createStack(stackId, onTop, this); - getRawBounds(outBounds); - } - - @Override - public void removeContainer() { - if (mContainer != null) { - mContainer.removeIfPossible(); - super.removeContainer(); - } - } - - void reparent(int displayId, Rect outStackBounds, boolean onTop) { - if (mContainer == null) { - throw new IllegalArgumentException("Trying to move unknown stackId=" + mStackId - + " to displayId=" + displayId); - } - - final DisplayContent targetDc = mRoot.getDisplayContent(displayId); - if (targetDc == null) { - throw new IllegalArgumentException("Trying to move stackId=" + mStackId - + " to unknown displayId=" + displayId); - } - - targetDc.moveStackToDisplay(mContainer, onTop); - getRawBounds(outStackBounds); - } - - void positionChildAt(Task child, int position) { - if (DEBUG_STACK) { - Slog.i(TAG_WM, "positionChildAt: positioning task=" + child + " at " + position); - } - if (child == null) { - if (DEBUG_STACK) { - Slog.i(TAG_WM, "positionChildAt: could not find task=" + this); - } - return; - } - if (mContainer == null) { - if (DEBUG_STACK) { - Slog.i(TAG_WM, "positionChildAt: could not find stack for task=" + mContainer); - } - return; - } - child.positionAt(position); - mContainer.getDisplayContent().layoutAndAssignWindowLayersIfNeeded(); - } - - void positionChildAtTop(Task child, boolean includingParents) { - if (child == null) { - // TODO: Fix the call-points that cause this to happen. - return; - } - - mContainer.positionChildAt(POSITION_TOP, child, includingParents); - - final DisplayContent displayContent = mContainer.getDisplayContent(); - if (displayContent.mAppTransition.isTransitionSet()) { - child.setSendingToBottom(false); - } - displayContent.layoutAndAssignWindowLayersIfNeeded(); - } - - void positionChildAtBottom(Task child, boolean includingParents) { - if (child == null) { - // TODO: Fix the call-points that cause this to happen. - return; - } - - mContainer.positionChildAt(POSITION_BOTTOM, child, includingParents); - - if (mContainer.getDisplayContent().mAppTransition.isTransitionSet()) { - child.setSendingToBottom(true); - } - mContainer.getDisplayContent().layoutAndAssignWindowLayersIfNeeded(); - } - - /** - * Re-sizes a stack and its containing tasks. - * - * @param bounds New stack bounds. Passing in null sets the bounds to fullscreen. - * @param taskBounds Bounds for tasks in the resized stack, keyed by task id. - * @param taskTempInsetBounds Inset bounds for individual tasks, keyed by task id. - */ - public void resize(Rect bounds, SparseArray<Rect> taskBounds, - SparseArray<Rect> taskTempInsetBounds) { - if (mContainer == null) { - throw new IllegalArgumentException("resizeStack: stack " + this + " not found."); - } - // We might trigger a configuration change. Save the current task bounds for freezing. - mContainer.prepareFreezingTaskBounds(); - if (mContainer.setBounds(bounds, taskBounds, taskTempInsetBounds) - && mContainer.isVisible()) { - mContainer.getDisplayContent().setLayoutNeeded(); - mService.mWindowPlacerLocked.performSurfacePlacement(); - } - } - - public void onPipAnimationEndResize() { - mContainer.onPipAnimationEndResize(); - } - - /** - * @see TaskStack.getStackDockedModeBoundsLocked(ConfigurationContainer, Rect, Rect, Rect) - */ - public void getStackDockedModeBounds(Configuration parentConfig, Rect dockedBounds, - Rect currentTempTaskBounds, - Rect outStackBounds, Rect outTempTaskBounds) { - if (mContainer != null) { - mContainer.getStackDockedModeBoundsLocked(parentConfig, dockedBounds, - currentTempTaskBounds, outStackBounds, outTempTaskBounds); - return; - } - outStackBounds.setEmpty(); - outTempTaskBounds.setEmpty(); - } - - public void prepareFreezingTaskBounds() { - if (mContainer == null) { - throw new IllegalArgumentException("prepareFreezingTaskBounds: stack " + this - + " not found."); - } - mContainer.prepareFreezingTaskBounds(); - } - - public void getRawBounds(Rect outBounds) { - if (mContainer.matchParentBounds()) { - outBounds.setEmpty(); - } else { - mContainer.getRawBounds(outBounds); - } - } - - public void getBounds(Rect outBounds) { - if (mContainer != null) { - mContainer.getBounds(outBounds); - return; - } - outBounds.setEmpty(); - } - - void requestResize(Rect bounds) { - mHandler.obtainMessage(H.REQUEST_RESIZE, bounds).sendToTarget(); - } - - @Override - public String toString() { - return "{StackWindowController stackId=" + mStackId + "}"; - } - - private static final class H extends Handler { - - static final int REQUEST_RESIZE = 0; - - private final WeakReference<StackWindowController> mController; - - H(WeakReference<StackWindowController> controller, Looper looper) { - super(looper); - mController = controller; - } - - @Override - public void handleMessage(Message msg) { - final StackWindowController controller = mController.get(); - final StackWindowListener listener = (controller != null) - ? controller.mListener : null; - if (listener == null) { - return; - } - switch (msg.what) { - case REQUEST_RESIZE: - listener.requestResize((Rect) msg.obj); - break; - } - } - } -} diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java index d334bd298ada..a7dd55b8a160 100644 --- a/services/core/java/com/android/server/wm/Task.java +++ b/services/core/java/com/android/server/wm/Task.java @@ -209,26 +209,14 @@ class Task extends WindowContainer<AppWindowToken> implements ConfigurationConta super.removeImmediately(); } - void reparent(StackWindowController stackController, int position, boolean moveParents) { - if (DEBUG_STACK) { - Slog.i(TAG_WM, "reparent: moving taskId=" + mTaskId - + " to stack=" + stackController + " at " + position); - } - final TaskStack stack = stackController.mContainer; - if (stack == null) { - throw new IllegalArgumentException("reparent: could not find stack=" - + stackController); - } - reparent(stack, position, moveParents); - getDisplayContent().layoutAndAssignWindowLayersIfNeeded(); - } - - void reparent(TaskStack stack, int position, boolean moveParents) { if (stack == mStack) { throw new IllegalArgumentException( "task=" + this + " already child of stack=" + mStack); } + if (stack == null) { + throw new IllegalArgumentException("reparent: could not find stack."); + } if (DEBUG_STACK) Slog.i(TAG, "reParentTask: removing taskId=" + mTaskId + " from stack=" + mStack); EventLog.writeEvent(WM_TASK_REMOVED, mTaskId, "reParentTask"); @@ -254,6 +242,7 @@ class Task extends WindowContainer<AppWindowToken> implements ConfigurationConta onDisplayChanged(displayContent); prevDisplayContent.setLayoutNeeded(); } + getDisplayContent().layoutAndAssignWindowLayersIfNeeded(); } /** @see ActivityTaskManagerService#positionTaskInStack(int, int, int). */ diff --git a/services/core/java/com/android/server/wm/TaskLaunchParamsModifier.java b/services/core/java/com/android/server/wm/TaskLaunchParamsModifier.java index 6acd8641271c..f3050a903c70 100644 --- a/services/core/java/com/android/server/wm/TaskLaunchParamsModifier.java +++ b/services/core/java/com/android/server/wm/TaskLaunchParamsModifier.java @@ -709,7 +709,7 @@ class TaskLaunchParamsModifier implements LaunchParamsModifier { final List<TaskRecord> tasksToCheck = new ArrayList<>(); for (int i = 0; i < display.getChildCount(); ++i) { - ActivityStack<?> stack = display.getChildAt(i); + final ActivityStack stack = display.getChildAt(i); if (!stack.inFreeformWindowingMode()) { continue; } diff --git a/services/core/java/com/android/server/wm/TaskRecord.java b/services/core/java/com/android/server/wm/TaskRecord.java index e9448588a03c..0529ed128130 100644 --- a/services/core/java/com/android/server/wm/TaskRecord.java +++ b/services/core/java/com/android/server/wm/TaskRecord.java @@ -455,17 +455,10 @@ class TaskRecord extends ConfigurationContainer { } final Rect bounds = updateOverrideConfigurationFromLaunchBounds(); - final StackWindowController stackController = getStack().getWindowContainerController(); + final TaskStack stack = getStack().getTaskStack(); - if (DEBUG_STACK) { - Slog.i(TAG_WM, "TaskRecord: taskId=" + taskId - + " stack=" + stackController + " bounds=" + bounds); - } - - final TaskStack stack = stackController.mContainer; if (stack == null) { - throw new IllegalArgumentException("TaskRecord: invalid stack=" - + stackController); + throw new IllegalArgumentException("TaskRecord: invalid stack=" + mStack); } EventLog.writeEvent(WM_TASK_CREATED, taskId, stack.mStackId); mTask = new Task(taskId, stack, userId, mService.mWindowManager, mResizeMode, @@ -705,6 +698,14 @@ class TaskRecord extends ConfigurationContainer { return false; } + final boolean toTopOfStack = position == MAX_VALUE; + if (toTopOfStack && toStack.getResumedActivity() != null + && toStack.topRunningActivityLocked() != null) { + // Pause the resumed activity on the target stack while re-parenting task on top of it. + toStack.startPausingLocked(false /* userLeaving */, false /* uiSleeping */, + null /* resuming */, false /* pauseImmediately */); + } + final int toStackWindowingMode = toStack.getWindowingMode(); final ActivityRecord topActivity = getTopActivity(); @@ -742,7 +743,7 @@ class TaskRecord extends ConfigurationContainer { // Must reparent first in window manager to avoid a situation where AM can delete the // we are coming from in WM before we reparent because it became empty. - mTask.reparent(toStack.getWindowContainerController(), position, + mTask.reparent(toStack.getTaskStack(), position, moveStackMode == REPARENT_MOVE_STACK_TO_FRONT); final boolean moveStackToFront = moveStackMode == REPARENT_MOVE_STACK_TO_FRONT diff --git a/services/core/java/com/android/server/wm/TaskStack.java b/services/core/java/com/android/server/wm/TaskStack.java index ee74bdfaa113..8ed7d04f026d 100644 --- a/services/core/java/com/android/server/wm/TaskStack.java +++ b/services/core/java/com/android/server/wm/TaskStack.java @@ -21,6 +21,7 @@ import static android.app.ActivityTaskManager.SPLIT_SCREEN_CREATE_MODE_TOP_OR_LE import static android.app.WindowConfiguration.ACTIVITY_TYPE_ASSISTANT; import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME; import static android.app.WindowConfiguration.ACTIVITY_TYPE_RECENTS; +import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD; import static android.app.WindowConfiguration.PINNED_WINDOWING_MODE_ELEVATION_IN_DIP; import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN; import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY; @@ -33,6 +34,10 @@ import static android.view.WindowManager.DOCKED_LEFT; import static android.view.WindowManager.DOCKED_RIGHT; import static android.view.WindowManager.DOCKED_TOP; +import static com.android.server.wm.BoundsAnimationController.NO_PIP_MODE_CHANGED_CALLBACKS; +import static com.android.server.wm.BoundsAnimationController.SCHEDULE_PIP_MODE_CHANGED_ON_END; +import static com.android.server.wm.BoundsAnimationController.SCHEDULE_PIP_MODE_CHANGED_ON_START; +import static com.android.server.wm.BoundsAnimationController.SchedulePipModeChangedState; import static com.android.server.wm.DragResizeMode.DRAG_RESIZE_MODE_DOCKED_DIVIDER; import static com.android.server.wm.StackProto.ADJUSTED_BOUNDS; import static com.android.server.wm.StackProto.ADJUSTED_FOR_IME; @@ -47,10 +52,12 @@ import static com.android.server.wm.StackProto.ID; import static com.android.server.wm.StackProto.MINIMIZE_AMOUNT; import static com.android.server.wm.StackProto.TASKS; import static com.android.server.wm.StackProto.WINDOW_CONTAINER; +import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_STACK; import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_TASK_MOVEMENT; import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM; import android.annotation.CallSuper; +import android.app.RemoteAction; import android.content.res.Configuration; import android.graphics.Point; import android.graphics.Rect; @@ -71,9 +78,10 @@ import com.android.internal.policy.DockedDividerUtils; import com.android.server.EventLogTags; import java.io.PrintWriter; +import java.util.List; public class TaskStack extends WindowContainer<Task> implements - BoundsAnimationTarget { + BoundsAnimationTarget, ConfigurationContainerListener { /** Minimum size of an adjusted stack bounds relative to original stack bounds. Used to * restrict IME adjustment so that a min portion of top stack remains visible.*/ private static final float ADJUSTED_STACK_FRACTION_MIN = 0.3f; @@ -93,6 +101,10 @@ public class TaskStack extends WindowContainer<Task> implements private Rect mTmpRect2 = new Rect(); private Rect mTmpRect3 = new Rect(); + /** For Pinned stack controlling. */ + private Rect mTmpFromBounds = new Rect(); + private Rect mTmpToBounds = new Rect(); + /** Stack bounds adjusted to screen content area (taking into account IM windows, etc.) */ private final Rect mAdjustedBounds = new Rect(); @@ -141,6 +153,9 @@ public class TaskStack extends WindowContainer<Task> implements private Dimmer mDimmer = new Dimmer(this); + // TODO: remove after unification. + ActivityStack mActivityStack; + /** * For {@link #prepareSurfaces}. */ @@ -150,10 +165,11 @@ public class TaskStack extends WindowContainer<Task> implements private final AnimatingAppWindowTokenRegistry mAnimatingAppWindowTokenRegistry = new AnimatingAppWindowTokenRegistry(); - TaskStack(WindowManagerService service, int stackId, StackWindowController controller) { + TaskStack(WindowManagerService service, int stackId, ActivityStack activityStack) { super(service); mStackId = stackId; - setController(controller); + mActivityStack = activityStack; + activityStack.registerConfigurationChangeListener(this); mDockedStackMinimizeThickness = service.mContext.getResources().getDimensionPixelSize( com.android.internal.R.dimen.docked_stack_minimize_thickness); EventLog.writeEvent(EventLogTags.WM_STACK_CREATED, stackId); @@ -572,6 +588,49 @@ public class TaskStack extends WindowContainer<Task> implements positionChildAt(position, task, moveParents /* includingParents */, showForAllUsers); } + void positionChildAt(Task child, int position) { + if (DEBUG_STACK) { + Slog.i(TAG_WM, "positionChildAt: positioning task=" + child + " at " + position); + } + if (child == null) { + if (DEBUG_STACK) { + Slog.i(TAG_WM, "positionChildAt: could not find task=" + this); + } + return; + } + child.positionAt(position); + getDisplayContent().layoutAndAssignWindowLayersIfNeeded(); + } + + void positionChildAtTop(Task child, boolean includingParents) { + if (child == null) { + // TODO: Fix the call-points that cause this to happen. + return; + } + + positionChildAt(POSITION_TOP, child, includingParents); + + final DisplayContent displayContent = getDisplayContent(); + if (displayContent.mAppTransition.isTransitionSet()) { + child.setSendingToBottom(false); + } + displayContent.layoutAndAssignWindowLayersIfNeeded(); + } + + void positionChildAtBottom(Task child, boolean includingParents) { + if (child == null) { + // TODO: Fix the call-points that cause this to happen. + return; + } + + positionChildAt(POSITION_BOTTOM, child, includingParents); + + if (getDisplayContent().mAppTransition.isTransitionSet()) { + child.setSendingToBottom(true); + } + getDisplayContent().layoutAndAssignWindowLayersIfNeeded(); + } + @Override void positionChildAt(int position, Task child, boolean includingParents) { positionChildAt(position, child, includingParents, child.showForAllUsers()); @@ -596,6 +655,21 @@ public class TaskStack extends WindowContainer<Task> implements EventLog.writeEvent(EventLogTags.WM_TASK_MOVED, child.mTaskId, toTop, targetPosition); } + void reparent(int displayId, Rect outStackBounds, boolean onTop) { + final DisplayContent targetDc = mWmService.mRoot.getDisplayContent(displayId); + if (targetDc == null) { + throw new IllegalArgumentException("Trying to move stackId=" + mStackId + + " to unknown displayId=" + displayId); + } + + targetDc.moveStackToDisplay(this, onTop); + if (matchParentBounds()) { + outStackBounds.setEmpty(); + } else { + getRawBounds(outStackBounds); + } + } + // TODO: We should really have users as a window container in the hierarchy so that we don't // have to do complicated things like we are doing in this method. private int findPositionForTask(Task task, int targetPosition, boolean showForAllUsers, @@ -725,6 +799,23 @@ public class TaskStack extends WindowContainer<Task> implements } /** + * Re-sizes a stack and its containing tasks. + * + * @param bounds New stack bounds. Passing in null sets the bounds to fullscreen. + * @param taskBounds Bounds for tasks in the resized stack, keyed by task id. + * @param taskTempInsetBounds Inset bounds for individual tasks, keyed by task id. + */ + void resize(Rect bounds, SparseArray<Rect> taskBounds, + SparseArray<Rect> taskTempInsetBounds) { + // We might trigger a configuration change. Save the current task bounds for freezing. + prepareFreezingTaskBounds(); + if (setBounds(bounds, taskBounds, taskTempInsetBounds) && isVisible()) { + getDisplayContent().setLayoutNeeded(); + mWmService.mWindowPlacerLocked.performSurfacePlacement(); + } + } + + /** * Calculate an amount by which to expand the stack bounds in each direction. * Used to make room for shadows in the pinned windowing mode. */ @@ -929,12 +1020,7 @@ public class TaskStack extends WindowContainer<Task> implements (dockedStack == null || dockedStack == this) ? null : dockedStack.getRawBounds(); getStackDockedModeBoundsLocked(mDisplayContent.getConfiguration(), dockedBounds, null /* currentTempTaskBounds */, bounds, tempBounds); - getController().requestResize(bounds); - } - - @Override - StackWindowController getController() { - return (StackWindowController) super.getController(); + mActivityStack.requestResize(bounds); } @Override @@ -947,6 +1033,14 @@ public class TaskStack extends WindowContainer<Task> implements } @Override + void removeImmediately() { + if (mActivityStack != null) { + mActivityStack.unregisterConfigurationChangeListener(this); + } + super.removeImmediately(); + } + + @Override void onParentSet() { super.onParentSet(); @@ -1572,14 +1666,13 @@ public class TaskStack extends WindowContainer<Task> implements // I don't believe you... } - final PinnedStackWindowController controller = - (PinnedStackWindowController) getController(); - if (schedulePipModeChangedCallback && controller != null) { + if (schedulePipModeChangedCallback && mActivityStack != null) { // We need to schedule the PiP mode change before the animation up. It is possible // in this case for the animation down to not have been completed, so always // force-schedule and update to the client to ensure that it is notified that it // is no longer in picture-in-picture mode - controller.updatePictureInPictureModeForPinnedStackAnimation(null, forceUpdate); + mActivityStack.updatePictureInPictureModeForPinnedStackAnimation(null, + forceUpdate); } } return true; @@ -1592,12 +1685,10 @@ public class TaskStack extends WindowContainer<Task> implements // Update to the final bounds if requested. This is done here instead of in the bounds // animator to allow us to coordinate this after we notify the PiP mode changed - final PinnedStackWindowController controller = - (PinnedStackWindowController) getController(); - if (schedulePipModeChangedCallback && controller != null) { + if (schedulePipModeChangedCallback) { // We need to schedule the PiP mode change after the animation down, so use the // final bounds - controller.updatePictureInPictureModeForPinnedStackAnimation( + mActivityStack.updatePictureInPictureModeForPinnedStackAnimation( mBoundsAnimationTarget, false /* forceUpdate */); } @@ -1624,6 +1715,135 @@ public class TaskStack extends WindowContainer<Task> implements } } + /** + * @return the current stack bounds transformed to the given {@param aspectRatio}. If + * the default bounds is {@code null}, then the {@param aspectRatio} is applied to the + * default bounds. + */ + Rect getPictureInPictureBounds(float aspectRatio, Rect stackBounds) { + if (!mWmService.mSupportsPictureInPicture) { + return null; + } + + final DisplayContent displayContent = getDisplayContent(); + if (displayContent == null) { + return null; + } + + if (!inPinnedWindowingMode()) { + return null; + } + + final PinnedStackController pinnedStackController = + displayContent.getPinnedStackController(); + if (stackBounds == null) { + // Calculate the aspect ratio bounds from the default bounds + stackBounds = pinnedStackController.getDefaultOrLastSavedBounds(); + } + + if (pinnedStackController.isValidPictureInPictureAspectRatio(aspectRatio)) { + return pinnedStackController.transformBoundsToAspectRatio(stackBounds, aspectRatio, + true /* useCurrentMinEdgeSize */); + } else { + return stackBounds; + } + } + + /** + * Animates the pinned stack. + */ + void animateResizePinnedStack(Rect toBounds, Rect sourceHintBounds, + int animationDuration, boolean fromFullscreen) { + if (!inPinnedWindowingMode()) { + return; + } + // Get the from-bounds + final Rect fromBounds = new Rect(); + getBounds(fromBounds); + + // Get non-null fullscreen to-bounds for animating if the bounds are null + @SchedulePipModeChangedState int schedulePipModeChangedState = + NO_PIP_MODE_CHANGED_CALLBACKS; + final boolean toFullscreen = toBounds == null; + if (toFullscreen) { + if (fromFullscreen) { + throw new IllegalArgumentException("Should not defer scheduling PiP mode" + + " change on animation to fullscreen."); + } + schedulePipModeChangedState = SCHEDULE_PIP_MODE_CHANGED_ON_START; + + mWmService.getStackBounds( + WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, mTmpToBounds); + if (!mTmpToBounds.isEmpty()) { + // If there is a fullscreen bounds, use that + toBounds = new Rect(mTmpToBounds); + } else { + // Otherwise, use the display bounds + toBounds = new Rect(); + getDisplayContent().getBounds(toBounds); + } + } else if (fromFullscreen) { + schedulePipModeChangedState = SCHEDULE_PIP_MODE_CHANGED_ON_END; + } + + setAnimationFinalBounds(sourceHintBounds, toBounds, toFullscreen); + + final Rect finalToBounds = toBounds; + final @SchedulePipModeChangedState int finalSchedulePipModeChangedState = + schedulePipModeChangedState; + final DisplayContent displayContent = getDisplayContent(); + displayContent.mBoundsAnimationController.getHandler().post(() -> { + displayContent.mBoundsAnimationController.animateBounds(this, fromBounds, + finalToBounds, animationDuration, finalSchedulePipModeChangedState, + fromFullscreen, toFullscreen); + }); + } + + /** + * Sets the current picture-in-picture aspect ratio. + */ + void setPictureInPictureAspectRatio(float aspectRatio) { + if (!mWmService.mSupportsPictureInPicture) { + return; + } + + if (!inPinnedWindowingMode()) { + return; + } + + final PinnedStackController pinnedStackController = + getDisplayContent().getPinnedStackController(); + + if (Float.compare(aspectRatio, pinnedStackController.getAspectRatio()) == 0) { + return; + } + getAnimationOrCurrentBounds(mTmpFromBounds); + mTmpToBounds.set(mTmpFromBounds); + getPictureInPictureBounds(aspectRatio, mTmpToBounds); + if (!mTmpToBounds.equals(mTmpFromBounds)) { + animateResizePinnedStack(mTmpToBounds, null /* sourceHintBounds */, + -1 /* duration */, false /* fromFullscreen */); + } + pinnedStackController.setAspectRatio( + pinnedStackController.isValidPictureInPictureAspectRatio(aspectRatio) + ? aspectRatio : -1f); + } + + /** + * Sets the current picture-in-picture actions. + */ + void setPictureInPictureActions(List<RemoteAction> actions) { + if (!mWmService.mSupportsPictureInPicture) { + return; + } + + if (!inPinnedWindowingMode()) { + return; + } + + getDisplayContent().getPinnedStackController().setActions(actions); + } + @Override public boolean isAttached() { synchronized (mWmService.mGlobalLock) { diff --git a/services/core/java/com/android/server/wm/TaskTapPointerEventListener.java b/services/core/java/com/android/server/wm/TaskTapPointerEventListener.java index b2194190f4f4..2e5df45f9080 100644 --- a/services/core/java/com/android/server/wm/TaskTapPointerEventListener.java +++ b/services/core/java/com/android/server/wm/TaskTapPointerEventListener.java @@ -31,6 +31,10 @@ import android.view.WindowManagerPolicyConstants.PointerEventListener; import com.android.server.wm.WindowManagerService.H; +/** + * 1. Adjust the top most focus display if touch down on some display. + * 2. Adjust the pointer icon when cursor moves to the task bounds. + */ public class TaskTapPointerEventListener implements PointerEventListener { private final Region mTouchExcludeRegion = new Region(); @@ -67,7 +71,7 @@ public class TaskTapPointerEventListener implements PointerEventListener { return; } WindowContainer parent = mDisplayContent.getParent(); - if (parent != null) { + if (parent != null && parent.getTopChild() != mDisplayContent) { parent.positionChildAt(WindowContainer.POSITION_TOP, mDisplayContent, true /* includingParents */); } @@ -80,8 +84,7 @@ public class TaskTapPointerEventListener implements PointerEventListener { if (motionEvent.getDisplayId() != getDisplayId()) { return; } - final int action = motionEvent.getAction(); - switch (action & MotionEvent.ACTION_MASK) { + switch (motionEvent.getActionMasked()) { case MotionEvent.ACTION_DOWN: { final int x = (int) motionEvent.getX(); final int y = (int) motionEvent.getY(); @@ -97,7 +100,7 @@ public class TaskTapPointerEventListener implements PointerEventListener { } } break; - + case MotionEvent.ACTION_HOVER_ENTER: case MotionEvent.ACTION_HOVER_MOVE: { final int x = (int) motionEvent.getX(); final int y = (int) motionEvent.getY(); @@ -125,6 +128,7 @@ public class TaskTapPointerEventListener implements PointerEventListener { mPointerIconType = iconType; if (mPointerIconType == TYPE_NOT_SPECIFIED) { // Find the underlying window and ask it restore the pointer icon. + mService.mH.removeMessages(H.RESTORE_POINTER_ICON); mService.mH.obtainMessage(H.RESTORE_POINTER_ICON, x, y, mDisplayContent).sendToTarget(); } else { @@ -133,6 +137,18 @@ public class TaskTapPointerEventListener implements PointerEventListener { } } break; + case MotionEvent.ACTION_HOVER_EXIT: { + final int x = (int) motionEvent.getX(); + final int y = (int) motionEvent.getY(); + if (mPointerIconType != TYPE_NOT_SPECIFIED) { + mPointerIconType = TYPE_NOT_SPECIFIED; + // Find the underlying window and ask it to restore the pointer icon. + mService.mH.removeMessages(H.RESTORE_POINTER_ICON); + mService.mH.obtainMessage(H.RESTORE_POINTER_ICON, + x, y, mDisplayContent).sendToTarget(); + } + } + break; } } diff --git a/services/core/java/com/android/server/wm/WindowContainer.java b/services/core/java/com/android/server/wm/WindowContainer.java index 25e61f876722..19058776d187 100644 --- a/services/core/java/com/android/server/wm/WindowContainer.java +++ b/services/core/java/com/android/server/wm/WindowContainer.java @@ -437,6 +437,7 @@ class WindowContainer<E extends WindowContainer> extends ConfigurationContainer< if (mChildren.peekLast() != child) { mChildren.remove(child); mChildren.add(child); + onChildPositionChanged(); } if (includingParents && getParent() != null) { getParent().positionChildAt(POSITION_TOP, this /* child */, @@ -447,6 +448,7 @@ class WindowContainer<E extends WindowContainer> extends ConfigurationContainer< if (mChildren.peekFirst() != child) { mChildren.remove(child); mChildren.addFirst(child); + onChildPositionChanged(); } if (includingParents && getParent() != null) { getParent().positionChildAt(POSITION_BOTTOM, this /* child */, @@ -460,8 +462,8 @@ class WindowContainer<E extends WindowContainer> extends ConfigurationContainer< // doing this adjustment here and remove any adjustments in the callers. mChildren.remove(child); mChildren.add(position, child); + onChildPositionChanged(); } - onChildPositionChanged(); } /** diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java index 90506e744250..fda7a85c1270 100644 --- a/services/core/java/com/android/server/wm/WindowManagerService.java +++ b/services/core/java/com/android/server/wm/WindowManagerService.java @@ -723,7 +723,7 @@ public class WindowManagerService extends IWindowManager.Stub void updateSystemUiSettings() { boolean changed; - synchronized (mWindowMap) { + synchronized (mGlobalLock) { changed = ImmersiveModeConfirmation.loadSetting(mCurrentUserId, mContext) || PolicyControl.reloadFromSetting(mContext); } @@ -2629,12 +2629,23 @@ public class WindowManagerService extends IWindowManager.Stub @Override public void onUserSwitched() { mSettingsObserver.updateSystemUiSettings(); - synchronized (mWindowMap) { + synchronized (mGlobalLock) { // force a re-application of focused window sysui visibility on each display. mRoot.forAllDisplayPolicies(DisplayPolicy::resetSystemUiVisibilityLw); } } + @Override + public void moveDisplayToTop(int displayId) { + synchronized (mGlobalLock) { + final DisplayContent displayContent = mRoot.getDisplayContent(displayId); + if (displayContent != null && mRoot.getTopChild() != displayContent) { + mRoot.positionChildAt(WindowContainer.POSITION_TOP, displayContent, + true /* includingParents */); + } + } + } + /** * Starts deferring layout passes. Useful when doing multiple changes but to optimize * performance, only one layout pass should be done. This can be called multiple times, and @@ -5932,8 +5943,6 @@ public class WindowManagerService extends IWindowManager.Stub pw.print(" apps="); pw.print(mAppsFreezingScreen); final DisplayContent defaultDisplayContent = getDefaultDisplayContentLocked(); pw.print(" mRotation="); pw.print(defaultDisplayContent.getRotation()); - pw.print(" mAltOrientation="); - pw.println(defaultDisplayContent.getAltOrientation()); pw.print(" mLastWindowForcedOrientation="); pw.print(defaultDisplayContent.getLastWindowForcedOrientation()); pw.print(" mLastOrientation="); @@ -6379,7 +6388,7 @@ public class WindowManagerService extends IWindowManager.Stub } void setForceDesktopModeOnExternalDisplays(boolean forceDesktopModeOnExternalDisplays) { - synchronized (mWindowMap) { + synchronized (mGlobalLock) { mForceDesktopModeOnExternalDisplays = forceDesktopModeOnExternalDisplays; } } diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java index cd29b3c29248..8f86c003e4b0 100644 --- a/services/core/java/com/android/server/wm/WindowState.java +++ b/services/core/java/com/android/server/wm/WindowState.java @@ -2405,6 +2405,14 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP && !cantReceiveTouchInput(); } + @Override + public boolean canShowWhenLocked() { + final boolean showBecauseOfActivity = + mAppToken != null && mAppToken.mActivityRecord.canShowWhenLocked(); + final boolean showBecauseOfWindow = (getAttrs().flags & FLAG_SHOW_WHEN_LOCKED) != 0; + return showBecauseOfActivity || showBecauseOfWindow; + } + /** @return false if this window desires touch events. */ boolean cantReceiveTouchInput() { return mAppToken != null && mAppToken.getTask() != null diff --git a/services/core/jni/com_android_server_input_InputManagerService.cpp b/services/core/jni/com_android_server_input_InputManagerService.cpp index 641200769cf0..90c9cc2b0a35 100644 --- a/services/core/jni/com_android_server_input_InputManagerService.cpp +++ b/services/core/jni/com_android_server_input_InputManagerService.cpp @@ -111,6 +111,7 @@ static struct { jmethodID getKeyboardLayoutOverlay; jmethodID getDeviceAlias; jmethodID getTouchCalibrationForInputDevice; + jmethodID getContextForDisplay; } gServiceClassInfo; static struct { @@ -260,17 +261,16 @@ public: /* --- PointerControllerPolicyInterface implementation --- */ - virtual void loadPointerIcon(SpriteIcon* icon); - virtual void loadPointerResources(PointerResources* outResources); + virtual void loadPointerIcon(SpriteIcon* icon, int32_t displayId); + virtual void loadPointerResources(PointerResources* outResources, int32_t displayId); virtual void loadAdditionalMouseResources(std::map<int32_t, SpriteIcon>* outResources, - std::map<int32_t, PointerAnimation>* outAnimationResources); + std::map<int32_t, PointerAnimation>* outAnimationResources, int32_t displayId); virtual int32_t getDefaultPointerIconId(); virtual int32_t getCustomPointerIconId(); private: sp<InputManager> mInputManager; - jobject mContextObj; jobject mServiceObj; sp<Looper> mLooper; @@ -329,7 +329,6 @@ NativeInputManager::NativeInputManager(jobject contextObj, mLooper(looper), mInteractive(true) { JNIEnv* env = jniEnv(); - mContextObj = env->NewGlobalRef(contextObj); mServiceObj = env->NewGlobalRef(serviceObj); { @@ -351,7 +350,6 @@ NativeInputManager::NativeInputManager(jobject contextObj, NativeInputManager::~NativeInputManager() { JNIEnv* env = jniEnv(); - env->DeleteGlobalRef(mContextObj); env->DeleteGlobalRef(mServiceObj); } @@ -1202,19 +1200,22 @@ bool NativeInputManager::checkInjectEventsPermissionNonReentrant( return result; } -void NativeInputManager::loadPointerIcon(SpriteIcon* icon) { +void NativeInputManager::loadPointerIcon(SpriteIcon* icon, int32_t displayId) { ATRACE_CALL(); JNIEnv* env = jniEnv(); ScopedLocalRef<jobject> pointerIconObj(env, env->CallObjectMethod( - mServiceObj, gServiceClassInfo.getPointerIcon)); + mServiceObj, gServiceClassInfo.getPointerIcon, displayId)); if (checkAndClearExceptionFromCallback(env, "getPointerIcon")) { return; } + ScopedLocalRef<jobject> displayContext(env, env->CallObjectMethod( + mServiceObj, gServiceClassInfo.getContextForDisplay, displayId)); + PointerIcon pointerIcon; status_t status = android_view_PointerIcon_load(env, pointerIconObj.get(), - mContextObj, &pointerIcon); + displayContext.get(), &pointerIcon); if (!status && !pointerIcon.isNullIcon()) { *icon = SpriteIcon(pointerIcon.bitmap, pointerIcon.hotSpotX, pointerIcon.hotSpotY); } else { @@ -1222,28 +1223,34 @@ void NativeInputManager::loadPointerIcon(SpriteIcon* icon) { } } -void NativeInputManager::loadPointerResources(PointerResources* outResources) { +void NativeInputManager::loadPointerResources(PointerResources* outResources, int32_t displayId) { ATRACE_CALL(); JNIEnv* env = jniEnv(); - loadSystemIconAsSprite(env, mContextObj, POINTER_ICON_STYLE_SPOT_HOVER, + ScopedLocalRef<jobject> displayContext(env, env->CallObjectMethod( + mServiceObj, gServiceClassInfo.getContextForDisplay, displayId)); + + loadSystemIconAsSprite(env, displayContext.get(), POINTER_ICON_STYLE_SPOT_HOVER, &outResources->spotHover); - loadSystemIconAsSprite(env, mContextObj, POINTER_ICON_STYLE_SPOT_TOUCH, + loadSystemIconAsSprite(env, displayContext.get(), POINTER_ICON_STYLE_SPOT_TOUCH, &outResources->spotTouch); - loadSystemIconAsSprite(env, mContextObj, POINTER_ICON_STYLE_SPOT_ANCHOR, + loadSystemIconAsSprite(env, displayContext.get(), POINTER_ICON_STYLE_SPOT_ANCHOR, &outResources->spotAnchor); } void NativeInputManager::loadAdditionalMouseResources(std::map<int32_t, SpriteIcon>* outResources, - std::map<int32_t, PointerAnimation>* outAnimationResources) { + std::map<int32_t, PointerAnimation>* outAnimationResources, int32_t displayId) { ATRACE_CALL(); JNIEnv* env = jniEnv(); + ScopedLocalRef<jobject> displayContext(env, env->CallObjectMethod( + mServiceObj, gServiceClassInfo.getContextForDisplay, displayId)); + for (int iconId = POINTER_ICON_STYLE_CONTEXT_MENU; iconId <= POINTER_ICON_STYLE_GRABBING; ++iconId) { PointerIcon pointerIcon; loadSystemIconAsSpriteWithPointerIcon( - env, mContextObj, iconId, &pointerIcon, &((*outResources)[iconId])); + env, displayContext.get(), iconId, &pointerIcon, &((*outResources)[iconId])); if (!pointerIcon.bitmapFrames.empty()) { PointerAnimation& animationData = (*outAnimationResources)[iconId]; size_t numFrames = pointerIcon.bitmapFrames.size() + 1; @@ -1258,7 +1265,7 @@ void NativeInputManager::loadAdditionalMouseResources(std::map<int32_t, SpriteIc } } } - loadSystemIconAsSprite(env, mContextObj, POINTER_ICON_STYLE_NULL, + loadSystemIconAsSprite(env, displayContext.get(), POINTER_ICON_STYLE_NULL, &((*outResources)[POINTER_ICON_STYLE_NULL])); } @@ -1819,7 +1826,7 @@ int register_android_server_InputManager(JNIEnv* env) { "getPointerLayer", "()I"); GET_METHOD_ID(gServiceClassInfo.getPointerIcon, clazz, - "getPointerIcon", "()Landroid/view/PointerIcon;"); + "getPointerIcon", "(I)Landroid/view/PointerIcon;"); GET_METHOD_ID(gServiceClassInfo.getPointerDisplayId, clazz, "getPointerDisplayId", "()I"); @@ -1835,6 +1842,10 @@ int register_android_server_InputManager(JNIEnv* env) { "getTouchCalibrationForInputDevice", "(Ljava/lang/String;I)Landroid/hardware/input/TouchCalibration;"); + GET_METHOD_ID(gServiceClassInfo.getContextForDisplay, clazz, + "getContextForDisplay", + "(I)Landroid/content/Context;") + // InputDevice FIND_CLASS(gInputDeviceClassInfo.clazz, "android/view/InputDevice"); diff --git a/services/core/jni/com_android_server_location_GnssLocationProvider.cpp b/services/core/jni/com_android_server_location_GnssLocationProvider.cpp index dcb2ff5f9df5..f3c19d099851 100644 --- a/services/core/jni/com_android_server_location_GnssLocationProvider.cpp +++ b/services/core/jni/com_android_server_location_GnssLocationProvider.cpp @@ -81,7 +81,7 @@ static jmethodID method_correctionSatFlags; static jmethodID method_correctionSatConstType; static jmethodID method_correctionSatId; static jmethodID method_correctionSatCarrierFreq; -static jmethodID method_correctionSatIsLos; +static jmethodID method_correctionSatIsLosProb; static jmethodID method_correctionSatEpl; static jmethodID method_correctionSatEplUnc; static jmethodID method_correctionSatRefPlane; @@ -2277,8 +2277,8 @@ static jboolean android_location_GnssMeasurementsProvider_inject_gnss_measuremen singleSatCorrClass, "getSatId", "()I"); method_correctionSatCarrierFreq = env->GetMethodID( singleSatCorrClass, "getCarrierFrequencyHz", "()F"); - method_correctionSatIsLos = env->GetMethodID( - singleSatCorrClass,"getSatIsLos", "()Z"); + method_correctionSatIsLosProb = env->GetMethodID( + singleSatCorrClass,"getProbSatIsLos", "()F"); method_correctionSatEpl = env->GetMethodID( singleSatCorrClass, "getExcessPathLengthMeters", "()F"); method_correctionSatEplUnc = env->GetMethodID( @@ -2296,8 +2296,8 @@ static jboolean android_location_GnssMeasurementsProvider_inject_gnss_measuremen env->CallIntMethod(singleSatCorrectionObj, method_correctionSatId); jfloat carrierFreqHz = env->CallFloatMethod( singleSatCorrectionObj, method_correctionSatCarrierFreq); - jboolean satIsLos = env->CallBooleanMethod(singleSatCorrectionObj, - method_correctionSatIsLos); + jfloat probSatIsLos = env->CallFloatMethod(singleSatCorrectionObj, + method_correctionSatIsLosProb); jfloat eplMeters = env->CallFloatMethod(singleSatCorrectionObj, method_correctionSatEpl); jfloat eplUncMeters = env->CallFloatMethod(singleSatCorrectionObj, @@ -2337,7 +2337,7 @@ static jboolean android_location_GnssMeasurementsProvider_inject_gnss_measuremen .constellation = static_cast<GnssConstellationType>(constType), .svid = static_cast<uint16_t>(satId), .carrierFrequencyHz = carrierFreqHz, - .satIsLos = static_cast<bool>(satIsLos), + .probSatIsLos = probSatIsLos, .excessPathLengthMeters = eplMeters, .excessPathLengthUncertaintyMeters = eplUncMeters, .reflectingPlane = reflectingPlane, diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java index fef2db921dcf..cef47caff740 100644 --- a/services/java/com/android/server/SystemServer.java +++ b/services/java/com/android/server/SystemServer.java @@ -74,6 +74,7 @@ import com.android.internal.util.EmergencyAffordanceManager; import com.android.internal.widget.ILockSettings; import com.android.server.am.ActivityManagerService; import com.android.server.appbinding.AppBindingService; +import com.android.server.attention.AttentionManagerService; import com.android.server.audio.AudioService; import com.android.server.biometrics.BiometricService; import com.android.server.biometrics.face.FaceService; @@ -148,10 +149,11 @@ import com.android.server.webkit.WebViewUpdateService; import com.android.server.wm.ActivityTaskManagerService; import com.android.server.wm.WindowManagerGlobalLock; import com.android.server.wm.WindowManagerService; -import com.google.android.startop.iorap.IorapForwardingService; import dalvik.system.VMRuntime; +import com.google.android.startop.iorap.IorapForwardingService; + import java.io.File; import java.io.IOException; import java.util.Locale; @@ -1230,6 +1232,10 @@ public final class SystemServer { traceEnd(); } + traceBeginAndSlog("StartAttentionManagerService"); + mSystemServiceManager.startService(AttentionManagerService.class); + traceEnd(); + traceBeginAndSlog("StartNetworkScoreService"); mSystemServiceManager.startService(NetworkScoreService.Lifecycle.class); traceEnd(); diff --git a/services/net/java/android/net/shared/LinkPropertiesParcelableUtil.java b/services/net/java/android/net/shared/LinkPropertiesParcelableUtil.java new file mode 100644 index 000000000000..5b77f543c62b --- /dev/null +++ b/services/net/java/android/net/shared/LinkPropertiesParcelableUtil.java @@ -0,0 +1,222 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.net.shared; + +import static android.net.shared.ParcelableUtil.fromParcelableArray; +import static android.net.shared.ParcelableUtil.toParcelableArray; + +import android.annotation.Nullable; +import android.net.InetAddresses; +import android.net.IpPrefix; +import android.net.IpPrefixParcelable; +import android.net.LinkAddress; +import android.net.LinkAddressParcelable; +import android.net.LinkProperties; +import android.net.LinkPropertiesParcelable; +import android.net.ProxyInfo; +import android.net.ProxyInfoParcelable; +import android.net.RouteInfo; +import android.net.RouteInfoParcelable; +import android.net.Uri; + +import java.net.InetAddress; +import java.util.Arrays; + +/** + * Collection of utility methods to convert to and from stable AIDL parcelables for LinkProperties + * and its attributes. + * @hide + */ +public final class LinkPropertiesParcelableUtil { + + /** + * Convert a ProxyInfo to a ProxyInfoParcelable + */ + public static ProxyInfoParcelable toStableParcelable(@Nullable ProxyInfo proxyInfo) { + if (proxyInfo == null) { + return null; + } + final ProxyInfoParcelable parcel = new ProxyInfoParcelable(); + parcel.host = proxyInfo.getHost(); + parcel.port = proxyInfo.getPort(); + parcel.exclusionList = proxyInfo.getExclusionList(); + parcel.pacFileUrl = proxyInfo.getPacFileUrl().toString(); + return parcel; + } + + /** + * Convert a ProxyInfoParcelable to a ProxyInfo + */ + public static ProxyInfo fromStableParcelable(@Nullable ProxyInfoParcelable parcel) { + if (parcel == null) { + return null; + } + if (Uri.EMPTY.toString().equals(parcel.pacFileUrl)) { + return ProxyInfo.buildDirectProxy( + parcel.host, parcel.port, Arrays.asList(parcel.exclusionList)); + } else { + return ProxyInfo.buildPacProxy(Uri.parse(parcel.pacFileUrl)); + } + } + + /** + * Convert an IpPrefixParcelable to an IpPrefix + */ + public static IpPrefixParcelable toStableParcelable(@Nullable IpPrefix ipPrefix) { + if (ipPrefix == null) { + return null; + } + final IpPrefixParcelable parcel = new IpPrefixParcelable(); + parcel.address = ipPrefix.getAddress().getHostAddress(); + parcel.prefixLength = ipPrefix.getPrefixLength(); + return parcel; + } + + /** + * Convert an IpPrefix to an IpPrefixParcelable + */ + public static IpPrefix fromStableParcelable(@Nullable IpPrefixParcelable parcel) { + if (parcel == null) { + return null; + } + return new IpPrefix(InetAddresses.parseNumericAddress(parcel.address), parcel.prefixLength); + } + + /** + * Convert a RouteInfoParcelable to a RouteInfo + */ + public static RouteInfoParcelable toStableParcelable(@Nullable RouteInfo routeInfo) { + if (routeInfo == null) { + return null; + } + final RouteInfoParcelable parcel = new RouteInfoParcelable(); + parcel.destination = toStableParcelable(routeInfo.getDestination()); + parcel.gatewayAddr = routeInfo.getGateway().getHostAddress(); + parcel.ifaceName = routeInfo.getInterface(); + parcel.type = routeInfo.getType(); + return parcel; + } + + /** + * Convert a RouteInfo to a RouteInfoParcelable + */ + public static RouteInfo fromStableParcelable(@Nullable RouteInfoParcelable parcel) { + if (parcel == null) { + return null; + } + final IpPrefix destination = fromStableParcelable(parcel.destination); + return new RouteInfo( + destination, InetAddresses.parseNumericAddress(parcel.gatewayAddr), + parcel.ifaceName, parcel.type); + } + + /** + * Convert a LinkAddressParcelable to a LinkAddress + */ + public static LinkAddressParcelable toStableParcelable(@Nullable LinkAddress la) { + if (la == null) { + return null; + } + final LinkAddressParcelable parcel = new LinkAddressParcelable(); + parcel.address = la.getAddress().getHostAddress(); + parcel.prefixLength = la.getPrefixLength(); + parcel.flags = la.getFlags(); + parcel.scope = la.getScope(); + return parcel; + } + + /** + * Convert a LinkAddress to a LinkAddressParcelable + */ + public static LinkAddress fromStableParcelable(@Nullable LinkAddressParcelable parcel) { + if (parcel == null) { + return null; + } + return new LinkAddress( + InetAddresses.parseNumericAddress(parcel.address), + parcel.prefixLength, + parcel.flags, + parcel.scope); + } + + /** + * Convert a LinkProperties to a LinkPropertiesParcelable + */ + public static LinkPropertiesParcelable toStableParcelable(@Nullable LinkProperties lp) { + if (lp == null) { + return null; + } + final LinkPropertiesParcelable parcel = new LinkPropertiesParcelable(); + parcel.ifaceName = lp.getInterfaceName(); + parcel.linkAddresses = toParcelableArray( + lp.getLinkAddresses(), + LinkPropertiesParcelableUtil::toStableParcelable, + LinkAddressParcelable.class); + parcel.dnses = toParcelableArray( + lp.getDnsServers(), InetAddress::getHostAddress, String.class); + parcel.pcscfs = toParcelableArray( + lp.getPcscfServers(), InetAddress::getHostAddress, String.class); + parcel.validatedPrivateDnses = toParcelableArray( + lp.getValidatedPrivateDnsServers(), InetAddress::getHostAddress, String.class); + parcel.usePrivateDns = lp.isPrivateDnsActive(); + parcel.privateDnsServerName = lp.getPrivateDnsServerName(); + parcel.domains = lp.getDomains(); + parcel.routes = toParcelableArray( + lp.getRoutes(), LinkPropertiesParcelableUtil::toStableParcelable, + RouteInfoParcelable.class); + parcel.httpProxy = toStableParcelable(lp.getHttpProxy()); + parcel.mtu = lp.getMtu(); + parcel.tcpBufferSizes = lp.getTcpBufferSizes(); + parcel.nat64Prefix = toStableParcelable(lp.getNat64Prefix()); + parcel.stackedLinks = toParcelableArray( + lp.getStackedLinks(), LinkPropertiesParcelableUtil::toStableParcelable, + LinkPropertiesParcelable.class); + return parcel; + } + + /** + * Convert a LinkPropertiesParcelable to a LinkProperties + */ + public static LinkProperties fromStableParcelable(@Nullable LinkPropertiesParcelable parcel) { + if (parcel == null) { + return null; + } + final LinkProperties lp = new LinkProperties(); + lp.setInterfaceName(parcel.ifaceName); + lp.setLinkAddresses(fromParcelableArray(parcel.linkAddresses, + LinkPropertiesParcelableUtil::fromStableParcelable)); + lp.setDnsServers(fromParcelableArray(parcel.dnses, InetAddresses::parseNumericAddress)); + lp.setPcscfServers(fromParcelableArray(parcel.pcscfs, InetAddresses::parseNumericAddress)); + lp.setValidatedPrivateDnsServers( + fromParcelableArray(parcel.validatedPrivateDnses, + InetAddresses::parseNumericAddress)); + lp.setUsePrivateDns(parcel.usePrivateDns); + lp.setPrivateDnsServerName(parcel.privateDnsServerName); + lp.setDomains(parcel.domains); + for (RouteInfoParcelable route : parcel.routes) { + lp.addRoute(fromStableParcelable(route)); + } + lp.setHttpProxy(fromStableParcelable(parcel.httpProxy)); + lp.setMtu(parcel.mtu); + lp.setTcpBufferSizes(parcel.tcpBufferSizes); + lp.setNat64Prefix(fromStableParcelable(parcel.nat64Prefix)); + for (LinkPropertiesParcelable stackedLink : parcel.stackedLinks) { + lp.addStackedLink(fromStableParcelable(stackedLink)); + } + return lp; + } +} diff --git a/services/net/java/android/net/shared/ParcelableUtil.java b/services/net/java/android/net/shared/ParcelableUtil.java new file mode 100644 index 000000000000..a18976c9eee6 --- /dev/null +++ b/services/net/java/android/net/shared/ParcelableUtil.java @@ -0,0 +1,63 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.net.shared; + +import android.annotation.NonNull; + +import java.lang.reflect.Array; +import java.util.ArrayList; +import java.util.List; +import java.util.function.Function; + +/** + * Utility methods to help convert to/from stable parcelables. + * @hide + */ +public final class ParcelableUtil { + // Below methods could be implemented easily with streams, but streams are frowned upon in + // frameworks code. + + /** + * Convert a list of BaseType items to an array of ParcelableType items using the specified + * converter function. + */ + public static <ParcelableType, BaseType> ParcelableType[] toParcelableArray( + @NonNull List<BaseType> base, + @NonNull Function<BaseType, ParcelableType> conv, + @NonNull Class<ParcelableType> parcelClass) { + final ParcelableType[] out = (ParcelableType[]) Array.newInstance(parcelClass, base.size()); + int i = 0; + for (BaseType b : base) { + out[i] = conv.apply(b); + i++; + } + return out; + } + + /** + * Convert an array of ParcelableType items to a list of BaseType items using the specified + * converter function. + */ + public static <ParcelableType, BaseType> ArrayList<BaseType> fromParcelableArray( + @NonNull ParcelableType[] parceled, @NonNull Function<ParcelableType, BaseType> conv) { + final ArrayList<BaseType> out = new ArrayList<>(parceled.length); + for (ParcelableType t : parceled) { + out.add(conv.apply(t)); + } + return out; + } +} diff --git a/services/tests/mockingservicestests/src/com/android/server/AppStateTrackerTest.java b/services/tests/mockingservicestests/src/com/android/server/AppStateTrackerTest.java index 4a48468867df..c8e67820ce46 100644 --- a/services/tests/mockingservicestests/src/com/android/server/AppStateTrackerTest.java +++ b/services/tests/mockingservicestests/src/com/android/server/AppStateTrackerTest.java @@ -85,7 +85,6 @@ import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; import java.util.function.Consumer; -import androidx.test.filters.FlakyTest; import androidx.test.filters.SmallTest; import androidx.test.runner.AndroidJUnit4; @@ -794,7 +793,6 @@ public class AppStateTrackerTest { } @Test - @FlakyTest(bugId = 114098433) public void testAllListeners() throws Exception { final AppStateTrackerTestable instance = newInstance(); callStart(instance); diff --git a/services/tests/servicestests/src/com/android/server/display/AppSaturationControllerTest.java b/services/tests/servicestests/src/com/android/server/display/AppSaturationControllerTest.java new file mode 100644 index 000000000000..e51884429718 --- /dev/null +++ b/services/tests/servicestests/src/com/android/server/display/AppSaturationControllerTest.java @@ -0,0 +1,115 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.server.display; + +import static com.android.server.display.AppSaturationController.TRANSLATION_VECTOR; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; + +import android.app.ActivityManager; +import android.os.UserHandle; + +import androidx.test.runner.AndroidJUnit4; + +import com.android.server.display.ColorDisplayService.ColorTransformController; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; + +import java.lang.ref.WeakReference; + +@RunWith(AndroidJUnit4.class) +public class AppSaturationControllerTest { + + private static final String TEST_PACKAGE_NAME = "com.android.test"; + + private int mUserId; + private AppSaturationController mAppSaturationController; + private float[] mMatrix; + + @Mock + private ColorTransformController mColorTransformController; + + @Before + public void setUp() { + MockitoAnnotations.initMocks(this); + mUserId = ActivityManager.getCurrentUser(); + mAppSaturationController = new AppSaturationController(); + mMatrix = new float[9]; + } + + @After + public void tearDown() { + mAppSaturationController = null; + mUserId = UserHandle.USER_NULL; + } + + @Test + public void addColorTransformController_appliesExistingSaturation() { + final WeakReference<ColorTransformController> ref = new WeakReference<>( + mColorTransformController); + mAppSaturationController.setSaturationLevel(TEST_PACKAGE_NAME, mUserId, 30); + mAppSaturationController.addColorTransformController(TEST_PACKAGE_NAME, mUserId, ref); + AppSaturationController.computeGrayscaleTransformMatrix(.3f, mMatrix); + verify(mColorTransformController).applyAppSaturation(eq(mMatrix), eq(TRANSLATION_VECTOR)); + } + + @Test + public void setSaturationLevel_resetToDefault() { + final WeakReference<ColorTransformController> ref = new WeakReference<>( + mColorTransformController); + mAppSaturationController.addColorTransformController(TEST_PACKAGE_NAME, mUserId, ref); + verify(mColorTransformController, never()) + .applyAppSaturation(any(), eq(TRANSLATION_VECTOR)); + mAppSaturationController.setSaturationLevel(TEST_PACKAGE_NAME, mUserId, 30); + AppSaturationController.computeGrayscaleTransformMatrix(.3f, mMatrix); + verify(mColorTransformController, times(1)) + .applyAppSaturation(eq(mMatrix), eq(TRANSLATION_VECTOR)); + mAppSaturationController.setSaturationLevel(TEST_PACKAGE_NAME, mUserId, 100); + AppSaturationController.computeGrayscaleTransformMatrix(1.0f, mMatrix); + verify(mColorTransformController, times(2)) + .applyAppSaturation(eq(mMatrix), eq(TRANSLATION_VECTOR)); + } + + @Test + public void setSaturationLevel_updateLevel() { + final WeakReference<ColorTransformController> ref = new WeakReference<>( + mColorTransformController); + mAppSaturationController.addColorTransformController(TEST_PACKAGE_NAME, mUserId, ref); + verify(mColorTransformController, never()) + .applyAppSaturation(any(), eq(TRANSLATION_VECTOR)); + mAppSaturationController.setSaturationLevel(TEST_PACKAGE_NAME, mUserId, 30); + AppSaturationController.computeGrayscaleTransformMatrix(.3f, mMatrix); + verify(mColorTransformController).applyAppSaturation(eq(mMatrix), eq(TRANSLATION_VECTOR)); + mAppSaturationController.setSaturationLevel(TEST_PACKAGE_NAME, mUserId, 70); + AppSaturationController.computeGrayscaleTransformMatrix(.7f, mMatrix); + verify(mColorTransformController, times(2)) + .applyAppSaturation(eq(mMatrix), eq(TRANSLATION_VECTOR)); + mAppSaturationController.setSaturationLevel(TEST_PACKAGE_NAME, mUserId, 100); + AppSaturationController.computeGrayscaleTransformMatrix(1.0f, mMatrix); + verify(mColorTransformController, times(3)) + .applyAppSaturation(eq(mMatrix), eq(TRANSLATION_VECTOR)); + } +} diff --git a/services/tests/servicestests/src/com/android/server/hdmi/ArcInitiationActionFromAvrTest.java b/services/tests/servicestests/src/com/android/server/hdmi/ArcInitiationActionFromAvrTest.java index 8b0e8abf069d..eb9b98ec65f7 100644 --- a/services/tests/servicestests/src/com/android/server/hdmi/ArcInitiationActionFromAvrTest.java +++ b/services/tests/servicestests/src/com/android/server/hdmi/ArcInitiationActionFromAvrTest.java @@ -30,6 +30,7 @@ import androidx.test.InstrumentationRegistry; import androidx.test.filters.SmallTest; import org.junit.Before; +import org.junit.Ignore; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; @@ -147,6 +148,7 @@ public class ArcInitiationActionFromAvrTest { mTestLooper.dispatchAll(); } + @Ignore("b/120845532") @Test public void arcInitiation_requestActiveSource() { mSendCecCommandSuccess = true; diff --git a/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecControllerTest.java b/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecControllerTest.java index 93a09dc3ff04..5d8131f35eb7 100644 --- a/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecControllerTest.java +++ b/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecControllerTest.java @@ -40,7 +40,6 @@ import androidx.test.filters.SmallTest; import com.android.server.hdmi.HdmiCecController.AllocateAddressCallback; import org.junit.Before; -import org.junit.Ignore; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; @@ -142,7 +141,6 @@ public class HdmiCecControllerTest { assertEquals(ADDR_UNREGISTERED, mLogicalAddress); } - @Ignore("b/110413065 Support multiple device types 4 and 5.") @Test public void testAllocatLogicalAddress_PlaybackPreferredNotOccupied() { mHdmiCecController.allocateLogicalAddress(DEVICE_PLAYBACK, ADDR_PLAYBACK_1, mCallback); @@ -158,7 +156,6 @@ public class HdmiCecControllerTest { assertEquals(ADDR_PLAYBACK_2, mLogicalAddress); } - @Ignore("b/110413065 Support multiple device types 4 and 5.") @Test public void testAllocatLogicalAddress_PlaybackNoPreferredNotOcuppied() { mHdmiCecController.allocateLogicalAddress(DEVICE_PLAYBACK, ADDR_UNREGISTERED, mCallback); diff --git a/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDeviceAudioSystemTest.java b/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDeviceAudioSystemTest.java index 3b51a2a70f83..3a6cdc2ad7c9 100644 --- a/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDeviceAudioSystemTest.java +++ b/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDeviceAudioSystemTest.java @@ -21,6 +21,7 @@ import static android.hardware.hdmi.HdmiControlManager.DEVICE_EVENT_UPDATE_DEVIC import static com.android.server.hdmi.Constants.ADDR_AUDIO_SYSTEM; import static com.android.server.hdmi.Constants.ADDR_BROADCAST; import static com.android.server.hdmi.Constants.ADDR_PLAYBACK_1; +import static com.android.server.hdmi.Constants.ADDR_PLAYBACK_2; import static com.android.server.hdmi.Constants.ADDR_TUNER_1; import static com.android.server.hdmi.Constants.ADDR_TV; import static com.android.server.hdmi.HdmiControlService.INITIATED_BY_ENABLE_CEC; @@ -29,9 +30,9 @@ import static com.android.server.hdmi.HdmiControlService.STANDBY_SCREEN_OFF; import static com.google.common.truth.Truth.assertThat; import android.hardware.hdmi.HdmiDeviceInfo; +import android.hardware.hdmi.HdmiPortInfo; import android.media.AudioManager; import android.os.Looper; -import android.os.SystemProperties; import android.os.test.TestLooper; import androidx.test.InstrumentationRegistry; @@ -46,7 +47,6 @@ import org.junit.runner.RunWith; import org.junit.runners.JUnit4; import java.util.ArrayList; - @SmallTest @RunWith(JUnit4.class) /** Tests for {@link HdmiCecLocalDeviceAudioSystem} class. */ @@ -67,9 +67,15 @@ public class HdmiCecLocalDeviceAudioSystemTest { private int mMusicVolume; private int mMusicMaxVolume; private boolean mMusicMute; - private int mAvrPhysicalAddress; + private static final int SELF_PHYSICAL_ADDRESS = 0x2000; + private static final int HDMI_1_PHYSICAL_ADDRESS = 0x2100; + private static final int HDMI_2_PHYSICAL_ADDRESS = 0x2200; + private static final int HDMI_3_PHYSICAL_ADDRESS = 0x2300; private int mInvokeDeviceEventState; private HdmiDeviceInfo mDeviceInfo; + private boolean mMutingEnabled; + private boolean mArcSupport; + private HdmiPortInfo[] mHdmiPortInfo; @Before public void setUp() { @@ -141,9 +147,20 @@ public class HdmiCecLocalDeviceAudioSystemTest { } @Override - int pathToPortId(int path) { - // port id is not useful for the test right now - return 1; + void writeStringSetting(String key, String value) { + // do nothing + } + + @Override + boolean readBooleanSetting(String key, boolean defVal) { + switch (key) { + case Constants.PROPERTY_SYSTEM_AUDIO_MODE_MUTING_ENABLE: + return mMutingEnabled; + case Constants.PROPERTY_ARC_SUPPORT: + return mArcSupport; + default: + return defVal; + } } }; @@ -154,11 +171,17 @@ public class HdmiCecLocalDeviceAudioSystemTest { void setIsActiveSource(boolean on) { mIsActiveSource = on; } + + @Override + protected int getPreferredAddress() { + return ADDR_PLAYBACK_1; + } }; mHdmiCecLocalDeviceAudioSystem.init(); mHdmiCecLocalDevicePlayback.init(); mHdmiControlService.setIoLooper(mMyLooper); mNativeWrapper = new FakeNativeWrapper(); + mNativeWrapper.setPhysicalAddress(SELF_PHYSICAL_ADDRESS); mHdmiCecController = HdmiCecController.createWithNativeWrapper(mHdmiControlService, mNativeWrapper); mHdmiControlService.setCecController(mHdmiCecController); @@ -166,15 +189,28 @@ public class HdmiCecLocalDeviceAudioSystemTest { mHdmiControlService.setMessageValidator(new HdmiCecMessageValidator(mHdmiControlService)); mLocalDevices.add(mHdmiCecLocalDeviceAudioSystem); mLocalDevices.add(mHdmiCecLocalDevicePlayback); + mHdmiCecLocalDeviceAudioSystem.setRoutingControlFeatureEnables(true); + mHdmiPortInfo = new HdmiPortInfo[4]; + mHdmiPortInfo[0] = + new HdmiPortInfo( + 0, HdmiPortInfo.PORT_INPUT, SELF_PHYSICAL_ADDRESS, true, false, false); + mHdmiPortInfo[1] = + new HdmiPortInfo( + 2, HdmiPortInfo.PORT_INPUT, HDMI_1_PHYSICAL_ADDRESS, true, false, false); + mHdmiPortInfo[2] = + new HdmiPortInfo( + 1, HdmiPortInfo.PORT_INPUT, HDMI_2_PHYSICAL_ADDRESS, true, false, false); + mHdmiPortInfo[3] = + new HdmiPortInfo( + 4, HdmiPortInfo.PORT_INPUT, HDMI_3_PHYSICAL_ADDRESS, true, false, false); + mNativeWrapper.setPortInfo(mHdmiPortInfo); mHdmiControlService.initPortInfo(); // No TV device interacts with AVR so system audio control won't be turned on here mHdmiControlService.allocateLogicalAddress(mLocalDevices, INITIATED_BY_ENABLE_CEC); mTestLooper.dispatchAll(); mNativeWrapper.clearResultMessages(); - mAvrPhysicalAddress = 0x2000; - mNativeWrapper.setPhysicalAddress(mAvrPhysicalAddress); - SystemProperties.set(Constants.PROPERTY_ARC_SUPPORT, "true"); - SystemProperties.set(Constants.PROPERTY_SYSTEM_AUDIO_MODE_MUTING_ENABLE, "true"); + mMutingEnabled = true; + mArcSupport = true; mInvokeDeviceEventState = 0; mDeviceInfo = null; } @@ -244,6 +280,8 @@ public class HdmiCecLocalDeviceAudioSystemTest { assertThat(mNativeWrapper.getOnlyResultMessage()).isEqualTo(expectedMessage); } + // Testing device has sadConfig.xml + @Ignore("b/120845532") @Test public void handleRequestShortAudioDescriptor_noAudioDeviceInfo() throws Exception { HdmiCecMessage expectedMessage = @@ -414,51 +452,6 @@ public class HdmiCecLocalDeviceAudioSystemTest { } @Test - public void pathToPort_isMe() throws Exception { - int targetPhysicalAddress = 0x1000; - mNativeWrapper.setPhysicalAddress(0x1000); - assertThat(mHdmiCecLocalDeviceAudioSystem - .getLocalPortFromPhysicalAddress(targetPhysicalAddress)) - .isEqualTo(0); - } - - @Test - public void pathToPort_isBelow() throws Exception { - int targetPhysicalAddress = 0x1100; - mNativeWrapper.setPhysicalAddress(0x1000); - assertThat(mHdmiCecLocalDeviceAudioSystem - .getLocalPortFromPhysicalAddress(targetPhysicalAddress)) - .isEqualTo(1); - } - - @Test - public void pathToPort_neitherMeNorBelow() throws Exception { - int targetPhysicalAddress = 0x3000; - mNativeWrapper.setPhysicalAddress(0x2000); - assertThat(mHdmiCecLocalDeviceAudioSystem - .getLocalPortFromPhysicalAddress(targetPhysicalAddress)) - .isEqualTo(-1); - - targetPhysicalAddress = 0x2200; - mNativeWrapper.setPhysicalAddress(0x3300); - assertThat(mHdmiCecLocalDeviceAudioSystem - .getLocalPortFromPhysicalAddress(targetPhysicalAddress)) - .isEqualTo(-1); - - targetPhysicalAddress = 0x2213; - mNativeWrapper.setPhysicalAddress(0x2212); - assertThat(mHdmiCecLocalDeviceAudioSystem - .getLocalPortFromPhysicalAddress(targetPhysicalAddress)) - .isEqualTo(-1); - - targetPhysicalAddress = 0x2340; - mNativeWrapper.setPhysicalAddress(0x2310); - assertThat(mHdmiCecLocalDeviceAudioSystem - .getLocalPortFromPhysicalAddress(targetPhysicalAddress)) - .isEqualTo(-1); - } - - @Test public void handleRequestArcInitiate_isNotDirectConnectedToTv() throws Exception { HdmiCecMessage message = HdmiCecMessageBuilder.buildRequestArcInitiation(ADDR_TV, ADDR_AUDIO_SYSTEM); @@ -530,7 +523,7 @@ public class HdmiCecLocalDeviceAudioSystemTest { ADDR_TV, Constants.MESSAGE_REQUEST_ARC_INITIATION, Constants.ABORT_UNRECOGNIZED_OPCODE); - SystemProperties.set(Constants.PROPERTY_ARC_SUPPORT, "false"); + mArcSupport = false; assertThat(mHdmiCecLocalDeviceAudioSystem.handleRequestArcInitiate(message)).isTrue(); mTestLooper.dispatchAll(); @@ -541,7 +534,7 @@ public class HdmiCecLocalDeviceAudioSystemTest { HdmiCecMessage message = HdmiCecMessageBuilder.buildSystemAudioModeRequest( ADDR_TUNER_1, ADDR_AUDIO_SYSTEM, - mAvrPhysicalAddress, true); + SELF_PHYSICAL_ADDRESS, true); HdmiCecMessage expectedMessage = HdmiCecMessageBuilder.buildFeatureAbortCommand( ADDR_AUDIO_SYSTEM, @@ -559,7 +552,7 @@ public class HdmiCecLocalDeviceAudioSystemTest { HdmiCecMessage message = HdmiCecMessageBuilder.buildSystemAudioModeRequest( ADDR_TUNER_1, ADDR_AUDIO_SYSTEM, - mAvrPhysicalAddress, true); + SELF_PHYSICAL_ADDRESS, true); HdmiCecMessage expectedMessage = HdmiCecMessageBuilder.buildSetSystemAudioMode( ADDR_AUDIO_SYSTEM, Constants.ADDR_BROADCAST, true); @@ -585,15 +578,14 @@ public class HdmiCecLocalDeviceAudioSystemTest { .isEqualTo(expectedActiveSource); } - @Ignore("b/110413065 Support multiple device types 4 and 5.") @Test public void handleRoutingChange_currentActivePortIsHome() { HdmiCecMessage message = - HdmiCecMessageBuilder.buildRoutingChange(ADDR_TV, 0x3000, mAvrPhysicalAddress); + HdmiCecMessageBuilder.buildRoutingChange(ADDR_TV, 0x3000, SELF_PHYSICAL_ADDRESS); HdmiCecMessage expectedMessage = - HdmiCecMessageBuilder.buildActiveSource(ADDR_PLAYBACK_1, mAvrPhysicalAddress); - ActiveSource expectedActiveSource = ActiveSource.of(ADDR_PLAYBACK_1, mAvrPhysicalAddress); + HdmiCecMessageBuilder.buildActiveSource(ADDR_PLAYBACK_1, SELF_PHYSICAL_ADDRESS); + ActiveSource expectedActiveSource = ActiveSource.of(ADDR_PLAYBACK_1, SELF_PHYSICAL_ADDRESS); int expectedLocalActivePort = Constants.CEC_SWITCH_HOME; assertThat(mHdmiCecLocalDeviceAudioSystem.handleRoutingChange(message)).isTrue(); @@ -608,17 +600,18 @@ public class HdmiCecLocalDeviceAudioSystemTest { @Test public void handleRoutingInformation_currentActivePortIsHDMI1() { HdmiCecMessage message = - HdmiCecMessageBuilder.buildRoutingInformation(ADDR_TV, 0x2000); - mHdmiCecLocalDeviceAudioSystem.setRoutingPort(Constants.CEC_SWITCH_HDMI1); + HdmiCecMessageBuilder.buildRoutingInformation(ADDR_TV, SELF_PHYSICAL_ADDRESS); + mHdmiCecLocalDeviceAudioSystem.setRoutingPort(mHdmiPortInfo[1].getId()); HdmiCecMessage expectedMessage = - HdmiCecMessageBuilder.buildRoutingInformation(ADDR_AUDIO_SYSTEM, 0x2100); + HdmiCecMessageBuilder.buildRoutingInformation( + ADDR_AUDIO_SYSTEM, HDMI_1_PHYSICAL_ADDRESS); assertThat(mHdmiCecLocalDeviceAudioSystem.handleRoutingInformation(message)).isTrue(); mTestLooper.dispatchAll(); assertThat(mNativeWrapper.getOnlyResultMessage()).isEqualTo(expectedMessage); } - @Ignore("b/110413065 Support multiple device types 4 and 5.") + @Ignore("b/120845532") @Test public void handleRoutingChange_homeIsActive_playbackSendActiveSource() { HdmiCecMessage message = @@ -667,7 +660,7 @@ public class HdmiCecLocalDeviceAudioSystemTest { mHdmiCecLocalDeviceAudioSystem.addDeviceInfo(oldDevice); HdmiDeviceInfo differentDevice = new HdmiDeviceInfo( - ADDR_PLAYBACK_1, 0x2100, 4, HdmiDeviceInfo.DEVICE_PLAYBACK, + ADDR_PLAYBACK_1, 0x2300, 4, HdmiDeviceInfo.DEVICE_PLAYBACK, Constants.UNKNOWN_VENDOR_ID, HdmiUtils.getDefaultDeviceName(ADDR_PLAYBACK_1)); mHdmiCecLocalDeviceAudioSystem.updateCecDevice(differentDevice); @@ -686,14 +679,13 @@ public class HdmiCecLocalDeviceAudioSystemTest { mHdmiCecLocalDeviceAudioSystem.addDeviceInfo(oldDevice); HdmiDeviceInfo differentDevice = new HdmiDeviceInfo( - ADDR_PLAYBACK_1, 0x2200, 1, HdmiDeviceInfo.DEVICE_PLAYBACK, - Constants.UNKNOWN_VENDOR_ID, HdmiUtils.getDefaultDeviceName(ADDR_PLAYBACK_1)); + ADDR_PLAYBACK_2, 0x2200, 1, HdmiDeviceInfo.DEVICE_PLAYBACK, + Constants.UNKNOWN_VENDOR_ID, HdmiUtils.getDefaultDeviceName(ADDR_PLAYBACK_2)); HdmiCecMessage reportPhysicalAddress = HdmiCecMessageBuilder .buildReportPhysicalAddressCommand( - ADDR_PLAYBACK_1, 0x2200, HdmiDeviceInfo.DEVICE_PLAYBACK); + ADDR_PLAYBACK_2, 0x2200, HdmiDeviceInfo.DEVICE_PLAYBACK); mHdmiCecLocalDeviceAudioSystem.handleReportPhysicalAddress(reportPhysicalAddress); - mHdmiCecLocalDeviceAudioSystem.addDeviceInfo(oldDevice); mTestLooper.dispatchAll(); assertThat(mDeviceInfo).isEqualTo(differentDevice); assertThat(mHdmiCecLocalDeviceAudioSystem diff --git a/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDevicePlaybackTest.java b/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDevicePlaybackTest.java index 792c617b99ea..feae4eed7eb1 100644 --- a/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDevicePlaybackTest.java +++ b/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDevicePlaybackTest.java @@ -81,7 +81,8 @@ public class HdmiCecLocalDevicePlaybackTest { mNativeWrapper.setPhysicalAddress(mPlaybackPhysicalAddress); } - @Ignore + // Playback device does not handle routing control related feature right now + @Ignore("b/120845532") @Test public void handleSetStreamPath_underCurrentDevice() { assertThat(mHdmiCecLocalDevicePlayback.getLocalActivePath()).isEqualTo(0); diff --git a/services/tests/servicestests/src/com/android/server/hdmi/HdmiControlServiceTest.java b/services/tests/servicestests/src/com/android/server/hdmi/HdmiControlServiceTest.java index 67ce13fdef72..1f660742122d 100644 --- a/services/tests/servicestests/src/com/android/server/hdmi/HdmiControlServiceTest.java +++ b/services/tests/servicestests/src/com/android/server/hdmi/HdmiControlServiceTest.java @@ -179,6 +179,7 @@ public class HdmiControlServiceTest { @Test public void pathToPort_pathExists_weAreNonTv() { mNativeWrapper.setPhysicalAddress(0x2000); + mHdmiControlService.initPortInfo(); assertThat(mHdmiControlService.pathToPortId(0x2120)).isEqualTo(1); assertThat(mHdmiControlService.pathToPortId(0x2234)).isEqualTo(2); } @@ -186,6 +187,7 @@ public class HdmiControlServiceTest { @Test public void pathToPort_pathExists_weAreTv() { mNativeWrapper.setPhysicalAddress(0x0000); + mHdmiControlService.initPortInfo(); assertThat(mHdmiControlService.pathToPortId(0x2120)).isEqualTo(3); assertThat(mHdmiControlService.pathToPortId(0x3234)).isEqualTo(4); } @@ -193,6 +195,7 @@ public class HdmiControlServiceTest { @Test public void pathToPort_pathInvalid() { mNativeWrapper.setPhysicalAddress(0x2000); + mHdmiControlService.initPortInfo(); assertThat(mHdmiControlService.pathToPortId(0x1000)).isEqualTo(Constants.INVALID_PORT_ID); } } diff --git a/services/tests/servicestests/src/com/android/server/hdmi/HdmiUtilsTest.java b/services/tests/servicestests/src/com/android/server/hdmi/HdmiUtilsTest.java new file mode 100644 index 000000000000..985c6476d767 --- /dev/null +++ b/services/tests/servicestests/src/com/android/server/hdmi/HdmiUtilsTest.java @@ -0,0 +1,146 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.server.hdmi; + +import static com.google.common.truth.Truth.assertThat; + +import android.util.Slog; + +import androidx.test.filters.SmallTest; + +import com.android.server.hdmi.HdmiUtils.CodecSad; +import com.android.server.hdmi.HdmiUtils.DeviceConfig; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; +import org.xmlpull.v1.XmlPullParserException; + +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.util.ArrayList; +import java.util.List; + +@SmallTest +@RunWith(JUnit4.class) +/** Tests for {@link HdmiUtils} class. */ +public class HdmiUtilsTest { + + private static final String TAG = "HdmiUtilsTest"; + + private final String mExampleXML = + "<!-- A sample Short Audio Descriptor configuration xml -->" + + "<config version=\"1.0\" xmlns:xi=\"http://www.w3.org/2001/XInclude\">" + + "<device type=\"VX_AUDIO_DEVICE_IN_HDMI_ARC\">" + + "<supportedFormat format=\"AUDIO_FORMAT_LPCM\" descriptor=\"011a03\"/>" + + "<supportedFormat format=\"AUDIO_FORMAT_DD\" descriptor=\"0d0506\"/>" + + "</device>" + + "<device type=\"AUDIO_DEVICE_IN_SPDIF\">" + + "<supportedFormat format=\"AUDIO_FORMAT_LPCM\" descriptor=\"010203\"/>" + + "<supportedFormat format=\"AUDIO_FORMAT_DD\" descriptor=\"040506\"/>" + + "</device>" + + "</config>"; + + @Test + public void pathToPort_isMe() { + int targetPhysicalAddress = 0x1000; + int myPhysicalAddress = 0x1000; + assertThat(HdmiUtils.getLocalPortFromPhysicalAddress( + targetPhysicalAddress, myPhysicalAddress)).isEqualTo( + HdmiUtils.TARGET_SAME_PHYSICAL_ADDRESS); + } + + @Test + public void pathToPort_isDirectlyBelow() { + int targetPhysicalAddress = 0x1100; + int myPhysicalAddress = 0x1000; + assertThat(HdmiUtils.getLocalPortFromPhysicalAddress( + targetPhysicalAddress, myPhysicalAddress)).isEqualTo(1); + } + + @Test + public void pathToPort_isBelow() { + int targetPhysicalAddress = 0x1110; + int myPhysicalAddress = 0x1000; + assertThat(HdmiUtils.getLocalPortFromPhysicalAddress( + targetPhysicalAddress, myPhysicalAddress)).isEqualTo(1); + } + + @Test + public void pathToPort_neitherMeNorBelow() { + int targetPhysicalAddress = 0x3000; + int myPhysicalAddress = 0x2000; + assertThat(HdmiUtils.getLocalPortFromPhysicalAddress( + targetPhysicalAddress, myPhysicalAddress)).isEqualTo( + HdmiUtils.TARGET_NOT_UNDER_LOCAL_DEVICE); + + targetPhysicalAddress = 0x2200; + myPhysicalAddress = 0x3300; + assertThat(HdmiUtils.getLocalPortFromPhysicalAddress( + targetPhysicalAddress, myPhysicalAddress)).isEqualTo( + HdmiUtils.TARGET_NOT_UNDER_LOCAL_DEVICE); + + targetPhysicalAddress = 0x2213; + myPhysicalAddress = 0x2212; + assertThat(HdmiUtils.getLocalPortFromPhysicalAddress( + targetPhysicalAddress, myPhysicalAddress)).isEqualTo( + HdmiUtils.TARGET_NOT_UNDER_LOCAL_DEVICE); + + targetPhysicalAddress = 0x2340; + myPhysicalAddress = 0x2310; + assertThat(HdmiUtils.getLocalPortFromPhysicalAddress( + targetPhysicalAddress, myPhysicalAddress)).isEqualTo( + HdmiUtils.TARGET_NOT_UNDER_LOCAL_DEVICE); + } + + @Test + public void parseSampleXML() { + List<DeviceConfig> config = new ArrayList<>(); + try { + config = HdmiUtils.ShortAudioDescriptorXmlParser.parse( + new ByteArrayInputStream(mExampleXML.getBytes(StandardCharsets.UTF_8))); + } catch (IOException e) { + Slog.e(TAG, e.getMessage(), e); + } catch (XmlPullParserException e) { + Slog.e(TAG, e.getMessage(), e); + } + + CodecSad expectedCodec1 = new CodecSad(Constants.AUDIO_CODEC_LPCM, "011a03"); + CodecSad expectedCodec2 = new CodecSad(Constants.AUDIO_CODEC_DD, "0d0506"); + CodecSad expectedCodec3 = new CodecSad(Constants.AUDIO_CODEC_LPCM, "010203"); + CodecSad expectedCodec4 = new CodecSad(Constants.AUDIO_CODEC_DD, "040506"); + + List<CodecSad> expectedList1 = new ArrayList<>(); + expectedList1.add(expectedCodec1); + expectedList1.add(expectedCodec2); + + List<CodecSad> expectedList2 = new ArrayList<>(); + expectedList2.add(expectedCodec3); + expectedList2.add(expectedCodec4); + + DeviceConfig expectedDevice1 = new DeviceConfig( + "VX_AUDIO_DEVICE_IN_HDMI_ARC", expectedList1); + DeviceConfig expectedDevice2 = new DeviceConfig( + "AUDIO_DEVICE_IN_SPDIF", expectedList2); + + List<DeviceConfig> expectedConfig = new ArrayList<>(); + expectedConfig.add(expectedDevice1); + expectedConfig.add(expectedDevice2); + + assertThat(config).isEqualTo(expectedConfig); + } +} diff --git a/services/tests/servicestests/src/com/android/server/hdmi/SystemAudioInitiationActionFromAvrTest.java b/services/tests/servicestests/src/com/android/server/hdmi/SystemAudioInitiationActionFromAvrTest.java index bd297eecf25c..440a49ab81fc 100644 --- a/services/tests/servicestests/src/com/android/server/hdmi/SystemAudioInitiationActionFromAvrTest.java +++ b/services/tests/servicestests/src/com/android/server/hdmi/SystemAudioInitiationActionFromAvrTest.java @@ -31,6 +31,7 @@ import androidx.test.InstrumentationRegistry; import androidx.test.filters.SmallTest; import org.junit.Before; +import org.junit.Ignore; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; @@ -150,6 +151,11 @@ public class SystemAudioInitiationActionFromAvrTest { int sourceAddress, int physicalAddress) { mBroadcastActiveSource = true; } + + @Override + int pathToPortId(int path) { + return -1; + } }; mHdmiCecLocalDeviceAudioSystem = new HdmiCecLocalDeviceAudioSystem(hdmiControlService) { @@ -270,6 +276,7 @@ public class SystemAudioInitiationActionFromAvrTest { assertTrue(mHdmiCecLocalDeviceAudioSystem.isSystemAudioActivated()); } + @Ignore("b/120845532") @Test public void testIsPlaybackDevice_cannotReceiveActiveSource() { resetTestVariables(); @@ -282,10 +289,10 @@ public class SystemAudioInitiationActionFromAvrTest { mTestLooper.dispatchAll(); assertThat(mMsgRequestActiveSourceCount).isEqualTo(1); - assertThat(mMsgSetSystemAudioModeCount).isEqualTo(1); + assertThat(mBroadcastActiveSource).isTrue(); assertThat(mQueryTvSystemAudioModeSupportCount).isEqualTo(1); + assertThat(mMsgSetSystemAudioModeCount).isEqualTo(1); assertThat(mHdmiCecLocalDeviceAudioSystem.isSystemAudioActivated()).isTrue(); - assertThat(mBroadcastActiveSource).isTrue(); } private void resetTestVariables() { diff --git a/services/tests/servicestests/src/com/android/server/job/JobCountTrackerTest.java b/services/tests/servicestests/src/com/android/server/job/JobCountTrackerTest.java new file mode 100644 index 000000000000..e5529cb899cc --- /dev/null +++ b/services/tests/servicestests/src/com/android/server/job/JobCountTrackerTest.java @@ -0,0 +1,305 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.server.job; + +import static com.google.common.truth.Truth.assertThat; + +import android.util.Log; + +import com.android.server.job.JobConcurrencyManager.JobCountTracker; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; + +import java.util.Random; + +import androidx.test.filters.MediumTest; +import androidx.test.runner.AndroidJUnit4; + +/** + * Test for {@link com.android.server.job.JobConcurrencyManager.JobCountTracker}. + */ +@RunWith(AndroidJUnit4.class) +@MediumTest +public class JobCountTrackerTest { + private static final String TAG = "JobCountTrackerTest"; + + private Random mRandom; + private JobCountTracker mJobCountTracker; + + @Before + public void setUp() { + mRandom = new Random(1); // Always use the same series of pseudo random values. + mJobCountTracker = new JobCountTracker(); + } + + /** + * Represents running and pending jobs. + */ + class Jobs { + public int runningFg; + public int runningBg; + public int pendingFg; + public int pendingBg; + + public void maybeEnqueueJobs(double startRatio, double fgJobRatio) { + while (mRandom.nextDouble() < startRatio) { + if (mRandom.nextDouble() < fgJobRatio) { + pendingFg++; + } else { + pendingBg++; + } + } + } + + public void maybeFinishJobs(double stopRatio) { + for (int i = runningBg; i > 0; i--) { + if (mRandom.nextDouble() < stopRatio) { + runningBg--; + } + } + for (int i = runningFg; i > 0; i--) { + if (mRandom.nextDouble() < stopRatio) { + runningFg--; + } + } + } + } + + + private void startPendingJobs(Jobs jobs, int totalMax, int maxBg, int minBg) { + mJobCountTracker.reset(totalMax, maxBg, minBg); + + for (int i = 0; i < jobs.runningFg; i++) { + mJobCountTracker.incrementRunningJobCount(true); + } + for (int i = 0; i < jobs.runningBg; i++) { + mJobCountTracker.incrementRunningJobCount(false); + } + + for (int i = 0; i < jobs.pendingFg; i++) { + mJobCountTracker.incrementPendingJobCount(true); + } + for (int i = 0; i < jobs.pendingBg; i++) { + mJobCountTracker.incrementPendingJobCount(false); + } + + mJobCountTracker.onCountDone(); + + while ((jobs.pendingFg > 0 && mJobCountTracker.canJobStart(true)) + || (jobs.pendingBg > 0 && mJobCountTracker.canJobStart(false))) { + final boolean isStartingFg = mRandom.nextBoolean(); + + if (isStartingFg) { + if (jobs.pendingFg > 0 && mJobCountTracker.canJobStart(true)) { + jobs.pendingFg--; + jobs.runningFg++; + mJobCountTracker.onStartingNewJob(true); + } + } else { + if (jobs.pendingBg > 0 && mJobCountTracker.canJobStart(false)) { + jobs.pendingBg--; + jobs.runningBg++; + mJobCountTracker.onStartingNewJob(false); + } + } + } + + Log.i(TAG, "" + mJobCountTracker); + } + + /** + * Used by the following testRandom* tests. + */ + private void checkRandom(Jobs jobs, int numTests, int totalMax, int maxBg, int minBg, + double startRatio, double fgJobRatio, double stopRatio) { + for (int i = 0; i < numTests; i++) { + + jobs.maybeFinishJobs(stopRatio); + jobs.maybeEnqueueJobs(startRatio, fgJobRatio); + + startPendingJobs(jobs, totalMax, maxBg, minBg); + + assertThat(jobs.runningFg).isAtMost(totalMax); + assertThat(jobs.runningBg).isAtMost(totalMax); + assertThat(jobs.runningFg + jobs.runningBg).isAtMost(totalMax); + assertThat(jobs.runningBg).isAtMost(maxBg); + } + } + + /** + * Randomly enqueue / stop jobs and make sure we won't run more jobs than we should. + */ + @Test + public void testRandom1() { + final Jobs jobs = new Jobs(); + + final int numTests = 5000; + final int totalMax = 6; + final int maxBg = 4; + final int minBg = 2; + final double stopRatio = 0.1; + final double fgJobRatio = 0.5; + final double startRatio = 0.1; + + checkRandom(jobs, numTests, totalMax, maxBg, minBg, startRatio, fgJobRatio , stopRatio); + } + + @Test + public void testRandom2() { + final Jobs jobs = new Jobs(); + + final int numTests = 5000; + final int totalMax = 2; + final int maxBg = 2; + final int minBg = 0; + final double stopRatio = 0.5; + final double fgJobRatio = 0.5; + final double startRatio = 0.5; + + checkRandom(jobs, numTests, totalMax, maxBg, minBg, startRatio, fgJobRatio, stopRatio); + } + + @Test + public void testRandom3() { + final Jobs jobs = new Jobs(); + + final int numTests = 5000; + final int totalMax = 2; + final int maxBg = 2; + final int minBg = 2; + final double stopRatio = 0.5; + final double fgJobRatio = 0.5; + final double startRatio = 0.5; + + checkRandom(jobs, numTests, totalMax, maxBg, minBg, startRatio, fgJobRatio, stopRatio); + } + + @Test + public void testRandom4() { + final Jobs jobs = new Jobs(); + + final int numTests = 5000; + final int totalMax = 10; + final int maxBg = 2; + final int minBg = 0; + final double stopRatio = 0.5; + final double fgJobRatio = 0.5; + final double startRatio = 0.5; + + checkRandom(jobs, numTests, totalMax, maxBg, minBg, startRatio, fgJobRatio, stopRatio); + } + + @Test + public void testRandom5() { + final Jobs jobs = new Jobs(); + + final int numTests = 5000; + final int totalMax = 6; + final int maxBg = 4; + final int minBg = 2; + final double stopRatio = 0.5; + final double fgJobRatio = 0.1; + final double startRatio = 0.5; + + checkRandom(jobs, numTests, totalMax, maxBg, minBg, startRatio, fgJobRatio, stopRatio); + } + + @Test + public void testRandom6() { + final Jobs jobs = new Jobs(); + + final int numTests = 5000; + final int totalMax = 6; + final int maxBg = 4; + final int minBg = 2; + final double stopRatio = 0.5; + final double fgJobRatio = 0.9; + final double startRatio = 0.5; + + checkRandom(jobs, numTests, totalMax, maxBg, minBg, startRatio, fgJobRatio, stopRatio); + } + + @Test + public void testRandom7() { + final Jobs jobs = new Jobs(); + + final int numTests = 5000; + final int totalMax = 6; + final int maxBg = 4; + final int minBg = 2; + final double stopRatio = 0.4; + final double fgJobRatio = 0.1; + final double startRatio = 0.5; + + checkRandom(jobs, numTests, totalMax, maxBg, minBg, startRatio, fgJobRatio, stopRatio); + } + + @Test + public void testRandom8() { + final Jobs jobs = new Jobs(); + + final int numTests = 5000; + final int totalMax = 6; + final int maxBg = 4; + final int minBg = 2; + final double stopRatio = 0.4; + final double fgJobRatio = 0.9; + final double startRatio = 0.5; + + checkRandom(jobs, numTests, totalMax, maxBg, minBg, startRatio, fgJobRatio, stopRatio); + } + + /** Used by the following tests */ + private void checkSimple(int totalMax, int maxBg, int minBg, + int runningFg, int runningBg, int pendingFg, int pendingBg, + int resultRunningFg, int resultRunningBg, int resultPendingFg, int resultPendingBg) { + final Jobs jobs = new Jobs(); + jobs.runningFg = runningFg; + jobs.runningBg = runningBg; + jobs.pendingFg = pendingFg; + jobs.pendingBg = pendingBg; + + startPendingJobs(jobs, totalMax, maxBg, minBg); + + assertThat(jobs.runningFg).isEqualTo(resultRunningFg); + assertThat(jobs.runningBg).isEqualTo(resultRunningBg); + + assertThat(jobs.pendingFg).isEqualTo(resultPendingFg); + assertThat(jobs.pendingBg).isEqualTo(resultPendingBg); + } + + + @Test + public void testBasic() { + // Args are: + // First 3: Total-max, bg-max, bg-min. + // Next 2: Running FG / BG + // Next 2: Pending FG / BG + // Next 4: Result running FG / BG, pending FG/BG. + checkSimple(6, 4, 2, /*run=*/ 0, 0, /*pen=*/ 1, 0, /*res run/pen=*/ 1, 0, 0, 0); + + checkSimple(6, 4, 2, /*run=*/ 0, 0, /*pen=*/ 10, 0, /*res run/pen=*/ 6, 0, 4, 0); + + // When there are BG jobs pending, 2 (min-BG) jobs should run. + checkSimple(6, 4, 2, /*run=*/ 0, 0, /*pen=*/ 10, 1, /*res run/pen=*/ 5, 1, 5, 0); + checkSimple(6, 4, 2, /*run=*/ 0, 0, /*pen=*/ 10, 3, /*res run/pen=*/ 4, 2, 6, 1); + + checkSimple(6, 4, 2, /*run=*/ 6, 0, /*pen=*/ 10, 3, /*res run/pen=*/ 6, 0, 10, 3); + } +} diff --git a/services/tests/servicestests/src/com/android/server/job/MaxJobCountsTest.java b/services/tests/servicestests/src/com/android/server/job/MaxJobCountsTest.java new file mode 100644 index 000000000000..01199a36ff5b --- /dev/null +++ b/services/tests/servicestests/src/com/android/server/job/MaxJobCountsTest.java @@ -0,0 +1,67 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.server.job; + +import android.util.KeyValueListParser; + +import com.android.server.job.JobSchedulerService.MaxJobCounts; + +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; + +import androidx.test.filters.SmallTest; +import androidx.test.runner.AndroidJUnit4; + +@RunWith(AndroidJUnit4.class) +@SmallTest +public class MaxJobCountsTest { + + private void check(String config, + int defaultTotal, int defaultMaxBg, int defaultMinBg, + int expectedTotal, int expectedMaxBg, int expectedMinBg) { + final KeyValueListParser parser = new KeyValueListParser(','); + parser.setString(config); + + final MaxJobCounts counts = new JobSchedulerService.MaxJobCounts( + defaultTotal, "total", + defaultMaxBg, "maxbg", + defaultMinBg, "minbg"); + + counts.parse(parser); + + Assert.assertEquals(expectedTotal, counts.getTotalMax()); + Assert.assertEquals(expectedMaxBg, counts.getMaxBg()); + Assert.assertEquals(expectedMinBg, counts.getMinBg()); + } + + @Test + public void test() { + check("", /*default*/ 5, 1, 0, /*expected*/ 5, 1, 0); + check("", /*default*/ 5, 0, 0, /*expected*/ 5, 1, 0); + check("", /*default*/ 0, 0, 0, /*expected*/ 1, 1, 0); + check("", /*default*/ -1, -1, -1, /*expected*/ 1, 1, 0); + check("", /*default*/ 5, 5, 5, /*expected*/ 5, 5, 4); + check("", /*default*/ 6, 5, 6, /*expected*/ 6, 5, 5); + check("", /*default*/ 4, 5, 6, /*expected*/ 4, 4, 3); + check("", /*default*/ 5, 1, 1, /*expected*/ 5, 1, 1); + + check("total=5,maxbg=4,minbg=3", /*default*/ 9, 9, 9, /*expected*/ 5, 4, 3); + check("total=5", /*default*/ 9, 9, 9, /*expected*/ 5, 5, 4); + check("maxbg=4", /*default*/ 9, 9, 9, /*expected*/ 9, 4, 4); + check("minbg=3", /*default*/ 9, 9, 9, /*expected*/ 9, 9, 3); + } +} diff --git a/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/KeySyncTaskTest.java b/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/KeySyncTaskTest.java index 8a9e5d181777..c2d4846b14c0 100644 --- a/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/KeySyncTaskTest.java +++ b/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/KeySyncTaskTest.java @@ -23,6 +23,7 @@ import static android.security.keystore.recovery.KeyChainProtectionParams.UI_FOR import static com.android.internal.widget.LockPatternUtils.CREDENTIAL_TYPE_PASSWORD; import static com.android.internal.widget.LockPatternUtils.CREDENTIAL_TYPE_PATTERN; + import static com.google.common.truth.Truth.assertThat; import static org.junit.Assert.assertArrayEquals; @@ -91,6 +92,9 @@ public class KeySyncTaskTest { private static final byte[] TEST_VAULT_HANDLE = new byte[]{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17}; private static final String TEST_APP_KEY_ALIAS = "rcleaver"; + private static final byte[] TEST_APP_KEY_METADATA_NULL = null; + private static final byte[] TEST_APP_KEY_METADATA_NON_NULL = + "mdata".getBytes(StandardCharsets.UTF_8); private static final int TEST_GENERATION_ID = 2; private static final int TEST_CREDENTIAL_TYPE = CREDENTIAL_TYPE_PATTERN; private static final String TEST_CREDENTIAL = "pas123"; @@ -251,7 +255,7 @@ public class KeySyncTaskTest { TEST_USER_ID, TEST_RECOVERY_AGENT_UID, TEST_APP_KEY_ALIAS, - WrappedKey.fromSecretKey(mEncryptKey, applicationKey)); + WrappedKey.fromSecretKey(mEncryptKey, applicationKey, TEST_APP_KEY_METADATA_NULL)); when(mSnapshotListenersStorage.hasListener(TEST_RECOVERY_AGENT_UID)).thenReturn(true); mKeySyncTask.run(); @@ -267,7 +271,7 @@ public class KeySyncTaskTest { TEST_USER_ID, TEST_RECOVERY_AGENT_UID, TEST_APP_KEY_ALIAS, - WrappedKey.fromSecretKey(mEncryptKey, applicationKey)); + WrappedKey.fromSecretKey(mEncryptKey, applicationKey, TEST_APP_KEY_METADATA_NULL)); mRecoverableKeyStoreDb.setRecoveryServiceCertPath( TEST_USER_ID, TEST_RECOVERY_AGENT_UID, TEST_ROOT_CERT_ALIAS, TestData.CERT_PATH_1); when(mSnapshotListenersStorage.hasListener(TEST_RECOVERY_AGENT_UID)).thenReturn(true); @@ -545,18 +549,20 @@ public class KeySyncTaskTest { assertEquals(TEST_APP_KEY_ALIAS, keyData.getAlias()); assertThat(keyData.getAlias()).isEqualTo(keyData.getAlias()); byte[] appKey = KeySyncUtils.decryptApplicationKey( - recoveryKey, keyData.getEncryptedKeyMaterial()); + recoveryKey, keyData.getEncryptedKeyMaterial(), TEST_APP_KEY_METADATA_NULL); assertThat(appKey).isEqualTo(applicationKey.getEncoded()); } @Test - public void run_sendsEncryptedKeysIfAvailableToSync_withCertPath() throws Exception { + public void run_sendsEncryptedKeysIfAvailableToSync_withCertPath_withNullKeyMetadata() + throws Exception { mRecoverableKeyStoreDb.setRecoveryServiceCertPath( TEST_USER_ID, TEST_RECOVERY_AGENT_UID, TEST_ROOT_CERT_ALIAS, TestData.CERT_PATH_1); mRecoverableKeyStoreDb.setServerParams( TEST_USER_ID, TEST_RECOVERY_AGENT_UID, TEST_VAULT_HANDLE); when(mSnapshotListenersStorage.hasListener(TEST_RECOVERY_AGENT_UID)).thenReturn(true); - addApplicationKey(TEST_USER_ID, TEST_RECOVERY_AGENT_UID, TEST_APP_KEY_ALIAS); + addApplicationKey(TEST_USER_ID, TEST_RECOVERY_AGENT_UID, TEST_APP_KEY_ALIAS, + TEST_APP_KEY_METADATA_NULL); mKeySyncTask.run(); @@ -564,6 +570,33 @@ public class KeySyncTaskTest { verify(mSnapshotListenersStorage).recoverySnapshotAvailable(TEST_RECOVERY_AGENT_UID); List<WrappedApplicationKey> applicationKeys = keyChainSnapshot.getWrappedApplicationKeys(); assertThat(applicationKeys).hasSize(1); + WrappedApplicationKey keyData = applicationKeys.get(0); + assertThat(keyData.getAlias()).isEqualTo(TEST_APP_KEY_ALIAS); + assertThat(keyData.getMetadata()).isEqualTo(TEST_APP_KEY_METADATA_NULL); + assertThat(keyChainSnapshot.getTrustedHardwareCertPath()) + .isEqualTo(TestData.CERT_PATH_1); + } + + @Test + public void run_sendsEncryptedKeysIfAvailableToSync_withCertPath_withNonNullKeyMetadata() + throws Exception { + mRecoverableKeyStoreDb.setRecoveryServiceCertPath( + TEST_USER_ID, TEST_RECOVERY_AGENT_UID, TEST_ROOT_CERT_ALIAS, TestData.CERT_PATH_1); + mRecoverableKeyStoreDb.setServerParams( + TEST_USER_ID, TEST_RECOVERY_AGENT_UID, TEST_VAULT_HANDLE); + when(mSnapshotListenersStorage.hasListener(TEST_RECOVERY_AGENT_UID)).thenReturn(true); + addApplicationKey(TEST_USER_ID, TEST_RECOVERY_AGENT_UID, TEST_APP_KEY_ALIAS, + TEST_APP_KEY_METADATA_NON_NULL); + + mKeySyncTask.run(); + + KeyChainSnapshot keyChainSnapshot = mRecoverySnapshotStorage.get(TEST_RECOVERY_AGENT_UID); + verify(mSnapshotListenersStorage).recoverySnapshotAvailable(TEST_RECOVERY_AGENT_UID); + List<WrappedApplicationKey> applicationKeys = keyChainSnapshot.getWrappedApplicationKeys(); + assertThat(applicationKeys).hasSize(1); + WrappedApplicationKey keyData = applicationKeys.get(0); + assertThat(keyData.getAlias()).isEqualTo(TEST_APP_KEY_ALIAS); + assertThat(keyData.getMetadata()).isEqualTo(TEST_APP_KEY_METADATA_NON_NULL); assertThat(keyChainSnapshot.getTrustedHardwareCertPath()) .isEqualTo(TestData.CERT_PATH_1); } @@ -788,6 +821,11 @@ public class KeySyncTaskTest { private SecretKey addApplicationKey(int userId, int recoveryAgentUid, String alias) throws Exception{ + return addApplicationKey(userId, recoveryAgentUid, alias, TEST_APP_KEY_METADATA_NULL); + } + + private SecretKey addApplicationKey(int userId, int recoveryAgentUid, String alias, + byte[] metadata) throws Exception { SecretKey applicationKey = generateKey(); mRecoverableKeyStoreDb.setServerParams( userId, recoveryAgentUid, TEST_VAULT_HANDLE); @@ -800,7 +838,7 @@ public class KeySyncTaskTest { userId, recoveryAgentUid, alias, - WrappedKey.fromSecretKey(mEncryptKey, applicationKey)); + WrappedKey.fromSecretKey(mEncryptKey, applicationKey, metadata)); return applicationKey; } diff --git a/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/KeySyncUtilsTest.java b/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/KeySyncUtilsTest.java index f832d3ceef8e..178fd104a1ae 100644 --- a/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/KeySyncUtilsTest.java +++ b/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/KeySyncUtilsTest.java @@ -22,6 +22,8 @@ import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; +import android.util.Pair; + import androidx.test.filters.SmallTest; import androidx.test.runner.AndroidJUnit4; @@ -65,7 +67,8 @@ public class KeySyncUtilsTest { private static final byte[] RECOVERY_RESPONSE_HEADER = "V1 reencrypted_recovery_key".getBytes(StandardCharsets.UTF_8); private static final int PUBLIC_KEY_LENGTH_BYTES = 65; - + private static final byte[] NULL_METADATA = null; + private static final byte[] NON_NULL_METADATA = "somemetadata".getBytes(StandardCharsets.UTF_8); @Test public void calculateThmKfHash_isShaOfLockScreenHashWithPrefix() throws Exception { @@ -125,18 +128,35 @@ public class KeySyncUtilsTest { } @Test - public void decryptApplicationKey_decryptsAnApplicationKeyEncryptedWithSecureBox() - throws Exception { + public void decryptApplicationKey_decryptsAnApplicationKey_nullMetadata() throws Exception { String alias = "phoebe"; SecretKey recoveryKey = KeySyncUtils.generateRecoveryKey(); SecretKey applicationKey = generateApplicationKey(); Map<String, byte[]> encryptedKeys = KeySyncUtils.encryptKeysWithRecoveryKey( - recoveryKey, ImmutableMap.of(alias, applicationKey)); + recoveryKey, + ImmutableMap.of(alias, Pair.create(applicationKey, NULL_METADATA))); byte[] encryptedKey = encryptedKeys.get(alias); - byte[] keyMaterial = - KeySyncUtils.decryptApplicationKey(recoveryKey.getEncoded(), encryptedKey); + byte[] keyMaterial = KeySyncUtils.decryptApplicationKey(recoveryKey.getEncoded(), + encryptedKey, NULL_METADATA); + + assertArrayEquals(applicationKey.getEncoded(), keyMaterial); + } + + @Test + public void decryptApplicationKey_decryptsAnApplicationKey_nonNullMetadata() throws Exception { + String alias = "phoebe"; + SecretKey recoveryKey = KeySyncUtils.generateRecoveryKey(); + SecretKey applicationKey = generateApplicationKey(); + Map<String, byte[]> encryptedKeys = + KeySyncUtils.encryptKeysWithRecoveryKey( + recoveryKey, + ImmutableMap.of(alias, Pair.create(applicationKey, NON_NULL_METADATA))); + byte[] encryptedKey = encryptedKeys.get(alias); + + byte[] keyMaterial = KeySyncUtils.decryptApplicationKey(recoveryKey.getEncoded(), + encryptedKey, NON_NULL_METADATA); assertArrayEquals(applicationKey.getEncoded(), keyMaterial); } @@ -147,12 +167,13 @@ public class KeySyncUtilsTest { Map<String, byte[]> encryptedKeys = KeySyncUtils.encryptKeysWithRecoveryKey( KeySyncUtils.generateRecoveryKey(), - ImmutableMap.of("casper", generateApplicationKey())); + ImmutableMap.of("casper", + Pair.create(generateApplicationKey(), NULL_METADATA))); byte[] encryptedKey = encryptedKeys.get(alias); try { - KeySyncUtils.decryptApplicationKey( - KeySyncUtils.generateRecoveryKey().getEncoded(), encryptedKey); + KeySyncUtils.decryptApplicationKey(KeySyncUtils.generateRecoveryKey().getEncoded(), + encryptedKey, NULL_METADATA); fail("Did not throw decrypting with bad key."); } catch (AEADBadTagException error) { // expected @@ -160,6 +181,47 @@ public class KeySyncUtilsTest { } @Test + public void decryptApplicationKey_throwsIfWrongMetadata() throws Exception { + String alias1 = "casper1"; + String alias2 = "casper2"; + String alias3 = "casper3"; + SecretKey recoveryKey = KeySyncUtils.generateRecoveryKey(); + + Map<String, byte[]> encryptedKeys = + KeySyncUtils.encryptKeysWithRecoveryKey( + recoveryKey, + ImmutableMap.of( + alias1, + Pair.create(generateApplicationKey(), NULL_METADATA), + alias2, + Pair.create(generateApplicationKey(), NON_NULL_METADATA), + alias3, + Pair.create(generateApplicationKey(), NON_NULL_METADATA))); + + try { + KeySyncUtils.decryptApplicationKey(recoveryKey.getEncoded(), + encryptedKeys.get(alias1), NON_NULL_METADATA); + fail("Did not throw decrypting with wrong metadata."); + } catch (AEADBadTagException error) { + // expected + } + try { + KeySyncUtils.decryptApplicationKey(recoveryKey.getEncoded(), + encryptedKeys.get(alias2), NULL_METADATA); + fail("Did not throw decrypting with wrong metadata."); + } catch (AEADBadTagException error) { + // expected + } + try { + KeySyncUtils.decryptApplicationKey(recoveryKey.getEncoded(), + encryptedKeys.get(alias3), "different".getBytes(StandardCharsets.UTF_8)); + fail("Did not throw decrypting with wrong metadata."); + } catch (AEADBadTagException error) { + // expected + } + } + + @Test public void decryptRecoveryKey_decryptsALocallyEncryptedKey() throws Exception { SecretKey recoveryKey = KeySyncUtils.generateRecoveryKey(); byte[] encrypted = KeySyncUtils.locallyEncryptRecoveryKey( diff --git a/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/RecoverableKeyGeneratorTest.java b/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/RecoverableKeyGeneratorTest.java index 48afb8b6abcb..c295177814b0 100644 --- a/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/RecoverableKeyGeneratorTest.java +++ b/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/RecoverableKeyGeneratorTest.java @@ -20,6 +20,7 @@ import static junit.framework.Assert.assertNotNull; import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; import android.content.Context; import android.security.keystore.AndroidKeyStoreSecretKey; @@ -60,6 +61,9 @@ public class RecoverableKeyGeneratorTest { private static final int TEST_USER_ID = 1000; private static final int KEYSTORE_UID_SELF = -1; private static final int GCM_TAG_LENGTH_BITS = 128; + private static final byte[] NULL_METADATA = null; + private static final byte[] NON_NULL_METADATA = "test-metadata".getBytes( + StandardCharsets.UTF_8); private PlatformEncryptionKey mPlatformKey; private PlatformDecryptionKey mDecryptKey; @@ -90,18 +94,29 @@ public class RecoverableKeyGeneratorTest { } @Test - public void generateAndStoreKey_storesWrappedKey() throws Exception { + public void generateAndStoreKey_storesWrappedKey_nullMetadata() throws Exception { mRecoverableKeyGenerator.generateAndStoreKey( - mPlatformKey, TEST_USER_ID, KEYSTORE_UID_SELF, TEST_ALIAS); + mPlatformKey, TEST_USER_ID, KEYSTORE_UID_SELF, TEST_ALIAS, NULL_METADATA); WrappedKey wrappedKey = mRecoverableKeyStoreDb.getKey(KEYSTORE_UID_SELF, TEST_ALIAS); assertNotNull(wrappedKey); + assertNull(wrappedKey.getKeyMetadata()); + } + + @Test + public void generateAndStoreKey_storesWrappedKey_nonNullMetadata() throws Exception { + mRecoverableKeyGenerator.generateAndStoreKey( + mPlatformKey, TEST_USER_ID, KEYSTORE_UID_SELF, TEST_ALIAS, NON_NULL_METADATA); + + WrappedKey wrappedKey = mRecoverableKeyStoreDb.getKey(KEYSTORE_UID_SELF, TEST_ALIAS); + assertNotNull(wrappedKey); + assertArrayEquals(NON_NULL_METADATA, wrappedKey.getKeyMetadata()); } @Test public void generateAndStoreKey_returnsRawMaterialOfCorrectLength() throws Exception { byte[] rawKey = mRecoverableKeyGenerator.generateAndStoreKey( - mPlatformKey, TEST_USER_ID, KEYSTORE_UID_SELF, TEST_ALIAS); + mPlatformKey, TEST_USER_ID, KEYSTORE_UID_SELF, TEST_ALIAS, NON_NULL_METADATA); assertEquals(KEY_SIZE_BYTES, rawKey.length); } @@ -109,7 +124,7 @@ public class RecoverableKeyGeneratorTest { @Test public void generateAndStoreKey_storesTheWrappedVersionOfTheRawMaterial() throws Exception { byte[] rawMaterial = mRecoverableKeyGenerator.generateAndStoreKey( - mPlatformKey, TEST_USER_ID, KEYSTORE_UID_SELF, TEST_ALIAS); + mPlatformKey, TEST_USER_ID, KEYSTORE_UID_SELF, TEST_ALIAS, NULL_METADATA); WrappedKey wrappedKey = mRecoverableKeyStoreDb.getKey(KEYSTORE_UID_SELF, TEST_ALIAS); Cipher cipher = Cipher.getInstance(KEY_WRAP_ALGORITHM); @@ -120,10 +135,30 @@ public class RecoverableKeyGeneratorTest { } @Test + public void importKey_storesNullMetadata() throws Exception { + mRecoverableKeyGenerator.importKey( + mPlatformKey, TEST_USER_ID, KEYSTORE_UID_SELF, TEST_ALIAS, + randomBytes(KEY_SIZE_BYTES), + NULL_METADATA); + assertNull(mRecoverableKeyStoreDb.getKey(KEYSTORE_UID_SELF, TEST_ALIAS).getKeyMetadata()); + } + + @Test + public void importKey_storesNonNullMetadata() throws Exception { + mRecoverableKeyGenerator.importKey( + mPlatformKey, TEST_USER_ID, KEYSTORE_UID_SELF, TEST_ALIAS, + randomBytes(KEY_SIZE_BYTES), + NON_NULL_METADATA); + assertArrayEquals(NON_NULL_METADATA, + mRecoverableKeyStoreDb.getKey(KEYSTORE_UID_SELF, TEST_ALIAS).getKeyMetadata()); + } + + @Test public void importKey_storesTheWrappedVersionOfTheRawMaterial() throws Exception { byte[] rawMaterial = randomBytes(KEY_SIZE_BYTES); mRecoverableKeyGenerator.importKey( - mPlatformKey, TEST_USER_ID, KEYSTORE_UID_SELF, TEST_ALIAS, rawMaterial); + mPlatformKey, TEST_USER_ID, KEYSTORE_UID_SELF, TEST_ALIAS, rawMaterial, + NULL_METADATA); WrappedKey wrappedKey = mRecoverableKeyStoreDb.getKey(KEYSTORE_UID_SELF, TEST_ALIAS); Cipher cipher = Cipher.getInstance(KEY_WRAP_ALGORITHM); @@ -145,10 +180,6 @@ public class RecoverableKeyGeneratorTest { return (AndroidKeyStoreSecretKey) keyGenerator.generateKey(); } - private static byte[] getUtf8Bytes(String s) { - return s.getBytes(StandardCharsets.UTF_8); - } - private static byte[] randomBytes(int n) { byte[] bytes = new byte[n]; new Random().nextBytes(bytes); diff --git a/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/RecoverableKeyStoreManagerTest.java b/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/RecoverableKeyStoreManagerTest.java index b15863dd3613..c78b96d2d294 100644 --- a/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/RecoverableKeyStoreManagerTest.java +++ b/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/RecoverableKeyStoreManagerTest.java @@ -52,6 +52,7 @@ import android.security.keystore.recovery.KeyDerivationParams; import android.security.keystore.recovery.RecoveryCertPath; import android.security.keystore.recovery.TrustedRootCertificates; import android.security.keystore.recovery.WrappedApplicationKey; +import android.util.Pair; import androidx.test.InstrumentationRegistry; import androidx.test.filters.SmallTest; @@ -134,6 +135,8 @@ public class RecoverableKeyStoreManagerTest { private static final int GENERATION_ID = 1; private static final byte[] NONCE = getUtf8Bytes("nonce"); private static final byte[] KEY_MATERIAL = getUtf8Bytes("keymaterial"); + private static final byte[] KEY_METADATA_NULL = null; + private static final byte[] KEY_METADATA_NON_NULL = getUtf8Bytes("keymetametadata"); private static final String KEY_ALGORITHM = "AES"; private static final String ANDROID_KEY_STORE_PROVIDER = "AndroidKeyStore"; private static final String WRAPPING_KEY_ALIAS = "RecoverableKeyStoreManagerTest/WrappingKey"; @@ -231,6 +234,77 @@ public class RecoverableKeyStoreManagerTest { } @Test + public void importKeyWithMetadata_nullMetadata_storesTheKey() throws Exception { + int uid = Binder.getCallingUid(); + int userId = UserHandle.getCallingUserId(); + byte[] keyMaterial = randomBytes(APPLICATION_KEY_SIZE_BYTES); + + mRecoverableKeyStoreManager.importKeyWithMetadata( + TEST_ALIAS, keyMaterial, KEY_METADATA_NULL); + + assertThat(mRecoverableKeyStoreDb.getKey(uid, TEST_ALIAS)).isNotNull(); + assertThat(mRecoverableKeyStoreDb.getShouldCreateSnapshot(userId, uid)).isTrue(); + } + + @Test + public void importKeyWithMetadata_nonNullMetadata_storesTheKey() throws Exception { + int uid = Binder.getCallingUid(); + int userId = UserHandle.getCallingUserId(); + byte[] keyMaterial = randomBytes(APPLICATION_KEY_SIZE_BYTES); + + mRecoverableKeyStoreManager.importKeyWithMetadata( + TEST_ALIAS, keyMaterial, KEY_METADATA_NON_NULL); + + assertThat(mRecoverableKeyStoreDb.getKey(uid, TEST_ALIAS)).isNotNull(); + assertThat(mRecoverableKeyStoreDb.getShouldCreateSnapshot(userId, uid)).isTrue(); + } + + @Test + public void importKeyWithMetadata_throwsIfInvalidLength() throws Exception { + byte[] keyMaterial = randomBytes(APPLICATION_KEY_SIZE_BYTES - 1); + try { + mRecoverableKeyStoreManager.importKeyWithMetadata( + TEST_ALIAS, keyMaterial, KEY_METADATA_NON_NULL); + fail("should have thrown"); + } catch (ServiceSpecificException e) { + assertThat(e.getMessage()).contains("not contain 256 bits"); + } + } + + @Test + public void importKeyWithMetadata_throwsIfNullKey() throws Exception { + try { + mRecoverableKeyStoreManager.importKeyWithMetadata( + TEST_ALIAS, /*keyBytes=*/ null, KEY_METADATA_NON_NULL); + fail("should have thrown"); + } catch (NullPointerException e) { + assertThat(e.getMessage()).contains("is null"); + } + } + + @Test + public void generateKeyWithMetadata_nullMetadata_storesTheKey() throws Exception { + int uid = Binder.getCallingUid(); + int userId = UserHandle.getCallingUserId(); + + mRecoverableKeyStoreManager.generateKeyWithMetadata(TEST_ALIAS, KEY_METADATA_NULL); + + assertThat(mRecoverableKeyStoreDb.getKey(uid, TEST_ALIAS)).isNotNull(); + assertThat(mRecoverableKeyStoreDb.getShouldCreateSnapshot(userId, uid)).isTrue(); + } + + @Test + public void generateKeyWithMetadata_nonNullMetadata_storesTheKey() throws Exception { + int uid = Binder.getCallingUid(); + int userId = UserHandle.getCallingUserId(); + + mRecoverableKeyStoreManager.generateKeyWithMetadata(TEST_ALIAS, KEY_METADATA_NON_NULL); + + assertThat(mRecoverableKeyStoreDb.getKey(uid, TEST_ALIAS)).isNotNull(); + assertThat(mRecoverableKeyStoreDb.getShouldCreateSnapshot(userId, uid)).isTrue(); + } + + @Test public void removeKey_removesAKey() throws Exception { int uid = Binder.getCallingUid(); mRecoverableKeyStoreManager.generateKey(TEST_ALIAS); @@ -1143,7 +1217,10 @@ public class RecoverableKeyStoreManagerTest { int status = 100; int status2 = 200; String alias = "key1"; - WrappedKey wrappedKey = new WrappedKey(NONCE, KEY_MATERIAL, GENERATION_ID, status); + byte[] keyMetadata = null; + + WrappedKey wrappedKey = new WrappedKey(NONCE, KEY_MATERIAL, keyMetadata, GENERATION_ID, + status); mRecoverableKeyStoreDb.insertKey(userId, uid, alias, wrappedKey); Map<String, Integer> statuses = mRecoverableKeyStoreManager.getRecoveryStatus(); @@ -1169,7 +1246,8 @@ public class RecoverableKeyStoreManagerTest { private static byte[] encryptedApplicationKey( SecretKey recoveryKey, byte[] applicationKey) throws Exception { return KeySyncUtils.encryptKeysWithRecoveryKey(recoveryKey, ImmutableMap.of( - TEST_ALIAS, new SecretKeySpec(applicationKey, "AES") + TEST_ALIAS, + Pair.create(new SecretKeySpec(applicationKey, "AES"), /*metadata=*/ null) )).get(TEST_ALIAS); } @@ -1203,7 +1281,7 @@ public class RecoverableKeyStoreManagerTest { private void generateKeyAndSimulateSync(int userId, int uid, int snapshotVersion) throws Exception{ - mRecoverableKeyStoreManager.generateKey(TEST_ALIAS); + mRecoverableKeyStoreManager.generateKeyWithMetadata(TEST_ALIAS, KEY_METADATA_NULL); // Simulate key sync. mRecoverableKeyStoreDb.setSnapshotVersion(userId, uid, snapshotVersion); mRecoverableKeyStoreDb.setShouldCreateSnapshot(userId, uid, false); diff --git a/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/TestOnlyInsecureCertificateHelperTest.java b/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/TestOnlyInsecureCertificateHelperTest.java index 944d6e0512eb..9b4c3beac582 100644 --- a/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/TestOnlyInsecureCertificateHelperTest.java +++ b/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/TestOnlyInsecureCertificateHelperTest.java @@ -3,6 +3,7 @@ package com.android.server.locksettings.recoverablekeystore; import static com.google.common.truth.Truth.assertThat; import android.security.keystore.recovery.TrustedRootCertificates; +import android.util.Pair; import androidx.test.filters.SmallTest; import androidx.test.runner.AndroidJUnit4; @@ -64,10 +65,10 @@ public class TestOnlyInsecureCertificateHelperTest { @Test public void testKeepOnlyWhitelistedInsecureKeys_emptyKeysList() throws Exception { - Map<String, SecretKey> rawKeys = new HashMap<>(); - Map<String, SecretKey> expectedResult = new HashMap<>(); + Map<String, Pair<SecretKey, byte[]>> rawKeys = new HashMap<>(); + Map<String, Pair<SecretKey, byte[]>> expectedResult = new HashMap<>(); - Map<String, SecretKey> filteredKeys = + Map<String, Pair<SecretKey, byte[]>> filteredKeys = mHelper.keepOnlyWhitelistedInsecureKeys(rawKeys); assertThat(filteredKeys.entrySet()).containsExactlyElementsIn(expectedResult.entrySet()); assertThat(filteredKeys.entrySet()).containsAllIn(rawKeys.entrySet()); @@ -75,13 +76,13 @@ public class TestOnlyInsecureCertificateHelperTest { @Test public void testKeepOnlyWhitelistedInsecureKeys_singleNonWhitelistedKey() throws Exception { - Map<String, SecretKey> rawKeys = new HashMap<>(); - Map<String, SecretKey> expectedResult = new HashMap<>(); + Map<String, Pair<SecretKey, byte[]>> rawKeys = new HashMap<>(); + Map<String, Pair<SecretKey, byte[]>> expectedResult = new HashMap<>(); String alias = "secureAlias"; - rawKeys.put(alias, TestData.generateKey()); + rawKeys.put(alias, Pair.create(TestData.generateKey(), /*metadata=*/ null)); - Map<String, SecretKey> filteredKeys = + Map<String, Pair<SecretKey, byte[]>> filteredKeys = mHelper.keepOnlyWhitelistedInsecureKeys(rawKeys); assertThat(filteredKeys.entrySet()).containsExactlyElementsIn(expectedResult.entrySet()); assertThat(rawKeys.entrySet()).containsAllIn(filteredKeys.entrySet()); @@ -89,14 +90,14 @@ public class TestOnlyInsecureCertificateHelperTest { @Test public void testKeepOnlyWhitelistedInsecureKeys_singleWhitelistedKey() throws Exception { - Map<String, SecretKey> rawKeys = new HashMap<>(); - Map<String, SecretKey> expectedResult = new HashMap<>(); + Map<String, Pair<SecretKey, byte[]>> rawKeys = new HashMap<>(); + Map<String, Pair<SecretKey, byte[]>> expectedResult = new HashMap<>(); String alias = TrustedRootCertificates.INSECURE_KEY_ALIAS_PREFIX; - rawKeys.put(alias, TestData.generateKey()); + rawKeys.put(alias, Pair.create(TestData.generateKey(), /*metadata=*/ null)); expectedResult.put(alias, rawKeys.get(alias)); - Map<String, SecretKey> filteredKeys = + Map<String, Pair<SecretKey, byte[]>> filteredKeys = mHelper.keepOnlyWhitelistedInsecureKeys(rawKeys); assertThat(filteredKeys.entrySet()).containsExactlyElementsIn(expectedResult.entrySet()); assertThat(rawKeys.entrySet()).containsAllIn(filteredKeys.entrySet()); @@ -104,21 +105,21 @@ public class TestOnlyInsecureCertificateHelperTest { @Test public void testKeepOnlyWhitelistedInsecureKeys() throws Exception { - Map<String, SecretKey> rawKeys = new HashMap<>(); - Map<String, SecretKey> expectedResult = new HashMap<>(); + Map<String, Pair<SecretKey, byte[]>> rawKeys = new HashMap<>(); + Map<String, Pair<SecretKey, byte[]>> expectedResult = new HashMap<>(); String alias = "SECURE_ALIAS" + TrustedRootCertificates.INSECURE_KEY_ALIAS_PREFIX; - rawKeys.put(alias, TestData.generateKey()); + rawKeys.put(alias, Pair.create(TestData.generateKey(), /*metadata=*/ null)); alias = TrustedRootCertificates.INSECURE_KEY_ALIAS_PREFIX + "1"; - rawKeys.put(alias, TestData.generateKey()); + rawKeys.put(alias, Pair.create(TestData.generateKey(), /*metadata=*/ null)); expectedResult.put(alias, rawKeys.get(alias)); alias = TrustedRootCertificates.INSECURE_KEY_ALIAS_PREFIX + "2"; - rawKeys.put(alias, TestData.generateKey()); + rawKeys.put(alias, Pair.create(TestData.generateKey(), /*metadata=*/ null)); expectedResult.put(alias, rawKeys.get(alias)); - Map<String, SecretKey> filteredKeys = + Map<String, Pair<SecretKey, byte[]>> filteredKeys = mHelper.keepOnlyWhitelistedInsecureKeys(rawKeys); assertThat(filteredKeys.entrySet()).containsExactlyElementsIn(expectedResult.entrySet()); assertThat(rawKeys.entrySet()).containsAllIn(filteredKeys.entrySet()); diff --git a/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/WrappedKeyTest.java b/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/WrappedKeyTest.java index b5ee60e7ec24..9813ab74721e 100644 --- a/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/WrappedKeyTest.java +++ b/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/WrappedKeyTest.java @@ -24,6 +24,7 @@ import static org.junit.Assert.fail; import android.security.keystore.AndroidKeyStoreSecretKey; import android.security.keystore.KeyGenParameterSpec; import android.security.keystore.KeyProperties; +import android.util.Pair; import androidx.test.filters.SmallTest; import androidx.test.runner.AndroidJUnit4; @@ -32,6 +33,7 @@ import org.junit.After; import org.junit.Test; import org.junit.runner.RunWith; +import java.nio.charset.StandardCharsets; import java.security.KeyStore; import java.util.HashMap; import java.util.Map; @@ -47,26 +49,49 @@ public class WrappedKeyTest { private static final String ANDROID_KEY_STORE_PROVIDER = "AndroidKeyStore"; private static final String KEY_ALGORITHM = "AES"; private static final String CIPHER_ALGORITHM = "AES/GCM/NoPadding"; - private static final String WRAPPING_KEY_ALIAS = "WrappedKeyTestWrappingKeyAlias"; + private static final String WRAPPED_KEY_ALIAS = "WrappedKeyTestWrappingKeyAlias"; private static final int GENERATION_ID = 1; private static final int GCM_TAG_LENGTH_BYTES = 16; private static final int BITS_PER_BYTE = 8; private static final int GCM_TAG_LENGTH_BITS = GCM_TAG_LENGTH_BYTES * BITS_PER_BYTE; + private static final byte[] NULL_METADATA = null; + private static final byte[] NON_NULL_METADATA = "keyMetadata".getBytes(StandardCharsets.UTF_8); @After public void tearDown() throws Exception { KeyStore keyStore = KeyStore.getInstance(ANDROID_KEY_STORE_PROVIDER); keyStore.load(/*param=*/ null); - keyStore.deleteEntry(WRAPPING_KEY_ALIAS); + keyStore.deleteEntry(WRAPPED_KEY_ALIAS); + } + + // TODO: Add tests for non-null metadata + + @Test + public void fromSecretKey_createsWrappedKeyThatCanBeUnwrapped_nullMetadata() throws Exception { + PlatformEncryptionKey wrappingKey = new PlatformEncryptionKey( + GENERATION_ID, generateAndroidKeyStoreKey()); + SecretKey rawKey = generateKey(); + + WrappedKey wrappedKey = WrappedKey.fromSecretKey(wrappingKey, rawKey, NULL_METADATA); + + Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM); + cipher.init( + Cipher.UNWRAP_MODE, + wrappingKey.getKey(), + new GCMParameterSpec(GCM_TAG_LENGTH_BITS, wrappedKey.getNonce())); + SecretKey unwrappedKey = (SecretKey) cipher.unwrap( + wrappedKey.getKeyMaterial(), KEY_ALGORITHM, Cipher.SECRET_KEY); + assertEquals(rawKey, unwrappedKey); } @Test - public void fromSecretKey_createsWrappedKeyThatCanBeUnwrapped() throws Exception { + public void fromSecretKey_createsWrappedKeyThatCanBeUnwrapped_nonNullMetadata() + throws Exception { PlatformEncryptionKey wrappingKey = new PlatformEncryptionKey( GENERATION_ID, generateAndroidKeyStoreKey()); SecretKey rawKey = generateKey(); - WrappedKey wrappedKey = WrappedKey.fromSecretKey(wrappingKey, rawKey); + WrappedKey wrappedKey = WrappedKey.fromSecretKey(wrappingKey, rawKey, NON_NULL_METADATA); Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM); cipher.init( @@ -84,27 +109,47 @@ public class WrappedKeyTest { GENERATION_ID, generateAndroidKeyStoreKey()); SecretKey rawKey = generateKey(); - WrappedKey wrappedKey = WrappedKey.fromSecretKey(wrappingKey, rawKey); + WrappedKey wrappedKey = WrappedKey.fromSecretKey(wrappingKey, rawKey, NULL_METADATA); assertEquals(GENERATION_ID, wrappedKey.getPlatformKeyGenerationId()); } @Test - public void decryptWrappedKeys_decryptsWrappedKeys() throws Exception { + public void decryptWrappedKeys_decryptsWrappedKeys_nullMetadata() throws Exception { String alias = "karlin"; AndroidKeyStoreSecretKey platformKey = generateAndroidKeyStoreKey(); SecretKey appKey = generateKey(); WrappedKey wrappedKey = WrappedKey.fromSecretKey( - new PlatformEncryptionKey(GENERATION_ID, platformKey), appKey); + new PlatformEncryptionKey(GENERATION_ID, platformKey), appKey, NULL_METADATA); HashMap<String, WrappedKey> keysByAlias = new HashMap<>(); keysByAlias.put(alias, wrappedKey); - Map<String, SecretKey> unwrappedKeys = WrappedKey.unwrapKeys( + Map<String, Pair<SecretKey, byte[]>> unwrappedKeys = WrappedKey.unwrapKeys( new PlatformDecryptionKey(GENERATION_ID, platformKey), keysByAlias); assertEquals(1, unwrappedKeys.size()); assertTrue(unwrappedKeys.containsKey(alias)); - assertArrayEquals(appKey.getEncoded(), unwrappedKeys.get(alias).getEncoded()); + assertArrayEquals(appKey.getEncoded(), unwrappedKeys.get(alias).first.getEncoded()); + assertArrayEquals(null, unwrappedKeys.get(alias).second); + } + + @Test + public void decryptWrappedKeys_decryptsWrappedKeys_nonNullMetadata() throws Exception { + String alias = "karlin"; + AndroidKeyStoreSecretKey platformKey = generateAndroidKeyStoreKey(); + SecretKey appKey = generateKey(); + WrappedKey wrappedKey = WrappedKey.fromSecretKey( + new PlatformEncryptionKey(GENERATION_ID, platformKey), appKey, NON_NULL_METADATA); + HashMap<String, WrappedKey> keysByAlias = new HashMap<>(); + keysByAlias.put(alias, wrappedKey); + + Map<String, Pair<SecretKey, byte[]>> unwrappedKeys = WrappedKey.unwrapKeys( + new PlatformDecryptionKey(GENERATION_ID, platformKey), keysByAlias); + + assertEquals(1, unwrappedKeys.size()); + assertTrue(unwrappedKeys.containsKey(alias)); + assertArrayEquals(appKey.getEncoded(), unwrappedKeys.get(alias).first.getEncoded()); + assertArrayEquals(NON_NULL_METADATA, unwrappedKeys.get(alias).second); } @Test @@ -113,11 +158,11 @@ public class WrappedKeyTest { AndroidKeyStoreSecretKey platformKey = generateAndroidKeyStoreKey(); SecretKey appKey = generateKey(); WrappedKey wrappedKey = WrappedKey.fromSecretKey( - new PlatformEncryptionKey(GENERATION_ID, platformKey), appKey); + new PlatformEncryptionKey(GENERATION_ID, platformKey), appKey, NULL_METADATA); HashMap<String, WrappedKey> keysByAlias = new HashMap<>(); keysByAlias.put(alias, wrappedKey); - Map<String, SecretKey> unwrappedKeys = WrappedKey.unwrapKeys( + Map<String, Pair<SecretKey, byte[]>> unwrappedKeys = WrappedKey.unwrapKeys( new PlatformDecryptionKey(GENERATION_ID, generateAndroidKeyStoreKey()), keysByAlias); @@ -128,7 +173,8 @@ public class WrappedKeyTest { public void decryptWrappedKeys_throwsIfPlatformKeyGenerationIdDoesNotMatch() throws Exception { AndroidKeyStoreSecretKey platformKey = generateAndroidKeyStoreKey(); WrappedKey wrappedKey = WrappedKey.fromSecretKey( - new PlatformEncryptionKey(GENERATION_ID, platformKey), generateKey()); + new PlatformEncryptionKey(GENERATION_ID, platformKey), generateKey(), + /*metadata=*/ null); HashMap<String, WrappedKey> keysByAlias = new HashMap<>(); keysByAlias.put("benji", wrappedKey); @@ -156,19 +202,11 @@ public class WrappedKeyTest { KEY_ALGORITHM, ANDROID_KEY_STORE_PROVIDER); keyGenerator.init(new KeyGenParameterSpec.Builder( - WRAPPING_KEY_ALIAS, + WRAPPED_KEY_ALIAS, KeyProperties.PURPOSE_ENCRYPT | KeyProperties.PURPOSE_DECRYPT) .setBlockModes(KeyProperties.BLOCK_MODE_GCM) .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_NONE) .build()); return (AndroidKeyStoreSecretKey) keyGenerator.generateKey(); } - - private PlatformDecryptionKey generatePlatformDecryptionKey() throws Exception { - return generatePlatformDecryptionKey(GENERATION_ID); - } - - private PlatformDecryptionKey generatePlatformDecryptionKey(int generationId) throws Exception { - return new PlatformDecryptionKey(generationId, generateAndroidKeyStoreKey()); - } } diff --git a/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/serialization/KeyChainSnapshotSerializerTest.java b/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/serialization/KeyChainSnapshotSerializerTest.java index 880255d79eb7..9c03df8e4369 100644 --- a/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/serialization/KeyChainSnapshotSerializerTest.java +++ b/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/serialization/KeyChainSnapshotSerializerTest.java @@ -55,12 +55,15 @@ public class KeyChainSnapshotSerializerTest { private static final String TEST_KEY_1_ALIAS = "key1"; private static final byte[] TEST_KEY_1_BYTES = new byte[] { 66, 77, 88 }; + private static final byte[] TEST_KEY_1_METADATA = new byte[] { 89, 87 }; private static final String TEST_KEY_2_ALIAS = "key2"; private static final byte[] TEST_KEY_2_BYTES = new byte[] { 99, 33, 11 }; + private static final byte[] TEST_KEY_2_METADATA = new byte[] {}; private static final String TEST_KEY_3_ALIAS = "key3"; private static final byte[] TEST_KEY_3_BYTES = new byte[] { 2, 8, 100 }; + private static final byte[] TEST_KEY_3_METADATA = new byte[] { 121 }; @Test public void roundTrip_persistsCounterId() throws Exception { @@ -144,6 +147,17 @@ public class KeyChainSnapshotSerializerTest { } @Test + public void roundTripKeys_0_persistsKeyMetadata_absent() throws Exception { + assertThat(roundTripKeys(/*withKeyMetadata=*/ false).get(0).getMetadata()).isEqualTo(null); + } + + @Test + public void roundTripKeys_0_persistsKeyMetadata_present() throws Exception { + assertThat(roundTripKeys(/*withKeyMetadata=*/ true).get(0).getMetadata()) + .isEqualTo(TEST_KEY_1_METADATA); + } + + @Test public void roundTripKeys_1_persistsAlias() throws Exception { assertThat(roundTripKeys().get(1).getAlias()).isEqualTo(TEST_KEY_2_ALIAS); } @@ -154,6 +168,17 @@ public class KeyChainSnapshotSerializerTest { } @Test + public void roundTripKeys_1_persistsKeyMetadata_absent() throws Exception { + assertThat(roundTripKeys(/*withKeyMetadata=*/ false).get(1).getMetadata()).isEqualTo(null); + } + + @Test + public void roundTripKeys_1_persistsKeyMetadata_present() throws Exception { + assertThat(roundTripKeys(/*withKeyMetadata=*/ true).get(1).getMetadata()) + .isEqualTo(TEST_KEY_2_METADATA); + } + + @Test public void roundTripKeys_2_persistsAlias() throws Exception { assertThat(roundTripKeys().get(2).getAlias()).isEqualTo(TEST_KEY_3_ALIAS); } @@ -164,28 +189,74 @@ public class KeyChainSnapshotSerializerTest { } @Test - public void serialize_doesNotThrowForTestSnapshot() throws Exception { + public void roundTripKeys_2_persistsKeyMetadata_absent() throws Exception { + assertThat(roundTripKeys(/*withKeyMetadata=*/ false).get(2).getMetadata()).isEqualTo(null); + } + + @Test + public void roundTripKeys_2_persistsKeyMetadata_present() throws Exception { + assertThat(roundTripKeys(/*withKeyMetadata=*/ true).get(2).getMetadata()) + .isEqualTo(TEST_KEY_3_METADATA); + } + + @Test + public void serialize_doesNotThrowForTestSnapshotWithoutKeyMetadata() throws Exception { KeyChainSnapshotSerializer.serialize( - createTestKeyChainSnapshot(), new ByteArrayOutputStream()); + createTestKeyChainSnapshot(/*withKeyMetadata=*/ false), + new ByteArrayOutputStream()); + } + + @Test + public void serialize_doesNotThrowForTestSnapshotWithKeyMetadata() throws Exception { + KeyChainSnapshotSerializer.serialize( + createTestKeyChainSnapshotWithKeyMetadata(), new ByteArrayOutputStream()); } private static List<WrappedApplicationKey> roundTripKeys() throws Exception { return roundTrip().getWrappedApplicationKeys(); } + private static List<WrappedApplicationKey> roundTripKeys(boolean withKeyMetadata) + throws Exception { + return roundTrip(withKeyMetadata).getWrappedApplicationKeys(); + } + private static KeyChainProtectionParams roundTripParams() throws Exception { - return roundTrip().getKeyChainProtectionParams().get(0); + return roundTrip(/*withKeyMetadata=*/ false).getKeyChainProtectionParams().get(0); } public static KeyChainSnapshot roundTrip() throws Exception { - KeyChainSnapshot snapshot = createTestKeyChainSnapshot(); + return roundTrip(/*withKeyMetadata=*/ false); + } + + public static KeyChainSnapshot roundTrip(boolean withKeyMetadata) throws Exception { + KeyChainSnapshot snapshot = createTestKeyChainSnapshot(withKeyMetadata); ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); KeyChainSnapshotSerializer.serialize(snapshot, byteArrayOutputStream); return KeyChainSnapshotDeserializer.deserialize( new ByteArrayInputStream(byteArrayOutputStream.toByteArray())); } - private static KeyChainSnapshot createTestKeyChainSnapshot() throws Exception { + private static KeyChainSnapshot createTestKeyChainSnapshot(boolean withKeyMetadata) + throws Exception { + KeyChainSnapshot.Builder builder = new KeyChainSnapshot.Builder() + .setCounterId(COUNTER_ID) + .setSnapshotVersion(SNAPSHOT_VERSION) + .setServerParams(SERVER_PARAMS) + .setMaxAttempts(MAX_ATTEMPTS) + .setEncryptedRecoveryKeyBlob(KEY_BLOB) + .setKeyChainProtectionParams(createKeyChainProtectionParamsList()) + .setTrustedHardwareCertPath(CERT_PATH); + if (withKeyMetadata) { + builder.setWrappedApplicationKeys(createKeysWithMetadata()); + } else { + builder.setWrappedApplicationKeys(createKeysWithoutMetadata()); + } + return builder.build(); + } + + private static KeyChainSnapshot createTestKeyChainSnapshotWithKeyMetadata() + throws Exception { return new KeyChainSnapshot.Builder() .setCounterId(COUNTER_ID) .setSnapshotVersion(SNAPSHOT_VERSION) @@ -193,16 +264,24 @@ public class KeyChainSnapshotSerializerTest { .setMaxAttempts(MAX_ATTEMPTS) .setEncryptedRecoveryKeyBlob(KEY_BLOB) .setKeyChainProtectionParams(createKeyChainProtectionParamsList()) - .setWrappedApplicationKeys(createKeys()) + .setWrappedApplicationKeys(createKeysWithMetadata()) .setTrustedHardwareCertPath(CERT_PATH) .build(); } - private static List<WrappedApplicationKey> createKeys() { + private static List<WrappedApplicationKey> createKeysWithoutMetadata() { ArrayList<WrappedApplicationKey> keyList = new ArrayList<>(); - keyList.add(createKey(TEST_KEY_1_ALIAS, TEST_KEY_1_BYTES)); - keyList.add(createKey(TEST_KEY_2_ALIAS, TEST_KEY_2_BYTES)); - keyList.add(createKey(TEST_KEY_3_ALIAS, TEST_KEY_3_BYTES)); + keyList.add(createKey(TEST_KEY_1_ALIAS, TEST_KEY_1_BYTES, /*metadata=*/ null)); + keyList.add(createKey(TEST_KEY_2_ALIAS, TEST_KEY_2_BYTES, /*metadata=*/ null)); + keyList.add(createKey(TEST_KEY_3_ALIAS, TEST_KEY_3_BYTES, /*metadata=*/ null)); + return keyList; + } + + private static List<WrappedApplicationKey> createKeysWithMetadata() { + ArrayList<WrappedApplicationKey> keyList = new ArrayList<>(); + keyList.add(createKey(TEST_KEY_1_ALIAS, TEST_KEY_1_BYTES, TEST_KEY_1_METADATA)); + keyList.add(createKey(TEST_KEY_2_ALIAS, TEST_KEY_2_BYTES, TEST_KEY_2_METADATA)); + keyList.add(createKey(TEST_KEY_3_ALIAS, TEST_KEY_3_BYTES, TEST_KEY_3_METADATA)); return keyList; } @@ -221,10 +300,13 @@ public class KeyChainSnapshotSerializerTest { return keyChainProtectionParamsList; } - private static WrappedApplicationKey createKey(String alias, byte[] bytes) { - return new WrappedApplicationKey.Builder() + private static WrappedApplicationKey createKey(String alias, byte[] bytes, byte[] metadata) { + WrappedApplicationKey.Builder builder = new WrappedApplicationKey.Builder() .setAlias(alias) - .setEncryptedKeyMaterial(bytes) - .build(); + .setEncryptedKeyMaterial(bytes); + if (metadata != null) { + builder.setMetadata(metadata); + } + return builder.build(); } } diff --git a/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/storage/RecoverableKeyStoreDbHelperTest.java b/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/storage/RecoverableKeyStoreDbHelperTest.java index 7130b4226ef1..35215c34d8f0 100644 --- a/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/storage/RecoverableKeyStoreDbHelperTest.java +++ b/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/storage/RecoverableKeyStoreDbHelperTest.java @@ -60,6 +60,7 @@ public class RecoverableKeyStoreDbHelperTest { private static final String TEST_ROOT_ALIAS = "root_cert_alias"; private static final byte[] TEST_CERT_PATH = "test-cert-path".getBytes(UTF_8); private static final long TEST_CERT_SERIAL = 1000L; + private static final byte[] TEST_KEY_METADATA = "test-key-metadata".getBytes(UTF_8); private static final String SQL_CREATE_V2_TABLE_KEYS = "CREATE TABLE " + KeysEntry.TABLE_NAME + "( " @@ -120,14 +121,14 @@ public class RecoverableKeyStoreDbHelperTest { @Test public void onCreate() throws Exception { mDatabaseHelper.onCreate(mDatabase); - checkAllColumns(); + checkAllColumns_latest(); } @Test public void onUpgrade_beforeV2() throws Exception { mDatabaseHelper.onUpgrade(mDatabase, /*oldVersion=*/ 1, RecoverableKeyStoreDbHelper.DATABASE_VERSION); - checkAllColumns(); + checkAllColumns_latest(); } @Test @@ -135,11 +136,11 @@ public class RecoverableKeyStoreDbHelperTest { createV2Tables(); mDatabaseHelper.onUpgrade(mDatabase, /*oldVersion=*/ 2, RecoverableKeyStoreDbHelper.DATABASE_VERSION); - checkAllColumns(); + checkAllColumns_latest(); } @Test - public void onUpgrade_v2_to_v3_to_v4() throws Exception { + public void onUpgrade_v2_to_v3_to_v4_to_latest() throws Exception { createV2Tables(); assertThat(isRootOfTrustTableAvailable()).isFalse(); // V2 doesn't have the table; @@ -148,9 +149,12 @@ public class RecoverableKeyStoreDbHelperTest { assertThat(isRootOfTrustTableAvailable()).isFalse(); // V3 doesn't have the table; - mDatabaseHelper.onUpgrade(mDatabase, /*oldVersion=*/ 3, + mDatabaseHelper.onUpgrade(mDatabase, /*oldVersion=*/ 3, /*newVersion=*/ 4); + checkAllColumns_v4(); + + mDatabaseHelper.onUpgrade(mDatabase, /*oldVersion=*/ 4, RecoverableKeyStoreDbHelper.DATABASE_VERSION); - checkAllColumns(); + checkAllColumns_latest(); } private boolean isRootOfTrustTableAvailable() { @@ -160,11 +164,11 @@ public class RecoverableKeyStoreDbHelperTest { values.put(RootOfTrustEntry.COLUMN_NAME_ROOT_ALIAS, TEST_ROOT_ALIAS); values.put(RootOfTrustEntry.COLUMN_NAME_CERT_PATH, TEST_CERT_PATH); values.put(RootOfTrustEntry.COLUMN_NAME_CERT_SERIAL, TEST_CERT_SERIAL); - return mDatabase.insert(RootOfTrustEntry.TABLE_NAME, /*nullColumnHack=*/ null, values) + return mDatabase.replace(RootOfTrustEntry.TABLE_NAME, /*nullColumnHack=*/ null, values) > -1; } - private void checkAllColumns() throws Exception { + private void checkAllColumns_v4() throws Exception { // Check the table containing encrypted application keys ContentValues values = new ContentValues(); values.put(KeysEntry.COLUMN_NAME_USER_ID, TEST_USER_ID); @@ -175,7 +179,7 @@ public class RecoverableKeyStoreDbHelperTest { values.put(KeysEntry.COLUMN_NAME_GENERATION_ID, TEST_GENERATION_ID); values.put(KeysEntry.COLUMN_NAME_LAST_SYNCED_AT, TEST_LAST_SYNCED_AT); values.put(KeysEntry.COLUMN_NAME_RECOVERY_STATUS, TEST_RECOVERY_STATUS); - assertThat(mDatabase.insert(KeysEntry.TABLE_NAME, /*nullColumnHack=*/ null, values)) + assertThat(mDatabase.replace(KeysEntry.TABLE_NAME, /*nullColumnHack=*/ null, values)) .isGreaterThan(-1L); // Check the table about user metadata @@ -183,7 +187,8 @@ public class RecoverableKeyStoreDbHelperTest { values.put(UserMetadataEntry.COLUMN_NAME_USER_ID, TEST_USER_ID); values.put(UserMetadataEntry.COLUMN_NAME_PLATFORM_KEY_GENERATION_ID, TEST_PLATFORM_KEY_GENERATION_ID); - assertThat(mDatabase.insert(UserMetadataEntry.TABLE_NAME, /*nullColumnHack=*/ null, values)) + assertThat( + mDatabase.replace(UserMetadataEntry.TABLE_NAME, /*nullColumnHack=*/ null, values)) .isGreaterThan(-1L); // Check the table about recovery service metadata @@ -202,11 +207,32 @@ public class RecoverableKeyStoreDbHelperTest { values.put(RecoveryServiceMetadataEntry.COLUMN_NAME_CERT_PATH, TEST_CERT_PATH); values.put(RecoveryServiceMetadataEntry.COLUMN_NAME_CERT_SERIAL, TEST_CERT_SERIAL); assertThat( - mDatabase.insert(RecoveryServiceMetadataEntry.TABLE_NAME, /*nullColumnHack=*/ null, + mDatabase.replace(RecoveryServiceMetadataEntry.TABLE_NAME, /*nullColumnHack=*/ null, values)) .isGreaterThan(-1L); // Check the table about recovery service and root of trust data introduced in V4 assertThat(isRootOfTrustTableAvailable()).isTrue(); } + + private void checkAllColumns_latest() throws Exception { + // Check all columns of the previous version first. + checkAllColumns_v4(); + + ContentValues values = new ContentValues(); + values.put(KeysEntry.COLUMN_NAME_USER_ID, TEST_USER_ID); + values.put(KeysEntry.COLUMN_NAME_UID, TEST_UID); + values.put(KeysEntry.COLUMN_NAME_ALIAS, TEST_ALIAS); + values.put(KeysEntry.COLUMN_NAME_NONCE, TEST_NONCE); + values.put(KeysEntry.COLUMN_NAME_WRAPPED_KEY, TEST_WRAPPED_KEY); + values.put(KeysEntry.COLUMN_NAME_GENERATION_ID, TEST_GENERATION_ID); + values.put(KeysEntry.COLUMN_NAME_LAST_SYNCED_AT, TEST_LAST_SYNCED_AT); + values.put(KeysEntry.COLUMN_NAME_RECOVERY_STATUS, TEST_RECOVERY_STATUS); + + // This column is added when upgrading from v4 to v5 + values.put(KeysEntry.COLUMN_NAME_KEY_METADATA, TEST_KEY_METADATA); + + assertThat(mDatabase.replace(KeysEntry.TABLE_NAME, /*nullColumnHack=*/ null, values)) + .isGreaterThan(-1L); + } } diff --git a/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/storage/RecoverableKeyStoreDbTest.java b/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/storage/RecoverableKeyStoreDbTest.java index 6a26f8c72e81..7de9ffc7f3cc 100644 --- a/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/storage/RecoverableKeyStoreDbTest.java +++ b/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/storage/RecoverableKeyStoreDbTest.java @@ -80,25 +80,33 @@ public class RecoverableKeyStoreDbTest { public void insertKey_replacesOldKey() { int userId = 12; int uid = 10009; - String alias = "test"; - WrappedKey oldWrappedKey = new WrappedKey( - getUtf8Bytes("nonce1"), - getUtf8Bytes("keymaterial1"), - /*platformKeyGenerationId=*/ 1); - mRecoverableKeyStoreDb.insertKey( - userId, uid, alias, oldWrappedKey); - byte[] nonce = getUtf8Bytes("nonce2"); - byte[] keyMaterial = getUtf8Bytes("keymaterial2"); - WrappedKey newWrappedKey = new WrappedKey( - nonce, keyMaterial, /*platformKeyGenerationId=*/2); + String alias = "test-alias"; - mRecoverableKeyStoreDb.insertKey( - userId, uid, alias, newWrappedKey); + byte[] nonce = getUtf8Bytes("nonce1"); + byte[] keyMaterial = getUtf8Bytes("keymaterial1"); + byte[] keyMetadata = null; + int generationId = 1; + WrappedKey wrappedKey = new WrappedKey(nonce, keyMaterial, keyMetadata, generationId); + mRecoverableKeyStoreDb.insertKey(userId, uid, alias, wrappedKey); WrappedKey retrievedKey = mRecoverableKeyStoreDb.getKey(uid, alias); assertArrayEquals(nonce, retrievedKey.getNonce()); assertArrayEquals(keyMaterial, retrievedKey.getKeyMaterial()); - assertEquals(2, retrievedKey.getPlatformKeyGenerationId()); + assertArrayEquals(keyMetadata, retrievedKey.getKeyMetadata()); + assertEquals(generationId, retrievedKey.getPlatformKeyGenerationId()); + + nonce = getUtf8Bytes("nonce2"); + keyMaterial = getUtf8Bytes("keymaterial2"); + keyMetadata = getUtf8Bytes("keymetadata2"); + generationId = 2; + wrappedKey = new WrappedKey(nonce, keyMaterial, keyMetadata, generationId); + mRecoverableKeyStoreDb.insertKey(userId, uid, alias, wrappedKey); + + retrievedKey = mRecoverableKeyStoreDb.getKey(uid, alias); + assertArrayEquals(nonce, retrievedKey.getNonce()); + assertArrayEquals(keyMaterial, retrievedKey.getKeyMaterial()); + assertArrayEquals(keyMetadata, retrievedKey.getKeyMetadata()); + assertEquals(generationId, retrievedKey.getPlatformKeyGenerationId()); } @Test @@ -108,10 +116,12 @@ public class RecoverableKeyStoreDbTest { WrappedKey key1 = new WrappedKey( getUtf8Bytes("nonce1"), getUtf8Bytes("key1"), + /*metadata=*/ null, /*platformKeyGenerationId=*/ 1); WrappedKey key2 = new WrappedKey( getUtf8Bytes("nonce2"), getUtf8Bytes("key2"), + /*metadata=*/ null, /*platformKeyGenerationId=*/ 1); mRecoverableKeyStoreDb.insertKey(userId, /*uid=*/ 1, alias, key1); @@ -133,6 +143,7 @@ public class RecoverableKeyStoreDbTest { WrappedKey key = new WrappedKey( getUtf8Bytes("nonce1"), getUtf8Bytes("key1"), + /*metadata=*/ null, /*platformKeyGenerationId=*/ 1); mRecoverableKeyStoreDb.insertKey(userId, uid, alias, key); @@ -158,13 +169,16 @@ public class RecoverableKeyStoreDbTest { String alias = "test"; byte[] nonce = getUtf8Bytes("nonce"); byte[] keyMaterial = getUtf8Bytes("keymaterial"); - WrappedKey wrappedKey = new WrappedKey(nonce, keyMaterial, generationId, 120); + byte[] keyMetadata = getUtf8Bytes("keymetametametadata"); + + WrappedKey wrappedKey = new WrappedKey(nonce, keyMaterial, keyMetadata, generationId, 120); mRecoverableKeyStoreDb.insertKey(userId, uid, alias, wrappedKey); WrappedKey retrievedKey = mRecoverableKeyStoreDb.getKey(uid, alias); assertArrayEquals(nonce, retrievedKey.getNonce()); assertArrayEquals(keyMaterial, retrievedKey.getKeyMaterial()); + assertArrayEquals(keyMetadata, retrievedKey.getKeyMetadata()); assertEquals(generationId, retrievedKey.getPlatformKeyGenerationId()); assertEquals(status,retrievedKey.getRecoveryStatus()); } @@ -174,20 +188,37 @@ public class RecoverableKeyStoreDbTest { int userId = 12; int uid = 1009; int generationId = 6; - String alias = "test"; - byte[] nonce = getUtf8Bytes("nonce"); - byte[] keyMaterial = getUtf8Bytes("keymaterial"); - WrappedKey wrappedKey = new WrappedKey(nonce, keyMaterial, generationId); - mRecoverableKeyStoreDb.insertKey(userId, uid, alias, wrappedKey); + + String alias1 = "alias1"; + byte[] nonce1 = getUtf8Bytes("nonce1"); + byte[] keyMaterial1 = getUtf8Bytes("keymaterial1"); + byte[] keyMetadata1 = getUtf8Bytes("keyallmetadata1"); + WrappedKey wrappedKey1 = new WrappedKey(nonce1, keyMaterial1, keyMetadata1, generationId); + mRecoverableKeyStoreDb.insertKey(userId, uid, alias1, wrappedKey1); + + String alias2 = "alias2"; + byte[] nonce2 = getUtf8Bytes("nonce2"); + byte[] keyMaterial2 = getUtf8Bytes("keymaterial2"); + byte[] keyMetadata2 = null; + WrappedKey wrappedKey2 = new WrappedKey(nonce2, keyMaterial2, keyMetadata2, generationId); + mRecoverableKeyStoreDb.insertKey(userId, uid, alias2, wrappedKey2); Map<String, WrappedKey> keys = mRecoverableKeyStoreDb.getAllKeys(userId, uid, generationId); + assertEquals(2, keys.size()); - assertEquals(1, keys.size()); - assertTrue(keys.containsKey(alias)); - WrappedKey retrievedKey = keys.get(alias); - assertArrayEquals(nonce, retrievedKey.getNonce()); - assertArrayEquals(keyMaterial, retrievedKey.getKeyMaterial()); - assertEquals(generationId, retrievedKey.getPlatformKeyGenerationId()); + assertTrue(keys.containsKey(alias1)); + WrappedKey retrievedKey1 = keys.get(alias1); + assertArrayEquals(nonce1, retrievedKey1.getNonce()); + assertArrayEquals(keyMaterial1, retrievedKey1.getKeyMaterial()); + assertArrayEquals(keyMetadata1, retrievedKey1.getKeyMetadata()); + assertEquals(generationId, retrievedKey1.getPlatformKeyGenerationId()); + + assertTrue(keys.containsKey(alias2)); + WrappedKey retrievedKey2 = keys.get(alias2); + assertArrayEquals(nonce2, retrievedKey2.getNonce()); + assertArrayEquals(keyMaterial2, retrievedKey2.getKeyMaterial()); + assertArrayEquals(keyMetadata2, retrievedKey2.getKeyMetadata()); + assertEquals(generationId, retrievedKey2.getPlatformKeyGenerationId()); } @Test @@ -197,6 +228,7 @@ public class RecoverableKeyStoreDbTest { WrappedKey wrappedKey = new WrappedKey( getUtf8Bytes("nonce"), getUtf8Bytes("keymaterial"), + /*metadata=*/ null, /*platformKeyGenerationId=*/ 5); mRecoverableKeyStoreDb.insertKey( userId, uid, /*alias=*/ "test", wrappedKey); @@ -212,7 +244,8 @@ public class RecoverableKeyStoreDbTest { int generationId = 12; int uid = 10009; WrappedKey wrappedKey = new WrappedKey( - getUtf8Bytes("nonce"), getUtf8Bytes("keymaterial"), generationId); + getUtf8Bytes("nonce"), getUtf8Bytes("keymaterial"), /*metadata=*/ null, + generationId); mRecoverableKeyStoreDb.insertKey( /*userId=*/ 1, uid, /*alias=*/ "test", wrappedKey); @@ -255,7 +288,10 @@ public class RecoverableKeyStoreDbTest { String alias = "test"; byte[] nonce = getUtf8Bytes("nonce"); byte[] keyMaterial = getUtf8Bytes("keymaterial"); - WrappedKey wrappedKey = new WrappedKey(nonce, keyMaterial, generationId, status); + byte[] keyMetadata = null; + + WrappedKey wrappedKey = new WrappedKey(nonce, keyMaterial, keyMetadata, generationId, + status); mRecoverableKeyStoreDb.insertKey(userId, uid, alias, wrappedKey); WrappedKey retrievedKey = mRecoverableKeyStoreDb.getKey(uid, alias); @@ -279,12 +315,16 @@ public class RecoverableKeyStoreDbTest { String alias3 = "test3"; byte[] nonce = getUtf8Bytes("nonce"); byte[] keyMaterial = getUtf8Bytes("keymaterial"); + byte[] keyMetadata = null; - WrappedKey wrappedKey = new WrappedKey(nonce, keyMaterial, generationId, status); + WrappedKey wrappedKey = new WrappedKey(nonce, keyMaterial, keyMetadata, generationId, + status); mRecoverableKeyStoreDb.insertKey(userId, uid, alias2, wrappedKey); - WrappedKey wrappedKey2 = new WrappedKey(nonce, keyMaterial, generationId, status); - mRecoverableKeyStoreDb.insertKey(userId, uid, alias3, wrappedKey); - WrappedKey wrappedKeyWithDefaultStatus = new WrappedKey(nonce, keyMaterial, generationId); + WrappedKey wrappedKey2 = new WrappedKey(nonce, keyMaterial, keyMetadata, generationId, + status); + mRecoverableKeyStoreDb.insertKey(userId, uid, alias3, wrappedKey2); + WrappedKey wrappedKeyWithDefaultStatus = new WrappedKey(nonce, keyMaterial, keyMetadata, + generationId); mRecoverableKeyStoreDb.insertKey(userId, uid, alias, wrappedKeyWithDefaultStatus); Map<String, Integer> statuses = mRecoverableKeyStoreDb.getStatusForAllKeys(uid); @@ -333,7 +373,10 @@ public class RecoverableKeyStoreDbTest { String alias = "test"; byte[] nonce = getUtf8Bytes("nonce"); byte[] keyMaterial = getUtf8Bytes("keymaterial"); - WrappedKey wrappedKey = new WrappedKey(nonce, keyMaterial, generationId, status); + byte[] keyMetadata = null; + + WrappedKey wrappedKey = new WrappedKey(nonce, keyMaterial, keyMetadata, generationId, + status); mRecoverableKeyStoreDb.insertKey(userId, uid, alias, wrappedKey); WrappedKey retrievedKey = mRecoverableKeyStoreDb.getKey(uid, alias); @@ -357,7 +400,10 @@ public class RecoverableKeyStoreDbTest { String alias = "test"; byte[] nonce = getUtf8Bytes("nonce"); byte[] keyMaterial = getUtf8Bytes("keymaterial"); - WrappedKey wrappedKey = new WrappedKey(nonce, keyMaterial, generationId, status); + byte[] keyMetadata = null; + + WrappedKey wrappedKey = new WrappedKey(nonce, keyMaterial, keyMetadata, generationId, + status); mRecoverableKeyStoreDb.insertKey(userId, uid, alias, wrappedKey); WrappedKey retrievedKey = mRecoverableKeyStoreDb.getKey(uid, alias); diff --git a/services/tests/servicestests/src/com/android/server/pm/BaseShortcutManagerTest.java b/services/tests/servicestests/src/com/android/server/pm/BaseShortcutManagerTest.java index 1f5c64e92ac0..bc1f7981258d 100644 --- a/services/tests/servicestests/src/com/android/server/pm/BaseShortcutManagerTest.java +++ b/services/tests/servicestests/src/com/android/server/pm/BaseShortcutManagerTest.java @@ -42,6 +42,7 @@ import android.app.Activity; import android.app.ActivityManager; import android.app.ActivityManagerInternal; import android.app.IUidObserver; +import android.app.Person; import android.app.usage.UsageStatsManagerInternal; import android.content.ActivityNotFoundException; import android.content.BroadcastReceiver; @@ -1588,6 +1589,14 @@ public abstract class BaseShortcutManagerTest extends InstrumentationTestCase { } /** + * Make a Person. + */ + protected Person makePerson(CharSequence name, String key, String uri) { + final Person.Builder builder = new Person.Builder(); + return builder.setName(name).setKey(key).setUri(uri).build(); + } + + /** * Make an component name, with the client context. */ @NonNull diff --git a/services/tests/servicestests/src/com/android/server/pm/PackageParserTest.java b/services/tests/servicestests/src/com/android/server/pm/PackageParserTest.java index ce59e6ec9760..85909d564a7b 100644 --- a/services/tests/servicestests/src/com/android/server/pm/PackageParserTest.java +++ b/services/tests/servicestests/src/com/android/server/pm/PackageParserTest.java @@ -276,6 +276,7 @@ public class PackageParserTest { assertEquals(a.mRestrictedAccountType, b.mRestrictedAccountType); assertEquals(a.mRequiredAccountType, b.mRequiredAccountType); assertEquals(a.mOverlayTarget, b.mOverlayTarget); + assertEquals(a.mOverlayTargetName, b.mOverlayTargetName); assertEquals(a.mOverlayCategory, b.mOverlayCategory); assertEquals(a.mOverlayPriority, b.mOverlayPriority); assertEquals(a.mOverlayIsStatic, b.mOverlayIsStatic); @@ -545,6 +546,7 @@ public class PackageParserTest { pkg.mOverlayCategory = "foo24"; pkg.mOverlayIsStatic = true; + pkg.mOverlayTargetName = "foo26"; pkg.baseHardwareAccelerated = true; pkg.coreApp = true; diff --git a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest2.java b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest2.java index 9b59f9151fd0..8d0365b534b5 100644 --- a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest2.java +++ b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest2.java @@ -248,6 +248,8 @@ public class ShortcutManagerTest2 extends BaseShortcutManagerTest { .setIntent(makeIntent("action", ShortcutActivity.class, "key", "val")) .setCategories(set(ShortcutInfo.SHORTCUT_CATEGORY_CONVERSATION, "xyz")) .setRank(123) + .setPerson(makePerson("person", "personKey", "personUri")) + .setLongLived() .setExtras(pb) .build(); si.addFlags(ShortcutInfo.FLAG_PINNED); @@ -267,9 +269,12 @@ public class ShortcutManagerTest2 extends BaseShortcutManagerTest { assertEquals("action", si.getIntent().getAction()); assertEquals("val", si.getIntent().getStringExtra("key")); assertEquals(123, si.getRank()); + assertEquals("person", si.getPersons()[0].getName()); + assertEquals("personKey", si.getPersons()[0].getKey()); + assertEquals("personUri", si.getPersons()[0].getUri()); assertEquals(1, si.getExtras().getInt("k")); - assertEquals(ShortcutInfo.FLAG_PINNED, si.getFlags()); + assertEquals(ShortcutInfo.FLAG_PINNED | ShortcutInfo.FLAG_LONG_LIVED, si.getFlags()); assertEquals("abc", si.getBitmapPath()); assertEquals(456, si.getIconResourceId()); @@ -345,6 +350,8 @@ public class ShortcutManagerTest2 extends BaseShortcutManagerTest { .setCategories(set(ShortcutInfo.SHORTCUT_CATEGORY_CONVERSATION, "xyz")) .setIntent(makeIntent("action", ShortcutActivity.class, "key", "val")) .setRank(123) + .setPerson(makePerson("person", "personKey", "personUri")) + .setLongLived() .setExtras(pb) .build(); sorig.addFlags(ShortcutInfo.FLAG_PINNED); @@ -368,9 +375,12 @@ public class ShortcutManagerTest2 extends BaseShortcutManagerTest { assertEquals("action", si.getIntent().getAction()); assertEquals("val", si.getIntent().getStringExtra("key")); assertEquals(123, si.getRank()); + assertEquals("person", si.getPersons()[0].getName()); + assertEquals("personKey", si.getPersons()[0].getKey()); + assertEquals("personUri", si.getPersons()[0].getUri()); assertEquals(1, si.getExtras().getInt("k")); - assertEquals(ShortcutInfo.FLAG_PINNED, si.getFlags()); + assertEquals(ShortcutInfo.FLAG_PINNED | ShortcutInfo.FLAG_LONG_LIVED, si.getFlags()); assertEquals("abc", si.getBitmapPath()); assertEquals(456, si.getIconResourceId()); assertEquals("string/r456", si.getIconResName()); @@ -388,9 +398,12 @@ public class ShortcutManagerTest2 extends BaseShortcutManagerTest { assertEquals("action", si.getIntent().getAction()); assertEquals("val", si.getIntent().getStringExtra("key")); assertEquals(123, si.getRank()); + assertEquals("person", si.getPersons()[0].getName()); + assertEquals("personKey", si.getPersons()[0].getKey()); + assertEquals("personUri", si.getPersons()[0].getUri()); assertEquals(1, si.getExtras().getInt("k")); - assertEquals(ShortcutInfo.FLAG_PINNED, si.getFlags()); + assertEquals(ShortcutInfo.FLAG_PINNED | ShortcutInfo.FLAG_LONG_LIVED, si.getFlags()); assertEquals(null, si.getBitmapPath()); assertEquals(456, si.getIconResourceId()); @@ -408,9 +421,12 @@ public class ShortcutManagerTest2 extends BaseShortcutManagerTest { assertEquals(set(ShortcutInfo.SHORTCUT_CATEGORY_CONVERSATION, "xyz"), si.getCategories()); assertEquals(null, si.getIntent()); assertEquals(123, si.getRank()); + assertEquals("person", si.getPersons()[0].getName()); + assertEquals("personKey", si.getPersons()[0].getKey()); + assertEquals("personUri", si.getPersons()[0].getUri()); assertEquals(1, si.getExtras().getInt("k")); - assertEquals(ShortcutInfo.FLAG_PINNED, si.getFlags()); + assertEquals(ShortcutInfo.FLAG_PINNED | ShortcutInfo.FLAG_LONG_LIVED, si.getFlags()); assertEquals(null, si.getBitmapPath()); assertEquals(456, si.getIconResourceId()); @@ -428,9 +444,11 @@ public class ShortcutManagerTest2 extends BaseShortcutManagerTest { assertEquals(null, si.getCategories()); assertEquals(null, si.getIntent()); assertEquals(0, si.getRank()); + assertEquals(null, si.getPersons()); assertEquals(null, si.getExtras()); - assertEquals(ShortcutInfo.FLAG_PINNED | ShortcutInfo.FLAG_KEY_FIELDS_ONLY, si.getFlags()); + assertEquals(ShortcutInfo.FLAG_PINNED | ShortcutInfo.FLAG_KEY_FIELDS_ONLY + | ShortcutInfo.FLAG_LONG_LIVED, si.getFlags()); assertEquals(null, si.getBitmapPath()); assertEquals(456, si.getIconResourceId()); @@ -692,6 +710,12 @@ public class ShortcutManagerTest2 extends BaseShortcutManagerTest { si = sorig.clone(/* flags=*/ 0); si.copyNonNullFieldsFrom(new ShortcutInfo.Builder(getTestContext()).setId("id") + .setPerson(makePerson("person", "", "")).build()); + assertEquals("text", si.getText()); + assertEquals("person", si.getPersons()[0].getName()); + + si = sorig.clone(/* flags=*/ 0); + si.copyNonNullFieldsFrom(new ShortcutInfo.Builder(getTestContext()).setId("id") .setIntent(makeIntent("action2", ShortcutActivity.class)).build()); assertEquals("text", si.getText()); assertEquals("action2", si.getIntent().getAction()); diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityDisplayTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityDisplayTests.java index 5bf3d2dabe24..56f4a8544f00 100644 --- a/services/tests/wmtests/src/com/android/server/wm/ActivityDisplayTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/ActivityDisplayTests.java @@ -36,6 +36,9 @@ import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyBoolean; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.doAnswer; import android.platform.test.annotations.Presubmit; @@ -54,11 +57,6 @@ import org.junit.Test; @Presubmit public class ActivityDisplayTests extends ActivityTestsBase { - @Before - public void setUp() throws Exception { - setupActivityTaskManagerService(); - } - @Test public void testLastFocusedStackIsUpdatedWhenMovingStack() { // Create a stack at bottom. @@ -277,4 +275,60 @@ public class ActivityDisplayTests extends ActivityTestsBase { assertTrue(anotherAlwaysOnTopStack.isAlwaysOnTop()); assertEquals(anotherAlwaysOnTopStack, display.getChildAt(topPosition - 1)); } + + @Test + public void testRemoveStackInWindowingModes() { + removeStackTests(() -> mRootActivityContainer.removeStacksInWindowingModes( + WINDOWING_MODE_FULLSCREEN)); + } + + @Test + public void testRemoveStackWithActivityTypes() { + removeStackTests( + () -> mRootActivityContainer.removeStacksWithActivityTypes(ACTIVITY_TYPE_STANDARD)); + } + + private void removeStackTests(Runnable runnable) { + final ActivityDisplay display = mRootActivityContainer.getDefaultDisplay(); + final ActivityStack stack1 = display.createStack(WINDOWING_MODE_FULLSCREEN, + ACTIVITY_TYPE_STANDARD, ON_TOP); + final ActivityStack stack2 = display.createStack(WINDOWING_MODE_FULLSCREEN, + ACTIVITY_TYPE_STANDARD, ON_TOP); + final ActivityStack stack3 = display.createStack(WINDOWING_MODE_FULLSCREEN, + ACTIVITY_TYPE_STANDARD, ON_TOP); + final ActivityStack stack4 = display.createStack(WINDOWING_MODE_FULLSCREEN, + ACTIVITY_TYPE_STANDARD, ON_TOP); + final TaskRecord task1 = new TaskBuilder(mService.mStackSupervisor).setStack( + stack1).setTaskId(1).build(); + final TaskRecord task2 = new TaskBuilder(mService.mStackSupervisor).setStack( + stack2).setTaskId(2).build(); + final TaskRecord task3 = new TaskBuilder(mService.mStackSupervisor).setStack( + stack3).setTaskId(3).build(); + final TaskRecord task4 = new TaskBuilder(mService.mStackSupervisor).setStack( + stack4).setTaskId(4).build(); + + // Reordering stacks while removing stacks. + doAnswer(invocation -> { + display.positionChildAtTop(stack3, false); + return true; + }).when(mSupervisor).removeTaskByIdLocked(eq(task4.taskId), anyBoolean(), anyBoolean(), + any()); + + // Removing stacks from the display while removing stacks. + doAnswer(invocation -> { + display.removeChild(stack2); + return true; + }).when(mSupervisor).removeTaskByIdLocked(eq(task2.taskId), anyBoolean(), anyBoolean(), + any()); + + runnable.run(); + verify(mSupervisor).removeTaskByIdLocked(eq(task4.taskId), anyBoolean(), anyBoolean(), + any()); + verify(mSupervisor).removeTaskByIdLocked(eq(task3.taskId), anyBoolean(), anyBoolean(), + any()); + verify(mSupervisor).removeTaskByIdLocked(eq(task2.taskId), anyBoolean(), anyBoolean(), + any()); + verify(mSupervisor).removeTaskByIdLocked(eq(task1.taskId), anyBoolean(), anyBoolean(), + any()); + } } diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityMetricsLaunchObserverTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityMetricsLaunchObserverTests.java index cac9cf69ce4d..ee228610ab21 100644 --- a/services/tests/wmtests/src/com/android/server/wm/ActivityMetricsLaunchObserverTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/ActivityMetricsLaunchObserverTests.java @@ -70,8 +70,6 @@ public class ActivityMetricsLaunchObserverTests extends ActivityTestsBase { @Before public void setUpAMLO() throws Exception { - setupActivityTaskManagerService(); - mLaunchObserver = mock(ActivityMetricsLaunchObserver.class); // ActivityStackSupervisor always creates its own instance of ActivityMetricsLogger. diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java index d1609c3955bf..319ffed3778c 100644 --- a/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java @@ -19,8 +19,10 @@ package com.android.server.wm; import static android.view.Display.DEFAULT_DISPLAY; import static com.android.dx.mockito.inline.extended.ExtendedMockito.any; +import static com.android.dx.mockito.inline.extended.ExtendedMockito.anyInt; import static com.android.dx.mockito.inline.extended.ExtendedMockito.doAnswer; import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn; +import static com.android.dx.mockito.inline.extended.ExtendedMockito.eq; import static com.android.dx.mockito.inline.extended.ExtendedMockito.mock; import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify; import static com.android.dx.mockito.inline.extended.ExtendedMockito.when; @@ -29,6 +31,7 @@ import static com.android.server.policy.WindowManagerPolicy.NAV_BAR_LEFT; import static com.android.server.policy.WindowManagerPolicy.NAV_BAR_RIGHT; import static com.android.server.wm.ActivityStack.ActivityState.INITIALIZING; import static com.android.server.wm.ActivityStack.ActivityState.PAUSING; +import static com.android.server.wm.ActivityStack.ActivityState.RESUMED; import static com.android.server.wm.ActivityStack.ActivityState.STOPPED; import static com.android.server.wm.ActivityStack.REMOVE_TASK_MODE_MOVING; @@ -39,6 +42,7 @@ import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; import android.app.ActivityOptions; +import android.app.servertransaction.ActivityConfigurationChangeItem; import android.app.servertransaction.ClientTransaction; import android.app.servertransaction.PauseActivityItem; import android.content.pm.ActivityInfo; @@ -69,10 +73,12 @@ public class ActivityRecordTests extends ActivityTestsBase { @Before public void setUp() throws Exception { - setupActivityTaskManagerService(); - mStack = new StackBuilder(mRootActivityContainer).build(); + mStack = (TestActivityStack) new StackBuilder(mRootActivityContainer).build(); mTask = mStack.getChildAt(0); mActivity = mTask.getTopActivity(); + + doReturn(false).when(mService).isBooting(); + doReturn(true).when(mService).isBooted(); } @Test @@ -115,22 +121,23 @@ public class ActivityRecordTests extends ActivityTestsBase { mActivity.setState(STOPPED, "testPausingWhenVisibleFromStopped"); - // The activity is in the focused stack so it should not move to paused. + // The activity is in the focused stack so it should be resumed. mActivity.makeVisibleIfNeeded(null /* starting */, true /* reportToClient */); - assertTrue(mActivity.isState(STOPPED)); + assertTrue(mActivity.isState(RESUMED)); assertFalse(pauseFound.value); - // Clear focused stack - final ActivityDisplay display = mRootActivityContainer.getDefaultDisplay(); - when(display.getFocusedStack()).thenReturn(null); + // Make the activity non focusable + mActivity.setState(STOPPED, "testPausingWhenVisibleFromStopped"); + doReturn(false).when(mActivity).isFocusable(); - // In the unfocused stack, the activity should move to paused. + // If the activity is not focusable, it should move to paused. mActivity.makeVisibleIfNeeded(null /* starting */, true /* reportToClient */); assertTrue(mActivity.isState(PAUSING)); assertTrue(pauseFound.value); // Make sure that the state does not change for current non-stopping states. mActivity.setState(INITIALIZING, "testPausingWhenVisibleFromStopped"); + doReturn(true).when(mActivity).isFocusable(); mActivity.makeVisibleIfNeeded(null /* starting */, true /* reportToClient */); @@ -321,4 +328,44 @@ public class ActivityRecordTests extends ActivityTestsBase { assertEquals(ActivityTaskManagerService.RELAUNCH_REASON_NONE, mActivity.mRelaunchReason); } + + @Test + public void testSetRequestedOrientationUpdatesConfiguration() throws Exception { + mActivity.setState(ActivityStack.ActivityState.RESUMED, "Testing"); + + mTask.onRequestedOverrideConfigurationChanged(mTask.getConfiguration()); + mActivity.setLastReportedConfiguration(new MergedConfiguration(new Configuration(), + mActivity.getConfiguration())); + + mActivity.info.configChanges |= ActivityInfo.CONFIG_ORIENTATION; + final Configuration newConfig = new Configuration(mActivity.getConfiguration()); + newConfig.orientation = newConfig.orientation == Configuration.ORIENTATION_PORTRAIT + ? Configuration.ORIENTATION_LANDSCAPE + : Configuration.ORIENTATION_PORTRAIT; + + // Mimic the behavior that display doesn't handle app's requested orientation. + doAnswer(invocation -> { + mTask.onConfigurationChanged(newConfig); + return null; + }).when(mActivity.mAppWindowToken).setOrientation(anyInt(), any(), any()); + + final int requestedOrientation; + switch (newConfig.orientation) { + case Configuration.ORIENTATION_LANDSCAPE: + requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE; + break; + case Configuration.ORIENTATION_PORTRAIT: + requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT; + break; + default: + throw new IllegalStateException("Orientation in new config should be either" + + "landscape or portrait."); + } + mActivity.setRequestedOrientation(requestedOrientation); + + final ActivityConfigurationChangeItem expected = + ActivityConfigurationChangeItem.obtain(newConfig); + verify(mService.getLifecycleManager()).scheduleTransaction(eq(mActivity.app.getThread()), + eq(mActivity.appToken), eq(expected)); + } } diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityStackSupervisorTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityStackSupervisorTests.java index f7b5d26ac87e..59e71c417439 100644 --- a/services/tests/wmtests/src/com/android/server/wm/ActivityStackSupervisorTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/ActivityStackSupervisorTests.java @@ -64,7 +64,6 @@ public class ActivityStackSupervisorTests extends ActivityTestsBase { @Before public void setUp() throws Exception { - setupActivityTaskManagerService(); mFullscreenStack = mRootActivityContainer.getDefaultDisplay().createStack( WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, true /* onTop */); } diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityStackTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityStackTests.java index 9d5f687b83a7..35c1edeace2d 100644 --- a/services/tests/wmtests/src/com/android/server/wm/ActivityStackTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/ActivityStackTests.java @@ -75,7 +75,6 @@ public class ActivityStackTests extends ActivityTestsBase { @Before public void setUp() throws Exception { - setupActivityTaskManagerService(); mDefaultDisplay = mRootActivityContainer.getDefaultDisplay(); mStack = spy(mDefaultDisplay.createStack(WINDOWING_MODE_UNDEFINED, ACTIVITY_TYPE_STANDARD, true /* onTop */)); @@ -266,13 +265,13 @@ public class ActivityStackTests extends ActivityTestsBase { // Do not move display to back because there is still another stack. stack2.moveToBack("testMoveStackToBackIncludingParent", stack2.topTask()); - verify(stack2.getWindowContainerController()).positionChildAtBottom(any(), + verify(stack2.getTaskStack()).positionChildAtBottom(any(), eq(false) /* includingParents */); // Also move display to back because there is only one stack left. display.removeChild(stack1); stack2.moveToBack("testMoveStackToBackIncludingParent", stack2.topTask()); - verify(stack2.getWindowContainerController()).positionChildAtBottom(any(), + verify(stack2.getTaskStack()).positionChildAtBottom(any(), eq(true) /* includingParents */); } diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityStartControllerTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityStartControllerTests.java index 2ba2fdbcb959..96db38b14ad5 100644 --- a/services/tests/wmtests/src/com/android/server/wm/ActivityStartControllerTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/ActivityStartControllerTests.java @@ -56,7 +56,6 @@ public class ActivityStartControllerTests extends ActivityTestsBase { @Before public void setUp() throws Exception { - mService = createActivityTaskManagerService(); mFactory = mock(Factory.class); mController = new ActivityStartController(mService, mService.mStackSupervisor, mFactory); mStarter = spy(new ActivityStarter(mController, mService, diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java index ec88718dab5d..a381023590c3 100644 --- a/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java @@ -117,7 +117,6 @@ public class ActivityStarterTests extends ActivityTestsBase { @Before public void setUp() throws Exception { - setupActivityTaskManagerService(); mController = mock(ActivityStartController.class); mActivityMetricsLogger = mock(ActivityMetricsLogger.class); clearInvocations(mActivityMetricsLogger); @@ -143,7 +142,7 @@ public class ActivityStarterTests extends ActivityTestsBase { .setStack(mService.mRootActivityContainer.getDefaultDisplay().createStack( WINDOWING_MODE_PINNED, ACTIVITY_TYPE_STANDARD, true /* onTop */)) .build(); - assertThat((Object) task2.getStack()).isInstanceOf(PinnedActivityStack.class); + assertThat((Object) task2.getStack()).isInstanceOf(ActivityStack.class); mStarter.updateBounds(task2, bounds); verify(mService, times(1)).resizeStack(eq(task2.getStack().mStackId), diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityTestsBase.java b/services/tests/wmtests/src/com/android/server/wm/ActivityTestsBase.java index 5589ca1be815..ea8f33f0c630 100644 --- a/services/tests/wmtests/src/com/android/server/wm/ActivityTestsBase.java +++ b/services/tests/wmtests/src/com/android/server/wm/ActivityTestsBase.java @@ -39,9 +39,6 @@ import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn; import static com.android.server.wm.ActivityStack.REMOVE_TASK_MODE_DESTROYING; import static com.android.server.wm.ActivityStackSupervisor.ON_TOP; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.Mockito.doCallRealMethod; - import android.app.ActivityManagerInternal; import android.app.ActivityOptions; import android.app.IApplicationThread; @@ -58,6 +55,7 @@ import android.hardware.display.DisplayManager; import android.hardware.display.DisplayManagerGlobal; import android.os.Handler; import android.os.Looper; +import android.os.PowerManager; import android.os.Process; import android.os.UserHandle; import android.service.voice.IVoiceInteractionSession; @@ -66,11 +64,11 @@ import android.view.Display; import android.view.DisplayInfo; import com.android.internal.app.IVoiceInteractor; -import com.android.server.appop.AppOpsService; import com.android.server.AttributeCache; import com.android.server.ServiceThread; import com.android.server.am.ActivityManagerService; import com.android.server.am.PendingIntentController; +import com.android.server.appop.AppOpsService; import com.android.server.firewall.IntentFirewall; import com.android.server.uri.UriGrantsManagerInternal; @@ -114,6 +112,10 @@ class ActivityTestsBase { @Before public void setUpBase() { mTestInjector.setUp(); + + mService = new TestActivityTaskManagerService(mContext); + mSupervisor = mService.mStackSupervisor; + mRootActivityContainer = mService.mRootActivityContainer; } @After @@ -125,17 +127,6 @@ class ActivityTestsBase { } } - ActivityTaskManagerService createActivityTaskManagerService() { - mService = new TestActivityTaskManagerService(mContext); - mSupervisor = mService.mStackSupervisor; - mRootActivityContainer = mService.mRootActivityContainer; - return mService; - } - - void setupActivityTaskManagerService() { - createActivityTaskManagerService(); - } - /** Creates a {@link TestActivityDisplay}. */ TestActivityDisplay createNewActivityDisplay() { return TestActivityDisplay.create(mSupervisor, sNextDisplayId++); @@ -377,7 +368,7 @@ class ActivityTestsBase { mStack.addTask(task, true, "creating test task"); task.setStack(mStack); task.setTask(); - mStack.getWindowContainerController().mContainer.addChild(task.mTask, 0); + mStack.getTaskStack().addChild(task.mTask, 0); } task.touchActiveTime(); @@ -435,6 +426,7 @@ class ActivityTestsBase { doReturn(mock(IPackageManager.class)).when(this).getPackageManager(); // allow background activity starts by default doReturn(true).when(this).isBackgroundActivityStartsEnabled(); + doNothing().when(this).updateCpuStats(); } void setup(IntentFirewall intentFirewall, PendingIntentController intentController, @@ -590,6 +582,8 @@ class ActivityTestsBase { doNothing().when(this).acquireLaunchWakelock(); doReturn(mKeyguardController).when(this).getKeyguardController(); + mLaunchingActivity = mock(PowerManager.WakeLock.class); + initialize(); } @@ -632,7 +626,7 @@ class ActivityTestsBase { @SuppressWarnings("TypeParameterUnusedInFormals") @Override - <T extends ActivityStack> T createStackUnchecked(int windowingMode, int activityType, + ActivityStack createStackUnchecked(int windowingMode, int activityType, int stackId, boolean onTop) { return new StackBuilder(mSupervisor.mRootActivityContainer).setDisplay(this) .setWindowingMode(windowingMode).setActivityType(activityType) @@ -681,10 +675,9 @@ class ActivityTestsBase { * method is called. Note that its functionality depends on the implementations of the * construction arguments. */ - protected static class TestActivityStack<T extends StackWindowController> - extends ActivityStack<T> { + protected static class TestActivityStack + extends ActivityStack { private int mOnActivityRemovedFromStackCount = 0; - private T mContainerController; static final int IS_TRANSLUCENT_UNSET = 0; static final int IS_TRANSLUCENT_FALSE = 1; @@ -724,20 +717,20 @@ class ActivityTestsBase { } @Override - protected T createStackWindowController(int displayId, boolean onTop, Rect outBounds) { - mContainerController = (T) WindowTestUtils.createMockStackWindowContainerController(); + protected void createTaskStack(int displayId, boolean onTop, Rect outBounds) { + mTaskStack = WindowTestUtils.createMockTaskStack(); // Primary pinned stacks require a non-empty out bounds to be set or else all tasks // will be moved to the full screen stack. if (getWindowingMode() == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY) { outBounds.set(0, 0, 100, 100); } - return mContainerController; + } @Override - T getWindowContainerController() { - return mContainerController; + TaskStack getTaskStack() { + return mTaskStack; } void setIsTranslucent(boolean isTranslucent) { @@ -827,27 +820,23 @@ class ActivityTestsBase { } @SuppressWarnings("TypeParameterUnusedInFormals") - <T extends ActivityStack> T build() { + ActivityStack build() { final int stackId = mStackId >= 0 ? mStackId : mDisplay.getNextStackId(); if (mWindowingMode == WINDOWING_MODE_PINNED) { - return (T) new PinnedActivityStack(mDisplay, stackId, - mRootActivityContainer.mStackSupervisor, mOnTop) { + return new ActivityStack(mDisplay, stackId, mRootActivityContainer.mStackSupervisor, + mWindowingMode, ACTIVITY_TYPE_STANDARD, mOnTop) { @Override Rect getDefaultPictureInPictureBounds(float aspectRatio) { return new Rect(50, 50, 100, 100); } @Override - PinnedStackWindowController createStackWindowController(int displayId, - boolean onTop, Rect outBounds) { - PinnedStackWindowController controller = - mock(PinnedStackWindowController.class); - controller.mContainer = mock(TaskStack.class); - return controller; + void createTaskStack(int displayId, boolean onTop, Rect outBounds) { + mTaskStack = mock(TaskStack.class); } }; } else { - return (T) new TestActivityStack(mDisplay, stackId, + return new TestActivityStack(mDisplay, stackId, mRootActivityContainer.mStackSupervisor, mWindowingMode, mActivityType, mOnTop, mCreateActivity); } diff --git a/services/tests/wmtests/src/com/android/server/wm/AppTransitionTests.java b/services/tests/wmtests/src/com/android/server/wm/AppTransitionTests.java index 51bebbbcd6b0..123de2d227bc 100644 --- a/services/tests/wmtests/src/com/android/server/wm/AppTransitionTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/AppTransitionTests.java @@ -60,7 +60,7 @@ public class AppTransitionTests extends WindowTestsBase { @BeforeClass public static void setUpRootWindowContainerMock() { - final WindowManagerService wm = WmServiceUtils.getWindowManagerService(); + final WindowManagerService wm = TestSystemServices.getWindowManagerService(); // For unit test, we don't need to test performSurfacePlacement to prevent some abnormal // interaction with surfaceflinger native side. sOriginalRootWindowContainer = wm.mRoot; @@ -74,7 +74,7 @@ public class AppTransitionTests extends WindowTestsBase { @AfterClass public static void tearDownRootWindowContainerMock() { - final WindowManagerService wm = WmServiceUtils.getWindowManagerService(); + final WindowManagerService wm = TestSystemServices.getWindowManagerService(); wm.mRoot = sOriginalRootWindowContainer; sOriginalRootWindowContainer = null; } @@ -181,7 +181,7 @@ public class AppTransitionTests extends WindowTestsBase { assertTrue(dc1.mOpeningApps.size() > 0); // Move stack to another display. - stack1.getController().reparent(dc2.getDisplayId(), new Rect(), true); + stack1.reparent(dc2.getDisplayId(), new Rect(), true); // Verify if token are cleared from both pending transition list in former display. assertFalse(dc1.mOpeningApps.contains(token1)); diff --git a/services/tests/wmtests/src/com/android/server/wm/DragDropControllerTests.java b/services/tests/wmtests/src/com/android/server/wm/DragDropControllerTests.java index bb3ab358e71a..68d8bc078d54 100644 --- a/services/tests/wmtests/src/com/android/server/wm/DragDropControllerTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/DragDropControllerTests.java @@ -94,8 +94,8 @@ public class DragDropControllerTests extends WindowTestsBase { private WindowState createDropTargetWindow(String name, int ownerId) { final WindowTestUtils.TestAppWindowToken token = WindowTestUtils.createTestAppWindowToken( mDisplayContent); - final TaskStack stack = createStackControllerOnStackOnDisplay( - WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, mDisplayContent).mContainer; + final TaskStack stack = createTaskStackOnDisplay( + WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, mDisplayContent); final Task task = createTaskInStack(stack, ownerId); task.addChild(token, 0); diff --git a/services/tests/wmtests/src/com/android/server/wm/LaunchParamsControllerTests.java b/services/tests/wmtests/src/com/android/server/wm/LaunchParamsControllerTests.java index 8c3dec7f1e75..b28ae40d5056 100644 --- a/services/tests/wmtests/src/com/android/server/wm/LaunchParamsControllerTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/LaunchParamsControllerTests.java @@ -71,7 +71,6 @@ public class LaunchParamsControllerTests extends ActivityTestsBase { @Before public void setUp() throws Exception { - mService = createActivityTaskManagerService(); mPersister = new TestLaunchParamsPersister(); mController = new LaunchParamsController(mService, mPersister); } diff --git a/services/tests/wmtests/src/com/android/server/wm/LaunchParamsPersisterTests.java b/services/tests/wmtests/src/com/android/server/wm/LaunchParamsPersisterTests.java index 86353643c128..aeda473a9e6e 100644 --- a/services/tests/wmtests/src/com/android/server/wm/LaunchParamsPersisterTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/LaunchParamsPersisterTests.java @@ -102,8 +102,6 @@ public class LaunchParamsPersisterTests extends ActivityTestsBase { mFolder = new File(cacheFolder, "launch_params_tests"); deleteRecursively(mFolder); - setupActivityTaskManagerService(); - mDisplayUniqueId = "test:" + Integer.toString(sNextUniqueId++); final DisplayInfo info = new DisplayInfo(); info.uniqueId = mDisplayUniqueId; diff --git a/services/tests/wmtests/src/com/android/server/wm/PendingRemoteAnimationRegistryTest.java b/services/tests/wmtests/src/com/android/server/wm/PendingRemoteAnimationRegistryTest.java index efd7d25c586d..beaac8e58686 100644 --- a/services/tests/wmtests/src/com/android/server/wm/PendingRemoteAnimationRegistryTest.java +++ b/services/tests/wmtests/src/com/android/server/wm/PendingRemoteAnimationRegistryTest.java @@ -52,7 +52,6 @@ public class PendingRemoteAnimationRegistryTest extends ActivityTestsBase { @Before public void setUp() throws Exception { MockitoAnnotations.initMocks(this); - mService = createActivityTaskManagerService(); mService.mH.runWithScissors(() -> { mHandler = new TestHandler(null, mClock); }, 0); diff --git a/services/tests/wmtests/src/com/android/server/wm/RootActivityContainerTests.java b/services/tests/wmtests/src/com/android/server/wm/RootActivityContainerTests.java index 58302d6b8b75..e3bacf96a86c 100644 --- a/services/tests/wmtests/src/com/android/server/wm/RootActivityContainerTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/RootActivityContainerTests.java @@ -82,7 +82,6 @@ public class RootActivityContainerTests extends ActivityTestsBase { @Before public void setUp() throws Exception { - setupActivityTaskManagerService(); mFullscreenStack = mRootActivityContainer.getDefaultDisplay().createStack( WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, true /* onTop */); } @@ -323,8 +322,8 @@ public class RootActivityContainerTests extends ActivityTestsBase { public void testFindTaskToMoveToFrontWhenRecentsOnTop() { // Create stack/task on default display. final ActivityDisplay display = mRootActivityContainer.getDefaultDisplay(); - final TestActivityStack targetStack = - new StackBuilder(mRootActivityContainer).setOnTop(false).build(); + final TestActivityStack targetStack = (TestActivityStack) new StackBuilder( + mRootActivityContainer).setOnTop(false).build(); final TaskRecord targetTask = targetStack.getChildAt(0); // Create Recents on top of the display. diff --git a/services/tests/wmtests/src/com/android/server/wm/RunningTasksTest.java b/services/tests/wmtests/src/com/android/server/wm/RunningTasksTest.java index a8b6dc373cbf..dc964806b7a9 100644 --- a/services/tests/wmtests/src/com/android/server/wm/RunningTasksTest.java +++ b/services/tests/wmtests/src/com/android/server/wm/RunningTasksTest.java @@ -49,7 +49,6 @@ public class RunningTasksTest extends ActivityTestsBase { @Before public void setUp() throws Exception { - setupActivityTaskManagerService(); mRunningTasks = new RunningTasks(); } diff --git a/services/tests/wmtests/src/com/android/server/wm/StackWindowControllerTests.java b/services/tests/wmtests/src/com/android/server/wm/StackWindowControllerTests.java deleted file mode 100644 index 5690b58737ab..000000000000 --- a/services/tests/wmtests/src/com/android/server/wm/StackWindowControllerTests.java +++ /dev/null @@ -1,105 +0,0 @@ -/* - * Copyright (C) 2017 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.server.wm; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertNull; -import static org.junit.Assert.assertTrue; - -import android.graphics.Rect; -import android.platform.test.annotations.Presubmit; - -import androidx.test.filters.SmallTest; - -import org.junit.Test; - -/** - * Test class for {@link StackWindowController}. - * - * Build/Install/Run: - * atest FrameworksServicesTests:StackWindowControllerTests - */ -@SmallTest -@Presubmit -public class StackWindowControllerTests extends WindowTestsBase { - @Test - public void testRemoveContainer() { - final StackWindowController stackController = - createStackControllerOnDisplay(mDisplayContent); - final WindowTestUtils.TestTask task = WindowTestUtils.createTestTask(stackController); - - final TaskStack stack = stackController.mContainer; - assertNotNull(stack); - assertNotNull(task); - stackController.removeContainer(); - // Assert that the container was removed. - assertNull(stackController.mContainer); - assertNull(stack.getDisplayContent()); - assertNull(task.getDisplayContent()); - assertNull(task.mStack); - } - - @Test - public void testRemoveContainer_deferRemoval() { - final StackWindowController stackController = - createStackControllerOnDisplay(mDisplayContent); - final WindowTestUtils.TestTask task = WindowTestUtils.createTestTask(stackController); - - final TaskStack stack = stackController.mContainer; - // Stack removal is deferred if one of its child is animating. - task.setLocalIsAnimating(true); - - stackController.removeContainer(); - // For the case of deferred removal the stack controller will no longer be connected to the - // container, but the task controller will still be connected to the its container until - // the stack window container is removed. - assertNull(stackController.mContainer); - assertNull(stack.getController()); - assertNotNull(task); - - stack.removeImmediately(); - // After removing, the task will be isolated. - assertNull(task.getParent()); - assertEquals(task.getChildCount(), 0); - assertNull(task.getController()); - } - - @Test - public void testReparent() { - // Create first stack on primary display. - final StackWindowController stack1Controller = - createStackControllerOnDisplay(mDisplayContent); - final TaskStack stack1 = stack1Controller.mContainer; - final WindowTestUtils.TestTask task1 = WindowTestUtils.createTestTask(stack1Controller); - task1.mOnDisplayChangedCalled = false; - - // Create second display and put second stack on it. - final DisplayContent dc = createNewDisplay(); - final StackWindowController stack2Controller = - createStackControllerOnDisplay(dc); - final TaskStack stack2 = stack2Controller.mContainer; - - // Reparent - stack1Controller.reparent(dc.getDisplayId(), new Rect(), true /* onTop */); - assertEquals(dc, stack1.getDisplayContent()); - final int stack1PositionInParent = stack1.getParent().mChildren.indexOf(stack1); - final int stack2PositionInParent = stack1.getParent().mChildren.indexOf(stack2); - assertEquals(stack1PositionInParent, stack2PositionInParent + 1); - assertTrue(task1.mOnDisplayChangedCalled); - } -} diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskLaunchParamsModifierTests.java b/services/tests/wmtests/src/com/android/server/wm/TaskLaunchParamsModifierTests.java index 53e99fae95d4..ace179acdeb5 100644 --- a/services/tests/wmtests/src/com/android/server/wm/TaskLaunchParamsModifierTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/TaskLaunchParamsModifierTests.java @@ -75,10 +75,6 @@ public class TaskLaunchParamsModifierTests extends ActivityTestsBase { @Before public void setUp() throws Exception { - setupActivityTaskManagerService(); - mService.mSupportsFreeformWindowManagement = true; - when(mSupervisor.canUseActivityOptionsLaunchBounds(any())).thenCallRealMethod(); - mActivity = new ActivityBuilder(mService).build(); mActivity.appInfo.targetSdkVersion = Build.VERSION_CODES.N_MR1; mActivity.info.applicationInfo.flags |= ApplicationInfo.FLAG_SUPPORTS_SCREEN_DENSITIES; diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskRecordTests.java b/services/tests/wmtests/src/com/android/server/wm/TaskRecordTests.java index 1c33dfb79551..e182c45f009e 100644 --- a/services/tests/wmtests/src/com/android/server/wm/TaskRecordTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/TaskRecordTests.java @@ -90,7 +90,6 @@ public class TaskRecordTests extends ActivityTestsBase { @Before public void setUp() throws Exception { TaskRecord.setTaskRecordFactory(null); - setupActivityTaskManagerService(); mParentBounds = new Rect(10 /*left*/, 30 /*top*/, 80 /*right*/, 60 /*bottom*/); } @@ -314,13 +313,11 @@ public class TaskRecordTests extends ActivityTestsBase { // Wire up task and stack. task.mTask.mTaskRecord = task; doCallRealMethod().when(task.mTask).onDescendantOrientationChanged(any(), any()); - doReturn(stack.getWindowContainerController().mContainer).when(task.mTask).getParent(); + doReturn(stack.getTaskStack()).when(task.mTask).getParent(); // Wire up stack and display content. - doCallRealMethod().when(stack.mWindowContainerController.mContainer) - .onDescendantOrientationChanged(any(), any()); - doReturn(display.mDisplayContent).when(stack.mWindowContainerController.mContainer) - .getParent(); + doCallRealMethod().when(stack.mTaskStack).onDescendantOrientationChanged(any(), any()); + doReturn(display.mDisplayContent).when(stack.mTaskStack).getParent(); activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT); assertTrue("Bounds of the task should be pillarboxed.", diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskStackContainersTests.java b/services/tests/wmtests/src/com/android/server/wm/TaskStackContainersTests.java index f01e9f0662c9..74ccccca43bb 100644 --- a/services/tests/wmtests/src/com/android/server/wm/TaskStackContainersTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/TaskStackContainersTests.java @@ -47,8 +47,8 @@ public class TaskStackContainersTests extends WindowTestsBase { @Before public void setUp() throws Exception { - mPinnedStack = createStackControllerOnStackOnDisplay( - WINDOWING_MODE_PINNED, ACTIVITY_TYPE_STANDARD, mDisplayContent).mContainer; + mPinnedStack = createTaskStackOnDisplay( + WINDOWING_MODE_PINNED, ACTIVITY_TYPE_STANDARD, mDisplayContent); // Stack should contain visible app window to be considered visible. final Task pinnedTask = createTaskInStack(mPinnedStack, 0 /* userId */); assertFalse(mPinnedStack.isVisible()); diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskStackTests.java b/services/tests/wmtests/src/com/android/server/wm/TaskStackTests.java index 7ac331829fb1..2554237cdbf5 100644 --- a/services/tests/wmtests/src/com/android/server/wm/TaskStackTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/TaskStackTests.java @@ -20,8 +20,12 @@ import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE; import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_PORTRAIT; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotEquals; +import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; +import android.graphics.Rect; import android.platform.test.annotations.Presubmit; import androidx.test.filters.SmallTest; @@ -106,4 +110,62 @@ public class TaskStackTests extends WindowTestsBase { assertNull(stack.getDisplayContent()); assertNull(task.mStack); } + + @Test + public void testRemoveContainer() { + final TaskStack stack = createTaskStackOnDisplay(mDisplayContent); + final WindowTestUtils.TestTask task = WindowTestUtils.createTestTask(stack); + + assertNotNull(stack); + assertNotNull(task); + stack.removeIfPossible(); + // Assert that the container was removed. + assertNull(stack.getParent()); + assertEquals(0, stack.getChildCount()); + assertNull(stack.getDisplayContent()); + assertNull(task.getDisplayContent()); + assertNull(task.mStack); + } + + @Test + public void testRemoveContainer_deferRemoval() { + final TaskStack stack = createTaskStackOnDisplay(mDisplayContent); + final WindowTestUtils.TestTask task = WindowTestUtils.createTestTask(stack); + + // Stack removal is deferred if one of its child is animating. + task.setLocalIsAnimating(true); + + stack.removeIfPossible(); + // For the case of deferred removal the task controller will still be connected to the its + // container until the stack window container is removed. + assertNotNull(stack.getParent()); + assertNotEquals(0, stack.getChildCount()); + assertNotNull(task); + + stack.removeImmediately(); + // After removing, the task will be isolated. + assertNull(task.getParent()); + assertEquals(0, task.getChildCount()); + assertNull(task.getController()); + } + + @Test + public void testReparent() { + // Create first stack on primary display. + final TaskStack stack1 = createTaskStackOnDisplay(mDisplayContent); + final WindowTestUtils.TestTask task1 = WindowTestUtils.createTestTask(stack1); + task1.mOnDisplayChangedCalled = false; + + // Create second display and put second stack on it. + final DisplayContent dc = createNewDisplay(); + final TaskStack stack2 = createTaskStackOnDisplay(dc); + + // Reparent + stack1.reparent(dc.getDisplayId(), new Rect(), true /* onTop */); + assertEquals(dc, stack1.getDisplayContent()); + final int stack1PositionInParent = stack1.getParent().mChildren.indexOf(stack1); + final int stack2PositionInParent = stack1.getParent().mChildren.indexOf(stack2); + assertEquals(stack1PositionInParent, stack2PositionInParent + 1); + assertTrue(task1.mOnDisplayChangedCalled); + } } diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskTests.java b/services/tests/wmtests/src/com/android/server/wm/TaskTests.java index 3e32ed37a6f3..ae211d3f1e38 100644 --- a/services/tests/wmtests/src/com/android/server/wm/TaskTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/TaskTests.java @@ -40,8 +40,7 @@ public class TaskTests extends WindowTestsBase { @Test public void testRemoveContainer() { - final StackWindowController stackController1 = - createStackControllerOnDisplay(mDisplayContent); + final TaskStack stackController1 = createTaskStackOnDisplay(mDisplayContent); final WindowTestUtils.TestTask task = WindowTestUtils.createTestTask(stackController1); final WindowTestUtils.TestAppWindowToken appToken = WindowTestUtils.createAppWindowTokenInTask(mDisplayContent, task); @@ -49,14 +48,13 @@ public class TaskTests extends WindowTestsBase { task.removeIfPossible(); // Assert that the container was removed. assertNull(task.getParent()); - assertEquals(task.getChildCount(), 0); + assertEquals(0, task.getChildCount()); assertNull(appToken.getParent()); } @Test public void testRemoveContainer_deferRemoval() { - final StackWindowController stackController1 = - createStackControllerOnDisplay(mDisplayContent); + final TaskStack stackController1 = createTaskStackOnDisplay(mDisplayContent); final WindowTestUtils.TestTask task = WindowTestUtils.createTestTask(stackController1); final WindowTestUtils.TestAppWindowToken appToken = WindowTestUtils.createAppWindowTokenInTask(mDisplayContent, task); @@ -67,22 +65,20 @@ public class TaskTests extends WindowTestsBase { // For the case of deferred removal the task will still be connected to the its app token // until the task window container is removed. assertNotNull(task.getParent()); - assertNotEquals(task.getChildCount(), 0); + assertNotEquals(0, task.getChildCount()); assertNotNull(appToken.getParent()); task.removeImmediately(); assertNull(task.getParent()); - assertEquals(task.getChildCount(), 0); + assertEquals(0, task.getChildCount()); assertNull(appToken.getParent()); } @Test public void testReparent() { - final StackWindowController stackController1 = - createStackControllerOnDisplay(mDisplayContent); + final TaskStack stackController1 = createTaskStackOnDisplay(mDisplayContent); final WindowTestUtils.TestTask task = WindowTestUtils.createTestTask(stackController1); - final StackWindowController stackController2 = - createStackControllerOnDisplay(mDisplayContent); + final TaskStack stackController2 = createTaskStackOnDisplay(mDisplayContent); final WindowTestUtils.TestTask task2 = WindowTestUtils.createTestTask(stackController2); boolean gotException = false; @@ -93,20 +89,17 @@ public class TaskTests extends WindowTestsBase { } assertTrue("Should not be able to reparent to the same parent", gotException); - final StackWindowController stackController3 = - createStackControllerOnDisplay(mDisplayContent); - stackController3.setContainer(null); gotException = false; try { - task.reparent(stackController3, 0, false/* moveParents */); + task.reparent(null, 0, false/* moveParents */); } catch (IllegalArgumentException e) { gotException = true; } - assertTrue("Should not be able to reparent to a stack that doesn't have a container", + assertTrue("Should not be able to reparent to a stack that doesn't exist", gotException); task.reparent(stackController2, 0, false/* moveParents */); - assertEquals(stackController2.mContainer, task.getParent()); + assertEquals(stackController2, task.getParent()); assertEquals(0, task.positionInParent()); assertEquals(1, task2.positionInParent()); } @@ -114,20 +107,17 @@ public class TaskTests extends WindowTestsBase { @Test public void testReparent_BetweenDisplays() { // Create first stack on primary display. - final StackWindowController stack1Controller = - createStackControllerOnDisplay(mDisplayContent); - final TaskStack stack1 = stack1Controller.mContainer; - final WindowTestUtils.TestTask task = WindowTestUtils.createTestTask(stack1Controller); + final TaskStack stack1 = createTaskStackOnDisplay(mDisplayContent); + final WindowTestUtils.TestTask task = WindowTestUtils.createTestTask(stack1); task.mOnDisplayChangedCalled = false; assertEquals(mDisplayContent, stack1.getDisplayContent()); // Create second display and put second stack on it. final DisplayContent dc = createNewDisplay(); - final StackWindowController stack2Controller = createStackControllerOnDisplay(dc); - final TaskStack stack2 = stack2Controller.mContainer; - final WindowTestUtils.TestTask task2 = WindowTestUtils.createTestTask(stack2Controller); + final TaskStack stack2 = createTaskStackOnDisplay(dc); + final WindowTestUtils.TestTask task2 = WindowTestUtils.createTestTask(stack2); // Reparent and check state - task.reparent(stack2Controller, 0, false /* moveParents */); + task.reparent(stack2, 0, false /* moveParents */); assertEquals(stack2, task.getParent()); assertEquals(0, task.positionInParent()); assertEquals(1, task2.positionInParent()); diff --git a/services/tests/wmtests/src/com/android/server/wm/WmServiceUtils.java b/services/tests/wmtests/src/com/android/server/wm/TestSystemServices.java index 05ac8c1072c0..b151fb7a613c 100644 --- a/services/tests/wmtests/src/com/android/server/wm/WmServiceUtils.java +++ b/services/tests/wmtests/src/com/android/server/wm/TestSystemServices.java @@ -66,7 +66,7 @@ import java.util.concurrent.CountDownLatch; /** * A Test utility class to create a mock {@link WindowManagerService} instance for tests. */ -class WmServiceUtils { +class TestSystemServices { private static StaticMockitoSession sMockitoSession; private static WindowManagerService sService; private static TestWindowManagerPolicy sPolicy; @@ -78,7 +78,7 @@ class WmServiceUtils { .strictness(Strictness.LENIENT) .startMocking(); - runWithDexmakerShareClassLoader(WmServiceUtils::setUpTestWindowService); + runWithDexmakerShareClassLoader(TestSystemServices::setUpTestWindowService); } static void tearDownWindowManagerService() { @@ -147,7 +147,7 @@ class WmServiceUtils { final WindowManagerGlobalLock wmLock = new WindowManagerGlobalLock(); doReturn(wmLock).when(atms).getGlobalLock(); - sPolicy = new TestWindowManagerPolicy(WmServiceUtils::getWindowManagerService); + sPolicy = new TestWindowManagerPolicy(TestSystemServices::getWindowManagerService); sService = WindowManagerService.main(context, ims, false, false, sPolicy, atms); sService.onInitReady(); diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowFrameTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowFrameTests.java index d9ef10d7eecb..0a4a8a43fbc5 100644 --- a/services/tests/wmtests/src/com/android/server/wm/WindowFrameTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/WindowFrameTests.java @@ -16,12 +16,15 @@ package com.android.server.wm; +import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD; +import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN; import static android.view.DisplayCutout.BOUNDS_POSITION_TOP; import static android.view.DisplayCutout.fromBoundingRect; import static android.view.WindowManager.LayoutParams.MATCH_PARENT; import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION; import static org.junit.Assert.assertEquals; +import static org.mockito.Mockito.mock; import android.app.ActivityManager.TaskDescription; import android.content.res.Configuration; @@ -58,7 +61,7 @@ public class WindowFrameTests extends WindowTestsBase { boolean mDockedResizingForTest = false; WindowStateWithTask(WindowManagerService wm, IWindow iWindow, WindowToken windowToken, WindowManager.LayoutParams attrs, Task t) { - super(wm, null, iWindow, windowToken, null, 0, 0, attrs, 0, 0, + super(wm, mock(Session.class), iWindow, windowToken, null, 0, 0, attrs, 0, 0, false /* ownerCanAddInternalSystemWindow */); mTask = t; } @@ -113,9 +116,9 @@ public class WindowFrameTests extends WindowTestsBase { @Before public void setUp() throws Exception { - mWindowToken = WindowTestUtils.createTestAppWindowToken( - mWm.getDefaultDisplayContentLocked()); - mStubStack = new TaskStack(mWm, 0, null); + mWindowToken = createAppWindowToken(mWm.getDefaultDisplayContentLocked(), + WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD); + mStubStack = WindowTestUtils.createMockTaskStack(); } // Do not use this function directly in the tests below. Instead, use more explicit function diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowTestUtils.java b/services/tests/wmtests/src/com/android/server/wm/WindowTestUtils.java index 20fc5ae2454e..44e998b7e62a 100644 --- a/services/tests/wmtests/src/com/android/server/wm/WindowTestUtils.java +++ b/services/tests/wmtests/src/com/android/server/wm/WindowTestUtils.java @@ -103,12 +103,10 @@ public class WindowTestUtils { } /** - * Creates a mock instance of {@link StackWindowController}. + * Creates a mock instance of {@link TestTaskStack}. */ - public static StackWindowController createMockStackWindowContainerController() { - StackWindowController controller = mock(StackWindowController.class); - controller.mContainer = mock(TestTaskStack.class); - return controller; + public static TaskStack createMockTaskStack() { + return mock(TestTaskStack.class); } /** Creates a {@link Task} and adds it to the specified {@link TaskStack}. */ @@ -201,6 +199,11 @@ public class WindowTestUtils { } @Override + void onParentSet() { + // Do nothing. + } + + @Override boolean isOnTop() { return mOnTop; } @@ -283,10 +286,9 @@ public class WindowTestUtils { } } - public static TestTask createTestTask(StackWindowController stackWindowController) { - return new TestTask(sNextTaskId++, stackWindowController.mContainer, 0, - stackWindowController.mService, RESIZE_MODE_UNRESIZEABLE, false, - mock(TaskRecord.class)); + public static TestTask createTestTask(TaskStack stack) { + return new TestTask(sNextTaskId++, stack, 0, stack.mWmService, RESIZE_MODE_UNRESIZEABLE, + false, mock(TaskRecord.class)); } public static class TestIApplicationToken implements IApplicationToken { @@ -334,5 +336,10 @@ public class WindowTestUtils { mHasSurface = hadSurface; } + + @Override + void onParentSet() { + // Do nothing; + } } } diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java b/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java index cdc0a477b9c6..e38118e875e0 100644 --- a/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java +++ b/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java @@ -41,7 +41,6 @@ import static com.android.dx.mockito.inline.extended.ExtendedMockito.mock; import android.content.Context; import android.content.res.Configuration; -import android.graphics.Rect; import android.hardware.display.DisplayManagerGlobal; import android.testing.DexmakerShareClassLoaderRule; import android.util.Log; @@ -102,14 +101,14 @@ class WindowTestsBase { public static void setUpOnceBase() { AttributeCache.init(getInstrumentation().getTargetContext()); - WmServiceUtils.setUpWindowManagerService(); + TestSystemServices.setUpWindowManagerService(); sPowerManagerWrapper = mock(WindowState.PowerManagerWrapper.class); } @AfterClass public static void tearDonwOnceBase() { - WmServiceUtils.tearDownWindowManagerService(); + TestSystemServices.tearDownWindowManagerService(); } @Before @@ -121,7 +120,7 @@ class WindowTestsBase { final Context context = getInstrumentation().getTargetContext(); - mWm = WmServiceUtils.getWindowManagerService(); + mWm = TestSystemServices.getWindowManagerService(); beforeCreateDisplay(); context.getDisplay().getDisplayInfo(mDisplayInfo); @@ -199,7 +198,7 @@ class WindowTestsBase { } // Cleaned up everything in Handler. - WmServiceUtils.cleanupWindowManagerHandlers(); + TestSystemServices.cleanupWindowManagerHandlers(); } catch (Exception e) { Log.e(TAG, "Failed to tear down test", e); throw e; @@ -220,7 +219,7 @@ class WindowTestsBase { * Waits until the main handler for WM has processed all messages. */ void waitUntilHandlersIdle() { - WmServiceUtils.waitUntilWindowManagerHandlersIdle(); + TestSystemServices.waitUntilWindowManagerHandlersIdle(); } private WindowToken createWindowToken( @@ -240,8 +239,7 @@ class WindowTestsBase { WindowTestUtils.TestAppWindowToken createTestAppWindowToken(DisplayContent dc, int windowingMode, int activityType) { - final TaskStack stack = createStackControllerOnStackOnDisplay(windowingMode, activityType, - dc).mContainer; + final TaskStack stack = createTaskStackOnDisplay(windowingMode, activityType, dc); final Task task = createTaskInStack(stack, 0 /* userId */); final WindowTestUtils.TestAppWindowToken appWindowToken = WindowTestUtils.createTestAppWindowToken(dc); @@ -350,28 +348,20 @@ class WindowTestsBase { /** Creates a {@link TaskStack} and adds it to the specified {@link DisplayContent}. */ TaskStack createTaskStackOnDisplay(DisplayContent dc) { synchronized (mWm.mGlobalLock) { - return createStackControllerOnDisplay(dc).mContainer; + return createTaskStackOnDisplay(WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, dc); } } - StackWindowController createStackControllerOnDisplay(DisplayContent dc) { - synchronized (mWm.mGlobalLock) { - return createStackControllerOnStackOnDisplay( - WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, dc); - } - } - - StackWindowController createStackControllerOnStackOnDisplay( - int windowingMode, int activityType, DisplayContent dc) { + TaskStack createTaskStackOnDisplay(int windowingMode, int activityType, DisplayContent dc) { synchronized (mWm.mGlobalLock) { final Configuration overrideConfig = new Configuration(); overrideConfig.windowConfiguration.setWindowingMode(windowingMode); overrideConfig.windowConfiguration.setActivityType(activityType); final int stackId = ++sNextStackId; - final StackWindowController controller = new StackWindowController(stackId, null, - dc.getDisplayId(), true /* onTop */, new Rect(), mWm); - controller.onRequestedOverrideConfigurationChanged(overrideConfig); - return controller; + final TaskStack stack = new TaskStack(mWm, stackId, mock(ActivityStack.class)); + dc.setStackOnDisplay(stackId, true, stack); + stack.onRequestedOverrideConfigurationChanged(overrideConfig); + return stack; } } diff --git a/services/usage/java/com/android/server/usage/IntervalStats.java b/services/usage/java/com/android/server/usage/IntervalStats.java index 94cc6502a12d..9a5bd1379717 100644 --- a/services/usage/java/com/android/server/usage/IntervalStats.java +++ b/services/usage/java/com/android/server/usage/IntervalStats.java @@ -22,6 +22,7 @@ import static android.app.usage.UsageEvents.Event.ACTIVITY_STOPPED; import static android.app.usage.UsageEvents.Event.CONFIGURATION_CHANGE; import static android.app.usage.UsageEvents.Event.CONTINUE_PREVIOUS_DAY; import static android.app.usage.UsageEvents.Event.CONTINUING_FOREGROUND_SERVICE; +import static android.app.usage.UsageEvents.Event.DEVICE_SHUTDOWN; import static android.app.usage.UsageEvents.Event.END_OF_DAY; import static android.app.usage.UsageEvents.Event.FLUSH_TO_DISK; import static android.app.usage.UsageEvents.Event.FOREGROUND_SERVICE_START; @@ -66,7 +67,7 @@ public class IntervalStats { public final ArrayMap<String, UsageStats> packageStats = new ArrayMap<>(); public final ArrayMap<Configuration, ConfigurationStats> configurations = new ArrayMap<>(); public Configuration activeConfiguration; - public EventList events; + public EventList events = new EventList(); // A string cache. This is important as when we're parsing XML files, we don't want to // keep hundreds of strings that have the same contents. We will read the string @@ -112,6 +113,9 @@ public class IntervalStats { } + public IntervalStats() { + } + /** * Gets the UsageStats object for the given package, or creates one and adds it internally. */ @@ -253,6 +257,7 @@ public class IntervalStats { case ROLLOVER_FOREGROUND_SERVICE: case CONTINUE_PREVIOUS_DAY: case CONTINUING_FOREGROUND_SERVICE: + case DEVICE_SHUTDOWN: return true; } return false; @@ -281,8 +286,9 @@ public class IntervalStats { @VisibleForTesting public void update(String packageName, String className, long timeStamp, int eventType, int instanceId) { - if (eventType == FLUSH_TO_DISK) { - // FLUSH_TO_DISK are sent to all packages. + if (eventType == DEVICE_SHUTDOWN + || eventType == FLUSH_TO_DISK) { + // DEVICE_SHUTDOWN and FLUSH_TO_DISK are sent to all packages. final int size = packageStats.size(); for (int i = 0; i < size; i++) { UsageStats usageStats = packageStats.valueAt(i); @@ -321,9 +327,6 @@ public class IntervalStats { */ @VisibleForTesting public void addEvent(Event event) { - if (events == null) { - events = new EventList(); - } // Cache common use strings event.mPackage = getCachedStringRef(event.mPackage); if (event.mClass != null) { diff --git a/services/usage/java/com/android/server/usage/UsageStatsService.java b/services/usage/java/com/android/server/usage/UsageStatsService.java index f146370b01d7..76a3aa81530e 100644 --- a/services/usage/java/com/android/server/usage/UsageStatsService.java +++ b/services/usage/java/com/android/server/usage/UsageStatsService.java @@ -18,6 +18,7 @@ package com.android.server.usage; import static android.app.usage.UsageEvents.Event.CHOOSER_ACTION; import static android.app.usage.UsageEvents.Event.CONFIGURATION_CHANGE; +import static android.app.usage.UsageEvents.Event.DEVICE_SHUTDOWN; import static android.app.usage.UsageEvents.Event.FLUSH_TO_DISK; import static android.app.usage.UsageEvents.Event.NOTIFICATION_INTERRUPTION; import static android.app.usage.UsageEvents.Event.SHORTCUT_INVOCATION; @@ -416,11 +417,30 @@ public class UsageStatsService extends SystemService implements */ void shutdown() { synchronized (mLock) { + mHandler.removeMessages(MSG_REPORT_EVENT); + Event event = new Event(DEVICE_SHUTDOWN, SystemClock.elapsedRealtime()); + // orderly shutdown, the last event is DEVICE_SHUTDOWN. + reportEventToAllUserId(event); flushToDiskLocked(); } } /** + * After power button is pressed for 3.5 seconds + * (as defined in {@link com.android.internal.R.integer#config_veryLongPressTimeout}), + * report DEVICE_SHUTDOWN event and persist the database. If the power button is pressed for 10 + * seconds and the device is shutdown, the database is already persisted and we are not losing + * data. + * This method is called from PhoneWindowManager, do not synchronize on mLock otherwise + * PhoneWindowManager may be blocked. + */ + void prepareForPossibleShutdown() { + Event event = new Event(DEVICE_SHUTDOWN, SystemClock.elapsedRealtime()); + mHandler.obtainMessage(MSG_REPORT_EVENT_TO_ALL_USERID, event).sendToTarget(); + mHandler.sendEmptyMessage(MSG_FLUSH_TO_DISK); + } + + /** * Called by the Binder stub. */ void reportEvent(Event event, int userId) { @@ -1487,6 +1507,11 @@ public class UsageStatsService extends SystemService implements } @Override + public void prepareForPossibleShutdown() { + UsageStatsService.this.prepareForPossibleShutdown(); + } + + @Override public void addAppIdleStateChangeListener(AppIdleStateChangeListener listener) { mAppStandby.addListener(listener); listener.onParoleStateChanged(isAppIdleParoleOn()); diff --git a/services/usage/java/com/android/server/usage/UserUsageStatsService.java b/services/usage/java/com/android/server/usage/UserUsageStatsService.java index 5128ae1f9130..2d1098c7cf5c 100644 --- a/services/usage/java/com/android/server/usage/UserUsageStatsService.java +++ b/services/usage/java/com/android/server/usage/UserUsageStatsService.java @@ -16,6 +16,7 @@ package com.android.server.usage; +import static android.app.usage.UsageEvents.Event.DEVICE_SHUTDOWN; import static android.app.usage.UsageStatsManager.INTERVAL_BEST; import static android.app.usage.UsageStatsManager.INTERVAL_COUNT; import static android.app.usage.UsageStatsManager.INTERVAL_DAILY; @@ -134,6 +135,18 @@ class UserUsageStatsService { updateRolloverDeadline(); } + // During system reboot, add a DEVICE_SHUTDOWN event to the end of event list, the timestamp + // is last time UsageStatsDatabase is persisted to disk. + final IntervalStats currentDailyStats = mCurrentStats[INTERVAL_DAILY]; + if (currentDailyStats != null) { + final int size = currentDailyStats.events.size(); + if (size == 0 || currentDailyStats.events.get(size - 1).mEventType != DEVICE_SHUTDOWN) { + // The last event in event list is not DEVICE_SHUTDOWN, then we insert one. + final Event event = new Event(DEVICE_SHUTDOWN, currentDailyStats.lastTimeSaved); + currentDailyStats.addEvent(event); + } + } + if (mDatabase.isNewUpdate()) { notifyNewUpdate(); } @@ -175,7 +188,9 @@ class UserUsageStatsService { // ACTIVITY_STOPPED. && event.mEventType != Event.ACTIVITY_DESTROYED // FLUSH_TO_DISK is a private event. - && event.mEventType != Event.FLUSH_TO_DISK) { + && event.mEventType != Event.FLUSH_TO_DISK + // DEVICE_SHUTDOWN is added to event list after reboot. + && event.mEventType != Event.DEVICE_SHUTDOWN) { currentDailyStats.addEvent(event); } @@ -393,10 +408,6 @@ class UserUsageStatsService { @Override public void combine(IntervalStats stats, boolean mutable, List<Event> accumulatedResult) { - if (stats.events == null) { - return; - } - final int startIndex = stats.events.firstIndexOnOrAfter(beginTime); final int size = stats.events.size(); for (int i = startIndex; i < size; i++) { @@ -434,10 +445,6 @@ class UserUsageStatsService { names.add(packageName); final List<Event> results = queryStats(INTERVAL_DAILY, beginTime, endTime, (stats, mutable, accumulatedResult) -> { - if (stats.events == null) { - return; - } - final int startIndex = stats.events.firstIndexOnOrAfter(beginTime); final int size = stats.events.size(); for (int i = startIndex; i < size; i++) { @@ -696,10 +703,6 @@ class UserUsageStatsService { @Override public void combine(IntervalStats stats, boolean mutable, List<Event> accumulatedResult) { - if (stats.events == null) { - return; - } - final int startIndex = stats.events.firstIndexOnOrAfter(beginTime); final int size = stats.events.size(); for (int i = startIndex; i < size; i++) { @@ -925,10 +928,12 @@ class UserUsageStatsService { return "SCREEN_INTERACTIVE"; case Event.SCREEN_NON_INTERACTIVE: return "SCREEN_NON_INTERACTIVE"; - case UsageEvents.Event.KEYGUARD_SHOWN: + case Event.KEYGUARD_SHOWN: return "KEYGUARD_SHOWN"; - case UsageEvents.Event.KEYGUARD_HIDDEN: + case Event.KEYGUARD_HIDDEN: return "KEYGUARD_HIDDEN"; + case Event.DEVICE_SHUTDOWN: + return "DEVICE_SHUTDOWN"; default: return "UNKNOWN_TYPE_" + eventType; } diff --git a/telephony/java/android/provider/Telephony.java b/telephony/java/android/provider/Telephony.java index c115a4bd2a10..15abdb78b214 100644 --- a/telephony/java/android/provider/Telephony.java +++ b/telephony/java/android/provider/Telephony.java @@ -2019,6 +2019,12 @@ public final class Telephony { /** * Helper functions for the "threads" table used by MMS and SMS. + * + * Thread IDs are determined by the participants in a conversation and can be used to match + * both SMS and MMS messages. + * + * To avoid issues where applications might cache a thread ID, the thread ID of a deleted thread + * must not be reused to point at a new thread. */ public static final class Threads implements ThreadsColumns { @@ -2072,14 +2078,10 @@ public final class Telephony { } /** - * Given the recipients list and subject of an unsaved message, - * return its thread ID. If the message starts a new thread, - * allocate a new thread ID. Otherwise, use the appropriate - * existing thread ID. - * - * <p>Find the thread ID of the same set of recipients (in any order, - * without any additions). If one is found, return it. Otherwise, - * return a unique thread ID.</p> + * Given a set of recipients return its thread ID. + * <p> + * If a thread exists containing the provided participants, return its thread ID. Otherwise, + * this will create a new thread containing the provided participants and return its ID. */ public static long getOrCreateThreadId( Context context, Set<String> recipients) { diff --git a/core/java/android/hardware/location/ActivityChangedEvent.aidl b/telephony/java/android/telephony/CarrierRestrictionRules.aidl index 21f24459ac85..8b1f0b918901 100644 --- a/core/java/android/hardware/location/ActivityChangedEvent.aidl +++ b/telephony/java/android/telephony/CarrierRestrictionRules.aidl @@ -1,5 +1,5 @@ /* - * Copyright (C) 2014 The Android Open Source Project + * Copyright 2018 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -11,9 +11,10 @@ * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and - * limitations under the License + * limitations under the License. */ -package android.hardware.location; +/** @hide */ +package android.telephony; -parcelable ActivityChangedEvent;
\ No newline at end of file +parcelable CarrierRestrictionRules; diff --git a/telephony/java/android/telephony/CarrierRestrictionRules.java b/telephony/java/android/telephony/CarrierRestrictionRules.java new file mode 100644 index 000000000000..37847aef9167 --- /dev/null +++ b/telephony/java/android/telephony/CarrierRestrictionRules.java @@ -0,0 +1,277 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.telephony; + +import android.annotation.IntDef; +import android.annotation.NonNull; +import android.annotation.SystemApi; +import android.os.Parcel; +import android.os.Parcelable; +import android.service.carrier.CarrierIdentifier; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.util.ArrayList; +import java.util.List; + +/** + * Contains the list of carrier restrictions. + * Allowed list: it indicates the list of carriers that are allowed. + * Excluded list: it indicates the list of carriers that are excluded. + * Default carrier restriction: it indicates the default behavior and the priority between the two + * lists: + * - not allowed: the device only allows usage of carriers that are present in the allowed list + * and not present in the excluded list. This implies that if a carrier is not present in either + * list, it is not allowed. + * - allowed: the device allows all carriers, except those present in the excluded list and not + * present in the allowed list. This implies that if a carrier is not present in either list, + * it is allowed. + * MultiSim policy: it indicates the behavior in case of devices with two or more SIM cards. + * - MULTISIM_POLICY_NONE: the same configuration is applied to all SIM slots independently. This + * is the default value if none is set. + * - MULTISIM_POLICY_ONE_VALID_SIM_MUST_BE_PRESENT: it indicates that any SIM card can be used + * as far as one SIM card matching the configuration is present in the device. + * + * Both lists support the character '?' as wild character. For example, an entry indicating + * MCC=310 and MNC=??? will match all networks with MCC=310. + * + * Example 1: Allowed list contains MCC and MNC of operator A. Excluded list contains operator B, + * which has same MCC and MNC, but also GID1 value. The priority allowed list is set + * to true. Only SIM cards of operator A are allowed, but not those of B or any other + * operator. + * Example 2: Allowed list contains MCC and MNC of operator A. Excluded list contains an entry + * with same MCC, and '???' as MNC. The priority allowed list is set to false. + * SIM cards of operator A and all SIM cards with a different MCC value are allowed. + * SIM cards of operators with same MCC value and different MNC are not allowed. + * @hide + */ +@SystemApi +public final class CarrierRestrictionRules implements Parcelable { + /** + * The device only allows usage of carriers that are present in the allowed list and not + * present in the excluded list. This implies that if a carrier is not present in either list, + * it is not allowed. + */ + public static final int CARRIER_RESTRICTION_DEFAULT_NOT_ALLOWED = 0; + + /** + * The device allows all carriers, except those present in the excluded list and not present + * in the allowed list. This implies that if a carrier is not present in either list, it is + * allowed. + */ + public static final int CARRIER_RESTRICTION_DEFAULT_ALLOWED = 1; + + /** The same configuration is applied to all SIM slots independently. */ + public static final int MULTISIM_POLICY_NONE = 0; + + /** Any SIM card can be used as far as one SIM card matching the configuration is present. */ + public static final int MULTISIM_POLICY_ONE_VALID_SIM_MUST_BE_PRESENT = 1; + + /** @hide */ + @Retention(RetentionPolicy.SOURCE) + @IntDef(prefix = "MULTISIM_POLICY_", + value = {MULTISIM_POLICY_NONE, MULTISIM_POLICY_ONE_VALID_SIM_MUST_BE_PRESENT}) + public @interface MultiSimPolicy {} + + /** @hide */ + @Retention(RetentionPolicy.SOURCE) + @IntDef(prefix = "CARRIER_RESTRICTION_DEFAULT_", + value = {CARRIER_RESTRICTION_DEFAULT_NOT_ALLOWED, CARRIER_RESTRICTION_DEFAULT_ALLOWED}) + public @interface CarrierRestrictionDefault {} + + private List<CarrierIdentifier> mAllowedCarriers; + private List<CarrierIdentifier> mExcludedCarriers; + @CarrierRestrictionDefault + private int mCarrierRestrictionDefault; + @MultiSimPolicy + private int mMultiSimPolicy; + + private CarrierRestrictionRules() { + mAllowedCarriers = new ArrayList<CarrierIdentifier>(); + mExcludedCarriers = new ArrayList<CarrierIdentifier>(); + mCarrierRestrictionDefault = CARRIER_RESTRICTION_DEFAULT_NOT_ALLOWED; + mMultiSimPolicy = MULTISIM_POLICY_NONE; + } + + private CarrierRestrictionRules(Parcel in) { + mAllowedCarriers = new ArrayList<CarrierIdentifier>(); + mExcludedCarriers = new ArrayList<CarrierIdentifier>(); + + in.readTypedList(mAllowedCarriers, CarrierIdentifier.CREATOR); + in.readTypedList(mExcludedCarriers, CarrierIdentifier.CREATOR); + mCarrierRestrictionDefault = in.readInt(); + mMultiSimPolicy = in.readInt(); + } + + /** + * Creates a new builder for this class + * @hide + */ + public static Builder newBuilder() { + return new Builder(); + } + + /** + * Indicates if all carriers are allowed + */ + public boolean isAllCarriersAllowed() { + return (mAllowedCarriers.isEmpty() && mExcludedCarriers.isEmpty() + && mCarrierRestrictionDefault == CARRIER_RESTRICTION_DEFAULT_ALLOWED); + } + + /** + * Retrieves list of allowed carriers + * + * @return the list of allowed carriers + */ + public @NonNull List<CarrierIdentifier> getAllowedCarriers() { + return mAllowedCarriers; + } + + /** + * Retrieves list of excluded carriers + * + * @return the list of excluded carriers + */ + public @NonNull List<CarrierIdentifier> getExcludedCarriers() { + return mExcludedCarriers; + } + + /** + * Retrieves the default behavior of carrier restrictions + */ + public @CarrierRestrictionDefault int getDefaultCarrierRestriction() { + return mCarrierRestrictionDefault; + } + + /** + * @return The policy used for multi-SIM devices + */ + public @MultiSimPolicy int getMultiSimPolicy() { + return mMultiSimPolicy; + } + + /** + * {@link Parcelable#writeToParcel} + */ + @Override + public void writeToParcel(Parcel out, int flags) { + out.writeTypedList(mAllowedCarriers); + out.writeTypedList(mExcludedCarriers); + out.writeInt(mCarrierRestrictionDefault); + out.writeInt(mMultiSimPolicy); + } + + /** + * {@link Parcelable#describeContents} + */ + @Override + public int describeContents() { + return 0; + } + + /** + * {@link Parcelable.Creator} + */ + public static final Creator<CarrierRestrictionRules> CREATOR = + new Creator<CarrierRestrictionRules>() { + @Override + public CarrierRestrictionRules createFromParcel(Parcel in) { + return new CarrierRestrictionRules(in); + } + + @Override + public CarrierRestrictionRules[] newArray(int size) { + return new CarrierRestrictionRules[size]; + } + }; + + @Override + public String toString() { + return "CarrierRestrictionRules(allowed:" + mAllowedCarriers + ", excluded:" + + mExcludedCarriers + ", default:" + mCarrierRestrictionDefault + + ", multisim policy:" + mMultiSimPolicy + ")"; + } + + /** + * Builder for a {@link CarrierRestrictionRules}. + */ + public static class Builder { + private final CarrierRestrictionRules mRules; + + /** {@hide} */ + public Builder() { + mRules = new CarrierRestrictionRules(); + } + + /** build command */ + public CarrierRestrictionRules build() { + return mRules; + } + + /** + * Indicate that all carriers are allowed. + */ + public Builder setAllCarriersAllowed() { + mRules.mAllowedCarriers.clear(); + mRules.mExcludedCarriers.clear(); + mRules.mCarrierRestrictionDefault = CARRIER_RESTRICTION_DEFAULT_ALLOWED; + return this; + } + + /** + * Set list of allowed carriers. + * + * @param allowedCarriers list of allowed carriers + */ + public Builder setAllowedCarriers(List<CarrierIdentifier> allowedCarriers) { + mRules.mAllowedCarriers = new ArrayList<CarrierIdentifier>(allowedCarriers); + return this; + } + + /** + * Set list of excluded carriers. + * + * @param excludedCarriers list of excluded carriers + */ + public Builder setExcludedCarriers(List<CarrierIdentifier> excludedCarriers) { + mRules.mExcludedCarriers = new ArrayList<CarrierIdentifier>(excludedCarriers); + return this; + } + + /** + * Set the default behavior of the carrier restrictions + * + * @param carrierRestrictionDefault prioritized carrier list + */ + public Builder setDefaultCarrierRestriction( + @CarrierRestrictionDefault int carrierRestrictionDefault) { + mRules.mCarrierRestrictionDefault = carrierRestrictionDefault; + return this; + } + + /** + * Set the policy to be used for multi-SIM devices + * + * @param multiSimPolicy multi SIM policy + */ + public Builder setMultiSimPolicy(@MultiSimPolicy int multiSimPolicy) { + mRules.mMultiSimPolicy = multiSimPolicy; + return this; + } + } +} diff --git a/telephony/java/android/telephony/CellConfigLte.java b/telephony/java/android/telephony/CellConfigLte.java index 35769f04c5ae..eafbfbc5076d 100644 --- a/telephony/java/android/telephony/CellConfigLte.java +++ b/telephony/java/android/telephony/CellConfigLte.java @@ -34,6 +34,11 @@ public class CellConfigLte implements Parcelable { } /** @hide */ + public CellConfigLte(android.hardware.radio.V1_4.CellConfigLte cellConfig) { + mIsEndcAvailable = cellConfig.isEndcAvailable; + } + + /** @hide */ public CellConfigLte(boolean isEndcAvailable) { mIsEndcAvailable = isEndcAvailable; } diff --git a/telephony/java/android/telephony/CellInfo.java b/telephony/java/android/telephony/CellInfo.java index b761bd7bf70c..8ce5c54c810e 100644 --- a/telephony/java/android/telephony/CellInfo.java +++ b/telephony/java/android/telephony/CellInfo.java @@ -19,8 +19,10 @@ package android.telephony; import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.UnsupportedAppUsage; +import android.hardware.radio.V1_4.CellInfo.Info; import android.os.Parcel; import android.os.Parcelable; +import android.os.SystemClock; import com.android.internal.annotations.VisibleForTesting; @@ -318,6 +320,13 @@ public abstract class CellInfo implements Parcelable { } /** @hide */ + protected CellInfo(android.hardware.radio.V1_4.CellInfo ci) { + this.mRegistered = ci.isRegistered; + this.mTimeStamp = SystemClock.elapsedRealtimeNanos(); + this.mCellConnectionStatus = ci.connectionStatus; + } + + /** @hide */ public static CellInfo create(android.hardware.radio.V1_0.CellInfo ci) { if (ci == null) return null; switch(ci.cellInfoType) { @@ -342,4 +351,17 @@ public abstract class CellInfo implements Parcelable { default: return null; } } + + /** @hide */ + public static CellInfo create(android.hardware.radio.V1_4.CellInfo ci) { + if (ci == null) return null; + switch (ci.info.getDiscriminator()) { + case Info.hidl_discriminator.gsm: return new CellInfoGsm(ci); + case Info.hidl_discriminator.cdma: return new CellInfoCdma(ci); + case Info.hidl_discriminator.lte: return new CellInfoLte(ci); + case Info.hidl_discriminator.wcdma: return new CellInfoWcdma(ci); + case Info.hidl_discriminator.tdscdma: return new CellInfoTdscdma(ci); + default: return null; + } + } } diff --git a/telephony/java/android/telephony/CellInfoCdma.java b/telephony/java/android/telephony/CellInfoCdma.java index c9f07dab6bbd..4440108879f2 100644 --- a/telephony/java/android/telephony/CellInfoCdma.java +++ b/telephony/java/android/telephony/CellInfoCdma.java @@ -67,6 +67,15 @@ public final class CellInfoCdma extends CellInfo implements Parcelable { new CellSignalStrengthCdma(cic.signalStrengthCdma, cic.signalStrengthEvdo); } + /** @hide */ + public CellInfoCdma(android.hardware.radio.V1_4.CellInfo ci) { + super(ci); + final android.hardware.radio.V1_2.CellInfoCdma cic = ci.info.cdma(); + mCellIdentityCdma = new CellIdentityCdma(cic.cellIdentityCdma); + mCellSignalStrengthCdma = + new CellSignalStrengthCdma(cic.signalStrengthCdma, cic.signalStrengthEvdo); + } + @Override public CellIdentityCdma getCellIdentity() { return mCellIdentityCdma; diff --git a/telephony/java/android/telephony/CellInfoGsm.java b/telephony/java/android/telephony/CellInfoGsm.java index ad16dfae7295..248adfcb2d90 100644 --- a/telephony/java/android/telephony/CellInfoGsm.java +++ b/telephony/java/android/telephony/CellInfoGsm.java @@ -63,6 +63,14 @@ public final class CellInfoGsm extends CellInfo implements Parcelable { mCellSignalStrengthGsm = new CellSignalStrengthGsm(cig.signalStrengthGsm); } + /** @hide */ + public CellInfoGsm(android.hardware.radio.V1_4.CellInfo ci) { + super(ci); + final android.hardware.radio.V1_2.CellInfoGsm cig = ci.info.gsm(); + mCellIdentityGsm = new CellIdentityGsm(cig.cellIdentityGsm); + mCellSignalStrengthGsm = new CellSignalStrengthGsm(cig.signalStrengthGsm); + } + @Override public CellIdentityGsm getCellIdentity() { return mCellIdentityGsm; diff --git a/telephony/java/android/telephony/CellInfoLte.java b/telephony/java/android/telephony/CellInfoLte.java index 75938317bf44..8e8ce8a1f5de 100644 --- a/telephony/java/android/telephony/CellInfoLte.java +++ b/telephony/java/android/telephony/CellInfoLte.java @@ -70,6 +70,15 @@ public final class CellInfoLte extends CellInfo implements Parcelable { mCellConfig = new CellConfigLte(); } + /** @hide */ + public CellInfoLte(android.hardware.radio.V1_4.CellInfo ci) { + super(ci); + final android.hardware.radio.V1_4.CellInfoLte cil = ci.info.lte(); + mCellIdentityLte = new CellIdentityLte(cil.base.cellIdentityLte); + mCellSignalStrengthLte = new CellSignalStrengthLte(cil.base.signalStrengthLte); + mCellConfig = new CellConfigLte(cil.cellConfig); + } + @Override public CellIdentityLte getCellIdentity() { if (DBG) log("getCellIdentity: " + mCellIdentityLte); diff --git a/telephony/java/android/telephony/CellInfoTdscdma.java b/telephony/java/android/telephony/CellInfoTdscdma.java index a8c49b7bf68e..2ab38fb77a90 100644 --- a/telephony/java/android/telephony/CellInfoTdscdma.java +++ b/telephony/java/android/telephony/CellInfoTdscdma.java @@ -64,6 +64,14 @@ public final class CellInfoTdscdma extends CellInfo implements Parcelable { mCellSignalStrengthTdscdma = new CellSignalStrengthTdscdma(cit.signalStrengthTdscdma); } + /** @hide */ + public CellInfoTdscdma(android.hardware.radio.V1_4.CellInfo ci) { + super(ci); + final android.hardware.radio.V1_2.CellInfoTdscdma cit = ci.info.tdscdma(); + mCellIdentityTdscdma = new CellIdentityTdscdma(cit.cellIdentityTdscdma); + mCellSignalStrengthTdscdma = new CellSignalStrengthTdscdma(cit.signalStrengthTdscdma); + } + @Override public CellIdentityTdscdma getCellIdentity() { return mCellIdentityTdscdma; } diff --git a/telephony/java/android/telephony/CellInfoWcdma.java b/telephony/java/android/telephony/CellInfoWcdma.java index a427e80fd65c..65e047077639 100644 --- a/telephony/java/android/telephony/CellInfoWcdma.java +++ b/telephony/java/android/telephony/CellInfoWcdma.java @@ -63,6 +63,14 @@ public final class CellInfoWcdma extends CellInfo implements Parcelable { mCellSignalStrengthWcdma = new CellSignalStrengthWcdma(ciw.signalStrengthWcdma); } + /** @hide */ + public CellInfoWcdma(android.hardware.radio.V1_4.CellInfo ci) { + super(ci); + final android.hardware.radio.V1_2.CellInfoWcdma ciw = ci.info.wcdma(); + mCellIdentityWcdma = new CellIdentityWcdma(ciw.cellIdentityWcdma); + mCellSignalStrengthWcdma = new CellSignalStrengthWcdma(ciw.signalStrengthWcdma); + } + @Override public CellIdentityWcdma getCellIdentity() { return mCellIdentityWcdma; diff --git a/telephony/java/android/telephony/PhoneStateListener.java b/telephony/java/android/telephony/PhoneStateListener.java index c81670139eae..9fee5932dadc 100644 --- a/telephony/java/android/telephony/PhoneStateListener.java +++ b/telephony/java/android/telephony/PhoneStateListener.java @@ -805,9 +805,11 @@ public class PhoneStateListener { PhoneStateListener psl = mPhoneStateListenerWeakRef.get(); if (psl == null) return; - Binder.withCleanCallingIdentity( - () -> mExecutor.execute( - () -> psl.onDataConnectionStateChanged(state, networkType))); + Binder.withCleanCallingIdentity(() -> mExecutor.execute( + () -> { + psl.onDataConnectionStateChanged(state, networkType); + psl.onDataConnectionStateChanged(state); + })); } public void onDataActivity(int direction) { diff --git a/telephony/java/android/telephony/SignalStrength.java b/telephony/java/android/telephony/SignalStrength.java index e77042d1930f..ad3ca6d129c9 100644 --- a/telephony/java/android/telephony/SignalStrength.java +++ b/telephony/java/android/telephony/SignalStrength.java @@ -86,11 +86,6 @@ public class SignalStrength implements Parcelable { CellSignalStrengthTdscdma mTdscdma; CellSignalStrengthLte mLte; - /** Parameters from the framework */ - @UnsupportedAppUsage - private int mLteRsrpBoost; // offset to be reduced from the rsrp threshold while calculating - // signal strength level - /** * Create a new SignalStrength from a intent notifier Bundle * @@ -140,7 +135,6 @@ public class SignalStrength implements Parcelable { mWcdma = wcdma; mTdscdma = tdscdma; mLte = lte; - mLteRsrpBoost = 0; } /** @@ -211,7 +205,6 @@ public class SignalStrength implements Parcelable { /** @hide */ public void updateLevel(PersistableBundle cc, ServiceState ss) { - mLteRsrpBoost = ss.getLteEarfcnRsrpBoost(); mCdma.updateLevel(cc, ss); mGsm.updateLevel(cc, ss); mWcdma.updateLevel(cc, ss); @@ -241,7 +234,6 @@ public class SignalStrength implements Parcelable { mWcdma = new CellSignalStrengthWcdma(s.mWcdma); mTdscdma = new CellSignalStrengthTdscdma(s.mTdscdma); mLte = new CellSignalStrengthLte(s.mLte); - mLteRsrpBoost = s.mLteRsrpBoost; } /** @@ -258,7 +250,6 @@ public class SignalStrength implements Parcelable { mWcdma = in.readParcelable(CellSignalStrengthWcdma.class.getClassLoader()); mTdscdma = in.readParcelable(CellSignalStrengthTdscdma.class.getClassLoader()); mLte = in.readParcelable(CellSignalStrengthLte.class.getClassLoader()); - mLteRsrpBoost = in.readInt(); } /** @@ -270,8 +261,6 @@ public class SignalStrength implements Parcelable { out.writeParcelable(mWcdma, flags); out.writeParcelable(mTdscdma, flags); out.writeParcelable(mLte, flags); - - out.writeInt(mLteRsrpBoost); } /** @@ -384,11 +373,6 @@ public class SignalStrength implements Parcelable { return mLte.getCqi(); } - /** @hide */ - public int getLteRsrpBoost() { - return mLteRsrpBoost; - } - /** * Retrieve an abstract level value for the overall signal strength. * @@ -616,7 +600,7 @@ public class SignalStrength implements Parcelable { */ @Override public int hashCode() { - return Objects.hash(mCdma, mGsm, mWcdma, mTdscdma, mLte, mLteRsrpBoost); + return Objects.hash(mCdma, mGsm, mWcdma, mTdscdma, mLte); } /** @@ -632,8 +616,7 @@ public class SignalStrength implements Parcelable { && mGsm.equals(s.mGsm) && mWcdma.equals(s.mWcdma) && mTdscdma.equals(s.mTdscdma) - && mLte.equals(s.mLte) - && mLteRsrpBoost == s.mLteRsrpBoost; + && mLte.equals(s.mLte); } /** @@ -647,7 +630,6 @@ public class SignalStrength implements Parcelable { .append(",mWcdma=").append(mWcdma) .append(",mTdscdma=").append(mTdscdma) .append(",mLte=").append(mLte) - .append(",mLteRsrpBoost=").append(mLteRsrpBoost) .append(",primary=").append(getPrimary().getClass().getSimpleName()) .append("}") .toString(); @@ -666,8 +648,6 @@ public class SignalStrength implements Parcelable { mWcdma = m.getParcelable("Wcdma"); mTdscdma = m.getParcelable("Tdscdma"); mLte = m.getParcelable("Lte"); - - mLteRsrpBoost = m.getInt("LteRsrpBoost"); } /** @@ -683,8 +663,6 @@ public class SignalStrength implements Parcelable { m.putParcelable("Wcdma", mWcdma); m.putParcelable("Tdscdma", mTdscdma); m.putParcelable("Lte", mLte); - - m.putInt("LteRsrpBoost", mLteRsrpBoost); } /** diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java index 3311218bdb3c..80533535017e 100644 --- a/telephony/java/android/telephony/TelephonyManager.java +++ b/telephony/java/android/telephony/TelephonyManager.java @@ -9055,6 +9055,8 @@ public class TelephonyManager { * <p>This method works only on devices with {@link * android.content.pm.PackageManager#FEATURE_TELEPHONY_CARRIERLOCK} enabled. * + * @deprecated use setCarrierRestrictionRules instead + * * @return The number of carriers set successfully. Should be length of * carrierList on success; -1 if carrierList null or on error. * @hide @@ -9062,44 +9064,144 @@ public class TelephonyManager { @SystemApi @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public int setAllowedCarriers(int slotIndex, List<CarrierIdentifier> carriers) { + // Execute the method setCarrierRestrictionRules with an empty excluded list and + // indicating priority for the allowed list. + CarrierRestrictionRules carrierRestrictionRules = CarrierRestrictionRules.newBuilder() + .setAllowedCarriers(carriers) + .setDefaultCarrierRestriction( + CarrierRestrictionRules.CARRIER_RESTRICTION_DEFAULT_NOT_ALLOWED) + .build(); + + int result = setCarrierRestrictionRules(carrierRestrictionRules); + + // Convert boolean result into int, as required by this method. + if (result == SET_CARRIER_RESTRICTION_SUCCESS) { + return carriers.size(); + } else { + return -1; + } + } + + /** + * The carrier restrictions were successfully set. + * @hide + */ + @SystemApi + public static final int SET_CARRIER_RESTRICTION_SUCCESS = 0; + + /** + * The carrier restrictions were not set due to lack of support in the modem. This can happen + * if the modem does not support setting the carrier restrictions or if the configuration + * passed in the {@code setCarrierRestrictionRules} is not supported by the modem. + * @hide + */ + @SystemApi + public static final int SET_CARRIER_RESTRICTION_NOT_SUPPORTED = 1; + + /** + * The setting of carrier restrictions failed. + * @hide + */ + @SystemApi + public static final int SET_CARRIER_RESTRICTION_ERROR = 2; + + /** @hide */ + @Retention(RetentionPolicy.SOURCE) + @IntDef(prefix = {"SET_CARRIER_RESTRICTION_"}, + value = { + SET_CARRIER_RESTRICTION_SUCCESS, + SET_CARRIER_RESTRICTION_NOT_SUPPORTED, + SET_CARRIER_RESTRICTION_ERROR + }) + public @interface SetCarrierRestrictionResult {} + + /** + * Set the allowed carrier list and the excluded carrier list indicating the priority between + * the two lists. + * Requires system privileges. + * + * <p>Requires Permission: + * {@link android.Manifest.permission#MODIFY_PHONE_STATE} + * + * <p>This method works only on devices with {@link + * android.content.pm.PackageManager#FEATURE_TELEPHONY_CARRIERLOCK} enabled. + * + * @return {@link #SET_CARRIER_RESTRICTION_SUCCESS} in case of success. + * {@link #SET_CARRIER_RESTRICTION_NOT_SUPPORTED} if the modem does not support the + * configuration. {@link #SET_CARRIER_RESTRICTION_ERROR} in all other error cases. + * @hide + */ + @SystemApi + @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) + @SetCarrierRestrictionResult + public int setCarrierRestrictionRules(@NonNull CarrierRestrictionRules rules) { try { ITelephony service = getITelephony(); if (service != null) { - return service.setAllowedCarriers(slotIndex, carriers); + return service.setAllowedCarriers(rules); } } catch (RemoteException e) { Log.e(TAG, "Error calling ITelephony#setAllowedCarriers", e); } catch (NullPointerException e) { Log.e(TAG, "Error calling ITelephony#setAllowedCarriers", e); } - return -1; + return SET_CARRIER_RESTRICTION_ERROR; } /** * Get the allowed carrier list for slotIndex. - * Require system privileges. In the future we may add this to carrier APIs. + * Requires system privileges. * * <p>This method returns valid data on devices with {@link * android.content.pm.PackageManager#FEATURE_TELEPHONY_CARRIERLOCK} enabled. * + * @deprecated Apps should use {@link getCarriersRestrictionRules} to retrieve the list of + * allowed and excliuded carriers, as the result of this API is valid only when the excluded + * list is empty. This API could return an empty list, even if some restrictions are present. + * * @return List of {@link android.telephony.CarrierIdentifier}; empty list * means all carriers are allowed. * @hide */ + @Deprecated @SystemApi @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public List<CarrierIdentifier> getAllowedCarriers(int slotIndex) { + CarrierRestrictionRules carrierRestrictionRule = getCarrierRestrictionRules(); + if (carrierRestrictionRule != null) { + return carrierRestrictionRule.getAllowedCarriers(); + } + return new ArrayList<CarrierIdentifier>(0); + } + + /** + * Get the allowed carrier list and the excluded carrier list indicating the priority between + * the two lists. + * Require system privileges. In the future we may add this to carrier APIs. + * + * <p>This method returns valid data on devices with {@link + * android.content.pm.PackageManager#FEATURE_TELEPHONY_CARRIERLOCK} enabled. + * + * @return {@link CarrierRestrictionRules} which contains the allowed carrier list and the + * excluded carrier list with the priority between the two lists. Returns {@code null} + * in case of error. + * @hide + */ + @SystemApi + @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) + @Nullable + public CarrierRestrictionRules getCarrierRestrictionRules() { try { ITelephony service = getITelephony(); if (service != null) { - return service.getAllowedCarriers(slotIndex); + return service.getAllowedCarriers(); } } catch (RemoteException e) { Log.e(TAG, "Error calling ITelephony#getAllowedCarriers", e); } catch (NullPointerException e) { Log.e(TAG, "Error calling ITelephony#getAllowedCarriers", e); } - return new ArrayList<CarrierIdentifier>(0); + return null; } /** @@ -9972,4 +10074,33 @@ public class TelephonyManager { } return ret; } + + /** + * Enable or disable a logical modem stack. When a logical modem is disabled, the corresponding + * SIM will still be visible to the user but its mapping modem will not have any radio activity. + * For example, we will disable a modem when user or system believes the corresponding SIM + * is temporarily not needed (e.g. out of coverage), and will enable it back on when needed. + * + * Requires that the calling app has permission + * {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE}. + * @param slotIndex which corresponding modem will operate on. + * @param enable whether to enable or disable the modem stack. + * @return whether the operation is successful. + * + * @hide + */ + @SystemApi + @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) + public boolean enableModemForSlot(int slotIndex, boolean enable) { + boolean ret = false; + try { + ITelephony telephony = getITelephony(); + if (telephony != null) { + ret = telephony.enableModemForSlot(slotIndex, enable); + } + } catch (RemoteException ex) { + Log.e(TAG, "enableModem RemoteException", ex); + } + return ret; + } } diff --git a/telephony/java/android/telephony/emergency/EmergencyNumber.java b/telephony/java/android/telephony/emergency/EmergencyNumber.java index a5f56bbebd75..e68256d086bc 100644 --- a/telephony/java/android/telephony/emergency/EmergencyNumber.java +++ b/telephony/java/android/telephony/emergency/EmergencyNumber.java @@ -27,6 +27,7 @@ import android.telephony.Rlog; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.util.ArrayList; +import java.util.Collections; import java.util.HashSet; import java.util.List; import java.util.Objects; @@ -176,6 +177,12 @@ public final class EmergencyNumber implements Parcelable, Comparable<EmergencyNu * Bit-field which indicates the number is from the platform-maintained database. */ public static final int EMERGENCY_NUMBER_SOURCE_DATABASE = 1 << 4; + /** + * Bit-field which indicates the number is from test mode. + * + * @hide + */ + public static final int EMERGENCY_NUMBER_SOURCE_TEST = 1 << 5; /** Bit-field which indicates the number is from the modem config. */ public static final int EMERGENCY_NUMBER_SOURCE_MODEM_CONFIG = EmergencyNumberSource.MODEM_CONFIG; @@ -327,6 +334,21 @@ public final class EmergencyNumber implements Parcelable, Comparable<EmergencyNu } /** + * Returns the bitmask of emergency service categories of the emergency number for + * internal dialing. + * + * @return bitmask of the emergency service categories + * + * @hide + */ + public @EmergencyServiceCategories int getEmergencyServiceCategoryBitmaskInternalDial() { + if (mEmergencyNumberSourceBitmask == EMERGENCY_NUMBER_SOURCE_DATABASE) { + return EMERGENCY_SERVICE_CATEGORY_UNSPECIFIED; + } + return mEmergencyServiceCategoryBitmask; + } + + /** * Returns the emergency service categories of the emergency number. * * Note: if the emergency number is in {@link #EMERGENCY_SERVICE_CATEGORY_UNSPECIFIED}, only @@ -577,6 +599,7 @@ public final class EmergencyNumber implements Parcelable, Comparable<EmergencyNu emergencyNumberList.remove(i--); } } + Collections.sort(emergencyNumberList); } /** @@ -613,6 +636,12 @@ public final class EmergencyNumber implements Parcelable, Comparable<EmergencyNu if (first.getEmergencyCallRouting() != second.getEmergencyCallRouting()) { return false; } + // Never merge two numbers if one of them is from test mode but the other one is not; + // This supports to remove a number from the test mode. + if (first.isFromSources(EMERGENCY_NUMBER_SOURCE_TEST) + ^ second.isFromSources(EMERGENCY_NUMBER_SOURCE_TEST)) { + return false; + } return true; } @@ -638,4 +667,13 @@ public final class EmergencyNumber implements Parcelable, Comparable<EmergencyNu } return null; } + + /** + * Validate Emergency Number address that only allows '0'-'9', '*', or '#' + * + * @hide + */ + public static boolean validateEmergencyNumberAddress(String address) { + return address.matches("[0-9*#]+"); + } } diff --git a/telephony/java/android/telephony/euicc/EuiccManager.java b/telephony/java/android/telephony/euicc/EuiccManager.java index 42a788d0cc8e..0e5c71d6ef90 100644 --- a/telephony/java/android/telephony/euicc/EuiccManager.java +++ b/telephony/java/android/telephony/euicc/EuiccManager.java @@ -361,7 +361,7 @@ public class EuiccManager { public boolean isEnabled() { // In the future, this may reach out to IEuiccController (if non-null) to check any dynamic // restrictions. - return getIEuiccController() != null; + return getIEuiccController() != null && mCardId != TelephonyManager.INVALID_CARD_ID; } /** diff --git a/telephony/java/android/telephony/ims/ImsCallProfile.java b/telephony/java/android/telephony/ims/ImsCallProfile.java index 525a96a4dae9..59167b7d5bba 100644 --- a/telephony/java/android/telephony/ims/ImsCallProfile.java +++ b/telephony/java/android/telephony/ims/ImsCallProfile.java @@ -347,6 +347,9 @@ public final class ImsCallProfile implements Parcelable { private @EmergencyCallRouting int mEmergencyCallRouting = EmergencyNumber.EMERGENCY_CALL_ROUTING_UNKNOWN; + /** Indicates if the call is for testing purpose */ + private boolean mEmergencyCallTesting = false; + /** * Extras associated with this {@link ImsCallProfile}. * <p> @@ -534,9 +537,10 @@ public final class ImsCallProfile implements Parcelable { + ", callType=" + mCallType + ", restrictCause=" + mRestrictCause + ", mediaProfile=" + mMediaProfile.toString() - + ", emergencyServiceCategories=" + mEmergencyCallRouting + + ", emergencyServiceCategories=" + mEmergencyServiceCategories + ", emergencyUrns=" + mEmergencyUrns - + ", emergencyCallRouting=" + mEmergencyCallRouting + " }"; + + ", emergencyCallRouting=" + mEmergencyCallRouting + + ", emergencyCallTesting=" + mEmergencyCallTesting + " }"; } @Override @@ -554,6 +558,7 @@ public final class ImsCallProfile implements Parcelable { out.writeInt(mEmergencyServiceCategories); out.writeStringList(mEmergencyUrns); out.writeInt(mEmergencyCallRouting); + out.writeBoolean(mEmergencyCallTesting); } private void readFromParcel(Parcel in) { @@ -564,6 +569,7 @@ public final class ImsCallProfile implements Parcelable { mEmergencyServiceCategories = in.readInt(); mEmergencyUrns = in.createStringArrayList(); mEmergencyCallRouting = in.readInt(); + mEmergencyCallTesting = in.readBoolean(); } public static final Creator<ImsCallProfile> CREATOR = new Creator<ImsCallProfile>() { @@ -784,9 +790,11 @@ public final class ImsCallProfile implements Parcelable { * @hide */ public void setEmergencyCallInfo(EmergencyNumber num) { - setEmergencyServiceCategories(num.getEmergencyServiceCategoryBitmask()); + setEmergencyServiceCategories(num.getEmergencyServiceCategoryBitmaskInternalDial()); setEmergencyUrns(num.getEmergencyUrns()); setEmergencyCallRouting(num.getEmergencyCallRouting()); + setEmergencyCallTesting(num.getEmergencyNumberSourceBitmask() + == EmergencyNumber.EMERGENCY_NUMBER_SOURCE_TEST); } /** @@ -843,6 +851,15 @@ public final class ImsCallProfile implements Parcelable { } /** + * Set if this is for testing emergency call, only valid if {@link #getServiceType} returns + * {@link #SERVICE_TYPE_EMERGENCY}. + */ + @VisibleForTesting + public void setEmergencyCallTesting(boolean isTesting) { + mEmergencyCallTesting = isTesting; + } + + /** * Get the emergency service categories, only valid if {@link #getServiceType} returns * {@link #SERVICE_TYPE_EMERGENCY} * @@ -892,4 +909,11 @@ public final class ImsCallProfile implements Parcelable { public @EmergencyCallRouting int getEmergencyCallRouting() { return mEmergencyCallRouting; } + + /** + * Get if the emergency call is for testing purpose. + */ + public boolean isEmergencyCallTesting() { + return mEmergencyCallTesting; + } } diff --git a/telephony/java/android/telephony/ims/ImsCallSession.java b/telephony/java/android/telephony/ims/ImsCallSession.java index 397d5d9b4eb5..47c468121484 100644 --- a/telephony/java/android/telephony/ims/ImsCallSession.java +++ b/telephony/java/android/telephony/ims/ImsCallSession.java @@ -18,6 +18,7 @@ package android.telephony.ims; import android.os.Message; import android.os.RemoteException; +import android.telephony.CallQuality; import android.telephony.ims.aidl.IImsCallSessionListener; import android.util.Log; @@ -450,6 +451,13 @@ public class ImsCallSession { public void callSessionRttAudioIndicatorChanged(ImsStreamMediaProfile profile) { // no-op } + + /** + * Called when the IMS service reports a change to the call quality. + */ + public void callQualityChanged(CallQuality callQuality) { + // no-op + } } private final IImsCallSession miSession; @@ -1414,6 +1422,16 @@ public class ImsCallSession { mListener.callSessionRttAudioIndicatorChanged(profile); } } + + /** + * Call quality updated + */ + @Override + public void callQualityChanged(CallQuality callQuality) { + if (mListener != null) { + mListener.callQualityChanged(callQuality); + } + } } /** diff --git a/telephony/java/android/telephony/ims/ImsCallSessionListener.java b/telephony/java/android/telephony/ims/ImsCallSessionListener.java index a4696a3f93aa..337375ac51c3 100644 --- a/telephony/java/android/telephony/ims/ImsCallSessionListener.java +++ b/telephony/java/android/telephony/ims/ImsCallSessionListener.java @@ -18,6 +18,7 @@ package android.telephony.ims; import android.annotation.SystemApi; import android.os.RemoteException; +import android.telephony.CallQuality; import android.telephony.ims.aidl.IImsCallSessionListener; import android.telephony.ims.stub.ImsCallSessionImplBase; @@ -612,5 +613,18 @@ public class ImsCallSessionListener { throw new RuntimeException(e); } } + + /** + * The call quality has changed. + * + * @param callQuality The new call quality + */ + public void callQualityChanged(CallQuality callQuality) { + try { + mListener.callQualityChanged(callQuality); + } catch (RemoteException e) { + throw new RuntimeException(e); + } + } } diff --git a/telephony/java/android/telephony/ims/ImsMmTelManager.java b/telephony/java/android/telephony/ims/ImsMmTelManager.java index e2350fe78500..9414abd98b1c 100644 --- a/telephony/java/android/telephony/ims/ImsMmTelManager.java +++ b/telephony/java/android/telephony/ims/ImsMmTelManager.java @@ -92,7 +92,7 @@ public class ImsMmTelManager { public static final int WIFI_MODE_WIFI_PREFERRED = 2; /** - * Callback class for receiving Registration callback events. + * Callback class for receiving IMS network Registration callback events. * @see #registerImsRegistrationCallback(Executor, RegistrationCallback) (RegistrationCallback) * @see #unregisterImsRegistrationCallback(RegistrationCallback) */ @@ -241,7 +241,8 @@ public class ImsMmTelManager { } /** - * Receives IMS capability status updates from the ImsService. + * Receives IMS capability status updates from the ImsService. This information is also + * available via the {@link #isAvailable(int, int)} method below. * * @see #registerMmTelCapabilityCallback(Executor, CapabilityCallback) (CapabilityCallback) * @see #unregisterMmTelCapabilityCallback(CapabilityCallback) @@ -290,6 +291,8 @@ public class ImsMmTelManager { * If unavailable, the feature is not able to support the unavailable capability at this * time. * + * This information can also be queried using the {@link #isAvailable(int, int)} API. + * * @param capabilities The new availability of the capabilities. */ public void onCapabilitiesStatusChanged( @@ -304,7 +307,7 @@ public class ImsMmTelManager { /**@hide*/ // Only exposed as public method for compatibility with deprecated ImsManager APIs. // TODO: clean up dependencies and change back to private visibility. - public void setExecutor(Executor executor) { + public final void setExecutor(Executor executor) { mBinder.setExecutor(executor); } } @@ -342,8 +345,7 @@ public class ImsMmTelManager { * Registers a {@link RegistrationCallback} with the system, which will provide registration * updates for the subscription specified in {@link #createForSubscriptionId(Context, int)}. Use * {@link SubscriptionManager.OnSubscriptionsChangedListener} to listen to Subscription changed - * events and call {@link #unregisterImsRegistrationCallback(RegistrationCallback)} to clean up - * after a subscription is removed. + * events and call {@link #unregisterImsRegistrationCallback(RegistrationCallback)} to clean up. * * When the callback is registered, it will initiate the callback c to be called with the * current registration state. @@ -351,6 +353,12 @@ public class ImsMmTelManager { * @param executor The executor the callback events should be run on. * @param c The {@link RegistrationCallback} to be added. * @see #unregisterImsRegistrationCallback(RegistrationCallback) + * @throws IllegalArgumentException if the subscription associated with this callback is not + * active (SIM is not inserted, ESIM inactive) or invalid, or a null {@link Executor} or + * {@link CapabilityCallback} callback. + * @throws IllegalStateException if the subscription associated with this callback is valid, but + * the {@link ImsService} associated with the subscription is not available. This can happen if + * the service crashed, for example. */ @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void registerImsRegistrationCallback(@CallbackExecutor Executor executor, @@ -370,11 +378,17 @@ public class ImsMmTelManager { } /** - * Removes an existing {@link RegistrationCallback}. Ensure to call this method when cleaning - * up to avoid memory leaks or when the subscription is removed. + * Removes an existing {@link RegistrationCallback}. + * + * When the subscription associated with this callback is removed (SIM removed, ESIM swap, + * etc...), this callback will automatically be removed. If this method is called for an + * inactive subscription, it will result in a no-op. + * * @param c The {@link RegistrationCallback} to be removed. * @see SubscriptionManager.OnSubscriptionsChangedListener * @see #registerImsRegistrationCallback(Executor, RegistrationCallback) + * @throws IllegalArgumentException if the subscription ID associated with this callback is + * invalid. */ @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void unregisterImsRegistrationCallback(@NonNull RegistrationCallback c) { @@ -389,12 +403,14 @@ public class ImsMmTelManager { } /** - * Registers a {@link CapabilityCallback} with the system, which will provide MmTel capability - * updates for the subscription specified in {@link #createForSubscriptionId(Context, int)}. + * Registers a {@link CapabilityCallback} with the system, which will provide MmTel service + * availability updates for the subscription specified in + * {@link #createForSubscriptionId(Context, int)}. The method {@link #isAvailable(int, int)} + * can also be used to query this information at any time. + * * Use {@link SubscriptionManager.OnSubscriptionsChangedListener} to listen to * subscription changed events and call - * {@link #unregisterImsRegistrationCallback(RegistrationCallback)} to clean up after a - * subscription is removed. + * {@link #unregisterImsRegistrationCallback(RegistrationCallback)} to clean up. * * When the callback is registered, it will initiate the callback c to be called with the * current capabilities. @@ -402,9 +418,15 @@ public class ImsMmTelManager { * @param executor The executor the callback events should be run on. * @param c The MmTel {@link CapabilityCallback} to be registered. * @see #unregisterMmTelCapabilityCallback(CapabilityCallback) + * @throws IllegalArgumentException if the subscription associated with this callback is not + * active (SIM is not inserted, ESIM inactive) or invalid, or a null {@link Executor} or + * {@link CapabilityCallback} callback. + * @throws IllegalStateException if the subscription associated with this callback is valid, but + * the {@link ImsService} associated with the subscription is not available. This can happen if + * the service crashed, for example. */ @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE) - public void registerMmTelCapabilityCallback(@CallbackExecutor Executor executor, + public void registerMmTelCapabilityCallback(@NonNull @CallbackExecutor Executor executor, @NonNull CapabilityCallback c) { if (c == null) { throw new IllegalArgumentException("Must include a non-null RegistrationCallback."); @@ -421,10 +443,15 @@ public class ImsMmTelManager { } /** - * Removes an existing MmTel {@link CapabilityCallback}. Be sure to call this when cleaning - * up to avoid memory leaks. + * Removes an existing MmTel {@link CapabilityCallback}. + * + * When the subscription associated with this callback is removed (SIM removed, ESIM swap, + * etc...), this callback will automatically be removed. If this method is called for an + * inactive subscription, it will result in a no-op. * @param c The MmTel {@link CapabilityCallback} to be removed. * @see #registerMmTelCapabilityCallback(Executor, CapabilityCallback) + * @throws IllegalArgumentException if the subscription ID associated with this callback is + * invalid. */ @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void unregisterMmTelCapabilityCallback(@NonNull CapabilityCallback c) { diff --git a/telephony/java/android/telephony/ims/ProvisioningManager.java b/telephony/java/android/telephony/ims/ProvisioningManager.java index 916e282f642e..d37198a3e25d 100644 --- a/telephony/java/android/telephony/ims/ProvisioningManager.java +++ b/telephony/java/android/telephony/ims/ProvisioningManager.java @@ -133,33 +133,40 @@ public class ProvisioningManager { } /** - * Register a new {@link Callback} to listen to changes to changes in - * IMS provisioning. Use {@link SubscriptionManager.OnSubscriptionsChangedListener} to listen to - * Subscription changed events and call - * {@link #unregisterProvisioningChangedCallback(Callback)} to clean up after a - * subscription is removed. + * Register a new {@link Callback} to listen to changes to changes in IMS provisioning. + * + * When the subscription associated with this callback is removed (SIM removed, ESIM swap, + * etc...), this callback will automatically be removed. * @param executor The {@link Executor} to call the callback methods on * @param callback The provisioning callbackto be registered. * @see #unregisterProvisioningChangedCallback(Callback) * @see SubscriptionManager.OnSubscriptionsChangedListener + * @throws IllegalArgumentException if the subscription associated with this callback is not + * active (SIM is not inserted, ESIM inactive) or the subscription is invalid. + * @throws IllegalStateException if the subscription associated with this callback is valid, but + * the {@link ImsService} associated with the subscription is not available. This can happen if + * the service crashed, for example. */ @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void registerProvisioningChangedCallback(@CallbackExecutor Executor executor, @NonNull Callback callback) { callback.setExecutor(executor); try { - getITelephony().registerImsProvisioningChangedCallback(mSubId, - callback.getBinder()); + getITelephony().registerImsProvisioningChangedCallback(mSubId, callback.getBinder()); } catch (RemoteException e) { throw e.rethrowAsRuntimeException(); } } /** - * Unregister an existing {@link Callback}. Ensure to call this method when cleaning - * up to avoid memory leaks or when the subscription is removed. + * Unregister an existing {@link Callback}. When the subscription associated with this + * callback is removed (SIM removed, ESIM swap, etc...), this callback will automatically be + * removed. If this method is called for an inactive subscription, it will result in a no-op. * @param callback The existing {@link Callback} to be removed. * @see #registerProvisioningChangedCallback(Executor, Callback) + * + * @throws IllegalArgumentException if the subscription associated with this callback is + * invalid. */ @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void unregisterProvisioningChangedCallback(@NonNull Callback callback) { diff --git a/telephony/java/android/telephony/ims/aidl/IImsCallSessionListener.aidl b/telephony/java/android/telephony/ims/aidl/IImsCallSessionListener.aidl index d0b31e16a4f0..d64e67a40201 100644 --- a/telephony/java/android/telephony/ims/aidl/IImsCallSessionListener.aidl +++ b/telephony/java/android/telephony/ims/aidl/IImsCallSessionListener.aidl @@ -16,6 +16,7 @@ package android.telephony.ims.aidl; +import android.telephony.CallQuality; import android.telephony.ims.ImsStreamMediaProfile; import android.telephony.ims.ImsCallProfile; import android.telephony.ims.ImsReasonInfo; @@ -126,22 +127,29 @@ oneway interface IImsCallSessionListener { */ void callSessionRttModifyRequestReceived(in ImsCallProfile callProfile); - /* Device issued RTT modify request and inturn received response + /** + * Device issued RTT modify request and inturn received response * from Remote UE * @param status Will be one of the following values from: * - {@link Connection.RttModifyStatus} */ void callSessionRttModifyResponseReceived(int status); - /* + /** * While in call, device received RTT message from Remote UE * @param rttMessage Received RTT message */ void callSessionRttMessageReceived(in String rttMessage); - /* + /** * While in call, there has been a change in RTT audio indicator. * @param profile updated ImsStreamMediaProfile */ void callSessionRttAudioIndicatorChanged(in ImsStreamMediaProfile profile); + + /** + * Notifies of a change to the call quality. + * @param callQuality then updated call quality + */ + void callQualityChanged(in CallQuality callQuality); } diff --git a/telephony/java/android/telephony/ims/compat/stub/ImsCallSessionImplBase.java b/telephony/java/android/telephony/ims/compat/stub/ImsCallSessionImplBase.java index bc58e46806c2..38566fe6d811 100644 --- a/telephony/java/android/telephony/ims/compat/stub/ImsCallSessionImplBase.java +++ b/telephony/java/android/telephony/ims/compat/stub/ImsCallSessionImplBase.java @@ -18,19 +18,18 @@ package android.telephony.ims.compat.stub; import android.os.Message; import android.os.RemoteException; - +import android.telephony.CallQuality; import android.telephony.ims.ImsCallProfile; +import android.telephony.ims.ImsCallSession; import android.telephony.ims.ImsConferenceState; import android.telephony.ims.ImsReasonInfo; import android.telephony.ims.ImsStreamMediaProfile; import android.telephony.ims.ImsSuppServiceNotification; import android.telephony.ims.aidl.IImsCallSessionListener; + import com.android.ims.internal.IImsCallSession; import com.android.ims.internal.IImsVideoCallProvider; -import android.annotation.UnsupportedAppUsage; -import android.telephony.ims.ImsCallSession; - /** * Compat implementation of ImsCallSessionImplBase for older implementations. * @@ -597,5 +596,10 @@ public class ImsCallSessionImplBase extends IImsCallSession.Stub { throws RemoteException { mNewListener.callSessionRttAudioIndicatorChanged(profile); } + + @Override + public void callQualityChanged(CallQuality callQuality) throws RemoteException { + mNewListener.callQualityChanged(callQuality); + } } } diff --git a/telephony/java/com/android/ims/internal/IImsCallSessionListener.aidl b/telephony/java/com/android/ims/internal/IImsCallSessionListener.aidl index bbb27af1ba36..579369f4b549 100644 --- a/telephony/java/com/android/ims/internal/IImsCallSessionListener.aidl +++ b/telephony/java/com/android/ims/internal/IImsCallSessionListener.aidl @@ -16,6 +16,7 @@ package com.android.ims.internal; +import android.telephony.CallQuality; import android.telephony.ims.ImsStreamMediaProfile; import android.telephony.ims.ImsCallProfile; import android.telephony.ims.ImsReasonInfo; @@ -140,22 +141,29 @@ oneway interface IImsCallSessionListener { void callSessionRttModifyRequestReceived(in IImsCallSession session, in ImsCallProfile callProfile); - /* Device issued RTT modify request and inturn received response + /** + * Device issued RTT modify request and inturn received response * from Remote UE * @param status Will be one of the following values from: * - {@link Connection.RttModifyStatus} */ void callSessionRttModifyResponseReceived(in int status); - /* + /** * While in call, device received RTT message from Remote UE * @param rttMessage Received RTT message */ void callSessionRttMessageReceived(in String rttMessage); - /* + /** * While in call, there has been a change in RTT audio indicator. * @param profile updated ImsStreamMediaProfile */ void callSessionRttAudioIndicatorChanged(in ImsStreamMediaProfile profile); + + /** + * Notifies of a change to the call quality. + * @param callQuality then updated call quality + */ + void callQualityChanged(in CallQuality callQuality); } diff --git a/telephony/java/com/android/internal/telephony/DctConstants.java b/telephony/java/com/android/internal/telephony/DctConstants.java index 3408291825d1..6e8d038eda4f 100644 --- a/telephony/java/com/android/internal/telephony/DctConstants.java +++ b/telephony/java/com/android/internal/telephony/DctConstants.java @@ -66,7 +66,8 @@ public class DctConstants { public static final int EVENT_DATA_CONNECTION_DETACHED = BASE + 9; public static final int EVENT_ROAMING_ON = BASE + 11; public static final int EVENT_ROAMING_OFF = BASE + 12; - public static final int EVENT_ENABLE_NEW_APN = BASE + 13; + public static final int EVENT_ENABLE_APN = BASE + 13; + public static final int EVENT_DISABLE_APN = BASE + 14; public static final int EVENT_DISCONNECT_DONE = BASE + 15; public static final int EVENT_DATA_CONNECTION_ATTACHED = BASE + 16; public static final int EVENT_DATA_STALL_ALARM = BASE + 17; @@ -86,7 +87,7 @@ public class DctConstants { public static final int CMD_NET_STAT_POLL = BASE + 40; public static final int EVENT_DATA_RAT_CHANGED = BASE + 41; public static final int CMD_CLEAR_PROVISIONING_SPINNER = BASE + 42; - public static final int EVENT_REDIRECTION_DETECTED = BASE + 44; + public static final int EVENT_NETWORK_STATUS_CHANGED = BASE + 44; public static final int EVENT_PCO_DATA_RECEIVED = BASE + 45; public static final int EVENT_DATA_ENABLED_CHANGED = BASE + 46; public static final int EVENT_DATA_RECONNECT = BASE + 47; diff --git a/telephony/java/com/android/internal/telephony/ITelephony.aidl b/telephony/java/com/android/internal/telephony/ITelephony.aidl index c5d82c5949f0..5736a465d449 100644 --- a/telephony/java/com/android/internal/telephony/ITelephony.aidl +++ b/telephony/java/com/android/internal/telephony/ITelephony.aidl @@ -28,6 +28,7 @@ import android.net.Uri; import android.service.carrier.CarrierIdentifier; import android.telecom.PhoneAccount; import android.telecom.PhoneAccountHandle; +import android.telephony.CarrierRestrictionRules; import android.telephony.CellInfo; import android.telephony.ClientRequestStats; import android.telephony.IccOpenLogicalChannelResponse; @@ -41,6 +42,7 @@ import android.telephony.ServiceState; import android.telephony.SignalStrength; import android.telephony.TelephonyHistogram; import android.telephony.VisualVoicemailSmsFilterSettings; +import android.telephony.emergency.EmergencyNumber; import android.telephony.ims.aidl.IImsCapabilityCallback; import android.telephony.ims.aidl.IImsConfig; import android.telephony.ims.aidl.IImsConfigCallback; @@ -1292,22 +1294,27 @@ interface ITelephony { List<TelephonyHistogram> getTelephonyHistograms(); /** - * Set the allowed carrier list for slotIndex - * Require system privileges. In the future we may add this to carrier APIs. + * Set the allowed carrier list and the excluded carrier list, indicating the priority between + * the two lists. * - * @return The number of carriers set successfully. Should match length of - * carriers on success. + * <p>Requires system privileges. In the future we may add this to carrier APIs. + * + * @return {@link #SET_CARRIER_RESTRICTION_SUCCESS} in case of success. + * {@link #SET_CARRIER_RESTRICTION_NOT_SUPPORTED} if the modem does not support the + * configuration. {@link #SET_CARRIER_RESTRICTION_ERROR} in all other error cases. */ - int setAllowedCarriers(int slotIndex, in List<CarrierIdentifier> carriers); + int setAllowedCarriers(in CarrierRestrictionRules carrierRestrictionRules); /** - * Get the allowed carrier list for slotIndex. - * Require system privileges. In the future we may add this to carrier APIs. + * Get the allowed carrier list and the excluded carrier list indicating the priority between + * the two lists. + * + * <p>Requires system privileges. In the future we may add this to carrier APIs. * - * @return List of {@link android.service.carrier.CarrierIdentifier}; empty list - * means all carriers are allowed. + * @return {@link CarrierRestrictionRules}; empty lists mean all carriers are allowed. It + * returns null in case of error. */ - List<CarrierIdentifier> getAllowedCarriers(int slotIndex); + CarrierRestrictionRules getAllowedCarriers(); /** * Returns carrier id of the given subscription. @@ -1776,4 +1783,19 @@ interface ITelephony { * Set the String provisioning value for the provisioning key specified. */ int setImsProvisioningString(int subId, int key, String value); + + /** + * Update Emergency Number List for Test Mode. + */ + void updateEmergencyNumberListTestMode(int action, in EmergencyNumber num); + + /** + * Get the full emergency number list for Test Mode. + */ + List<String> getEmergencyNumberListTestMode(); + + /** + * Enable or disable a logical modem stack associated with the slotIndex. + */ + boolean enableModemForSlot(int slotIndex, boolean enable); } diff --git a/telephony/java/com/android/internal/telephony/ITelephonyRegistry.aidl b/telephony/java/com/android/internal/telephony/ITelephonyRegistry.aidl index 5632c630999b..2be1f419db4d 100644 --- a/telephony/java/com/android/internal/telephony/ITelephonyRegistry.aidl +++ b/telephony/java/com/android/internal/telephony/ITelephonyRegistry.aidl @@ -20,6 +20,7 @@ import android.content.Intent; import android.net.LinkProperties; import android.net.NetworkCapabilities; import android.os.Bundle; +import android.telephony.CallQuality; import android.telephony.CellInfo; import android.telephony.PhoneCapability; import android.telephony.PhysicalChannelConfig; @@ -65,7 +66,7 @@ interface ITelephonyRegistry { void notifyPhysicalChannelConfigurationForSubscriber(in int subId, in List<PhysicalChannelConfig> configs); void notifyPreciseCallState(int ringingCallState, int foregroundCallState, - int backgroundCallState); + int backgroundCallState, int phoneId); void notifyDisconnectCause(int disconnectCause, int preciseDisconnectCause); void notifyPreciseDataConnectionFailed(String apnType, String apn, int failCause); @@ -82,4 +83,5 @@ interface ITelephonyRegistry { void notifyPreferredDataSubIdChanged(int preferredSubId); void notifyRadioPowerStateChanged(in int state); void notifyEmergencyNumberList(); + void notifyCallQualityChanged(in CallQuality callQuality, int phoneId); } diff --git a/telephony/java/com/android/internal/telephony/RILConstants.java b/telephony/java/com/android/internal/telephony/RILConstants.java index 1c103a9fc747..930003462110 100644 --- a/telephony/java/com/android/internal/telephony/RILConstants.java +++ b/telephony/java/com/android/internal/telephony/RILConstants.java @@ -489,6 +489,7 @@ public interface RILConstants { int RIL_REQUEST_STOP_NETWORK_SCAN = 143; int RIL_REQUEST_START_KEEPALIVE = 144; int RIL_REQUEST_STOP_KEEPALIVE = 145; + int RIL_REQUEST_ENABLE_MODEM = 146; /* The following requests are not defined in RIL.h */ int RIL_REQUEST_HAL_NON_RIL_BASE = 200; diff --git a/tests/ActivityViewTest/AndroidManifest.xml b/tests/ActivityViewTest/AndroidManifest.xml index 0be1ea0fdfd2..17eb029166f0 100644 --- a/tests/ActivityViewTest/AndroidManifest.xml +++ b/tests/ActivityViewTest/AndroidManifest.xml @@ -57,5 +57,10 @@ android:exported="true" android:configChanges="orientation|screenSize|smallestScreenSize|screenLayout|colorMode|density"> </activity> + + <activity android:name=".ActivityViewVisibilityActivity" + android:label="AV Visibility" + android:configChanges="orientation|screenSize|smallestScreenSize|screenLayout|colorMode|density"> + </activity> </application> </manifest> diff --git a/tests/ActivityViewTest/res/layout/activity_view_main_activity.xml b/tests/ActivityViewTest/res/layout/activity_view_main_activity.xml index ba2e91166440..efcaef679a9c 100644 --- a/tests/ActivityViewTest/res/layout/activity_view_main_activity.xml +++ b/tests/ActivityViewTest/res/layout/activity_view_main_activity.xml @@ -41,4 +41,10 @@ android:text="Test Resize ActivityView" android:textAllCaps="false"/> + <Button + android:id="@+id/visibility_activity_view_button" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:text="Test ActivityView Visibility" + android:textAllCaps="false"/> </LinearLayout> diff --git a/tests/ActivityViewTest/res/layout/activity_view_visibility_activity.xml b/tests/ActivityViewTest/res/layout/activity_view_visibility_activity.xml new file mode 100644 index 000000000000..d29d4dfc0428 --- /dev/null +++ b/tests/ActivityViewTest/res/layout/activity_view_visibility_activity.xml @@ -0,0 +1,46 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 2019 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> + +<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" + android:orientation="vertical" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:background="#cfd8dc"> + + <LinearLayout + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:orientation="horizontal"> + + <Button + android:id="@+id/activity_launch_button" + android:layout_width="200dp" + android:layout_height="wrap_content" + android:text="Launch test activity" /> + + <Spinner + android:id="@+id/visibility_spinner" + android:layout_width="200dp" + android:layout_height="match_parent"/> + + </LinearLayout> + + <ActivityView + android:id="@+id/activity_view" + android:layout_width="match_parent" + android:layout_height="match_parent" /> + +</LinearLayout> diff --git a/tests/ActivityViewTest/src/com/google/android/test/activityview/ActivityViewMainActivity.java b/tests/ActivityViewTest/src/com/google/android/test/activityview/ActivityViewMainActivity.java index 66f0c6a56afd..4f09c28fe711 100644 --- a/tests/ActivityViewTest/src/com/google/android/test/activityview/ActivityViewMainActivity.java +++ b/tests/ActivityViewTest/src/com/google/android/test/activityview/ActivityViewMainActivity.java @@ -35,5 +35,8 @@ public class ActivityViewMainActivity extends Activity { findViewById(R.id.resize_activity_view_button).setOnClickListener( v -> startActivity(new Intent(this, ActivityViewResizeActivity.class))); + + findViewById(R.id.visibility_activity_view_button).setOnClickListener( + v -> startActivity(new Intent(this, ActivityViewVisibilityActivity.class))); } } diff --git a/tests/ActivityViewTest/src/com/google/android/test/activityview/ActivityViewTestActivity.java b/tests/ActivityViewTest/src/com/google/android/test/activityview/ActivityViewTestActivity.java index ba2c764bd7d7..52aba2b13c42 100644 --- a/tests/ActivityViewTest/src/com/google/android/test/activityview/ActivityViewTestActivity.java +++ b/tests/ActivityViewTest/src/com/google/android/test/activityview/ActivityViewTestActivity.java @@ -24,12 +24,14 @@ import static android.view.MotionEvent.ACTION_UP; import android.app.Activity; import android.content.res.Configuration; import android.os.Bundle; +import android.util.Log; import android.view.MotionEvent; import android.view.View; import android.view.ViewTreeObserver; import android.widget.TextView; public class ActivityViewTestActivity extends Activity { + private static final String TAG = "ActivityViewTestActivity"; private View mRoot; private TextView mTextView; @@ -84,6 +86,7 @@ public class ActivityViewTestActivity extends Activity { } private void updateStateText(String state) { + Log.d(TAG, state); mTextView.setText(state); } diff --git a/tests/ActivityViewTest/src/com/google/android/test/activityview/ActivityViewVisibilityActivity.java b/tests/ActivityViewTest/src/com/google/android/test/activityview/ActivityViewVisibilityActivity.java new file mode 100644 index 000000000000..ecd2cf3c578e --- /dev/null +++ b/tests/ActivityViewTest/src/com/google/android/test/activityview/ActivityViewVisibilityActivity.java @@ -0,0 +1,75 @@ +/** + * Copyright (c) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.android.test.activityview; + +import static android.view.View.GONE; +import static android.view.View.INVISIBLE; +import static android.view.View.VISIBLE; + +import android.app.Activity; +import android.app.ActivityView; +import android.content.Intent; +import android.os.Bundle; +import android.view.View; +import android.widget.AdapterView; +import android.widget.ArrayAdapter; +import android.widget.Button; +import android.widget.Spinner; + +public class ActivityViewVisibilityActivity extends Activity { + private static final String[] sVisibilityOptions = {"VISIBLE", "INVISIBLE", "GONE"}; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_view_visibility_activity); + + final ActivityView activityView = findViewById(R.id.activity_view); + final Button launchButton = findViewById(R.id.activity_launch_button); + launchButton.setOnClickListener(v -> { + final Intent intent = new Intent(this, ActivityViewTestActivity.class); + intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_MULTIPLE_TASK); + activityView.startActivity(intent); + }); + + final Spinner visibilitySpinner = findViewById(R.id.visibility_spinner); + final ArrayAdapter<String> adapter = new ArrayAdapter<>(this, + android.R.layout.simple_spinner_item, sVisibilityOptions); + adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); + visibilitySpinner.setAdapter(adapter); + visibilitySpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() { + @Override + public void onItemSelected(AdapterView<?> parent, View view, int position, long id) { + switch (position) { + case 0: + activityView.setVisibility(VISIBLE); + break; + case 1: + activityView.setVisibility(INVISIBLE); + break; + case 2: + activityView.setVisibility(GONE); + break; + } + } + + @Override + public void onNothingSelected(AdapterView<?> parent) { + } + }); + } +} diff --git a/tests/RollbackTest/src/com/android/tests/rollback/RollbackTest.java b/tests/RollbackTest/src/com/android/tests/rollback/RollbackTest.java index 77cd9d8f20a3..c2e735e184b0 100644 --- a/tests/RollbackTest/src/com/android/tests/rollback/RollbackTest.java +++ b/tests/RollbackTest/src/com/android/tests/rollback/RollbackTest.java @@ -178,10 +178,10 @@ public class RollbackTest { } /** - * Test that rollback data is properly persisted. + * Test that multiple available rollbacks are properly persisted. */ @Test - public void testRollbackDataPersistence() throws Exception { + public void testAvailableRollbackPersistence() throws Exception { try { RollbackTestUtils.adoptShellPermissionIdentity( Manifest.permission.INSTALL_PACKAGES, @@ -190,36 +190,157 @@ public class RollbackTest { RollbackManager rm = RollbackTestUtils.getRollbackManager(); - // TODO: Test this with multi-package rollback, not just single - // package rollback. - // Prep installation of TEST_APP_A RollbackTestUtils.uninstall(TEST_APP_A); RollbackTestUtils.install("RollbackTestAppAv1.apk", false); RollbackTestUtils.install("RollbackTestAppAv2.apk", true); assertEquals(2, RollbackTestUtils.getInstalledVersion(TEST_APP_A)); + RollbackTestUtils.uninstall(TEST_APP_B); + RollbackTestUtils.install("RollbackTestAppBv1.apk", false); + RollbackTestUtils.install("RollbackTestAppBv2.apk", true); + assertEquals(2, RollbackTestUtils.getInstalledVersion(TEST_APP_B)); + + // Both test apps should now be available for rollback. + // TODO: See if there is a way to remove this race condition + // between when the app is installed and when the rollback + // is made available. + Thread.sleep(1000); + + assertTrue(rm.getPackagesWithAvailableRollbacks().contains(TEST_APP_A)); + RollbackInfo rollbackA = rm.getAvailableRollback(TEST_APP_A); + assertNotNull(rollbackA); + assertEquals(TEST_APP_A, rollbackA.targetPackage.packageName); + assertEquals(2, rollbackA.targetPackage.higherVersion.versionCode); + assertEquals(1, rollbackA.targetPackage.lowerVersion.versionCode); + + assertTrue(rm.getPackagesWithAvailableRollbacks().contains(TEST_APP_B)); + RollbackInfo rollbackB = rm.getAvailableRollback(TEST_APP_B); + assertNotNull(rollbackB); + assertEquals(TEST_APP_B, rollbackB.targetPackage.packageName); + assertEquals(2, rollbackB.targetPackage.higherVersion.versionCode); + assertEquals(1, rollbackB.targetPackage.lowerVersion.versionCode); + + // Reload the persisted data. + rm.reloadPersistedData(); + + // The apps should still be available for rollback. + rollbackA = rm.getAvailableRollback(TEST_APP_A); + assertNotNull(rollbackA); + assertEquals(TEST_APP_A, rollbackA.targetPackage.packageName); + assertEquals(2, rollbackA.targetPackage.higherVersion.versionCode); + assertEquals(1, rollbackA.targetPackage.lowerVersion.versionCode); + + assertTrue(rm.getPackagesWithAvailableRollbacks().contains(TEST_APP_B)); + rollbackB = rm.getAvailableRollback(TEST_APP_B); + assertNotNull(rollbackB); + assertEquals(TEST_APP_B, rollbackB.targetPackage.packageName); + assertEquals(2, rollbackB.targetPackage.higherVersion.versionCode); + assertEquals(1, rollbackB.targetPackage.lowerVersion.versionCode); + + // Rollback of B should not rollback A + RollbackTestUtils.rollback(rollbackB); + assertEquals(2, RollbackTestUtils.getInstalledVersion(TEST_APP_A)); + assertEquals(1, RollbackTestUtils.getInstalledVersion(TEST_APP_B)); + } finally { + RollbackTestUtils.dropShellPermissionIdentity(); + } + } + + /** + * Test that available multi-package rollbacks are properly persisted. + */ + @Test + public void testAvailableMultiPackageRollbackPersistence() throws Exception { + try { + RollbackTestUtils.adoptShellPermissionIdentity( + Manifest.permission.INSTALL_PACKAGES, + Manifest.permission.DELETE_PACKAGES, + Manifest.permission.MANAGE_ROLLBACKS); + + RollbackManager rm = RollbackTestUtils.getRollbackManager(); + + RollbackTestUtils.uninstall(TEST_APP_A); + RollbackTestUtils.uninstall(TEST_APP_B); + RollbackTestUtils.installMultiPackage(false, + "RollbackTestAppAv1.apk", + "RollbackTestAppBv1.apk"); + RollbackTestUtils.installMultiPackage(true, + "RollbackTestAppAv2.apk", + "RollbackTestAppBv2.apk"); + assertEquals(2, RollbackTestUtils.getInstalledVersion(TEST_APP_A)); + assertEquals(2, RollbackTestUtils.getInstalledVersion(TEST_APP_B)); + // The app should now be available for rollback. // TODO: See if there is a way to remove this race condition // between when the app is installed and when the rollback // is made available. Thread.sleep(1000); + assertTrue(rm.getPackagesWithAvailableRollbacks().contains(TEST_APP_A)); - RollbackInfo rollback = rm.getAvailableRollback(TEST_APP_A); - assertNotNull(rollback); - assertEquals(TEST_APP_A, rollback.targetPackage.packageName); - assertEquals(2, rollback.targetPackage.higherVersion.versionCode); - assertEquals(1, rollback.targetPackage.lowerVersion.versionCode); + RollbackInfo rollbackA = rm.getAvailableRollback(TEST_APP_A); + assertNotNull(rollbackA); + assertEquals(TEST_APP_A, rollbackA.targetPackage.packageName); + assertEquals(2, rollbackA.targetPackage.higherVersion.versionCode); + assertEquals(1, rollbackA.targetPackage.lowerVersion.versionCode); + + assertTrue(rm.getPackagesWithAvailableRollbacks().contains(TEST_APP_B)); + RollbackInfo rollbackB = rm.getAvailableRollback(TEST_APP_B); + assertNotNull(rollbackB); + assertEquals(TEST_APP_B, rollbackB.targetPackage.packageName); + assertEquals(2, rollbackB.targetPackage.higherVersion.versionCode); + assertEquals(1, rollbackB.targetPackage.lowerVersion.versionCode); // Reload the persisted data. rm.reloadPersistedData(); - // The app should still be available for rollback. + // The apps should still be available for rollback. + rollbackA = rm.getAvailableRollback(TEST_APP_A); + assertNotNull(rollbackA); + assertEquals(TEST_APP_A, rollbackA.targetPackage.packageName); + assertEquals(2, rollbackA.targetPackage.higherVersion.versionCode); + assertEquals(1, rollbackA.targetPackage.lowerVersion.versionCode); + + assertTrue(rm.getPackagesWithAvailableRollbacks().contains(TEST_APP_B)); + rollbackB = rm.getAvailableRollback(TEST_APP_B); + assertNotNull(rollbackB); + assertEquals(TEST_APP_B, rollbackB.targetPackage.packageName); + assertEquals(2, rollbackB.targetPackage.higherVersion.versionCode); + assertEquals(1, rollbackB.targetPackage.lowerVersion.versionCode); + + // Rollback of B should rollback A as well + RollbackTestUtils.rollback(rollbackB); + assertEquals(1, RollbackTestUtils.getInstalledVersion(TEST_APP_A)); + assertEquals(1, RollbackTestUtils.getInstalledVersion(TEST_APP_B)); + } finally { + RollbackTestUtils.dropShellPermissionIdentity(); + } + } + + /** + * Test that recently executed rollback data is properly persisted. + */ + @Test + public void testRecentlyExecutedRollbackPersistence() throws Exception { + try { + RollbackTestUtils.adoptShellPermissionIdentity( + Manifest.permission.INSTALL_PACKAGES, + Manifest.permission.DELETE_PACKAGES, + Manifest.permission.MANAGE_ROLLBACKS); + + RollbackManager rm = RollbackTestUtils.getRollbackManager(); + + RollbackTestUtils.uninstall(TEST_APP_A); + RollbackTestUtils.install("RollbackTestAppAv1.apk", false); + RollbackTestUtils.install("RollbackTestAppAv2.apk", true); + assertEquals(2, RollbackTestUtils.getInstalledVersion(TEST_APP_A)); + + // The app should now be available for rollback. + // TODO: See if there is a way to remove this race condition + // between when the app is installed and when the rollback + // is made available. + Thread.sleep(1000); assertTrue(rm.getPackagesWithAvailableRollbacks().contains(TEST_APP_A)); - rollback = rm.getAvailableRollback(TEST_APP_A); - assertNotNull(rollback); - assertEquals(TEST_APP_A, rollback.targetPackage.packageName); - assertEquals(2, rollback.targetPackage.higherVersion.versionCode); - assertEquals(1, rollback.targetPackage.lowerVersion.versionCode); + RollbackInfo rollback = rm.getAvailableRollback(TEST_APP_A); // Roll back the app. RollbackTestUtils.rollback(rollback); diff --git a/tests/net/Android.mk b/tests/net/Android.mk index f6f35fdadcd1..685067377166 100644 --- a/tests/net/Android.mk +++ b/tests/net/Android.mk @@ -54,6 +54,7 @@ LOCAL_JNI_SHARED_LIBRARIES := \ libnativehelper \ libpackagelistparser \ libpcre2 \ + libprocessgroup \ libselinux \ libui \ libutils \ diff --git a/tests/net/java/android/net/shared/LinkPropertiesParcelableUtilTest.java b/tests/net/java/android/net/shared/LinkPropertiesParcelableUtilTest.java new file mode 100644 index 000000000000..4cabfc95b49d --- /dev/null +++ b/tests/net/java/android/net/shared/LinkPropertiesParcelableUtilTest.java @@ -0,0 +1,193 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.net.shared; + +import static android.net.shared.LinkPropertiesParcelableUtil.fromStableParcelable; +import static android.net.shared.LinkPropertiesParcelableUtil.toStableParcelable; + +import static org.junit.Assert.assertEquals; + +import android.net.InetAddresses; +import android.net.IpPrefix; +import android.net.LinkAddress; +import android.net.LinkProperties; +import android.net.ProxyInfo; +import android.net.RouteInfo; +import android.net.Uri; +import android.support.test.filters.SmallTest; +import android.support.test.runner.AndroidJUnit4; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; + +import java.lang.reflect.Modifier; +import java.util.Arrays; +import java.util.Collections; + +/** + * Tests for {@link LinkPropertiesParcelableUtil} + */ +@RunWith(AndroidJUnit4.class) +@SmallTest +public class LinkPropertiesParcelableUtilTest { + private LinkProperties mLinkProperties; + + private static final String TEST_LINKPROPS_IFACE = "TEST_IFACE"; + private static final String TEST_STACKED_LINK_1_IFACE = "TEST_STACKED_IFACE_1"; + private static final String TEST_STACKED_LINK_2_IFACE = "TEST_STACKED_IFACE_2"; + + @Before + public void setUp() { + mLinkProperties = makeLinkProperties(TEST_LINKPROPS_IFACE); + mLinkProperties.addStackedLink(makeLinkProperties(TEST_STACKED_LINK_1_IFACE)); + mLinkProperties.addStackedLink(makeLinkProperties(TEST_STACKED_LINK_2_IFACE)); + } + + private static LinkProperties makeLinkProperties(String iface) { + final LinkProperties lp = new LinkProperties(); + lp.setInterfaceName(iface); + lp.setLinkAddresses(Arrays.asList( + new LinkAddress(InetAddresses.parseNumericAddress("192.168.0.42"), 16), + new LinkAddress(InetAddresses.parseNumericAddress("2001:db8::7"), 42))); + lp.setDnsServers(Arrays.asList( + InetAddresses.parseNumericAddress("2001:db8::42"), + InetAddresses.parseNumericAddress("192.168.1.1") + )); + lp.setValidatedPrivateDnsServers(Arrays.asList( + InetAddresses.parseNumericAddress("2001:db8::43"), + InetAddresses.parseNumericAddress("192.168.42.43") + )); + lp.setPcscfServers(Arrays.asList( + InetAddresses.parseNumericAddress("2001:db8::47"), + InetAddresses.parseNumericAddress("192.168.42.47") + )); + lp.setUsePrivateDns(true); + lp.setPrivateDnsServerName("test.example.com"); + lp.setDomains("test1.example.com,test2.example.com"); + lp.addRoute(new RouteInfo( + new IpPrefix(InetAddresses.parseNumericAddress("2001:db8::44"), 45), + InetAddresses.parseNumericAddress("2001:db8::45"), + iface, + RouteInfo.RTN_UNICAST + )); + lp.addRoute(new RouteInfo( + new IpPrefix(InetAddresses.parseNumericAddress("192.168.44.45"), 16), + InetAddresses.parseNumericAddress("192.168.45.1"), + iface, + RouteInfo.RTN_THROW + )); + lp.setHttpProxy(new ProxyInfo("test3.example.com", 8000, + "excl1.example.com,excl2.example.com")); + lp.setMtu(5000); + lp.setTcpBufferSizes("1,2,3,4,5,6"); + lp.setNat64Prefix(new IpPrefix(InetAddresses.parseNumericAddress("2001:db8::48"), 96)); + + // Verify that this test does not miss any new field added later. + // If any added field is not included in LinkProperties#equals, assertLinkPropertiesEquals + // must also be updated. + assertEquals(14, Arrays.stream(LinkProperties.class.getDeclaredFields()) + .filter(f -> !Modifier.isStatic(f.getModifiers())).count()); + + return lp; + } + + @Test + public void testParcelUnparcel() { + doParcelUnparcelTest(); + } + + @Test + public void testParcelUnparcel_NullInterface() { + mLinkProperties.setInterfaceName(null); + doParcelUnparcelTest(); + } + + @Test + public void testParcelUnparcel_NullPrivateDnsServer() { + mLinkProperties.setPrivateDnsServerName(null); + doParcelUnparcelTest(); + } + + @Test + public void testParcelUnparcel_NullDomains() { + mLinkProperties.setDomains(null); + doParcelUnparcelTest(); + } + + @Test + public void testParcelUnparcel_NullProxy() { + mLinkProperties.setHttpProxy(null); + doParcelUnparcelTest(); + } + + @Test + public void testParcelUnparcel_NullTcpBufferSizes() { + mLinkProperties.setTcpBufferSizes(null); + doParcelUnparcelTest(); + } + + @Test + public void testParcelUnparcel_EmptyLinkAddresses() { + mLinkProperties.setLinkAddresses(Collections.emptyList()); + doParcelUnparcelTest(); + } + + @Test + public void testParcelUnparcel_EmptyDnses() { + mLinkProperties.setDnsServers(Collections.emptyList()); + doParcelUnparcelTest(); + } + + @Test + public void testParcelUnparcel_EmptyValidatedPrivateDnses() { + mLinkProperties.setValidatedPrivateDnsServers(Collections.emptyList()); + doParcelUnparcelTest(); + } + + @Test + public void testParcelUnparcel_EmptyRoutes() { + for (RouteInfo r : mLinkProperties.getAllRoutes()) { + mLinkProperties.removeRoute(r); + } + doParcelUnparcelTest(); + } + + @Test + public void testParcelUnparcel_PacFileProxyInfo() { + mLinkProperties.setHttpProxy(new ProxyInfo(Uri.parse("http://pacfile.example.com"))); + doParcelUnparcelTest(); + } + + @Test + public void testParcelUnparcel_NullNat64Prefix() { + mLinkProperties.setNat64Prefix(null); + doParcelUnparcelTest(); + } + + private void doParcelUnparcelTest() { + final LinkProperties unparceled = fromStableParcelable(toStableParcelable(mLinkProperties)); + assertLinkPropertiesEquals(mLinkProperties, unparceled); + } + + private static void assertLinkPropertiesEquals(LinkProperties expected, LinkProperties actual) { + assertEquals(expected, actual); + + // LinkProperties equals() does not include stacked links + assertEquals(expected.getStackedLinks(), actual.getStackedLinks()); + } +} diff --git a/tests/net/java/com/android/server/ConnectivityServiceTest.java b/tests/net/java/com/android/server/ConnectivityServiceTest.java index 2a92a7dabd98..882babff4aee 100644 --- a/tests/net/java/com/android/server/ConnectivityServiceTest.java +++ b/tests/net/java/com/android/server/ConnectivityServiceTest.java @@ -122,7 +122,6 @@ import android.net.NetworkSpecifier; import android.net.NetworkStack; import android.net.NetworkUtils; import android.net.RouteInfo; -import android.net.StringNetworkSpecifier; import android.net.UidRange; import android.net.metrics.IpConnectivityLog; import android.net.shared.NetworkMonitorUtils; @@ -145,6 +144,7 @@ import android.support.test.InstrumentationRegistry; import android.support.test.filters.SmallTest; import android.support.test.runner.AndroidJUnit4; import android.test.mock.MockContentResolver; +import android.text.TextUtils; import android.util.ArraySet; import android.util.Log; @@ -2567,16 +2567,76 @@ public class ConnectivityServiceTest { return new NetworkRequest.Builder().addTransportType(TRANSPORT_WIFI); } + /** + * Verify request matching behavior with network specifiers. + * + * Note: this test is somewhat problematic since it involves removing capabilities from + * agents - i.e. agents rejecting requests which they previously accepted. This is flagged + * as a WTF bug in + * {@link ConnectivityService#mixInCapabilities(NetworkAgentInfo, NetworkCapabilities)} but + * does work. + */ @Test public void testNetworkSpecifier() { + // A NetworkSpecifier subclass that matches all networks but must not be visible to apps. + class ConfidentialMatchAllNetworkSpecifier extends NetworkSpecifier implements + Parcelable { + @Override + public boolean satisfiedBy(NetworkSpecifier other) { + return true; + } + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(Parcel dest, int flags) {} + + @Override + public NetworkSpecifier redact() { + return null; + } + } + + // A network specifier that matches either another LocalNetworkSpecifier with the same + // string or a ConfidentialMatchAllNetworkSpecifier, and can be passed to apps as is. + class LocalStringNetworkSpecifier extends NetworkSpecifier implements Parcelable { + private String mString; + + LocalStringNetworkSpecifier(String string) { + mString = string; + } + + @Override + public boolean satisfiedBy(NetworkSpecifier other) { + if (other instanceof LocalStringNetworkSpecifier) { + return TextUtils.equals(mString, + ((LocalStringNetworkSpecifier) other).mString); + } + if (other instanceof ConfidentialMatchAllNetworkSpecifier) return true; + return false; + } + + @Override + public int describeContents() { + return 0; + } + @Override + public void writeToParcel(Parcel dest, int flags) {} + } + + NetworkRequest rEmpty1 = newWifiRequestBuilder().build(); NetworkRequest rEmpty2 = newWifiRequestBuilder().setNetworkSpecifier((String) null).build(); NetworkRequest rEmpty3 = newWifiRequestBuilder().setNetworkSpecifier("").build(); NetworkRequest rEmpty4 = newWifiRequestBuilder().setNetworkSpecifier( (NetworkSpecifier) null).build(); - NetworkRequest rFoo = newWifiRequestBuilder().setNetworkSpecifier("foo").build(); + NetworkRequest rFoo = newWifiRequestBuilder().setNetworkSpecifier( + new LocalStringNetworkSpecifier("foo")).build(); NetworkRequest rBar = newWifiRequestBuilder().setNetworkSpecifier( - new StringNetworkSpecifier("bar")).build(); + new LocalStringNetworkSpecifier("bar")).build(); TestNetworkCallback cEmpty1 = new TestNetworkCallback(); TestNetworkCallback cEmpty2 = new TestNetworkCallback(); @@ -2585,7 +2645,7 @@ public class ConnectivityServiceTest { TestNetworkCallback cFoo = new TestNetworkCallback(); TestNetworkCallback cBar = new TestNetworkCallback(); TestNetworkCallback[] emptyCallbacks = new TestNetworkCallback[] { - cEmpty1, cEmpty2, cEmpty3 }; + cEmpty1, cEmpty2, cEmpty3, cEmpty4 }; mCm.registerNetworkCallback(rEmpty1, cEmpty1); mCm.registerNetworkCallback(rEmpty2, cEmpty2); @@ -2594,6 +2654,9 @@ public class ConnectivityServiceTest { mCm.registerNetworkCallback(rFoo, cFoo); mCm.registerNetworkCallback(rBar, cBar); + LocalStringNetworkSpecifier nsFoo = new LocalStringNetworkSpecifier("foo"); + LocalStringNetworkSpecifier nsBar = new LocalStringNetworkSpecifier("bar"); + mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI); mWiFiNetworkAgent.connect(false); cEmpty1.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent); @@ -2602,30 +2665,54 @@ public class ConnectivityServiceTest { cEmpty4.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent); assertNoCallbacks(cFoo, cBar); - mWiFiNetworkAgent.setNetworkSpecifier(new StringNetworkSpecifier("foo")); + mWiFiNetworkAgent.setNetworkSpecifier(nsFoo); cFoo.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent); for (TestNetworkCallback c: emptyCallbacks) { - c.expectCallback(CallbackState.NETWORK_CAPABILITIES, mWiFiNetworkAgent); + c.expectCapabilitiesLike((caps) -> caps.getNetworkSpecifier().equals(nsFoo), + mWiFiNetworkAgent); } - cFoo.expectCallback(CallbackState.NETWORK_CAPABILITIES, mWiFiNetworkAgent); + cFoo.expectCapabilitiesLike((caps) -> caps.getNetworkSpecifier().equals(nsFoo), + mWiFiNetworkAgent); + assertEquals(nsFoo, + mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).getNetworkSpecifier()); cFoo.assertNoCallback(); - mWiFiNetworkAgent.setNetworkSpecifier(new StringNetworkSpecifier("bar")); + mWiFiNetworkAgent.setNetworkSpecifier(nsBar); cFoo.expectCallback(CallbackState.LOST, mWiFiNetworkAgent); cBar.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent); for (TestNetworkCallback c: emptyCallbacks) { - c.expectCallback(CallbackState.NETWORK_CAPABILITIES, mWiFiNetworkAgent); + c.expectCapabilitiesLike((caps) -> caps.getNetworkSpecifier().equals(nsBar), + mWiFiNetworkAgent); } - cBar.expectCallback(CallbackState.NETWORK_CAPABILITIES, mWiFiNetworkAgent); + cBar.expectCapabilitiesLike((caps) -> caps.getNetworkSpecifier().equals(nsBar), + mWiFiNetworkAgent); + assertEquals(nsBar, + mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).getNetworkSpecifier()); + cBar.assertNoCallback(); + + mWiFiNetworkAgent.setNetworkSpecifier(new ConfidentialMatchAllNetworkSpecifier()); + cFoo.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent); + for (TestNetworkCallback c : emptyCallbacks) { + c.expectCapabilitiesLike((caps) -> caps.getNetworkSpecifier() == null, + mWiFiNetworkAgent); + } + cFoo.expectCapabilitiesLike((caps) -> caps.getNetworkSpecifier() == null, + mWiFiNetworkAgent); + cBar.expectCapabilitiesLike((caps) -> caps.getNetworkSpecifier() == null, + mWiFiNetworkAgent); + assertNull( + mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()).getNetworkSpecifier()); + cFoo.assertNoCallback(); cBar.assertNoCallback(); mWiFiNetworkAgent.setNetworkSpecifier(null); + cFoo.expectCallback(CallbackState.LOST, mWiFiNetworkAgent); cBar.expectCallback(CallbackState.LOST, mWiFiNetworkAgent); for (TestNetworkCallback c: emptyCallbacks) { c.expectCallback(CallbackState.NETWORK_CAPABILITIES, mWiFiNetworkAgent); } - assertNoCallbacks(cEmpty1, cEmpty2, cEmpty3, cFoo, cBar); + assertNoCallbacks(cEmpty1, cEmpty2, cEmpty3, cEmpty4, cFoo, cBar); } @Test diff --git a/tests/net/java/com/android/server/IpSecServiceParameterizedTest.java b/tests/net/java/com/android/server/IpSecServiceParameterizedTest.java index d8f961850906..a844cfeeeb80 100644 --- a/tests/net/java/com/android/server/IpSecServiceParameterizedTest.java +++ b/tests/net/java/com/android/server/IpSecServiceParameterizedTest.java @@ -535,7 +535,10 @@ public class IpSecServiceParameterizedTest { IpSecTransformResponse createTransformResp = mIpSecService.createTransform(ipSecConfig, new Binder(), "blessedPackage"); - ParcelFileDescriptor pfd = ParcelFileDescriptor.fromSocket(new Socket()); + + Socket socket = new Socket(); + socket.bind(null); + ParcelFileDescriptor pfd = ParcelFileDescriptor.fromSocket(socket); int resourceId = createTransformResp.resourceId; mIpSecService.applyTransportModeTransform(pfd, IpSecManager.DIRECTION_OUT, resourceId); @@ -552,7 +555,9 @@ public class IpSecServiceParameterizedTest { @Test public void testRemoveTransportModeTransform() throws Exception { - ParcelFileDescriptor pfd = ParcelFileDescriptor.fromSocket(new Socket()); + Socket socket = new Socket(); + socket.bind(null); + ParcelFileDescriptor pfd = ParcelFileDescriptor.fromSocket(socket); mIpSecService.removeTransportModeTransforms(pfd); verify(mMockNetd).ipSecRemoveTransportModeTransform(pfd); diff --git a/tests/net/java/com/android/server/IpSecServiceTest.java b/tests/net/java/com/android/server/IpSecServiceTest.java index 724446e11c83..5be7c7bb2040 100644 --- a/tests/net/java/com/android/server/IpSecServiceTest.java +++ b/tests/net/java/com/android/server/IpSecServiceTest.java @@ -422,7 +422,9 @@ public class IpSecServiceTest { @Test public void testRemoveTransportModeTransform() throws Exception { - ParcelFileDescriptor pfd = ParcelFileDescriptor.fromSocket(new Socket()); + Socket socket = new Socket(); + socket.bind(null); + ParcelFileDescriptor pfd = ParcelFileDescriptor.fromSocket(socket); mIpSecService.removeTransportModeTransforms(pfd); verify(mMockNetd).ipSecRemoveTransportModeTransform(pfd); diff --git a/tools/aapt2/ResourceParser.cpp b/tools/aapt2/ResourceParser.cpp index 58702dc465cc..2f8ca2d62061 100644 --- a/tools/aapt2/ResourceParser.cpp +++ b/tools/aapt2/ResourceParser.cpp @@ -714,7 +714,8 @@ bool ResourceParser::ParseResource(xml::XmlPullParser* parser, } } - diag_->Warn(DiagMessage(out_resource->source) + // If the resource type was not recognized, write the error and return false. + diag_->Error(DiagMessage(out_resource->source) << "unknown resource type '" << parser->element_name() << "'"); return false; } @@ -1164,8 +1165,6 @@ bool ResourceParser::ParseOverlayable(xml::XmlPullParser* parser, ParsedResource current_policies |= OverlayableItem::Policy::kPublic; } else if (trimmed_part == "product") { current_policies |= OverlayableItem::Policy::kProduct; - } else if (trimmed_part == "product_services") { - current_policies |= OverlayableItem::Policy::kProductServices; } else if (trimmed_part == "system") { current_policies |= OverlayableItem::Policy::kSystem; } else if (trimmed_part == "vendor") { diff --git a/tools/aapt2/ResourceParser_test.cpp b/tools/aapt2/ResourceParser_test.cpp index debca9c1e1ba..827c7deaf452 100644 --- a/tools/aapt2/ResourceParser_test.cpp +++ b/tools/aapt2/ResourceParser_test.cpp @@ -935,9 +935,6 @@ TEST_F(ResourceParserTest, ParseOverlayablePolicy) { <policy type="product"> <item type="string" name="bar" /> </policy> - <policy type="product_services"> - <item type="string" name="baz" /> - </policy> <policy type="system"> <item type="string" name="fiz" /> </policy> @@ -966,14 +963,6 @@ TEST_F(ResourceParserTest, ParseOverlayablePolicy) { EXPECT_THAT(result_overlayable_item.overlayable->name, Eq("Name")); EXPECT_THAT(result_overlayable_item.policies, Eq(OverlayableItem::Policy::kProduct)); - search_result = table_.FindResource(test::ParseNameOrDie("string/baz")); - ASSERT_TRUE(search_result); - ASSERT_THAT(search_result.value().entry, NotNull()); - ASSERT_TRUE(search_result.value().entry->overlayable_item); - result_overlayable_item = search_result.value().entry->overlayable_item.value(); - EXPECT_THAT(result_overlayable_item.overlayable->name, Eq("Name")); - EXPECT_THAT(result_overlayable_item.policies, Eq(OverlayableItem::Policy::kProductServices)); - search_result = table_.FindResource(test::ParseNameOrDie("string/fiz")); ASSERT_TRUE(search_result); ASSERT_THAT(search_result.value().entry, NotNull()); @@ -1028,7 +1017,7 @@ TEST_F(ResourceParserTest, ParseOverlayableBadPolicyError) { TEST_F(ResourceParserTest, ParseOverlayableMultiplePolicy) { std::string input = R"( <overlayable name="Name"> - <policy type="vendor|product_services"> + <policy type="vendor|public"> <item type="string" name="foo" /> </policy> <policy type="product|system"> @@ -1044,7 +1033,7 @@ TEST_F(ResourceParserTest, ParseOverlayableMultiplePolicy) { OverlayableItem result_overlayable_item = search_result.value().entry->overlayable_item.value(); EXPECT_THAT(result_overlayable_item.overlayable->name, Eq("Name")); EXPECT_THAT(result_overlayable_item.policies, Eq(OverlayableItem::Policy::kVendor - | OverlayableItem::Policy::kProductServices)); + | OverlayableItem::Policy::kPublic)); search_result = table_.FindResource(test::ParseNameOrDie("string/bar")); ASSERT_TRUE(search_result); @@ -1139,7 +1128,7 @@ TEST_F(ResourceParserTest, NestPolicyInOverlayableError) { std::string input = R"( <overlayable name="Name"> <policy type="vendor|product"> - <policy type="product_services"> + <policy type="public"> <item type="string" name="foo" /> </policy> </policy> diff --git a/tools/aapt2/ResourceTable.h b/tools/aapt2/ResourceTable.h index eaf6a47a15fd..7ca99ea42b50 100644 --- a/tools/aapt2/ResourceTable.h +++ b/tools/aapt2/ResourceTable.h @@ -92,9 +92,6 @@ struct OverlayableItem { // The resource can be overlaid by any overlay on the product partition. kProduct = 0x08, - - // The resource can be overlaid by any overlay on the product services partition. - kProductServices = 0x10 }; std::shared_ptr<Overlayable> overlayable; diff --git a/tools/aapt2/ResourceTable_test.cpp b/tools/aapt2/ResourceTable_test.cpp index a733134f123c..b97dc6b205ca 100644 --- a/tools/aapt2/ResourceTable_test.cpp +++ b/tools/aapt2/ResourceTable_test.cpp @@ -248,7 +248,7 @@ TEST(ResourceTableTest, SetOverlayable) { Source("res/values/overlayable.xml", 40)); OverlayableItem overlayable_item(overlayable); overlayable_item.policies |= OverlayableItem::Policy::kProduct; - overlayable_item.policies |= OverlayableItem::Policy::kProductServices; + overlayable_item.policies |= OverlayableItem::Policy::kVendor; overlayable_item.comment = "comment"; overlayable_item.source = Source("res/values/overlayable.xml", 42); @@ -265,7 +265,7 @@ TEST(ResourceTableTest, SetOverlayable) { EXPECT_THAT(result_overlayable_item.overlayable->source.path, Eq("res/values/overlayable.xml")); EXPECT_THAT(result_overlayable_item.overlayable->source.line, 40); EXPECT_THAT(result_overlayable_item.policies, Eq(OverlayableItem::Policy::kProduct - | OverlayableItem::Policy::kProductServices)); + | OverlayableItem::Policy::kVendor)); ASSERT_THAT(result_overlayable_item.comment, StrEq("comment")); EXPECT_THAT(result_overlayable_item.source.path, Eq("res/values/overlayable.xml")); EXPECT_THAT(result_overlayable_item.source.line, 42); diff --git a/tools/aapt2/ResourceUtils.cpp b/tools/aapt2/ResourceUtils.cpp index c6f91527c91c..ab4805f626a5 100644 --- a/tools/aapt2/ResourceUtils.cpp +++ b/tools/aapt2/ResourceUtils.cpp @@ -16,6 +16,7 @@ #include "ResourceUtils.h" +#include <algorithm> #include <sstream> #include "android-base/stringprintf.h" @@ -503,6 +504,14 @@ Maybe<int> ParseSdkVersion(const StringPiece& str) { if (entry.first == trimmed_str) { return entry.second; } + + // Try parsing codename from "[codename].[preview_sdk_fingerprint]" value. + const StringPiece::const_iterator begin = std::begin(trimmed_str); + const StringPiece::const_iterator end = std::end(trimmed_str); + const StringPiece::const_iterator codename_end = std::find(begin, end, '.'); + if (codename_end != end && entry.first == trimmed_str.substr(begin, codename_end)) { + return entry.second; + } return {}; } diff --git a/tools/aapt2/ResourceUtils_test.cpp b/tools/aapt2/ResourceUtils_test.cpp index 5ce464074335..9018b0fc372a 100644 --- a/tools/aapt2/ResourceUtils_test.cpp +++ b/tools/aapt2/ResourceUtils_test.cpp @@ -16,6 +16,7 @@ #include "ResourceUtils.h" +#include "SdkConstants.h" #include "Resource.h" #include "test/Test.h" @@ -212,6 +213,17 @@ TEST(ResourceUtilsTest, ItemsWithWhitespaceAreParsedCorrectly) { Pointee(ValueEq(BinaryPrimitive(Res_value::TYPE_FLOAT, expected_float_flattened)))); } +TEST(ResourceUtilsTest, ParseSdkVersionWithCodename) { + const android::StringPiece codename = + GetDevelopmentSdkCodeNameAndVersion().first; + const int version = GetDevelopmentSdkCodeNameAndVersion().second; + + EXPECT_THAT(ResourceUtils::ParseSdkVersion(codename), Eq(Maybe<int>(version))); + EXPECT_THAT( + ResourceUtils::ParseSdkVersion(codename.to_string() + ".fingerprint"), + Eq(Maybe<int>(version))); +} + TEST(ResourceUtilsTest, StringBuilderWhitespaceRemoval) { EXPECT_THAT(ResourceUtils::StringBuilder() .AppendText(" hey guys ") diff --git a/tools/aapt2/Resources.proto b/tools/aapt2/Resources.proto index da541be9502b..73b568e77689 100644 --- a/tools/aapt2/Resources.proto +++ b/tools/aapt2/Resources.proto @@ -155,7 +155,6 @@ message OverlayableItem { SYSTEM = 1; VENDOR = 2; PRODUCT = 3; - PRODUCT_SERVICES = 4; } // The location of the <item> declaration in source. diff --git a/tools/aapt2/cmd/Compile.cpp b/tools/aapt2/cmd/Compile.cpp index 52375a39b93f..92beb4eb7ce4 100644 --- a/tools/aapt2/cmd/Compile.cpp +++ b/tools/aapt2/cmd/Compile.cpp @@ -701,7 +701,10 @@ int Compile(IAaptContext* context, io::IFileCollection* inputs, IArchiveWriter* } const std::string out_path = BuildIntermediateContainerFilename(path_data); - error |= !compile_func(context, options, path_data, file, output_writer, out_path); + if (!compile_func(context, options, path_data, file, output_writer, out_path)) { + context->GetDiagnostics()->Error(DiagMessage(file->GetSource()) << "file failed to compile"); + error = true; + } } return error ? 1 : 0; diff --git a/tools/aapt2/format/binary/BinaryResourceParser.cpp b/tools/aapt2/format/binary/BinaryResourceParser.cpp index 7d4c6f348403..40aaa05c2b30 100644 --- a/tools/aapt2/format/binary/BinaryResourceParser.cpp +++ b/tools/aapt2/format/binary/BinaryResourceParser.cpp @@ -473,10 +473,6 @@ bool BinaryResourceParser::ParseOverlayable(const ResChunk_header* chunk) { & ResTable_overlayable_policy_header::POLICY_PRODUCT_PARTITION) { policies |= OverlayableItem::Policy::kProduct; } - if (policy_header->policy_flags - & ResTable_overlayable_policy_header::POLICY_PRODUCT_SERVICES_PARTITION) { - policies |= OverlayableItem::Policy::kProductServices; - } const ResTable_ref* const ref_begin = reinterpret_cast<const ResTable_ref*>( ((uint8_t *)policy_header) + util::DeviceToHost32(policy_header->header.headerSize)); diff --git a/tools/aapt2/format/binary/TableFlattener.cpp b/tools/aapt2/format/binary/TableFlattener.cpp index c4ecbafc008b..9d341cc1ca4a 100644 --- a/tools/aapt2/format/binary/TableFlattener.cpp +++ b/tools/aapt2/format/binary/TableFlattener.cpp @@ -485,9 +485,6 @@ class PackageFlattener { if (item.policies & OverlayableItem::Policy::kProduct) { policy_flags |= ResTable_overlayable_policy_header::POLICY_PRODUCT_PARTITION; } - if (item.policies & OverlayableItem::Policy::kProductServices) { - policy_flags |= ResTable_overlayable_policy_header::POLICY_PRODUCT_SERVICES_PARTITION; - } } auto policy = overlayable_chunk->policy_ids.find(policy_flags); diff --git a/tools/aapt2/format/binary/TableFlattener_test.cpp b/tools/aapt2/format/binary/TableFlattener_test.cpp index 18fecf60c977..ddc117399390 100644 --- a/tools/aapt2/format/binary/TableFlattener_test.cpp +++ b/tools/aapt2/format/binary/TableFlattener_test.cpp @@ -660,12 +660,10 @@ TEST_F(TableFlattenerTest, FlattenMultipleOverlayablePolicies) { OverlayableItem overlayable_item_zero(overlayable); overlayable_item_zero.policies |= OverlayableItem::Policy::kProduct; overlayable_item_zero.policies |= OverlayableItem::Policy::kSystem; - overlayable_item_zero.policies |= OverlayableItem::Policy::kProductServices; std::string name_one = "com.app.test:integer/overlayable_one_item"; OverlayableItem overlayable_item_one(overlayable); overlayable_item_one.policies |= OverlayableItem::Policy::kPublic; - overlayable_item_one.policies |= OverlayableItem::Policy::kProductServices; std::string name_two = "com.app.test:integer/overlayable_two_item"; OverlayableItem overlayable_item_two(overlayable); @@ -698,16 +696,14 @@ TEST_F(TableFlattenerTest, FlattenMultipleOverlayablePolicies) { ASSERT_TRUE(search_result.value().entry->overlayable_item); OverlayableItem& overlayable_item = search_result.value().entry->overlayable_item.value(); EXPECT_EQ(overlayable_item.policies, OverlayableItem::Policy::kSystem - | OverlayableItem::Policy::kProduct - | OverlayableItem::Policy::kProductServices); + | OverlayableItem::Policy::kProduct); search_result = output_table.FindResource(test::ParseNameOrDie(name_one)); ASSERT_TRUE(search_result); ASSERT_THAT(search_result.value().entry, NotNull()); ASSERT_TRUE(search_result.value().entry->overlayable_item); overlayable_item = search_result.value().entry->overlayable_item.value(); - EXPECT_EQ(overlayable_item.policies, OverlayableItem::Policy::kPublic - | OverlayableItem::Policy::kProductServices); + EXPECT_EQ(overlayable_item.policies, OverlayableItem::Policy::kPublic); search_result = output_table.FindResource(test::ParseNameOrDie(name_two)); ASSERT_TRUE(search_result); @@ -735,13 +731,11 @@ TEST_F(TableFlattenerTest, FlattenMultipleOverlayable) { OverlayableItem overlayable_item_zero(group); overlayable_item_zero.policies |= OverlayableItem::Policy::kProduct; overlayable_item_zero.policies |= OverlayableItem::Policy::kSystem; - overlayable_item_zero.policies |= OverlayableItem::Policy::kProductServices; auto group_one = std::make_shared<Overlayable>("OtherName", "overlay://customization"); std::string name_one = "com.app.test:integer/overlayable_one"; OverlayableItem overlayable_item_one(group_one); overlayable_item_one.policies |= OverlayableItem::Policy::kPublic; - overlayable_item_one.policies |= OverlayableItem::Policy::kProductServices; std::string name_two = "com.app.test:integer/overlayable_two"; OverlayableItem overlayable_item_two(group); @@ -773,8 +767,7 @@ TEST_F(TableFlattenerTest, FlattenMultipleOverlayable) { EXPECT_EQ(result_overlayable.overlayable->name, "TestName"); EXPECT_EQ(result_overlayable.overlayable->actor, "overlay://theme"); EXPECT_EQ(result_overlayable.policies, OverlayableItem::Policy::kSystem - | OverlayableItem::Policy::kProduct - | OverlayableItem::Policy::kProductServices); + | OverlayableItem::Policy::kProduct); search_result = output_table.FindResource(test::ParseNameOrDie(name_one)); ASSERT_TRUE(search_result); ASSERT_THAT(search_result.value().entry, NotNull()); @@ -782,8 +775,7 @@ TEST_F(TableFlattenerTest, FlattenMultipleOverlayable) { result_overlayable = search_result.value().entry->overlayable_item.value(); EXPECT_EQ(result_overlayable.overlayable->name, "OtherName"); EXPECT_EQ(result_overlayable.overlayable->actor, "overlay://customization"); - EXPECT_EQ(result_overlayable.policies, OverlayableItem::Policy::kPublic - | OverlayableItem::Policy::kProductServices); + EXPECT_EQ(result_overlayable.policies, OverlayableItem::Policy::kPublic); search_result = output_table.FindResource(test::ParseNameOrDie(name_two)); ASSERT_TRUE(search_result); ASSERT_THAT(search_result.value().entry, NotNull()); diff --git a/tools/aapt2/format/proto/ProtoDeserialize.cpp b/tools/aapt2/format/proto/ProtoDeserialize.cpp index 6b5746d63bf8..aff1b391f861 100644 --- a/tools/aapt2/format/proto/ProtoDeserialize.cpp +++ b/tools/aapt2/format/proto/ProtoDeserialize.cpp @@ -390,9 +390,6 @@ bool DeserializeOverlayableItemFromPb(const pb::OverlayableItem& pb_overlayable, case pb::OverlayableItem::PRODUCT: out_overlayable->policies |= OverlayableItem::Policy::kProduct; break; - case pb::OverlayableItem::PRODUCT_SERVICES: - out_overlayable->policies |= OverlayableItem::Policy::kProductServices; - break; default: *out_error = "unknown overlayable policy"; return false; diff --git a/tools/aapt2/format/proto/ProtoSerialize.cpp b/tools/aapt2/format/proto/ProtoSerialize.cpp index 76fbb464b62a..b549e2369f98 100644 --- a/tools/aapt2/format/proto/ProtoSerialize.cpp +++ b/tools/aapt2/format/proto/ProtoSerialize.cpp @@ -303,9 +303,6 @@ static void SerializeOverlayableItemToPb(const OverlayableItem& overlayable_item if (overlayable_item.policies & OverlayableItem::Policy::kProduct) { pb_overlayable_item->add_policy(pb::OverlayableItem::PRODUCT); } - if (overlayable_item.policies & OverlayableItem::Policy::kProductServices) { - pb_overlayable_item->add_policy(pb::OverlayableItem::PRODUCT_SERVICES); - } if (overlayable_item.policies & OverlayableItem::Policy::kSystem) { pb_overlayable_item->add_policy(pb::OverlayableItem::SYSTEM); } diff --git a/tools/aapt2/format/proto/ProtoSerialize_test.cpp b/tools/aapt2/format/proto/ProtoSerialize_test.cpp index 4a3c1b86236e..cce3939704cf 100644 --- a/tools/aapt2/format/proto/ProtoSerialize_test.cpp +++ b/tools/aapt2/format/proto/ProtoSerialize_test.cpp @@ -519,7 +519,7 @@ TEST(ProtoSerializeTest, SerializeAndDeserializeOverlayable) { OverlayableItem overlayable_item_bar(std::make_shared<Overlayable>( "TaskBar", "overlay://theme")); - overlayable_item_bar.policies |= OverlayableItem::Policy::kProductServices; + overlayable_item_bar.policies |= OverlayableItem::Policy::kPublic; overlayable_item_bar.policies |= OverlayableItem::Policy::kVendor; OverlayableItem overlayable_item_baz(std::make_shared<Overlayable>( @@ -565,7 +565,7 @@ TEST(ProtoSerializeTest, SerializeAndDeserializeOverlayable) { overlayable_item = search_result.value().entry->overlayable_item.value(); EXPECT_THAT(overlayable_item.overlayable->name, Eq("TaskBar")); EXPECT_THAT(overlayable_item.overlayable->actor, Eq("overlay://theme")); - EXPECT_THAT(overlayable_item.policies, Eq(OverlayableItem::Policy::kProductServices + EXPECT_THAT(overlayable_item.policies, Eq(OverlayableItem::Policy::kPublic | OverlayableItem::Policy::kVendor)); search_result = new_table.FindResource(test::ParseNameOrDie("com.app.a:bool/baz")); diff --git a/tools/aapt2/link/TableMerger_test.cpp b/tools/aapt2/link/TableMerger_test.cpp index 921d634e583e..ad3674e16774 100644 --- a/tools/aapt2/link/TableMerger_test.cpp +++ b/tools/aapt2/link/TableMerger_test.cpp @@ -484,7 +484,7 @@ TEST_F(TableMergerTest, SetOverlayableLater) { OverlayableItem overlayable_item(overlayable); overlayable_item.policies |= OverlayableItem::Policy::kPublic; - overlayable_item.policies |= OverlayableItem::Policy::kProductServices; + overlayable_item.policies |= OverlayableItem::Policy::kSystem; std::unique_ptr<ResourceTable> table_b = test::ResourceTableBuilder() .SetPackageId("com.app.a", 0x7f) @@ -506,7 +506,7 @@ TEST_F(TableMergerTest, SetOverlayableLater) { EXPECT_THAT(result_overlayable_item.overlayable->name, Eq("CustomizableResources")); EXPECT_THAT(result_overlayable_item.overlayable->actor, Eq("overlay://customization")); EXPECT_THAT(result_overlayable_item.policies, Eq(OverlayableItem::Policy::kPublic - | OverlayableItem::Policy::kProductServices)); + | OverlayableItem::Policy::kSystem)); } TEST_F(TableMergerTest, SameResourceDifferentNameFail) { diff --git a/tools/processors/view_inspector/Android.bp b/tools/processors/view_inspector/Android.bp index ca6b3c4572f5..9b5df56e3987 100644 --- a/tools/processors/view_inspector/Android.bp +++ b/tools/processors/view_inspector/Android.bp @@ -5,7 +5,7 @@ java_library_host { java_resource_dirs: ["src/resources"], static_libs: [ - "javapoet", + "javapoet", ], use_tools_jar: true, @@ -18,9 +18,9 @@ java_test_host { java_resource_dirs: ["test/resources"], static_libs: [ - "guava", "junit", - "view-inspector-annotation-processor", + "guava", + "view-inspector-annotation-processor" ], test_suites: ["general-tests"], diff --git a/tools/processors/view_inspector/TEST_MAPPING b/tools/processors/view_inspector/TEST_MAPPING index a91b5b452c39..b4c9cab6916e 100644 --- a/tools/processors/view_inspector/TEST_MAPPING +++ b/tools/processors/view_inspector/TEST_MAPPING @@ -2,6 +2,8 @@ "presubmit": [ { "name": "view-inspector-annotation-processor-test" + }, { + "name": "CtsViewInspectorAnnotationProcessorTestCases" } ] } diff --git a/tools/processors/view_inspector/src/java/android/processor/view/inspector/AnnotationUtils.java b/tools/processors/view_inspector/src/java/android/processor/view/inspector/AnnotationUtils.java index f157949f4d1b..fc4cd01a5a2a 100644 --- a/tools/processors/view_inspector/src/java/android/processor/view/inspector/AnnotationUtils.java +++ b/tools/processors/view_inspector/src/java/android/processor/view/inspector/AnnotationUtils.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2018 The Android Open Source Project + * Copyright 2019 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -24,6 +24,7 @@ import javax.lang.model.element.AnnotationMirror; import javax.lang.model.element.AnnotationValue; import javax.lang.model.element.Element; import javax.lang.model.element.ExecutableElement; +import javax.lang.model.element.TypeElement; import javax.lang.model.type.TypeMirror; import javax.lang.model.util.Elements; import javax.lang.model.util.Types; @@ -78,40 +79,126 @@ final class AnnotationUtils { } /** - * Extract a string-valued property from an {@link AnnotationMirror}. + * Determine if an annotation with the supplied qualified name is present on the element. * - * @param propertyName The name of the requested property - * @param annotationMirror The mirror to search for the property - * @return The String value of the annotation or null + * @param element The element to check for the presence of an annotation + * @param annotationQualifiedName The name of the annotation to check for + * @return True if the annotation is present, false otherwise */ - Optional<String> stringProperty(String propertyName, AnnotationMirror annotationMirror) { - final AnnotationValue value = valueByName(propertyName, annotationMirror); - if (value != null) { - return Optional.of((String) value.getValue()); - } else { - return Optional.empty(); + boolean hasAnnotation(Element element, String annotationQualifiedName) { + final TypeElement namedElement = mElementUtils.getTypeElement(annotationQualifiedName); + + if (namedElement != null) { + final TypeMirror annotationType = namedElement.asType(); + + for (AnnotationMirror annotation : element.getAnnotationMirrors()) { + if (mTypeUtils.isSubtype(annotation.getAnnotationType(), annotationType)) { + return true; + } + } } + + return false; } + /** + * Get the typed value of an annotation property by name. + * + * The returned optional will be empty if the value was left at the default, or if the value + * of the property is null. + * + * @param propertyName The name of the property to search for + * @param valueClass The expected class of the property value + * @param element The element the annotation is on, used for exceptions + * @param annotationMirror An annotation mirror to search for the property + * @param <T> The type of the value + * @return An optional containing the typed value of the named property + */ + <T> Optional<T> typedValueByName( + String propertyName, + Class<T> valueClass, + Element element, + AnnotationMirror annotationMirror) { + return valueByName(propertyName, annotationMirror).map(annotationValue -> { + final Object value = annotationValue.getValue(); + + if (value == null) { + throw new ProcessingException( + String.format( + "Unexpected null value for annotation property \"%s\".", + propertyName), + element, + annotationMirror, + annotationValue); + } + + if (valueClass.isAssignableFrom(value.getClass())) { + return valueClass.cast(value); + } else { + throw new ProcessingException( + String.format( + "Expected annotation property \"%s\" to have type %s, but got %s.", + propertyName, + valueClass.getCanonicalName(), + value.getClass().getCanonicalName()), + element, + annotationMirror, + annotationValue); + } + }); + } + + /** + * Get the untyped value of an annotation property by name. + * + * The returned optional will be empty if the value was left at the default, or if the value + * of the property is null. + * + * @param propertyName The name of the property to search for + * @param element The element the annotation is on, used for exceptions + * @param annotationMirror An annotation mirror to search for the property + * @return An optional containing the untyped value of the named property + * @see AnnotationValue#getValue() + */ + Optional<Object> untypedValueByName( + String propertyName, + Element element, + AnnotationMirror annotationMirror) { + return valueByName(propertyName, annotationMirror).map(annotationValue -> { + final Object value = annotationValue.getValue(); + + if (value == null) { + throw new ProcessingException( + String.format( + "Unexpected null value for annotation property \"%s\".", + propertyName), + element, + annotationMirror, + annotationValue); + } + + return value; + }); + } /** * Extract a {@link AnnotationValue} from a mirror by string property name. * * @param propertyName The name of the property requested property - * @param annotationMirror - * @return + * @param annotationMirror The mirror to search for the property + * @return The value of the property */ - AnnotationValue valueByName(String propertyName, AnnotationMirror annotationMirror) { + Optional<AnnotationValue> valueByName(String propertyName, AnnotationMirror annotationMirror) { final Map<? extends ExecutableElement, ? extends AnnotationValue> valueMap = annotationMirror.getElementValues(); for (ExecutableElement method : valueMap.keySet()) { if (method.getSimpleName().contentEquals(propertyName)) { - return valueMap.get(method); + return Optional.ofNullable(valueMap.get(method)); } } - return null; + // Property not explicitly defined, use default value. + return Optional.empty(); } - } diff --git a/tools/processors/view_inspector/src/java/android/processor/view/inspector/InspectableClassModel.java b/tools/processors/view_inspector/src/java/android/processor/view/inspector/InspectableClassModel.java index 579745d2aaef..f1ebb87fed4d 100644 --- a/tools/processors/view_inspector/src/java/android/processor/view/inspector/InspectableClassModel.java +++ b/tools/processors/view_inspector/src/java/android/processor/view/inspector/InspectableClassModel.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2018 The Android Open Source Project + * Copyright 2019 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -21,6 +21,7 @@ import com.squareup.javapoet.ClassName; import java.util.Collection; import java.util.HashMap; import java.util.Map; +import java.util.Objects; import java.util.Optional; /** @@ -70,7 +71,7 @@ public final class InspectableClassModel { * @return The property or an empty optional */ public Optional<Property> getProperty(String name) { - return Optional.of(mPropertyMap.get(name)); + return Optional.ofNullable(mPropertyMap.get(name)); } /** @@ -87,13 +88,15 @@ public final class InspectableClassModel { */ public static final class Property { private final String mName; - private String mGetter; - private Type mType; + private final String mGetter; + private final Type mType; private boolean mAttributeIdInferrableFromR = true; private int mAttributeId = 0; - public Property(String name) { - mName = name; + public Property(String name, String getter, Type type) { + mName = Objects.requireNonNull(name, "Name must not be null"); + mGetter = Objects.requireNonNull(getter, "Getter must not be null"); + mType = Objects.requireNonNull(type, "Type must not be null"); } public int getAttributeId() { @@ -126,18 +129,10 @@ public final class InspectableClassModel { return mGetter; } - public void setGetter(String getter) { - mGetter = getter; - } - public Type getType() { return mType; } - public void setType(Type type) { - mType = type; - } - public enum Type { /** Primitive or boxed {@code boolean} */ BOOLEAN, diff --git a/tools/processors/view_inspector/src/java/android/processor/view/inspector/InspectableNodeNameProcessor.java b/tools/processors/view_inspector/src/java/android/processor/view/inspector/InspectableNodeNameProcessor.java index a186a82af160..46819b28c1e8 100644 --- a/tools/processors/view_inspector/src/java/android/processor/view/inspector/InspectableNodeNameProcessor.java +++ b/tools/processors/view_inspector/src/java/android/processor/view/inspector/InspectableNodeNameProcessor.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2018 The Android Open Source Project + * Copyright 2019 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -23,7 +23,7 @@ import javax.lang.model.element.AnnotationMirror; import javax.lang.model.element.Element; /** - * Process {InspectableNodeName} annotations + * Process {@code @InspectableNodeName} annotations. * * @see android.view.inspector.InspectableNodeName */ @@ -58,7 +58,8 @@ public final class InspectableNodeNameProcessor implements ModelProcessor { try { final AnnotationMirror mirror = mAnnotationUtils.exactlyOneMirror(mQualifiedName, element); - final Optional<String> nodeName = mAnnotationUtils.stringProperty("value", mirror); + final Optional<String> nodeName = mAnnotationUtils + .typedValueByName("value", String.class, element, mirror); if (!model.getNodeName().isPresent() || model.getNodeName().equals(nodeName)) { model.setNodeName(nodeName); diff --git a/tools/processors/view_inspector/src/java/android/processor/view/inspector/InspectablePropertyProcessor.java b/tools/processors/view_inspector/src/java/android/processor/view/inspector/InspectablePropertyProcessor.java new file mode 100644 index 000000000000..f666be7a2a61 --- /dev/null +++ b/tools/processors/view_inspector/src/java/android/processor/view/inspector/InspectablePropertyProcessor.java @@ -0,0 +1,408 @@ +/* + * Copyright 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.processor.view.inspector; + +import android.processor.view.inspector.InspectableClassModel.Property; + +import java.util.Set; +import java.util.regex.Pattern; + +import javax.annotation.processing.ProcessingEnvironment; +import javax.lang.model.element.AnnotationMirror; +import javax.lang.model.element.Element; +import javax.lang.model.element.ElementKind; +import javax.lang.model.element.ExecutableElement; +import javax.lang.model.element.Modifier; +import javax.lang.model.element.TypeElement; +import javax.lang.model.type.NoType; +import javax.lang.model.type.TypeKind; +import javax.lang.model.type.TypeMirror; + +/** + * Process {@code @InspectableProperty} annotations. + * + * @see android.view.inspector.InspectableProperty + */ +public final class InspectablePropertyProcessor implements ModelProcessor { + private final String mQualifiedName; + private final ProcessingEnvironment mProcessingEnv; + private final AnnotationUtils mAnnotationUtils; + + /** + * Regex that matches methods names of the form {@code #getValue()}. + */ + private static final Pattern GETTER_GET_PREFIX = Pattern.compile("\\Aget[A-Z]"); + + /** + * Regex that matches method name of the form {@code #isPredicate()}. + */ + private static final Pattern GETTER_IS_PREFIX = Pattern.compile("\\Ais[A-Z]"); + + /** + * Set of android and androidx annotation qualified names for colors packed into {@code int}. + * + * @see android.annotation.ColorInt + */ + private static final String[] COLOR_INT_ANNOTATION_NAMES = { + "android.annotation.ColorInt", + "androidx.annotation.ColorInt"}; + + /** + * Set of android and androidx annotation qualified names for colors packed into {@code long}. + * @see android.annotation.ColorLong + */ + private static final String[] COLOR_LONG_ANNOTATION_NAMES = { + "android.annotation.ColorLong", + "androidx.annotation.ColorLong"}; + + /** + * @param annotationQualifiedName The qualified name of the annotation to process + * @param processingEnv The processing environment from the parent processor + */ + public InspectablePropertyProcessor( + String annotationQualifiedName, + ProcessingEnvironment processingEnv) { + mQualifiedName = annotationQualifiedName; + mProcessingEnv = processingEnv; + mAnnotationUtils = new AnnotationUtils(processingEnv); + } + + @Override + public void process(Element element, InspectableClassModel model) { + try { + final AnnotationMirror annotation = + mAnnotationUtils.exactlyOneMirror(mQualifiedName, element); + final ExecutableElement getter = ensureGetter(element); + final Property property = buildProperty(getter, annotation); + + model.getProperty(property.getName()).ifPresent(p -> { + throw new ProcessingException( + String.format( + "Property \"%s\" is already defined on #%s().", + p.getName(), + p.getGetter()), + getter, + annotation); + }); + + model.putProperty(property); + } catch (ProcessingException processingException) { + processingException.print(mProcessingEnv.getMessager()); + } + } + + /** + * Check that an element is shaped like a getter. + * + * @param element An element that hopefully represents a getter + * @throws ProcessingException if the element isn't a getter + * @return An {@link ExecutableElement} that represents a getter method. + */ + private ExecutableElement ensureGetter(Element element) { + if (element.getKind() != ElementKind.METHOD) { + throw new ProcessingException( + String.format("Expected a method, got a %s", element.getKind()), + element); + } + + final ExecutableElement method = (ExecutableElement) element; + final Set<Modifier> modifiers = method.getModifiers(); + + if (modifiers.contains(Modifier.PRIVATE)) { + throw new ProcessingException( + "Property getter methods must not be private.", + element); + } + + if (modifiers.contains(Modifier.ABSTRACT)) { + throw new ProcessingException( + "Property getter methods must not be abstract.", + element); + } + + if (modifiers.contains(Modifier.STATIC)) { + throw new ProcessingException( + "Property getter methods must not be static.", + element); + } + + if (!method.getParameters().isEmpty()) { + throw new ProcessingException( + String.format( + "Expected a getter method to take no parameters, " + + "but got %d parameters.", + method.getParameters().size()), + element); + } + + if (method.isVarArgs()) { + throw new ProcessingException( + "Expected a getter method to take no arguments, but got a var args method.", + element); + } + + if (method.getReturnType() instanceof NoType) { + throw new ProcessingException( + "Expected a getter to have a return type, got void.", + element); + } + + return method; + } + + /** + * Build a {@link Property} from a getter and an inspectable property annotation. + * + * @param getter An element representing the getter to build from + * @param annotation A mirror of an inspectable property-shaped annotation + * @throws ProcessingException If the supplied data is invalid and a property cannot be modeled + * @return A property for the getter and annotation + */ + private Property buildProperty(ExecutableElement getter, AnnotationMirror annotation) { + final String name = mAnnotationUtils + .typedValueByName("name", String.class, getter, annotation) + .orElseGet(() -> inferPropertyNameFromGetter(getter)); + + final Property property = new Property( + name, + getter.getSimpleName().toString(), + determinePropertyType(getter, annotation)); + + mAnnotationUtils + .typedValueByName("hasAttributeId", Boolean.class, getter, annotation) + .ifPresent(property::setAttributeIdInferrableFromR); + + mAnnotationUtils + .typedValueByName("attributeId", Integer.class, getter, annotation) + .ifPresent(property::setAttributeId); + + return property; + } + + /** + * Determine the property type from the annotation, return type, or context clues. + * + * @param getter An element representing the getter to build from + * @param annotation A mirror of an inspectable property-shaped annotation + * @return The resolved property type + * @throws ProcessingException If the property type cannot be resolved + * @see android.view.inspector.InspectableProperty#valueType() + */ + private Property.Type determinePropertyType( + ExecutableElement getter, + AnnotationMirror annotation) { + + final String valueType = mAnnotationUtils + .untypedValueByName("valueType", getter, annotation) + .map(Object::toString) + .orElse("INFERRED"); + + final Property.Type returnType = convertReturnTypeToPropertyType(getter); + + switch (valueType) { + case "INFERRED": + if (hasColorAnnotation(getter)) { + return Property.Type.COLOR; + } else { + return returnType; + } + case "NONE": + return returnType; + case "COLOR": + switch (returnType) { + case COLOR: + case INT: + case LONG: + return Property.Type.COLOR; + default: + throw new ProcessingException( + "Color must be a long, integer, or android.graphics.Color", + getter, + annotation); + } + case "GRAVITY": + if (returnType == Property.Type.INT) { + return Property.Type.GRAVITY; + } else { + throw new ProcessingException( + String.format("Gravity must be an integer, got %s", returnType), + getter, + annotation); + } + case "INT_ENUM": + case "INT_FLAG": + throw new ProcessingException("Not implemented", getter, annotation); + default: + throw new ProcessingException( + String.format("Unknown value type enumeration value: %s", valueType), + getter, + annotation); + } + } + + /** + * Get a property type from the return type of a getter. + * + * @param getter The getter to extract the return type of + * @throws ProcessingException If the return type is not a primitive or an object + * @return The property type returned by the getter + */ + private Property.Type convertReturnTypeToPropertyType(ExecutableElement getter) { + final TypeMirror returnType = getter.getReturnType(); + + switch (unboxType(returnType)) { + case BOOLEAN: + return Property.Type.BOOLEAN; + case BYTE: + return Property.Type.BYTE; + case CHAR: + return Property.Type.CHAR; + case DOUBLE: + return Property.Type.DOUBLE; + case FLOAT: + return Property.Type.FLOAT; + case INT: + return Property.Type.INT; + case LONG: + return Property.Type.LONG; + case SHORT: + return Property.Type.SHORT; + case DECLARED: + if (isColorType(returnType)) { + return Property.Type.COLOR; + } else { + return Property.Type.OBJECT; + } + default: + throw new ProcessingException( + String.format("Unsupported return type %s.", returnType), + getter); + } + } + + /** + * Determine if a getter is annotated with color annotation matching its return type. + * + * Note that an {@code int} return value annotated with {@link android.annotation.ColorLong} is + * not considered to be annotated, nor is a {@code long} annotated with + * {@link android.annotation.ColorInt}. + * + * @param getter The getter to query + * @return True if the getter has a color annotation, false otherwise + * + */ + private boolean hasColorAnnotation(ExecutableElement getter) { + switch (unboxType(getter.getReturnType())) { + case INT: + for (String name : COLOR_INT_ANNOTATION_NAMES) { + if (mAnnotationUtils.hasAnnotation(getter, name)) { + return true; + } + } + return false; + case LONG: + for (String name : COLOR_LONG_ANNOTATION_NAMES) { + if (mAnnotationUtils.hasAnnotation(getter, name)) { + return true; + } + } + return false; + default: + return false; + } + } + + /** + * Infer a property name from a getter method. + * + * If the method is prefixed with {@code get}, the prefix will be stripped, and the + * capitalization fixed. E.g.: {@code getSomeProperty} to {@code someProperty}. + * + * Additionally, if the method's return type is a boolean, an {@code is} prefix will also be + * stripped. E.g.: {@code isPropertyEnabled} to {@code propertyEnabled}. + * + * Failing that, this method will just return the full name of the getter. + * + * @param getter An element representing a getter + * @return A string property name + */ + private String inferPropertyNameFromGetter(ExecutableElement getter) { + final String name = getter.getSimpleName().toString(); + + if (GETTER_GET_PREFIX.matcher(name).find()) { + return name.substring(3, 4).toLowerCase() + name.substring(4); + } else if (isBoolean(getter.getReturnType()) && GETTER_IS_PREFIX.matcher(name).find()) { + return name.substring(2, 3).toLowerCase() + name.substring(3); + } else { + return name; + } + } + + /** + * Determine if a {@link TypeMirror} is a boxed or unboxed boolean. + * + * @param type The type mirror to check + * @return True if the type is a boolean + */ + private boolean isBoolean(TypeMirror type) { + if (type.getKind() == TypeKind.DECLARED) { + return mProcessingEnv.getTypeUtils().unboxedType(type).getKind() == TypeKind.BOOLEAN; + } else { + return type.getKind() == TypeKind.BOOLEAN; + } + } + + /** + * Unbox a type mirror if it represents a boxed type, otherwise pass it through. + * + * @param typeMirror The type mirror to unbox + * @return The same type mirror, or an unboxed primitive version + */ + private TypeKind unboxType(TypeMirror typeMirror) { + final TypeKind typeKind = typeMirror.getKind(); + + if (typeKind.isPrimitive()) { + return typeKind; + } else if (typeKind == TypeKind.DECLARED) { + try { + return mProcessingEnv.getTypeUtils().unboxedType(typeMirror).getKind(); + } catch (IllegalArgumentException e) { + return typeKind; + } + } else { + return typeKind; + } + } + + /** + * Determine if a type mirror represents a subtype of {@link android.graphics.Color}. + * + * @param typeMirror The type mirror to test + * @return True if it represents a subclass of color, false otherwise + */ + private boolean isColorType(TypeMirror typeMirror) { + final TypeElement colorType = mProcessingEnv + .getElementUtils() + .getTypeElement("android.graphics.Color"); + + if (colorType == null) { + return false; + } else { + return mProcessingEnv.getTypeUtils().isSubtype(typeMirror, colorType.asType()); + } + } +} diff --git a/tools/processors/view_inspector/src/java/android/processor/view/inspector/InspectionCompanionGenerator.java b/tools/processors/view_inspector/src/java/android/processor/view/inspector/InspectionCompanionGenerator.java index 3b85dbb77d5c..dd4d8f54fb68 100644 --- a/tools/processors/view_inspector/src/java/android/processor/view/inspector/InspectionCompanionGenerator.java +++ b/tools/processors/view_inspector/src/java/android/processor/view/inspector/InspectionCompanionGenerator.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2018 The Android Open Source Project + * Copyright 2019 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -51,12 +51,6 @@ public final class InspectionCompanionGenerator { private static final ClassName R_CLASS_NAME = ClassName.get("android", "R"); /** - * The class name of {@link android.content.res.ResourceId}. - */ - private static final ClassName RESOURCE_ID_CLASS_NAME = ClassName.get( - "android.content.res", "ResourceId"); - - /** * The class name of {@link android.view.inspector.InspectionCompanion}. */ private static final ClassName INSPECTION_COMPANION = ClassName.get( @@ -91,11 +85,11 @@ public final class InspectionCompanionGenerator { private static final String GENERATED_CLASS_SUFFIX = "$$InspectionCompanion"; /** - * The null resource ID. + * The null resource ID, copied to avoid a host dependency on platform code. * - * @see android.content.res.ResourceId#ID_NULL + * @see android.content.res.Resources#ID_NULL */ - private static final int NO_ID = 0; + private static final int ID_NULL = 0; /** * @param filer A filer to write the generated source to @@ -289,8 +283,8 @@ public final class InspectionCompanionGenerator { if (property.isAttributeIdInferrableFromR()) { builder.add("$T.attr.$L", R_CLASS_NAME, property.getName()); } else { - if (property.getAttributeId() == NO_ID) { - builder.add("$T.ID_NULL", RESOURCE_ID_CLASS_NAME); + if (property.getAttributeId() == ID_NULL) { + builder.add("$L", ID_NULL); } else { builder.add("$L", String.format("0x%08x", property.getAttributeId())); } diff --git a/tools/processors/view_inspector/src/java/android/processor/view/inspector/ModelProcessor.java b/tools/processors/view_inspector/src/java/android/processor/view/inspector/ModelProcessor.java index 3ffcff8a87d3..6f522608a9b4 100644 --- a/tools/processors/view_inspector/src/java/android/processor/view/inspector/ModelProcessor.java +++ b/tools/processors/view_inspector/src/java/android/processor/view/inspector/ModelProcessor.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2018 The Android Open Source Project + * Copyright 2019 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/tools/processors/view_inspector/src/java/android/processor/view/inspector/PlatformInspectableProcessor.java b/tools/processors/view_inspector/src/java/android/processor/view/inspector/PlatformInspectableProcessor.java index e531b67d9ea2..455f5b08e49e 100644 --- a/tools/processors/view_inspector/src/java/android/processor/view/inspector/PlatformInspectableProcessor.java +++ b/tools/processors/view_inspector/src/java/android/processor/view/inspector/PlatformInspectableProcessor.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2018 The Android Open Source Project + * Copyright 2019 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -46,11 +46,14 @@ import javax.lang.model.element.TypeElement; * @see android.view.inspector.InspectableProperty */ @SupportedAnnotationTypes({ - PlatformInspectableProcessor.NODE_NAME_QUALIFIED_NAME + PlatformInspectableProcessor.NODE_NAME_QUALIFIED_NAME, + PlatformInspectableProcessor.PROPERTY_QUALIFIED_NAME }) public final class PlatformInspectableProcessor extends AbstractProcessor { static final String NODE_NAME_QUALIFIED_NAME = "android.view.inspector.InspectableNodeName"; + static final String PROPERTY_QUALIFIED_NAME = + "android.view.inspector.InspectableProperty"; @Override public SourceVersion getSupportedSourceVersion() { @@ -68,6 +71,11 @@ public final class PlatformInspectableProcessor extends AbstractProcessor { new InspectableNodeNameProcessor(NODE_NAME_QUALIFIED_NAME, processingEnv), modelMap); + } else if (annotation.getQualifiedName().contentEquals(PROPERTY_QUALIFIED_NAME)) { + runModelProcessor( + roundEnv.getElementsAnnotatedWith(annotation), + new InspectablePropertyProcessor(PROPERTY_QUALIFIED_NAME, processingEnv), + modelMap); } else { fail("Unexpected annotation type", annotation); diff --git a/tools/processors/view_inspector/src/java/android/processor/view/inspector/ProcessingException.java b/tools/processors/view_inspector/src/java/android/processor/view/inspector/ProcessingException.java index 6360e0a2de39..b4c6466b2b2f 100644 --- a/tools/processors/view_inspector/src/java/android/processor/view/inspector/ProcessingException.java +++ b/tools/processors/view_inspector/src/java/android/processor/view/inspector/ProcessingException.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2018 The Android Open Source Project + * Copyright 2019 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/tools/processors/view_inspector/src/resources/META-INF/services/javax.annotation.processing.Processor b/tools/processors/view_inspector/src/resources/META-INF/services/javax.annotation.processing.Processor index fa4f71ffd0fa..79185cc80f04 100644 --- a/tools/processors/view_inspector/src/resources/META-INF/services/javax.annotation.processing.Processor +++ b/tools/processors/view_inspector/src/resources/META-INF/services/javax.annotation.processing.Processor @@ -1 +1 @@ -android.processor.inspector.view.PlatformInspectableProcessor +android.processor.view.inspector.PlatformInspectableProcessor diff --git a/tools/processors/view_inspector/test/java/android/processor/view/inspector/InspectionCompanionGeneratorTest.java b/tools/processors/view_inspector/test/java/android/processor/view/inspector/InspectionCompanionGeneratorTest.java index f639719800f6..b0775dc77f45 100644 --- a/tools/processors/view_inspector/test/java/android/processor/view/inspector/InspectionCompanionGeneratorTest.java +++ b/tools/processors/view_inspector/test/java/android/processor/view/inspector/InspectionCompanionGeneratorTest.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2018 The Android Open Source Project + * Copyright 2019 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -20,7 +20,7 @@ import android.processor.view.inspector.InspectableClassModel.Property; import static junit.framework.Assert.assertEquals; import static junit.framework.Assert.assertNotNull; -import static junit.framework.TestCase.fail; +import static junit.framework.Assert.fail; import com.google.common.base.Charsets; import com.google.common.io.Resources; @@ -65,27 +65,28 @@ public class InspectionCompanionGeneratorTest { @Test public void testSimpleProperties() { - addProperty("boolean", Property.Type.BOOLEAN, "getBoolean"); - addProperty("byte", Property.Type.BYTE, "getByte"); - addProperty("char", Property.Type.CHAR, "getChar"); - addProperty("double", Property.Type.DOUBLE, "getDouble"); - addProperty("float", Property.Type.FLOAT, "getFloat"); - addProperty("int", Property.Type.INT, "getInt"); - addProperty("long", Property.Type.LONG, "getLong"); - addProperty("short", Property.Type.SHORT, "getShort"); - - addProperty("object", Property.Type.OBJECT, "getObject"); - addProperty("color", Property.Type.COLOR, "getColor"); - addProperty("gravity", Property.Type.GRAVITY, "getGravity"); + addProperty("boolean", "getBoolean", Property.Type.BOOLEAN); + addProperty("byte", "getByte", Property.Type.BYTE); + addProperty("char", "getChar", Property.Type.CHAR); + addProperty("double", "getDouble", Property.Type.DOUBLE); + addProperty("float", "getFloat", Property.Type.FLOAT); + addProperty("int", "getInt", Property.Type.INT); + addProperty("long", "getLong", Property.Type.LONG); + addProperty("short", "getShort", Property.Type.SHORT); + + addProperty("object", "getObject", Property.Type.OBJECT); + addProperty("color", "getColor", Property.Type.COLOR); + addProperty("gravity", "getGravity", Property.Type.GRAVITY); assertGeneratedFileEquals("SimpleProperties"); } @Test public void testNoAttributeId() { - final Property property = new Property("noAttributeProperty"); - property.setType(Property.Type.INT); - property.setGetter("getNoAttributeProperty"); + final Property property = new Property( + "noAttributeProperty", + "getNoAttributeProperty", + Property.Type.INT); property.setAttributeIdInferrableFromR(false); mModel.putProperty(property); @@ -94,19 +95,18 @@ public class InspectionCompanionGeneratorTest { @Test public void testSuppliedAttributeId() { - final Property property = new Property("suppliedAttributeProperty"); - property.setType(Property.Type.INT); - property.setGetter("getSuppliedAttributeProperty"); + final Property property = new Property( + "suppliedAttributeProperty", + "getSuppliedAttributeProperty", + Property.Type.INT); property.setAttributeId(0xdecafbad); mModel.putProperty(property); assertGeneratedFileEquals("SuppliedAttributeId"); } - private Property addProperty(String name, Property.Type type, String getter) { - final Property property = new Property(name); - property.setType(type); - property.setGetter(getter); + private Property addProperty(String name, String getter, Property.Type type) { + final Property property = new Property(name, getter, type); mModel.putProperty(property); return property; } diff --git a/tools/processors/view_inspector/test/resources/android/processor/view/inspector/InspectionCompanionGeneratorTest/NoAttributeId.java.txt b/tools/processors/view_inspector/test/resources/android/processor/view/inspector/InspectionCompanionGeneratorTest/NoAttributeId.java.txt index 277e84065fb7..23d0f7807aa5 100644 --- a/tools/processors/view_inspector/test/resources/android/processor/view/inspector/InspectionCompanionGeneratorTest/NoAttributeId.java.txt +++ b/tools/processors/view_inspector/test/resources/android/processor/view/inspector/InspectionCompanionGeneratorTest/NoAttributeId.java.txt @@ -1,6 +1,5 @@ package com.android.inspectable; -import android.content.res.ResourceId; import android.view.inspector.InspectionCompanion; import android.view.inspector.PropertyMapper; import android.view.inspector.PropertyReader; @@ -25,7 +24,7 @@ public final class TestInspectable$$InspectionCompanion implements InspectionCom @Override public void mapProperties(PropertyMapper propertyMapper) { - mNoAttributePropertyId = propertyMapper.mapInt("noAttributeProperty", ResourceId.ID_NULL); + mNoAttributePropertyId = propertyMapper.mapInt("noAttributeProperty", 0); mPropertiesMapped = true; } diff --git a/wifi/java/android/net/wifi/EasyConnectStatusCallback.java b/wifi/java/android/net/wifi/EasyConnectStatusCallback.java index 3b4a6cd7508c..b8c82fd9e0ae 100644 --- a/wifi/java/android/net/wifi/EasyConnectStatusCallback.java +++ b/wifi/java/android/net/wifi/EasyConnectStatusCallback.java @@ -101,7 +101,7 @@ public abstract class EasyConnectStatusCallback { /** * Easy Connect Failure event: General protocol failure. */ - public static final int EASY_CONNECT_EVENT_FAILURE = -7; + public static final int EASY_CONNECT_EVENT_FAILURE_GENERIC = -7; /** * Easy Connect Failure event: Feature or option is not supported. @@ -123,7 +123,7 @@ public abstract class EasyConnectStatusCallback { EASY_CONNECT_EVENT_FAILURE_CONFIGURATION, EASY_CONNECT_EVENT_FAILURE_BUSY, EASY_CONNECT_EVENT_FAILURE_TIMEOUT, - EASY_CONNECT_EVENT_FAILURE, + EASY_CONNECT_EVENT_FAILURE_GENERIC, EASY_CONNECT_EVENT_FAILURE_NOT_SUPPORTED, EASY_CONNECT_EVENT_FAILURE_INVALID_NETWORK, }) diff --git a/wifi/java/android/net/wifi/IWifiManager.aidl b/wifi/java/android/net/wifi/IWifiManager.aidl index 07f7cb39a78c..46c419130233 100644 --- a/wifi/java/android/net/wifi/IWifiManager.aidl +++ b/wifi/java/android/net/wifi/IWifiManager.aidl @@ -46,7 +46,7 @@ import android.os.WorkSource; */ interface IWifiManager { - int getSupportedFeatures(); + long getSupportedFeatures(); WifiActivityEnergyInfo reportActivityInfo(); diff --git a/wifi/java/android/net/wifi/WifiInfo.java b/wifi/java/android/net/wifi/WifiInfo.java index 840af5d5cd06..35fba3dcf7cf 100644 --- a/wifi/java/android/net/wifi/WifiInfo.java +++ b/wifi/java/android/net/wifi/WifiInfo.java @@ -16,6 +16,7 @@ package android.net.wifi; +import android.annotation.SystemApi; import android.annotation.UnsupportedAppUsage; import android.net.NetworkInfo.DetailedState; import android.net.NetworkUtils; @@ -470,6 +471,7 @@ public class WifiInfo implements Parcelable { } /** {@hide} */ + @SystemApi public boolean isOsuAp() { return mOsuAp; } diff --git a/wifi/java/android/net/wifi/WifiManager.java b/wifi/java/android/net/wifi/WifiManager.java index f7725f054317..8c00cebf6c59 100644 --- a/wifi/java/android/net/wifi/WifiManager.java +++ b/wifi/java/android/net/wifi/WifiManager.java @@ -20,6 +20,7 @@ import static android.Manifest.permission.ACCESS_COARSE_LOCATION; import static android.Manifest.permission.ACCESS_WIFI_STATE; import static android.Manifest.permission.READ_WIFI_CREDENTIAL; +import android.annotation.CallbackExecutor; import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; @@ -68,6 +69,7 @@ import java.util.List; import java.util.Map; import java.util.Set; import java.util.concurrent.CountDownLatch; +import java.util.concurrent.Executor; /** * This class provides the primary API for managing all aspects of Wi-Fi @@ -236,9 +238,11 @@ public class WifiManager { public static final int WIFI_CREDENTIAL_FORGOT = 1; /** @hide */ + @SystemApi public static final int PASSPOINT_HOME_NETWORK = 0; /** @hide */ + @SystemApi public static final int PASSPOINT_ROAMING_NETWORK = 1; /** @@ -1221,7 +1225,11 @@ public class WifiManager { * @throws UnsupportedOperationException if Passpoint is not enabled on the device. * @hide */ - @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS) + @SystemApi + @RequiresPermission(anyOf = { + android.Manifest.permission.NETWORK_SETTINGS, + android.Manifest.permission.NETWORK_SETUP_WIZARD + }) public List<Pair<WifiConfiguration, Map<Integer, List<ScanResult>>>> getAllMatchingWifiConfigs( @NonNull List<ScanResult> scanResults) { List<Pair<WifiConfiguration, Map<Integer, List<ScanResult>>>> configs = new ArrayList<>(); @@ -1260,7 +1268,11 @@ public class WifiManager { * @throws UnsupportedOperationException if Passpoint is not enabled on the device. * @hide */ - @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS) + @SystemApi + @RequiresPermission(anyOf = { + android.Manifest.permission.NETWORK_SETTINGS, + android.Manifest.permission.NETWORK_SETUP_WIZARD + }) public Map<OsuProvider, List<ScanResult>> getMatchingOsuProviders( List<ScanResult> scanResults) { try { @@ -1283,7 +1295,11 @@ public class WifiManager { * @throws UnsupportedOperationException if Passpoint is not enabled on the device. * @hide */ - @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS) + @SystemApi + @RequiresPermission(anyOf = { + android.Manifest.permission.NETWORK_SETTINGS, + android.Manifest.permission.NETWORK_SETUP_WIZARD + }) public Map<OsuProvider, PasspointConfiguration> getMatchingPasspointConfigsForOsuProviders( @NonNull Set<OsuProvider> osuProviders) { try { @@ -1729,7 +1745,13 @@ public class WifiManager { * @param fqdn The FQDN of the Passpoint configuration to be removed * @throws IllegalArgumentException if no configuration is associated with the given FQDN. * @throws UnsupportedOperationException if Passpoint is not enabled on the device. + * @deprecated This is no longer supported. */ + @Deprecated + @RequiresPermission(anyOf = { + android.Manifest.permission.NETWORK_SETTINGS, + android.Manifest.permission.NETWORK_SETUP_WIZARD + }) public void removePasspointConfiguration(String fqdn) { try { if (!mService.removePasspointConfiguration(fqdn, mContext.getOpPackageName())) { @@ -1747,7 +1769,13 @@ public class WifiManager { * * @return A list of {@link PasspointConfiguration} * @throws UnsupportedOperationException if Passpoint is not enabled on the device. + * @deprecated This is no longer supported. */ + @Deprecated + @RequiresPermission(anyOf = { + android.Manifest.permission.NETWORK_SETTINGS, + android.Manifest.permission.NETWORK_SETUP_WIZARD + }) public List<PasspointConfiguration> getPasspointConfigurations() { try { return mService.getPasspointConfigurations(); @@ -2057,7 +2085,7 @@ public class WifiManager { /** @hide */ public static final int WIFI_FEATURE_DPP = 0x80000000; // DPP (Easy-Connect) - private int getSupportedFeatures() { + private long getSupportedFeatures() { try { return mService.getSupportedFeatures(); } catch (RemoteException e) { @@ -2065,7 +2093,7 @@ public class WifiManager { } } - private boolean isFeatureSupported(int feature) { + private boolean isFeatureSupported(long feature) { return (getSupportedFeatures() & feature) == feature; } /** @@ -4325,6 +4353,11 @@ public class WifiManager { * @param callback {@link ProvisioningCallback} for updates regarding provisioning flow * @hide */ + @SystemApi + @RequiresPermission(anyOf = { + android.Manifest.permission.NETWORK_SETTINGS, + android.Manifest.permission.NETWORK_SETUP_WIZARD + }) public void startSubscriptionProvisioning(OsuProvider provider, ProvisioningCallback callback, @Nullable Handler handler) { Looper looper = (handler == null) ? Looper.getMainLooper() : handler.getLooper(); @@ -4502,9 +4535,14 @@ public class WifiManager { } /** - * @return true if this device supports Wi-Fi Device Provisioning Protocol (Easy-connect) + * Wi-Fi Easy Connect (DPP) introduces standardized mechanisms to simplify the provisioning and + * configuration of Wi-Fi devices. + * For more details, visit <a href="https://www.wi-fi.org/">https://www.wi-fi.org/</a> and + * search for "Easy Connect" or "Device Provisioning Protocol specification". + * + * @return true if this device supports Wi-Fi Easy-connect (Device Provisioning Protocol) */ - public boolean isDppSupported() { + public boolean isEasyConnectSupported() { return isFeatureSupported(WIFI_FEATURE_DPP); } @@ -4624,8 +4662,7 @@ public class WifiManager { * @param selectedNetworkId Selected network ID to be sent to the peer * @param enrolleeNetworkRole The network role of the enrollee * @param callback Callback for status updates - * @param handler The handler on whose thread to execute the callbacks. Null for - * main thread. + * @param executor The Executor on which to run the callback. * @hide */ @SystemApi @@ -4634,12 +4671,12 @@ public class WifiManager { android.Manifest.permission.NETWORK_SETUP_WIZARD}) public void startEasyConnectAsConfiguratorInitiator(@NonNull String enrolleeUri, int selectedNetworkId, @EasyConnectNetworkRole int enrolleeNetworkRole, - @Nullable Handler handler, @NonNull EasyConnectStatusCallback callback) { - Looper looper = (handler == null) ? Looper.getMainLooper() : handler.getLooper(); + @NonNull @CallbackExecutor Executor executor, + @NonNull EasyConnectStatusCallback callback) { Binder binder = new Binder(); try { mService.startDppAsConfiguratorInitiator(binder, enrolleeUri, selectedNetworkId, - enrolleeNetworkRole, new EasyConnectCallbackProxy(looper, callback)); + enrolleeNetworkRole, new EasyConnectCallbackProxy(executor, callback)); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -4652,8 +4689,7 @@ public class WifiManager { * * @param configuratorUri URI of the Configurator obtained separately (e.g. QR code scanning) * @param callback Callback for status updates - * @param handler The handler on whose thread to execute the callbacks. Null for main - * thread. + * @param executor The Executor on which to run the callback. * @hide */ @SystemApi @@ -4661,19 +4697,22 @@ public class WifiManager { android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.NETWORK_SETUP_WIZARD}) public void startEasyConnectAsEnrolleeInitiator(@NonNull String configuratorUri, - @Nullable Handler handler, @NonNull EasyConnectStatusCallback callback) { - Looper looper = (handler == null) ? Looper.getMainLooper() : handler.getLooper(); + @NonNull @CallbackExecutor Executor executor, + @NonNull EasyConnectStatusCallback callback) { Binder binder = new Binder(); try { mService.startDppAsEnrolleeInitiator(binder, configuratorUri, - new EasyConnectCallbackProxy(looper, callback)); + new EasyConnectCallbackProxy(executor, callback)); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } /** - * Stop or abort a current Easy Connect (DPP) session. + * Stop or abort a current Easy Connect (DPP) session. This call, once processed, will + * terminate any ongoing transaction, and clean up all associated resources. Caller should not + * expect any callbacks once this call is made. However, due to the asynchronous nature of + * this call, a callback may be fired if it was already pending in the queue. * * @hide */ @@ -4697,19 +4736,19 @@ public class WifiManager { */ @SystemApi private static class EasyConnectCallbackProxy extends IDppCallback.Stub { - private final Handler mHandler; + private final Executor mExecutor; private final EasyConnectStatusCallback mEasyConnectStatusCallback; - EasyConnectCallbackProxy(Looper looper, + EasyConnectCallbackProxy(Executor executor, EasyConnectStatusCallback easyConnectStatusCallback) { - mHandler = new Handler(looper); + mExecutor = executor; mEasyConnectStatusCallback = easyConnectStatusCallback; } @Override public void onSuccessConfigReceived(int newNetworkId) { Log.d(TAG, "Easy Connect onSuccessConfigReceived callback"); - mHandler.post(() -> { + mExecutor.execute(() -> { mEasyConnectStatusCallback.onEnrolleeSuccess(newNetworkId); }); } @@ -4717,7 +4756,7 @@ public class WifiManager { @Override public void onSuccess(int status) { Log.d(TAG, "Easy Connect onSuccess callback"); - mHandler.post(() -> { + mExecutor.execute(() -> { mEasyConnectStatusCallback.onConfiguratorSuccess(status); }); } @@ -4725,7 +4764,7 @@ public class WifiManager { @Override public void onFailure(int status) { Log.d(TAG, "Easy Connect onFailure callback"); - mHandler.post(() -> { + mExecutor.execute(() -> { mEasyConnectStatusCallback.onFailure(status); }); } @@ -4733,7 +4772,7 @@ public class WifiManager { @Override public void onProgress(int status) { Log.d(TAG, "Easy Connect onProgress callback"); - mHandler.post(() -> { + mExecutor.execute(() -> { mEasyConnectStatusCallback.onProgress(status); }); } diff --git a/wifi/java/android/net/wifi/WifiNetworkAgentSpecifier.java b/wifi/java/android/net/wifi/WifiNetworkAgentSpecifier.java index 955e040a46f1..aa1669ee6d94 100644 --- a/wifi/java/android/net/wifi/WifiNetworkAgentSpecifier.java +++ b/wifi/java/android/net/wifi/WifiNetworkAgentSpecifier.java @@ -168,8 +168,9 @@ public final class WifiNetworkAgentSpecifier extends NetworkSpecifier implements @Override public String toString() { StringBuilder sb = new StringBuilder("WifiNetworkAgentSpecifier ["); - sb.append("WifiConfiguration=").append( - mWifiConfiguration == null ? null : mWifiConfiguration.configKey()) + sb.append("WifiConfiguration=") + .append(", SSID=").append(mWifiConfiguration.SSID) + .append(", BSSID=").append(mWifiConfiguration.BSSID) .append(", mOriginalRequestorUid=").append(mOriginalRequestorUid) .append("]"); return sb.toString(); @@ -180,4 +181,9 @@ public final class WifiNetworkAgentSpecifier extends NetworkSpecifier implements throw new IllegalStateException("WifiNetworkAgentSpecifier should never be used " + "for requests."); } + + @Override + public NetworkSpecifier redact() { + return null; + } } diff --git a/wifi/java/android/net/wifi/WifiNetworkSpecifier.java b/wifi/java/android/net/wifi/WifiNetworkSpecifier.java index 4348399b404b..6e4eeef4dd55 100644 --- a/wifi/java/android/net/wifi/WifiNetworkSpecifier.java +++ b/wifi/java/android/net/wifi/WifiNetworkSpecifier.java @@ -162,11 +162,11 @@ public final class WifiNetworkSpecifier extends NetworkSpecifier implements Parc @Override public String toString() { return new StringBuilder() - .append("WifiNetworkSpecifierWifiNetworkSpecifier [") + .append("WifiNetworkSpecifier [") .append(", SSID Match pattern=").append(ssidPatternMatcher) .append(", BSSID Match pattern=").append(bssidPatternMatcher) - .append(", WifiConfiguration=").append( - wifiConfiguration == null ? null : wifiConfiguration.configKey()) + .append(", SSID=").append(wifiConfiguration.SSID) + .append(", BSSID=").append(wifiConfiguration.BSSID) .append(", requestorUid=").append(requestorUid) .append("]") .toString(); diff --git a/wifi/java/android/net/wifi/WifiNetworkSuggestion.java b/wifi/java/android/net/wifi/WifiNetworkSuggestion.java index 760f1e6bc5e2..3c90eb763e81 100644 --- a/wifi/java/android/net/wifi/WifiNetworkSuggestion.java +++ b/wifi/java/android/net/wifi/WifiNetworkSuggestion.java @@ -130,7 +130,8 @@ public final class WifiNetworkSuggestion implements Parcelable { @Override public String toString() { StringBuilder sb = new StringBuilder("WifiNetworkSuggestion [") - .append(", WifiConfiguration=").append(wifiConfiguration) + .append(", SSID=").append(wifiConfiguration.SSID) + .append(", BSSID=").append(wifiConfiguration.BSSID) .append(", isAppInteractionRequired=").append(isAppInteractionRequired) .append(", isUserInteractionRequired=").append(isUserInteractionRequired) .append(", suggestorUid=").append(suggestorUid) diff --git a/wifi/java/android/net/wifi/aware/WifiAwareAgentNetworkSpecifier.java b/wifi/java/android/net/wifi/aware/WifiAwareAgentNetworkSpecifier.java index 14263830660f..4bee837d6089 100644 --- a/wifi/java/android/net/wifi/aware/WifiAwareAgentNetworkSpecifier.java +++ b/wifi/java/android/net/wifi/aware/WifiAwareAgentNetworkSpecifier.java @@ -149,6 +149,11 @@ public class WifiAwareAgentNetworkSpecifier extends NetworkSpecifier implements "WifiAwareAgentNetworkSpecifier should not be used in network requests"); } + @Override + public NetworkSpecifier redact() { + return null; + } + private void initialize() { try { mDigester = MessageDigest.getInstance("SHA-256"); diff --git a/wifi/java/android/net/wifi/hotspot2/OsuProvider.java b/wifi/java/android/net/wifi/hotspot2/OsuProvider.java index 6d82ca152202..f91790f5b3b1 100644 --- a/wifi/java/android/net/wifi/hotspot2/OsuProvider.java +++ b/wifi/java/android/net/wifi/hotspot2/OsuProvider.java @@ -16,6 +16,7 @@ package android.net.wifi.hotspot2; +import android.annotation.SystemApi; import android.graphics.drawable.Icon; import android.net.Uri; import android.net.wifi.WifiSsid; @@ -36,16 +37,19 @@ import java.util.Objects; * * @hide */ +@SystemApi public final class OsuProvider implements Parcelable { /** * OSU (Online Sign-Up) method: OMA DM (Open Mobile Alliance Device Management). * For more info, refer to Section 8.3 of the Hotspot 2.0 Release 2 Technical Specification. + * @hide */ public static final int METHOD_OMA_DM = 0; /** * OSU (Online Sign-Up) method: SOAP XML SPP (Subscription Provisioning Protocol). * For more info, refer to Section 8.4 of the Hotspot 2.0 Release 2 Technical Specification. + * @hide */ public static final int METHOD_SOAP_XML_SPP = 1; @@ -84,6 +88,7 @@ public final class OsuProvider implements Parcelable { */ private final Icon mIcon; + /** @hide */ public OsuProvider(WifiSsid osuSsid, Map<String, String> friendlyNames, String serviceDescription, Uri serverUri, String nai, List<Integer> methodList, Icon icon) { @@ -104,6 +109,7 @@ public final class OsuProvider implements Parcelable { * Copy constructor. * * @param source The source to copy from + * @hide */ public OsuProvider(OsuProvider source) { if (source == null) { @@ -130,10 +136,12 @@ public final class OsuProvider implements Parcelable { mIcon = source.mIcon; } + /** @hide */ public WifiSsid getOsuSsid() { return mOsuSsid; } + /** @hide */ public void setOsuSsid(WifiSsid osuSsid) { mOsuSsid = osuSsid; } @@ -162,10 +170,12 @@ public final class OsuProvider implements Parcelable { return mFriendlyNames.get(mFriendlyNames.keySet().stream().findFirst().get()); } + /** @hide */ public Map<String, String> getFriendlyNameList() { return mFriendlyNames; } + /** @hide */ public String getServiceDescription() { return mServiceDescription; } @@ -174,14 +184,17 @@ public final class OsuProvider implements Parcelable { return mServerUri; } + /** @hide */ public String getNetworkAccessIdentifier() { return mNetworkAccessIdentifier; } + /** @hide */ public List<Integer> getMethodList() { return mMethodList; } + /** @hide */ public Icon getIcon() { return mIcon; } diff --git a/wifi/java/android/net/wifi/hotspot2/ProvisioningCallback.java b/wifi/java/android/net/wifi/hotspot2/ProvisioningCallback.java index a62d63cd8910..1ee874a9698b 100644 --- a/wifi/java/android/net/wifi/hotspot2/ProvisioningCallback.java +++ b/wifi/java/android/net/wifi/hotspot2/ProvisioningCallback.java @@ -16,6 +16,7 @@ package android.net.wifi.hotspot2; +import android.annotation.SystemApi; import android.net.wifi.WifiManager; import android.os.Handler; @@ -25,6 +26,7 @@ import android.os.Handler; * * @hide */ +@SystemApi public abstract class ProvisioningCallback { /** diff --git a/wifi/java/com/android/server/wifi/BaseWifiService.java b/wifi/java/com/android/server/wifi/BaseWifiService.java index 2c96c057e37d..b3ac9f15eb9a 100644 --- a/wifi/java/com/android/server/wifi/BaseWifiService.java +++ b/wifi/java/com/android/server/wifi/BaseWifiService.java @@ -64,7 +64,7 @@ public class BaseWifiService extends IWifiManager.Stub { private static final String TAG = BaseWifiService.class.getSimpleName(); @Override - public int getSupportedFeatures() { + public long getSupportedFeatures() { throw new UnsupportedOperationException(); } |