diff options
642 files changed, 15531 insertions, 8301 deletions
diff --git a/Android.bp b/Android.bp index e756b3428164..eacf57ccd38c 100644 --- a/Android.bp +++ b/Android.bp @@ -366,7 +366,8 @@ filegroup { ":framework-tethering-srcs", ":framework-wifi-updatable-sources", ":updatable-media-srcs", - ] + ], + visibility: ["//visibility:private"], } java_library { @@ -383,7 +384,31 @@ java_library { "framework-wifi.stubs.module_lib", ], sdk_version: "module_current", - visibility: [":__pkg__"], + visibility: ["//visibility:private"], +} + +java_library { + name: "framework-all", + installable: false, + static_libs: [ + "framework-minus-apex", + "framework-appsearch", + "framework-graphics.impl", + "framework-mediaprovider.impl", + "framework-permission.impl", + "framework-sdkextensions.impl", + "framework-statsd.impl", + "framework-tethering.impl", + "framework-wifi.impl", + "updatable-media", + ], + apex_available: ["//apex_available:platform"], + sdk_version: "core_platform", + visibility: [ + // DO NOT ADD ANY MORE ENTRIES TO THIS LIST + "//external/robolectric-shadows:__subpackages__", + "//frameworks/layoutlib:__subpackages__", + ], } filegroup { @@ -474,53 +499,6 @@ java_library { installable: false, } -java_defaults { - name: "framework-defaults", - defaults: ["framework-aidl-export-defaults"], - installable: true, - - aidl: { - generate_get_transaction_name: true, - }, - - srcs: ["core/java/**/*.logtags"], - - exclude_srcs: [ - // See comment on framework-atb-backward-compatibility module below - "core/java/android/content/pm/AndroidTestBaseUpdater.java", - ], - - sdk_version: "core_platform", - libs: [ - "app-compat-annotations", - "ext", - "unsupportedappusage", - ], - - jarjar_rules: ":framework-jarjar-rules", - - static_libs: [ - "framework-internal-utils", - ], - - dxflags: [ - "--core-library", - "--multi-dex", - ], - - plugins: [ - "view-inspector-annotation-processor", - "staledataclass-annotation-processor", - "error_prone_android_framework", - ], - - required: [ - // TODO: remove gps_debug and protolog.conf.json when the build system propagates "required" properly. - "gps_debug.conf", - "protolog.conf.json.gz", - ], -} - filegroup { name: "framework-jarjar-rules", srcs: ["framework-jarjar-rules.txt"], @@ -560,19 +538,47 @@ filegroup { java_library { name: "framework-minus-apex", - defaults: ["framework-defaults"], - srcs: [":framework-non-updatable-sources"], + defaults: ["framework-aidl-export-defaults"], + srcs: [ + ":framework-non-updatable-sources", + "core/java/**/*.logtags", + ], + // See comment on framework-atb-backward-compatibility module below + exclude_srcs: ["core/java/android/content/pm/AndroidTestBaseUpdater.java"], + aidl: { + generate_get_transaction_name: true, + }, + dxflags: [ + "--core-library", + "--multi-dex", + ], installable: true, + jarjar_rules: ":framework-jarjar-rules", javac_shard_size: 150, + plugins: [ + "view-inspector-annotation-processor", + "staledataclass-annotation-processor", + "error_prone_android_framework", + ], required: [ "framework-platform-compat-config", + // TODO: remove gps_debug and protolog.conf.json when the build system propagates "required" properly. + "gps_debug.conf", "libcore-platform-compat-config", + "protolog.conf.json.gz", "services-platform-compat-config", "documents-ui-compat-config", "calendar-provider-compat-config", ], - libs: ["framework-updatable-stubs-module_libs_api"], + libs: [ + "app-compat-annotations", + "ext", + "framework-updatable-stubs-module_libs_api", + "unsupportedappusage", + ], + sdk_version: "core_platform", static_libs: [ + "framework-internal-utils", // If MimeMap ever becomes its own APEX, then this dependency would need to be removed // in favor of an API stubs dependency in java_library "framework" below. "mimemap", @@ -615,32 +621,6 @@ java_library { apex_available: ["//apex_available:platform"], } -java_library { - name: "framework-all", - defaults: ["framework-defaults"], - srcs: [":framework-all-sources"], - installable: false, - static_libs: [ - "exoplayer2-extractor", - "android.hardware.wifi-V1.0-java-constants", - "mediatranscoding_aidl_interface-java", - - // Additional dependencies needed to build the ike API classes. - "ike-internals", - ], - plugins: [ - "intdef-annotation-processor", - ], - libs: ["icing-java-proto-lite"], - apex_available: ["//apex_available:platform"], - visibility: [ - // DO NOT ADD ANY MORE ENTRIES TO THIS LIST - "//external/robolectric-shadows:__subpackages__", - "//frameworks/base", - "//frameworks/layoutlib:__subpackages__", - ], -} - platform_compat_config { name: "framework-platform-compat-config", src: ":framework-minus-apex", diff --git a/apct-tests/perftests/core/src/android/os/PackageParsingPerfTest.kt b/apct-tests/perftests/core/src/android/os/PackageParsingPerfTest.kt index 29721c593646..9e519f7afb93 100644 --- a/apct-tests/perftests/core/src/android/os/PackageParsingPerfTest.kt +++ b/apct-tests/perftests/core/src/android/os/PackageParsingPerfTest.kt @@ -184,11 +184,11 @@ class PackageParsingPerfTest { override fun startParsingPackage( packageName: String, - baseCodePath: String, - codePath: String, + baseApkPath: String, + path: String, manifestArray: TypedArray, isCoreApp: Boolean - ) = ParsingPackageImpl(packageName, baseCodePath, codePath, manifestArray) + ) = ParsingPackageImpl(packageName, baseApkPath, path, manifestArray) }) override fun parseImpl(file: File) = diff --git a/apct-tests/perftests/windowmanager/src/android/wm/RelayoutPerfTest.java b/apct-tests/perftests/windowmanager/src/android/wm/RelayoutPerfTest.java index 269742854cb0..a701f8631969 100644 --- a/apct-tests/perftests/windowmanager/src/android/wm/RelayoutPerfTest.java +++ b/apct-tests/perftests/windowmanager/src/android/wm/RelayoutPerfTest.java @@ -21,14 +21,12 @@ import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentat import android.app.Activity; import android.content.Context; import android.graphics.Point; -import android.graphics.Rect; import android.os.RemoteException; import android.perftests.utils.BenchmarkState; import android.perftests.utils.PerfStatusReporter; import android.perftests.utils.PerfTestActivity; import android.platform.test.annotations.Presubmit; import android.util.MergedConfiguration; -import android.view.DisplayCutout; import android.view.IWindow; import android.view.IWindowSession; import android.view.InsetsSourceControl; @@ -38,6 +36,7 @@ import android.view.View; import android.view.WindowManager; import android.view.WindowManagerGlobal; import android.widget.LinearLayout; +import android.window.ClientWindowFrames; import androidx.test.filters.LargeTest; import androidx.test.rule.ActivityTestRule; @@ -125,13 +124,7 @@ public class RelayoutPerfTest extends WindowManagerPerfTestBase } private static class RelayoutRunner { - final Rect mOutFrame = new Rect(); - final Rect mOutContentInsets = new Rect(); - final Rect mOutVisibleInsets = new Rect(); - final Rect mOutStableInsets = new Rect(); - final Rect mOutBackDropFrame = new Rect(); - final DisplayCutout.ParcelableWrapper mOutDisplayCutout = - new DisplayCutout.ParcelableWrapper(DisplayCutout.NO_CUTOUT); + final ClientWindowFrames mOutFrames = new ClientWindowFrames(); final MergedConfiguration mOutMergedConfiguration = new MergedConfiguration(); final InsetsState mOutInsetsState = new InsetsState(); final InsetsSourceControl[] mOutControls = new InsetsSourceControl[0]; @@ -164,11 +157,9 @@ public class RelayoutPerfTest extends WindowManagerPerfTestBase final IWindowSession session = WindowManagerGlobal.getWindowSession(); while (state.keepRunning()) { session.relayout(mWindow, mSeq, mParams, mWidth, mHeight, - mViewVisibility.getAsInt(), mFlags, mFrameNumber, mOutFrame, - mOutContentInsets, mOutVisibleInsets, mOutStableInsets, - mOutBackDropFrame, mOutDisplayCutout, mOutMergedConfiguration, - mOutSurfaceControl, mOutInsetsState, mOutControls, mOutSurfaceSize, - mOutBlastSurfaceControl); + mViewVisibility.getAsInt(), mFlags, mFrameNumber, mOutFrames, + mOutMergedConfiguration, mOutSurfaceControl, mOutInsetsState, mOutControls, + mOutSurfaceSize, mOutBlastSurfaceControl); } } } diff --git a/apex/Android.bp b/apex/Android.bp index 410e21141f86..266e6720c1a1 100644 --- a/apex/Android.bp +++ b/apex/Android.bp @@ -101,20 +101,16 @@ java_defaults { annotations_enabled: true, - stubs_library_visibility: [ - "//visibility:public", - ], - - // Set the visibility of the modules creating the stubs source. - stubs_source_visibility: [ - // Ignore any visibility rules specified on the java_sdk_library when - // setting the visibility of the stubs source modules. - "//visibility:override", - - // Currently, the stub source is not required for anything other than building - // the stubs library so is private to avoid misuse. - "//visibility:private", + // Allow access to the stubs from anywhere + visibility: ["//visibility:public"], + stubs_library_visibility: ["//visibility:public"], + + // Hide impl library and stub sources + impl_library_visibility: [ + ":__package__", + "//frameworks/base", // For framework-all ], + stubs_source_visibility: ["//visibility:private"], // Collates API usages from each module for further analysis. plugins: ["java_api_finder"], diff --git a/apex/jobscheduler/service/java/com/android/server/DeviceIdleController.java b/apex/jobscheduler/service/java/com/android/server/DeviceIdleController.java index 6c3398f91db1..d8386b5f1153 100644 --- a/apex/jobscheduler/service/java/com/android/server/DeviceIdleController.java +++ b/apex/jobscheduler/service/java/com/android/server/DeviceIdleController.java @@ -21,14 +21,12 @@ import android.app.ActivityManager; import android.app.ActivityManagerInternal; import android.app.AlarmManager; import android.content.BroadcastReceiver; -import android.content.ContentResolver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.content.pm.ApplicationInfo; import android.content.pm.PackageManager; import android.content.pm.PackageManager.NameNotFoundException; -import android.database.ContentObserver; import android.hardware.Sensor; import android.hardware.SensorEvent; import android.hardware.SensorEventListener; @@ -63,11 +61,10 @@ import android.os.ShellCallback; import android.os.ShellCommand; import android.os.SystemClock; import android.os.UserHandle; -import android.provider.Settings; +import android.provider.DeviceConfig; import android.util.ArrayMap; import android.util.ArraySet; import android.util.AtomicFile; -import android.util.KeyValueListParser; import android.util.MutableLong; import android.util.Pair; import android.util.Slog; @@ -856,7 +853,7 @@ public class DeviceIdleController extends SystemService * global Settings. Any access to this class or its fields should be done while * holding the DeviceIdleController lock. */ - public final class Constants extends ContentObserver { + public final class Constants implements DeviceConfig.OnPropertiesChangedListener { // Key names stored in the settings value. private static final String KEY_LIGHT_IDLE_AFTER_INACTIVE_TIMEOUT = "light_after_inactive_to"; @@ -884,15 +881,15 @@ public class DeviceIdleController extends SystemService private static final String KEY_MAX_IDLE_TIMEOUT = "max_idle_to"; private static final String KEY_IDLE_FACTOR = "idle_factor"; private static final String KEY_MIN_TIME_TO_ALARM = "min_time_to_alarm"; + // TODO(166121524): update flag names private static final String KEY_MAX_TEMP_APP_WHITELIST_DURATION = "max_temp_app_whitelist_duration"; private static final String KEY_MMS_TEMP_APP_WHITELIST_DURATION = "mms_temp_app_whitelist_duration"; private static final String KEY_SMS_TEMP_APP_WHITELIST_DURATION = "sms_temp_app_whitelist_duration"; - // TODO(b/124466289): update value to match the name - private static final String KEY_NOTIFICATION_ALLOWLIST_DURATION = - "notification_whitelist_duration"; + private static final String KEY_NOTIFICATION_ALLOWLIST_DURATION_MS = + "notification_allowlist_duration_ms"; /** * Whether to wait for the user to unlock the device before causing screen-on to * exit doze. Default = true @@ -903,52 +900,106 @@ public class DeviceIdleController extends SystemService private static final String KEY_PRE_IDLE_FACTOR_SHORT = "pre_idle_factor_short"; + private static final long DEFAULT_LIGHT_IDLE_AFTER_INACTIVE_TIMEOUT = + !COMPRESS_TIME ? 3 * 60 * 1000L : 15 * 1000L; + private static final long DEFAULT_LIGHT_PRE_IDLE_TIMEOUT = + !COMPRESS_TIME ? 3 * 60 * 1000L : 30 * 1000L; + private static final long DEFAULT_LIGHT_IDLE_TIMEOUT = + !COMPRESS_TIME ? 5 * 60 * 1000L : 15 * 1000L; + private static final float DEFAULT_LIGHT_IDLE_FACTOR = 2f; + private static final long DEFAULT_LIGHT_MAX_IDLE_TIMEOUT = + !COMPRESS_TIME ? 15 * 60 * 1000L : 60 * 1000L; + private static final long DEFAULT_LIGHT_IDLE_MAINTENANCE_MIN_BUDGET = + !COMPRESS_TIME ? 1 * 60 * 1000L : 15 * 1000L; + private static final long DEFAULT_LIGHT_IDLE_MAINTENANCE_MAX_BUDGET = + !COMPRESS_TIME ? 5 * 60 * 1000L : 30 * 1000L; + private static final long DEFAULT_MIN_LIGHT_MAINTENANCE_TIME = + !COMPRESS_TIME ? 5 * 1000L : 1 * 1000L; + private static final long DEFAULT_MIN_DEEP_MAINTENANCE_TIME = + !COMPRESS_TIME ? 30 * 1000L : 5 * 1000L; + private static final long DEFAULT_INACTIVE_TIMEOUT = + (30 * 60 * 1000L) / (!COMPRESS_TIME ? 1 : 10); + private static final long DEFAULT_INACTIVE_TIMEOUT_SMALL_BATTERY = + (15 * 60 * 1000L) / (!COMPRESS_TIME ? 1 : 10); + private static final long DEFAULT_SENSING_TIMEOUT = + !COMPRESS_TIME ? 4 * 60 * 1000L : 60 * 1000L; + private static final long DEFAULT_LOCATING_TIMEOUT = + !COMPRESS_TIME ? 30 * 1000L : 15 * 1000L; + private static final float DEFAULT_LOCATION_ACCURACY = 20f; + private static final long DEFAULT_MOTION_INACTIVE_TIMEOUT = + !COMPRESS_TIME ? 10 * 60 * 1000L : 60 * 1000L; + private static final long DEFAULT_IDLE_AFTER_INACTIVE_TIMEOUT = + (30 * 60 * 1000L) / (!COMPRESS_TIME ? 1 : 10); + private static final long DEFAULT_IDLE_AFTER_INACTIVE_TIMEOUT_SMALL_BATTERY = + (15 * 60 * 1000L) / (!COMPRESS_TIME ? 1 : 10); + private static final long DEFAULT_IDLE_PENDING_TIMEOUT = + !COMPRESS_TIME ? 5 * 60 * 1000L : 30 * 1000L; + private static final long DEFAULT_MAX_IDLE_PENDING_TIMEOUT = + !COMPRESS_TIME ? 10 * 60 * 1000L : 60 * 1000L; + private static final float DEFAULT_IDLE_PENDING_FACTOR = 2f; + private static final long DEFAULT_QUICK_DOZE_DELAY_TIMEOUT = + !COMPRESS_TIME ? 60 * 1000L : 15 * 1000L; + private static final long DEFAULT_IDLE_TIMEOUT = + !COMPRESS_TIME ? 60 * 60 * 1000L : 6 * 60 * 1000L; + private static final long DEFAULT_MAX_IDLE_TIMEOUT = + !COMPRESS_TIME ? 6 * 60 * 60 * 1000L : 30 * 60 * 1000L; + private static final float DEFAULT_IDLE_FACTOR = 2f; + private static final long DEFAULT_MIN_TIME_TO_ALARM = + !COMPRESS_TIME ? 30 * 60 * 1000L : 6 * 60 * 1000L; + private static final long DEFAULT_MAX_TEMP_APP_WHITELIST_DURATION = 5 * 60 * 1000L; + private static final long DEFAULT_MMS_TEMP_APP_WHITELIST_DURATION = 60 * 1000L; + private static final long DEFAULT_SMS_TEMP_APP_WHITELIST_DURATION = 20 * 1000L; + private static final long DEFAULT_NOTIFICATION_ALLOWLIST_DURATION_MS = 30 * 1000L; + private static final boolean DEFAULT_WAIT_FOR_UNLOCK = true; + private static final float DEFAULT_PRE_IDLE_FACTOR_LONG = 1.67f; + private static final float DEFAULT_PRE_IDLE_FACTOR_SHORT = .33f; + /** * This is the time, after becoming inactive, that we go in to the first * light-weight idle mode. - * @see Settings.Global#DEVICE_IDLE_CONSTANTS + * * @see #KEY_LIGHT_IDLE_AFTER_INACTIVE_TIMEOUT */ - public long LIGHT_IDLE_AFTER_INACTIVE_TIMEOUT; + public long LIGHT_IDLE_AFTER_INACTIVE_TIMEOUT = DEFAULT_LIGHT_IDLE_AFTER_INACTIVE_TIMEOUT; /** * This is amount of time we will wait from the point where we decide we would * like to go idle until we actually do, while waiting for jobs and other current * activity to finish. - * @see Settings.Global#DEVICE_IDLE_CONSTANTS + * * @see #KEY_LIGHT_PRE_IDLE_TIMEOUT */ - public long LIGHT_PRE_IDLE_TIMEOUT; + public long LIGHT_PRE_IDLE_TIMEOUT = DEFAULT_LIGHT_PRE_IDLE_TIMEOUT; /** * This is the initial time that we will run in idle maintenance mode. - * @see Settings.Global#DEVICE_IDLE_CONSTANTS + * * @see #KEY_LIGHT_IDLE_TIMEOUT */ - public long LIGHT_IDLE_TIMEOUT; + public long LIGHT_IDLE_TIMEOUT = DEFAULT_LIGHT_IDLE_TIMEOUT; /** * Scaling factor to apply to the light idle mode time each time we complete a cycle. - * @see Settings.Global#DEVICE_IDLE_CONSTANTS + * * @see #KEY_LIGHT_IDLE_FACTOR */ - public float LIGHT_IDLE_FACTOR; + public float LIGHT_IDLE_FACTOR = DEFAULT_LIGHT_IDLE_FACTOR; /** * This is the maximum time we will run in idle maintenance mode. - * @see Settings.Global#DEVICE_IDLE_CONSTANTS + * * @see #KEY_LIGHT_MAX_IDLE_TIMEOUT */ - public long LIGHT_MAX_IDLE_TIMEOUT; + public long LIGHT_MAX_IDLE_TIMEOUT = DEFAULT_LIGHT_MAX_IDLE_TIMEOUT; /** * This is the minimum amount of time we want to make available for maintenance mode * when lightly idling. That is, we will always have at least this amount of time * available maintenance before timing out and cutting off maintenance mode. - * @see Settings.Global#DEVICE_IDLE_CONSTANTS + * * @see #KEY_LIGHT_IDLE_MAINTENANCE_MIN_BUDGET */ - public long LIGHT_IDLE_MAINTENANCE_MIN_BUDGET; + public long LIGHT_IDLE_MAINTENANCE_MIN_BUDGET = DEFAULT_LIGHT_IDLE_MAINTENANCE_MIN_BUDGET; /** * This is the maximum amount of time we want to make available for maintenance mode @@ -956,10 +1007,10 @@ public class DeviceIdleController extends SystemService * budget and this time is being added to the budget reserve, this is the maximum * reserve size we will allow to grow and thus the maximum amount of time we will * allow for the maintenance window. - * @see Settings.Global#DEVICE_IDLE_CONSTANTS + * * @see #KEY_LIGHT_IDLE_MAINTENANCE_MAX_BUDGET */ - public long LIGHT_IDLE_MAINTENANCE_MAX_BUDGET; + public long LIGHT_IDLE_MAINTENANCE_MAX_BUDGET = DEFAULT_LIGHT_IDLE_MAINTENANCE_MAX_BUDGET; /** * This is the minimum amount of time that we will stay in maintenance mode after @@ -967,10 +1018,10 @@ public class DeviceIdleController extends SystemService * in to maintenance mode and scheduling their work -- otherwise we may * see there is nothing to do (no jobs pending) and go out of maintenance * mode immediately. - * @see Settings.Global#DEVICE_IDLE_CONSTANTS + * * @see #KEY_MIN_LIGHT_MAINTENANCE_TIME */ - public long MIN_LIGHT_MAINTENANCE_TIME; + public long MIN_LIGHT_MAINTENANCE_TIME = DEFAULT_MIN_LIGHT_MAINTENANCE_TIME; /** * This is the minimum amount of time that we will stay in maintenance mode after @@ -978,271 +1029,323 @@ public class DeviceIdleController extends SystemService * in to maintenance mode and scheduling their work -- otherwise we may * see there is nothing to do (no jobs pending) and go out of maintenance * mode immediately. - * @see Settings.Global#DEVICE_IDLE_CONSTANTS * @see #KEY_MIN_DEEP_MAINTENANCE_TIME */ - public long MIN_DEEP_MAINTENANCE_TIME; + public long MIN_DEEP_MAINTENANCE_TIME = DEFAULT_MIN_DEEP_MAINTENANCE_TIME; /** * This is the time, after becoming inactive, at which we start looking at the * motion sensor to determine if the device is being left alone. We don't do this * immediately after going inactive just because we don't want to be continually running * the motion sensor whenever the screen is off. - * @see Settings.Global#DEVICE_IDLE_CONSTANTS * @see #KEY_INACTIVE_TIMEOUT */ - public long INACTIVE_TIMEOUT; + public long INACTIVE_TIMEOUT = DEFAULT_INACTIVE_TIMEOUT; /** * If we don't receive a callback from AnyMotion in this amount of time + * {@link #LOCATING_TIMEOUT}, we will change from * STATE_SENSING to STATE_INACTIVE, and any AnyMotion callbacks while not in STATE_SENSING * will be ignored. - * @see Settings.Global#DEVICE_IDLE_CONSTANTS * @see #KEY_SENSING_TIMEOUT */ - public long SENSING_TIMEOUT; + public long SENSING_TIMEOUT = DEFAULT_SENSING_TIMEOUT; /** * This is how long we will wait to try to get a good location fix before going in to * idle mode. - * @see Settings.Global#DEVICE_IDLE_CONSTANTS * @see #KEY_LOCATING_TIMEOUT */ - public long LOCATING_TIMEOUT; + public long LOCATING_TIMEOUT = DEFAULT_LOCATING_TIMEOUT; /** * The desired maximum accuracy (in meters) we consider the location to be good enough to go * on to idle. We will be trying to get an accuracy fix at least this good or until * {@link #LOCATING_TIMEOUT} expires. - * @see Settings.Global#DEVICE_IDLE_CONSTANTS * @see #KEY_LOCATION_ACCURACY */ - public float LOCATION_ACCURACY; + public float LOCATION_ACCURACY = DEFAULT_LOCATION_ACCURACY; /** * This is the time, after seeing motion, that we wait after becoming inactive from * that until we start looking for motion again. - * @see Settings.Global#DEVICE_IDLE_CONSTANTS * @see #KEY_MOTION_INACTIVE_TIMEOUT */ - public long MOTION_INACTIVE_TIMEOUT; + public long MOTION_INACTIVE_TIMEOUT = DEFAULT_MOTION_INACTIVE_TIMEOUT; /** * This is the time, after the inactive timeout elapses, that we will wait looking * for motion until we truly consider the device to be idle. - * @see Settings.Global#DEVICE_IDLE_CONSTANTS * @see #KEY_IDLE_AFTER_INACTIVE_TIMEOUT */ - public long IDLE_AFTER_INACTIVE_TIMEOUT; + public long IDLE_AFTER_INACTIVE_TIMEOUT = DEFAULT_IDLE_AFTER_INACTIVE_TIMEOUT; /** * This is the initial time, after being idle, that we will allow ourself to be back * in the IDLE_MAINTENANCE state allowing the system to run normally until we return to * idle. - * @see Settings.Global#DEVICE_IDLE_CONSTANTS * @see #KEY_IDLE_PENDING_TIMEOUT */ - public long IDLE_PENDING_TIMEOUT; + public long IDLE_PENDING_TIMEOUT = DEFAULT_IDLE_PENDING_TIMEOUT; /** * Maximum pending idle timeout (time spent running) we will be allowed to use. - * @see Settings.Global#DEVICE_IDLE_CONSTANTS * @see #KEY_MAX_IDLE_PENDING_TIMEOUT */ - public long MAX_IDLE_PENDING_TIMEOUT; + public long MAX_IDLE_PENDING_TIMEOUT = DEFAULT_MAX_IDLE_PENDING_TIMEOUT; /** * Scaling factor to apply to current pending idle timeout each time we cycle through * that state. - * @see Settings.Global#DEVICE_IDLE_CONSTANTS * @see #KEY_IDLE_PENDING_FACTOR */ - public float IDLE_PENDING_FACTOR; + public float IDLE_PENDING_FACTOR = DEFAULT_IDLE_PENDING_FACTOR; /** * This is amount of time we will wait from the point where we go into * STATE_QUICK_DOZE_DELAY until we actually go into STATE_IDLE, while waiting for jobs * and other current activity to finish. - * @see Settings.Global#DEVICE_IDLE_CONSTANTS * @see #KEY_QUICK_DOZE_DELAY_TIMEOUT */ - public long QUICK_DOZE_DELAY_TIMEOUT; + public long QUICK_DOZE_DELAY_TIMEOUT = DEFAULT_QUICK_DOZE_DELAY_TIMEOUT; /** * This is the initial time that we want to sit in the idle state before waking up * again to return to pending idle and allowing normal work to run. - * @see Settings.Global#DEVICE_IDLE_CONSTANTS * @see #KEY_IDLE_TIMEOUT */ - public long IDLE_TIMEOUT; + public long IDLE_TIMEOUT = DEFAULT_IDLE_TIMEOUT; /** * Maximum idle duration we will be allowed to use. - * @see Settings.Global#DEVICE_IDLE_CONSTANTS * @see #KEY_MAX_IDLE_TIMEOUT */ - public long MAX_IDLE_TIMEOUT; + public long MAX_IDLE_TIMEOUT = DEFAULT_MAX_IDLE_TIMEOUT; /** * Scaling factor to apply to current idle timeout each time we cycle through that state. - * @see Settings.Global#DEVICE_IDLE_CONSTANTS * @see #KEY_IDLE_FACTOR */ - public float IDLE_FACTOR; + public float IDLE_FACTOR = DEFAULT_IDLE_FACTOR; /** * This is the minimum time we will allow until the next upcoming alarm for us to * actually go in to idle mode. - * @see Settings.Global#DEVICE_IDLE_CONSTANTS * @see #KEY_MIN_TIME_TO_ALARM */ - public long MIN_TIME_TO_ALARM; + public long MIN_TIME_TO_ALARM = DEFAULT_MIN_TIME_TO_ALARM; /** * Max amount of time to temporarily whitelist an app when it receives a high priority * tickle. - * @see Settings.Global#DEVICE_IDLE_CONSTANTS + * * @see #KEY_MAX_TEMP_APP_WHITELIST_DURATION */ - public long MAX_TEMP_APP_WHITELIST_DURATION; + public long MAX_TEMP_APP_WHITELIST_DURATION = DEFAULT_MAX_TEMP_APP_WHITELIST_DURATION; /** * Amount of time we would like to whitelist an app that is receiving an MMS. - * @see Settings.Global#DEVICE_IDLE_CONSTANTS * @see #KEY_MMS_TEMP_APP_WHITELIST_DURATION */ - public long MMS_TEMP_APP_WHITELIST_DURATION; + public long MMS_TEMP_APP_WHITELIST_DURATION = DEFAULT_MMS_TEMP_APP_WHITELIST_DURATION; /** * Amount of time we would like to whitelist an app that is receiving an SMS. - * @see Settings.Global#DEVICE_IDLE_CONSTANTS * @see #KEY_SMS_TEMP_APP_WHITELIST_DURATION */ - public long SMS_TEMP_APP_WHITELIST_DURATION; + public long SMS_TEMP_APP_WHITELIST_DURATION = DEFAULT_SMS_TEMP_APP_WHITELIST_DURATION; /** * Amount of time we would like to whitelist an app that is handling a * {@link android.app.PendingIntent} triggered by a {@link android.app.Notification}. - * @see Settings.Global#DEVICE_IDLE_CONSTANTS - * @see #KEY_NOTIFICATION_ALLOWLIST_DURATION + * @see #KEY_NOTIFICATION_ALLOWLIST_DURATION_MS */ - public long NOTIFICATION_ALLOWLIST_DURATION; + public long NOTIFICATION_ALLOWLIST_DURATION_MS = DEFAULT_NOTIFICATION_ALLOWLIST_DURATION_MS; /** * Pre idle time factor use to make idle delay longer */ - public float PRE_IDLE_FACTOR_LONG; + public float PRE_IDLE_FACTOR_LONG = DEFAULT_PRE_IDLE_FACTOR_LONG; /** * Pre idle time factor use to make idle delay shorter */ - public float PRE_IDLE_FACTOR_SHORT; + public float PRE_IDLE_FACTOR_SHORT = DEFAULT_PRE_IDLE_FACTOR_SHORT; - public boolean WAIT_FOR_UNLOCK; + public boolean WAIT_FOR_UNLOCK = DEFAULT_WAIT_FOR_UNLOCK; - private final ContentResolver mResolver; private final boolean mSmallBatteryDevice; - private final KeyValueListParser mParser = new KeyValueListParser(','); - public Constants(Handler handler, ContentResolver resolver) { - super(handler); - mResolver = resolver; + public Constants() { mSmallBatteryDevice = ActivityManager.isSmallBatteryDevice(); - mResolver.registerContentObserver( - Settings.Global.getUriFor(Settings.Global.DEVICE_IDLE_CONSTANTS), - false, this); - updateConstants(); + if (mSmallBatteryDevice) { + INACTIVE_TIMEOUT = DEFAULT_INACTIVE_TIMEOUT_SMALL_BATTERY; + IDLE_AFTER_INACTIVE_TIMEOUT = DEFAULT_IDLE_AFTER_INACTIVE_TIMEOUT_SMALL_BATTERY; + } + DeviceConfig.addOnPropertiesChangedListener(DeviceConfig.NAMESPACE_DEVICE_IDLE, + JobSchedulerBackgroundThread.getExecutor(), this); + // Load all the constants. + onPropertiesChanged(DeviceConfig.getProperties(DeviceConfig.NAMESPACE_DEVICE_IDLE)); } - @Override - public void onChange(boolean selfChange, Uri uri) { - updateConstants(); - } - private void updateConstants() { + @Override + public void onPropertiesChanged(DeviceConfig.Properties properties) { synchronized (DeviceIdleController.this) { - try { - mParser.setString(Settings.Global.getString(mResolver, - Settings.Global.DEVICE_IDLE_CONSTANTS)); - } catch (IllegalArgumentException e) { - // Failed to parse the settings string, log this and move on - // with defaults. - Slog.e(TAG, "Bad device idle settings", e); + for (String name : properties.getKeyset()) { + if (name == null) { + continue; + } + switch (name) { + case KEY_LIGHT_IDLE_AFTER_INACTIVE_TIMEOUT: + LIGHT_IDLE_AFTER_INACTIVE_TIMEOUT = properties.getLong( + KEY_LIGHT_IDLE_AFTER_INACTIVE_TIMEOUT, + DEFAULT_LIGHT_IDLE_AFTER_INACTIVE_TIMEOUT); + break; + case KEY_LIGHT_PRE_IDLE_TIMEOUT: + LIGHT_PRE_IDLE_TIMEOUT = properties.getLong( + KEY_LIGHT_PRE_IDLE_TIMEOUT, DEFAULT_LIGHT_PRE_IDLE_TIMEOUT); + break; + case KEY_LIGHT_IDLE_TIMEOUT: + LIGHT_IDLE_TIMEOUT = properties.getLong( + KEY_LIGHT_IDLE_TIMEOUT, DEFAULT_LIGHT_IDLE_TIMEOUT); + break; + case KEY_LIGHT_IDLE_FACTOR: + LIGHT_IDLE_FACTOR = properties.getFloat( + KEY_LIGHT_IDLE_FACTOR, DEFAULT_LIGHT_IDLE_FACTOR); + break; + case KEY_LIGHT_MAX_IDLE_TIMEOUT: + LIGHT_MAX_IDLE_TIMEOUT = properties.getLong( + KEY_LIGHT_MAX_IDLE_TIMEOUT, DEFAULT_LIGHT_MAX_IDLE_TIMEOUT); + break; + case KEY_LIGHT_IDLE_MAINTENANCE_MIN_BUDGET: + LIGHT_IDLE_MAINTENANCE_MIN_BUDGET = properties.getLong( + KEY_LIGHT_IDLE_MAINTENANCE_MIN_BUDGET, + DEFAULT_LIGHT_IDLE_MAINTENANCE_MIN_BUDGET); + break; + case KEY_LIGHT_IDLE_MAINTENANCE_MAX_BUDGET: + LIGHT_IDLE_MAINTENANCE_MAX_BUDGET = properties.getLong( + KEY_LIGHT_IDLE_MAINTENANCE_MAX_BUDGET, + DEFAULT_LIGHT_IDLE_MAINTENANCE_MAX_BUDGET); + break; + case KEY_MIN_LIGHT_MAINTENANCE_TIME: + MIN_LIGHT_MAINTENANCE_TIME = properties.getLong( + KEY_MIN_LIGHT_MAINTENANCE_TIME, + DEFAULT_MIN_LIGHT_MAINTENANCE_TIME); + break; + case KEY_MIN_DEEP_MAINTENANCE_TIME: + MIN_DEEP_MAINTENANCE_TIME = properties.getLong( + KEY_MIN_DEEP_MAINTENANCE_TIME, + DEFAULT_MIN_DEEP_MAINTENANCE_TIME); + break; + case KEY_INACTIVE_TIMEOUT: + final long defaultInactiveTimeout = mSmallBatteryDevice + ? DEFAULT_INACTIVE_TIMEOUT_SMALL_BATTERY + : DEFAULT_INACTIVE_TIMEOUT; + INACTIVE_TIMEOUT = properties.getLong( + KEY_INACTIVE_TIMEOUT, defaultInactiveTimeout); + break; + case KEY_SENSING_TIMEOUT: + SENSING_TIMEOUT = properties.getLong( + KEY_SENSING_TIMEOUT, DEFAULT_SENSING_TIMEOUT); + break; + case KEY_LOCATING_TIMEOUT: + LOCATING_TIMEOUT = properties.getLong( + KEY_LOCATING_TIMEOUT, DEFAULT_LOCATING_TIMEOUT); + break; + case KEY_LOCATION_ACCURACY: + LOCATION_ACCURACY = properties.getFloat( + KEY_LOCATION_ACCURACY, DEFAULT_LOCATION_ACCURACY); + break; + case KEY_MOTION_INACTIVE_TIMEOUT: + MOTION_INACTIVE_TIMEOUT = properties.getLong( + KEY_MOTION_INACTIVE_TIMEOUT, DEFAULT_MOTION_INACTIVE_TIMEOUT); + break; + case KEY_IDLE_AFTER_INACTIVE_TIMEOUT: + final long defaultIdleAfterInactiveTimeout = mSmallBatteryDevice + ? DEFAULT_IDLE_AFTER_INACTIVE_TIMEOUT_SMALL_BATTERY + : DEFAULT_IDLE_AFTER_INACTIVE_TIMEOUT; + IDLE_AFTER_INACTIVE_TIMEOUT = properties.getLong( + KEY_IDLE_AFTER_INACTIVE_TIMEOUT, + defaultIdleAfterInactiveTimeout); + break; + case KEY_IDLE_PENDING_TIMEOUT: + IDLE_PENDING_TIMEOUT = properties.getLong( + KEY_IDLE_PENDING_TIMEOUT, DEFAULT_IDLE_PENDING_TIMEOUT); + break; + case KEY_MAX_IDLE_PENDING_TIMEOUT: + MAX_IDLE_PENDING_TIMEOUT = properties.getLong( + KEY_MAX_IDLE_PENDING_TIMEOUT, DEFAULT_MAX_IDLE_PENDING_TIMEOUT); + break; + case KEY_IDLE_PENDING_FACTOR: + IDLE_PENDING_FACTOR = properties.getFloat( + KEY_IDLE_PENDING_FACTOR, DEFAULT_IDLE_PENDING_FACTOR); + break; + case KEY_QUICK_DOZE_DELAY_TIMEOUT: + QUICK_DOZE_DELAY_TIMEOUT = properties.getLong( + KEY_QUICK_DOZE_DELAY_TIMEOUT, DEFAULT_QUICK_DOZE_DELAY_TIMEOUT); + break; + case KEY_IDLE_TIMEOUT: + IDLE_TIMEOUT = properties.getLong( + KEY_IDLE_TIMEOUT, DEFAULT_IDLE_TIMEOUT); + break; + case KEY_MAX_IDLE_TIMEOUT: + MAX_IDLE_TIMEOUT = properties.getLong( + KEY_MAX_IDLE_TIMEOUT, DEFAULT_MAX_IDLE_TIMEOUT); + break; + case KEY_IDLE_FACTOR: + IDLE_FACTOR = properties.getFloat(KEY_IDLE_FACTOR, DEFAULT_IDLE_FACTOR); + break; + case KEY_MIN_TIME_TO_ALARM: + MIN_TIME_TO_ALARM = properties.getLong( + KEY_MIN_TIME_TO_ALARM, DEFAULT_MIN_TIME_TO_ALARM); + break; + case KEY_MAX_TEMP_APP_WHITELIST_DURATION: + MAX_TEMP_APP_WHITELIST_DURATION = properties.getLong( + KEY_MAX_TEMP_APP_WHITELIST_DURATION, + DEFAULT_MAX_TEMP_APP_WHITELIST_DURATION); + break; + case KEY_MMS_TEMP_APP_WHITELIST_DURATION: + MMS_TEMP_APP_WHITELIST_DURATION = properties.getLong( + KEY_MMS_TEMP_APP_WHITELIST_DURATION, + DEFAULT_MMS_TEMP_APP_WHITELIST_DURATION); + break; + case KEY_SMS_TEMP_APP_WHITELIST_DURATION: + SMS_TEMP_APP_WHITELIST_DURATION = properties.getLong( + KEY_SMS_TEMP_APP_WHITELIST_DURATION, + DEFAULT_SMS_TEMP_APP_WHITELIST_DURATION); + break; + case KEY_NOTIFICATION_ALLOWLIST_DURATION_MS: + NOTIFICATION_ALLOWLIST_DURATION_MS = properties.getLong( + KEY_NOTIFICATION_ALLOWLIST_DURATION_MS, + DEFAULT_NOTIFICATION_ALLOWLIST_DURATION_MS); + break; + case KEY_WAIT_FOR_UNLOCK: + WAIT_FOR_UNLOCK = properties.getBoolean( + KEY_WAIT_FOR_UNLOCK, DEFAULT_WAIT_FOR_UNLOCK); + break; + case KEY_PRE_IDLE_FACTOR_LONG: + PRE_IDLE_FACTOR_LONG = properties.getFloat( + KEY_PRE_IDLE_FACTOR_LONG, DEFAULT_PRE_IDLE_FACTOR_LONG); + break; + case KEY_PRE_IDLE_FACTOR_SHORT: + PRE_IDLE_FACTOR_SHORT = properties.getFloat( + KEY_PRE_IDLE_FACTOR_SHORT, DEFAULT_PRE_IDLE_FACTOR_SHORT); + break; + default: + Slog.e(TAG, "Unknown configuration key: " + name); + break; + } } - - LIGHT_IDLE_AFTER_INACTIVE_TIMEOUT = mParser.getDurationMillis( - KEY_LIGHT_IDLE_AFTER_INACTIVE_TIMEOUT, - !COMPRESS_TIME ? 3 * 60 * 1000L : 15 * 1000L); - LIGHT_PRE_IDLE_TIMEOUT = mParser.getDurationMillis(KEY_LIGHT_PRE_IDLE_TIMEOUT, - !COMPRESS_TIME ? 3 * 60 * 1000L : 30 * 1000L); - LIGHT_IDLE_TIMEOUT = mParser.getDurationMillis(KEY_LIGHT_IDLE_TIMEOUT, - !COMPRESS_TIME ? 5 * 60 * 1000L : 15 * 1000L); - LIGHT_IDLE_FACTOR = mParser.getFloat(KEY_LIGHT_IDLE_FACTOR, - 2f); - LIGHT_MAX_IDLE_TIMEOUT = mParser.getDurationMillis(KEY_LIGHT_MAX_IDLE_TIMEOUT, - !COMPRESS_TIME ? 15 * 60 * 1000L : 60 * 1000L); - LIGHT_IDLE_MAINTENANCE_MIN_BUDGET = mParser.getDurationMillis( - KEY_LIGHT_IDLE_MAINTENANCE_MIN_BUDGET, - !COMPRESS_TIME ? 1 * 60 * 1000L : 15 * 1000L); - LIGHT_IDLE_MAINTENANCE_MAX_BUDGET = mParser.getDurationMillis( - KEY_LIGHT_IDLE_MAINTENANCE_MAX_BUDGET, - !COMPRESS_TIME ? 5 * 60 * 1000L : 30 * 1000L); - MIN_LIGHT_MAINTENANCE_TIME = mParser.getDurationMillis( - KEY_MIN_LIGHT_MAINTENANCE_TIME, - !COMPRESS_TIME ? 5 * 1000L : 1 * 1000L); - MIN_DEEP_MAINTENANCE_TIME = mParser.getDurationMillis( - KEY_MIN_DEEP_MAINTENANCE_TIME, - !COMPRESS_TIME ? 30 * 1000L : 5 * 1000L); - long inactiveTimeoutDefault = (mSmallBatteryDevice ? 15 : 30) * 60 * 1000L; - INACTIVE_TIMEOUT = mParser.getDurationMillis(KEY_INACTIVE_TIMEOUT, - !COMPRESS_TIME ? inactiveTimeoutDefault : (inactiveTimeoutDefault / 10)); - SENSING_TIMEOUT = mParser.getDurationMillis(KEY_SENSING_TIMEOUT, - !COMPRESS_TIME ? 4 * 60 * 1000L : 60 * 1000L); - LOCATING_TIMEOUT = mParser.getDurationMillis(KEY_LOCATING_TIMEOUT, - !COMPRESS_TIME ? 30 * 1000L : 15 * 1000L); - LOCATION_ACCURACY = mParser.getFloat(KEY_LOCATION_ACCURACY, 20); - MOTION_INACTIVE_TIMEOUT = mParser.getDurationMillis(KEY_MOTION_INACTIVE_TIMEOUT, - !COMPRESS_TIME ? 10 * 60 * 1000L : 60 * 1000L); - long idleAfterInactiveTimeout = (mSmallBatteryDevice ? 15 : 30) * 60 * 1000L; - IDLE_AFTER_INACTIVE_TIMEOUT = mParser.getDurationMillis( - KEY_IDLE_AFTER_INACTIVE_TIMEOUT, - !COMPRESS_TIME ? idleAfterInactiveTimeout - : (idleAfterInactiveTimeout / 10)); - IDLE_PENDING_TIMEOUT = mParser.getDurationMillis(KEY_IDLE_PENDING_TIMEOUT, - !COMPRESS_TIME ? 5 * 60 * 1000L : 30 * 1000L); - MAX_IDLE_PENDING_TIMEOUT = mParser.getDurationMillis(KEY_MAX_IDLE_PENDING_TIMEOUT, - !COMPRESS_TIME ? 10 * 60 * 1000L : 60 * 1000L); - IDLE_PENDING_FACTOR = mParser.getFloat(KEY_IDLE_PENDING_FACTOR, - 2f); - QUICK_DOZE_DELAY_TIMEOUT = mParser.getDurationMillis( - KEY_QUICK_DOZE_DELAY_TIMEOUT, !COMPRESS_TIME ? 60 * 1000L : 15 * 1000L); - IDLE_TIMEOUT = mParser.getDurationMillis(KEY_IDLE_TIMEOUT, - !COMPRESS_TIME ? 60 * 60 * 1000L : 6 * 60 * 1000L); - MAX_IDLE_TIMEOUT = mParser.getDurationMillis(KEY_MAX_IDLE_TIMEOUT, - !COMPRESS_TIME ? 6 * 60 * 60 * 1000L : 30 * 60 * 1000L); - IDLE_FACTOR = mParser.getFloat(KEY_IDLE_FACTOR, - 2f); - MIN_TIME_TO_ALARM = mParser.getDurationMillis(KEY_MIN_TIME_TO_ALARM, - !COMPRESS_TIME ? 30 * 60 * 1000L : 6 * 60 * 1000L); - MAX_TEMP_APP_WHITELIST_DURATION = mParser.getDurationMillis( - KEY_MAX_TEMP_APP_WHITELIST_DURATION, 5 * 60 * 1000L); - MMS_TEMP_APP_WHITELIST_DURATION = mParser.getDurationMillis( - KEY_MMS_TEMP_APP_WHITELIST_DURATION, 60 * 1000L); - SMS_TEMP_APP_WHITELIST_DURATION = mParser.getDurationMillis( - KEY_SMS_TEMP_APP_WHITELIST_DURATION, 20 * 1000L); - NOTIFICATION_ALLOWLIST_DURATION = mParser.getDurationMillis( - KEY_NOTIFICATION_ALLOWLIST_DURATION, 30 * 1000L); - WAIT_FOR_UNLOCK = mParser.getBoolean(KEY_WAIT_FOR_UNLOCK, true); - PRE_IDLE_FACTOR_LONG = mParser.getFloat(KEY_PRE_IDLE_FACTOR_LONG, 1.67f); - PRE_IDLE_FACTOR_SHORT = mParser.getFloat(KEY_PRE_IDLE_FACTOR_SHORT, 0.33f); } } void dump(PrintWriter pw) { pw.println(" Settings:"); - pw.print(" "); pw.print(KEY_LIGHT_IDLE_AFTER_INACTIVE_TIMEOUT); pw.print("="); + pw.print(" "); + pw.print(KEY_LIGHT_IDLE_AFTER_INACTIVE_TIMEOUT); + pw.print("="); TimeUtils.formatDuration(LIGHT_IDLE_AFTER_INACTIVE_TIMEOUT, pw); pw.println(); @@ -1344,8 +1447,8 @@ public class DeviceIdleController extends SystemService TimeUtils.formatDuration(SMS_TEMP_APP_WHITELIST_DURATION, pw); pw.println(); - pw.print(" "); pw.print(KEY_NOTIFICATION_ALLOWLIST_DURATION); pw.print("="); - TimeUtils.formatDuration(NOTIFICATION_ALLOWLIST_DURATION, pw); + pw.print(" "); pw.print(KEY_NOTIFICATION_ALLOWLIST_DURATION_MS); pw.print("="); + TimeUtils.formatDuration(NOTIFICATION_ALLOWLIST_DURATION_MS, pw); pw.println(); pw.print(" "); pw.print(KEY_WAIT_FOR_UNLOCK); pw.print("="); @@ -1794,7 +1897,7 @@ public class DeviceIdleController extends SystemService // duration in milliseconds @Override public long getNotificationAllowlistDuration() { - return mConstants.NOTIFICATION_ALLOWLIST_DURATION; + return mConstants.NOTIFICATION_ALLOWLIST_DURATION_MS; } @Override @@ -1871,10 +1974,9 @@ public class DeviceIdleController extends SystemService return mConnectivityManager; } - Constants getConstants(DeviceIdleController controller, Handler handler, - ContentResolver resolver) { + Constants getConstants(DeviceIdleController controller) { if (mConstants == null) { - mConstants = controller.new Constants(handler, resolver); + mConstants = controller.new Constants(); } return mConstants; } @@ -2023,7 +2125,7 @@ public class DeviceIdleController extends SystemService } } - mConstants = mInjector.getConstants(this, mHandler, getContext().getContentResolver()); + mConstants = mInjector.getConstants(this); readConfigFileLocked(); updateWhitelistAppIdsLocked(); diff --git a/apex/jobscheduler/service/java/com/android/server/job/controllers/ConnectivityController.java b/apex/jobscheduler/service/java/com/android/server/job/controllers/ConnectivityController.java index f1c624d1d9f5..67997cf31501 100644 --- a/apex/jobscheduler/service/java/com/android/server/job/controllers/ConnectivityController.java +++ b/apex/jobscheduler/service/java/com/android/server/job/controllers/ConnectivityController.java @@ -22,6 +22,7 @@ import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_METERED; import static com.android.server.job.JobSchedulerService.RESTRICTED_INDEX; +import android.annotation.Nullable; import android.app.job.JobInfo; import android.net.ConnectivityManager; import android.net.ConnectivityManager.NetworkCallback; @@ -86,9 +87,12 @@ public final class ConnectivityController extends RestrictingController implemen @GuardedBy("mLock") private final SparseArray<ArraySet<JobStatus>> mRequestedWhitelistJobs = new SparseArray<>(); - /** List of currently available networks. */ + /** + * Set of currently available networks mapped to their latest network capabilities. Cache the + * latest capabilities to avoid unnecessary calls into ConnectivityManager. + */ @GuardedBy("mLock") - private final ArraySet<Network> mAvailableNetworks = new ArraySet<>(); + private final ArrayMap<Network, NetworkCapabilities> mAvailableNetworks = new ArrayMap<>(); private static final int MSG_DATA_SAVER_TOGGLED = 0; private static final int MSG_UID_RULES_CHANGES = 1; @@ -165,9 +169,8 @@ public final class ConnectivityController extends RestrictingController implemen public boolean isNetworkAvailable(JobStatus job) { synchronized (mLock) { for (int i = 0; i < mAvailableNetworks.size(); ++i) { - final Network network = mAvailableNetworks.valueAt(i); - final NetworkCapabilities capabilities = mConnManager.getNetworkCapabilities( - network); + final Network network = mAvailableNetworks.keyAt(i); + final NetworkCapabilities capabilities = mAvailableNetworks.valueAt(i); final boolean satisfied = isSatisfied(job, network, capabilities, mConstants); if (DEBUG) { Slog.v(TAG, "isNetworkAvailable(" + job + ") with network " + network @@ -427,9 +430,33 @@ public final class ConnectivityController extends RestrictingController implemen return false; } + @Nullable + private NetworkCapabilities getNetworkCapabilities(@Nullable Network network) { + if (network == null) { + return null; + } + synchronized (mLock) { + // There is technically a race here if the Network object is reused. This can happen + // only if that Network disconnects and the auto-incrementing network ID in + // ConnectivityService wraps. This should no longer be a concern if/when we only make + // use of asynchronous calls. + if (mAvailableNetworks.get(network) != null) { + return mAvailableNetworks.get(network); + } + + // This should almost never happen because any time a new network connects, the + // NetworkCallback would populate mAvailableNetworks. However, it's currently necessary + // because we also call synchronous methods such as getActiveNetworkForUid. + // TODO(134978280): remove after switching to callback-based APIs + final NetworkCapabilities capabilities = mConnManager.getNetworkCapabilities(network); + mAvailableNetworks.put(network, capabilities); + return capabilities; + } + } + private boolean updateConstraintsSatisfied(JobStatus jobStatus) { final Network network = mConnManager.getActiveNetworkForUid(jobStatus.getSourceUid()); - final NetworkCapabilities capabilities = mConnManager.getNetworkCapabilities(network); + final NetworkCapabilities capabilities = getNetworkCapabilities(network); return updateConstraintsSatisfied(jobStatus, network, capabilities); } @@ -470,19 +497,13 @@ public final class ConnectivityController extends RestrictingController implemen */ private void updateTrackedJobs(int filterUid, Network filterNetwork) { synchronized (mLock) { - // Since this is a really hot codepath, temporarily cache any - // answers that we get from ConnectivityManager. - final ArrayMap<Network, NetworkCapabilities> networkToCapabilities = new ArrayMap<>(); - boolean changed = false; if (filterUid == -1) { for (int i = mTrackedJobs.size() - 1; i >= 0; i--) { - changed |= updateTrackedJobsLocked(mTrackedJobs.valueAt(i), - filterNetwork, networkToCapabilities); + changed |= updateTrackedJobsLocked(mTrackedJobs.valueAt(i), filterNetwork); } } else { - changed = updateTrackedJobsLocked(mTrackedJobs.get(filterUid), - filterNetwork, networkToCapabilities); + changed = updateTrackedJobsLocked(mTrackedJobs.get(filterUid), filterNetwork); } if (changed) { mStateChangedListener.onControllerStateChanged(); @@ -490,18 +511,13 @@ public final class ConnectivityController extends RestrictingController implemen } } - private boolean updateTrackedJobsLocked(ArraySet<JobStatus> jobs, Network filterNetwork, - ArrayMap<Network, NetworkCapabilities> networkToCapabilities) { + private boolean updateTrackedJobsLocked(ArraySet<JobStatus> jobs, Network filterNetwork) { if (jobs == null || jobs.size() == 0) { return false; } final Network network = mConnManager.getActiveNetworkForUid(jobs.valueAt(0).getSourceUid()); - NetworkCapabilities capabilities = networkToCapabilities.get(network); - if (capabilities == null) { - capabilities = mConnManager.getNetworkCapabilities(network); - networkToCapabilities.put(network, capabilities); - } + final NetworkCapabilities capabilities = getNetworkCapabilities(network); final boolean networkMatch = (filterNetwork == null || Objects.equals(filterNetwork, network)); @@ -544,9 +560,9 @@ public final class ConnectivityController extends RestrictingController implemen @Override public void onAvailable(Network network) { if (DEBUG) Slog.v(TAG, "onAvailable: " + network); - synchronized (mLock) { - mAvailableNetworks.add(network); - } + // Documentation says not to call getNetworkCapabilities here but wait for + // onCapabilitiesChanged instead. onCapabilitiesChanged should be called immediately + // after this, so no need to update mAvailableNetworks here. } @Override @@ -554,6 +570,9 @@ public final class ConnectivityController extends RestrictingController implemen if (DEBUG) { Slog.v(TAG, "onCapabilitiesChanged: " + network); } + synchronized (mLock) { + mAvailableNetworks.put(network, capabilities); + } updateTrackedJobs(-1, network); } @@ -630,6 +649,8 @@ public final class ConnectivityController extends RestrictingController implemen pw.println("Available networks:"); pw.increaseIndent(); for (int i = 0; i < mAvailableNetworks.size(); i++) { + pw.print(mAvailableNetworks.keyAt(i)); + pw.print(": "); pw.println(mAvailableNetworks.valueAt(i)); } pw.decreaseIndent(); @@ -667,7 +688,7 @@ public final class ConnectivityController extends RestrictingController implemen mRequestedWhitelistJobs.keyAt(i)); } for (int i = 0; i < mAvailableNetworks.size(); i++) { - Network network = mAvailableNetworks.valueAt(i); + Network network = mAvailableNetworks.keyAt(i); if (network != null) { network.dumpDebug(proto, StateControllerProto.ConnectivityController.AVAILABLE_NETWORKS); diff --git a/apex/media/framework/Android.bp b/apex/media/framework/Android.bp index 4417b681efc3..ce4b030467a7 100644 --- a/apex/media/framework/Android.bp +++ b/apex/media/framework/Android.bp @@ -44,7 +44,6 @@ java_library { plugins: ["java_api_finder"], hostdex: true, // for hiddenapi check - visibility: ["//frameworks/av/apex:__subpackages__"], apex_available: [ "com.android.media", "test_com.android.media", @@ -83,7 +82,7 @@ filegroup { "java/android/media/MediaParser.java" ], path: "java", -} +} java_sdk_library { name: "framework-media", @@ -99,15 +98,7 @@ java_sdk_library { libs: [ "framework_media_annotation", ], - - // Allow access to the stubs from anywhere. - visibility: ["//visibility:public"], - - // Restrict access to implementation library. - impl_library_visibility: [ - "//visibility:override", // Ignore the visibility property. - "//frameworks/av/apex:__subpackages__", - ], + impl_library_visibility: ["//frameworks/av/apex:__subpackages__"], } diff --git a/apex/permission/framework/Android.bp b/apex/permission/framework/Android.bp index be553feb1d34..c0560f61460f 100644 --- a/apex/permission/framework/Android.bp +++ b/apex/permission/framework/Android.bp @@ -25,14 +25,8 @@ java_sdk_library { name: "framework-permission", defaults: ["framework-module-defaults"], - // Allow access to the stubs from anywhere. - visibility: ["//visibility:public"], - // Restrict access to implementation library. - impl_library_visibility: [ - "//visibility:override", // Ignore the visibility property. - "//frameworks/base/apex/permission:__subpackages__", - ], + impl_library_visibility: ["//frameworks/base/apex/permission:__subpackages__"], srcs: [ ":framework-permission-sources", diff --git a/apex/permission/service/Android.bp b/apex/permission/service/Android.bp index 7f3187949712..b7d843352d8e 100644 --- a/apex/permission/service/Android.bp +++ b/apex/permission/service/Android.bp @@ -23,15 +23,7 @@ filegroup { java_sdk_library { name: "service-permission", defaults: ["framework-system-server-module-defaults"], - visibility: [ - "//frameworks/base/services/core", - "//frameworks/base/apex/permission", - "//frameworks/base/apex/permission/testing", - "//frameworks/base/apex/permission/tests", - "//frameworks/base/services/tests/mockingservicestests", - ], impl_library_visibility: [ - "//visibility:override", "//frameworks/base/apex/permission/tests", "//frameworks/base/services/tests/mockingservicestests", "//frameworks/base/services/tests/servicestests", diff --git a/apex/statsd/framework/Android.bp b/apex/statsd/framework/Android.bp index b06f4019b480..bf4323ddfb0b 100644 --- a/apex/statsd/framework/Android.bp +++ b/apex/statsd/framework/Android.bp @@ -72,19 +72,7 @@ java_sdk_library { hostdex: true, // for hiddenapi check - visibility: [ - "//frameworks/base", // Framework - "//frameworks/base/apex/statsd:__subpackages__", // statsd apex - "//frameworks/base/packages/Tethering", // Tethering - "//frameworks/opt/net/wifi/service", // wifi service - "//packages/providers/MediaProvider", // MediaProvider apk - ], - - // Restrict access to implementation library. - impl_library_visibility: [ - "//visibility:override", // Ignore the visibility property. - "//frameworks/base/apex/statsd:__subpackages__", // statsd apex - ], + impl_library_visibility: ["//frameworks/base/apex/statsd/framework/test:__subpackages__"], apex_available: [ "com.android.os.statsd", diff --git a/apex/statsd/service/java/com/android/server/stats/StatsManagerService.java b/apex/statsd/service/java/com/android/server/stats/StatsManagerService.java index 97846f2397a5..1e3846bc4a0b 100644 --- a/apex/statsd/service/java/com/android/server/stats/StatsManagerService.java +++ b/apex/statsd/service/java/com/android/server/stats/StatsManagerService.java @@ -27,6 +27,7 @@ import android.os.Binder; import android.os.IPullAtomCallback; import android.os.IStatsManagerService; import android.os.IStatsd; +import android.os.PowerManager; import android.os.Process; import android.os.RemoteException; import android.util.ArrayMap; @@ -412,8 +413,13 @@ public class StatsManagerService extends IStatsManagerService.Stub { @Override public byte[] getData(long key, String packageName) throws IllegalStateException { enforceDumpAndUsageStatsPermission(packageName); + PowerManager powerManager = (PowerManager) + mContext.getSystemService(Context.POWER_SERVICE); + PowerManager.WakeLock wl = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, + /*tag=*/ StatsManagerService.class.getCanonicalName()); int callingUid = Binder.getCallingUid(); final long token = Binder.clearCallingIdentity(); + wl.acquire(); try { IStatsd statsd = waitForStatsd(); if (statsd != null) { @@ -423,6 +429,7 @@ public class StatsManagerService extends IStatsManagerService.Stub { Log.e(TAG, "Failed to getData with statsd"); throw new IllegalStateException(e.getMessage(), e); } finally { + wl.release(); Binder.restoreCallingIdentity(token); } throw new IllegalStateException("Failed to connect to statsd to getData"); diff --git a/api/current.txt b/api/current.txt index a1629f1a937e..5f32dec22de9 100644 --- a/api/current.txt +++ b/api/current.txt @@ -1005,7 +1005,7 @@ package android { field public static final int numericModifiers = 16844111; // 0x101054f field public static final int numericShortcut = 16843236; // 0x10101e4 field public static final int offset = 16844052; // 0x1010514 - field public static final int onClick = 16843375; // 0x101026f + field @Deprecated public static final int onClick = 16843375; // 0x101026f field public static final int oneshot = 16843159; // 0x1010197 field public static final int opacity = 16843550; // 0x101031e field public static final int opticalInsetBottom = 16844171; // 0x101058b @@ -6188,6 +6188,7 @@ package android.app { method public android.app.PictureInPictureParams build(); method public android.app.PictureInPictureParams.Builder setActions(java.util.List<android.app.RemoteAction>); method public android.app.PictureInPictureParams.Builder setAspectRatio(android.util.Rational); + method @NonNull public android.app.PictureInPictureParams.Builder setAutoEnterAllowed(boolean); method public android.app.PictureInPictureParams.Builder setSourceRectHint(android.graphics.Rect); } @@ -31302,6 +31303,7 @@ package android.net.wifi { @Deprecated public static class WifiConfiguration.GroupCipher { field @Deprecated public static final int CCMP = 3; // 0x3 + field @Deprecated public static final int GCMP_128 = 7; // 0x7 field @Deprecated public static final int GCMP_256 = 5; // 0x5 field @Deprecated public static final int SMS4 = 6; // 0x6 field @Deprecated public static final int TKIP = 2; // 0x2 @@ -31331,6 +31333,7 @@ package android.net.wifi { @Deprecated public static class WifiConfiguration.PairwiseCipher { field @Deprecated public static final int CCMP = 2; // 0x2 + field @Deprecated public static final int GCMP_128 = 5; // 0x5 field @Deprecated public static final int GCMP_256 = 3; // 0x3 field @Deprecated public static final int NONE = 0; // 0x0 field @Deprecated public static final int SMS4 = 4; // 0x4 @@ -31737,6 +31740,7 @@ package android.net.wifi.aware { method public void onPublishStarted(@NonNull android.net.wifi.aware.PublishDiscoverySession); method public void onServiceDiscovered(android.net.wifi.aware.PeerHandle, byte[], java.util.List<byte[]>); method public void onServiceDiscoveredWithinRange(android.net.wifi.aware.PeerHandle, byte[], java.util.List<byte[]>, int); + method public void onServiceLost(@NonNull android.net.wifi.aware.PeerHandle); method public void onSessionConfigFailed(); method public void onSessionConfigUpdated(); method public void onSessionTerminated(); @@ -31812,6 +31816,7 @@ package android.net.wifi.aware { method public void attach(@NonNull android.net.wifi.aware.AttachCallback, @NonNull android.net.wifi.aware.IdentityChangedListener, @Nullable android.os.Handler); method public android.net.wifi.aware.Characteristics getCharacteristics(); method public boolean isAvailable(); + method public boolean isDeviceAttached(); field public static final String ACTION_WIFI_AWARE_STATE_CHANGED = "android.net.wifi.aware.action.WIFI_AWARE_STATE_CHANGED"; field public static final int WIFI_AWARE_DATA_PATH_ROLE_INITIATOR = 0; // 0x0 field public static final int WIFI_AWARE_DATA_PATH_ROLE_RESPONDER = 1; // 0x1 @@ -48399,7 +48404,8 @@ package android.telephony { method public boolean isVoiceCapable(); method public boolean isVoicemailVibrationEnabled(android.telecom.PhoneAccountHandle); method public boolean isWorldPhone(); - method public void listen(android.telephony.PhoneStateListener, int); + method @Deprecated public void listen(android.telephony.PhoneStateListener, int); + method public void listen(long, @NonNull android.telephony.PhoneStateListener); method @RequiresPermission(android.Manifest.permission.ACCESS_FINE_LOCATION) public void requestCellInfoUpdate(@NonNull java.util.concurrent.Executor, @NonNull android.telephony.TelephonyManager.CellInfoCallback); method @RequiresPermission(allOf={android.Manifest.permission.MODIFY_PHONE_STATE, android.Manifest.permission.ACCESS_FINE_LOCATION}) public android.telephony.NetworkScan requestNetworkScan(android.telephony.NetworkScanRequest, java.util.concurrent.Executor, android.telephony.TelephonyScanManager.NetworkScanCallback); method public void sendDialerSpecialCode(String); diff --git a/api/module-lib-current.txt b/api/module-lib-current.txt index 17545a469cb8..c12d897b9d72 100644 --- a/api/module-lib-current.txt +++ b/api/module-lib-current.txt @@ -35,17 +35,32 @@ package android.graphics { package android.media { public class AudioManager { + method public void adjustStreamVolumeForUid(int, int, int, @NonNull String, int, int, int); + method public void adjustSuggestedStreamVolumeForUid(int, int, int, @NonNull String, int, int, int); + method public void setStreamVolumeForUid(int, int, int, @NonNull String, int, int, int); field public static final int FLAG_FROM_KEY = 4096; // 0x1000 } + public static final class MediaMetadata.Builder { + ctor public MediaMetadata.Builder(@NonNull android.media.MediaMetadata, @IntRange(from=1) int); + } + } package android.media.session { + public static final class MediaController.PlaybackInfo implements android.os.Parcelable { + ctor public MediaController.PlaybackInfo(int, int, @IntRange(from=0) int, @IntRange(from=0) int, @NonNull android.media.AudioAttributes, @Nullable String); + } + public final class MediaSession { field public static final int FLAG_EXCLUSIVE_GLOBAL_PRIORITY = 65536; // 0x10000 } + public static final class MediaSession.Token implements android.os.Parcelable { + method public int getUid(); + } + public final class MediaSessionManager { method public void dispatchMediaKeyEventAsSystemService(@NonNull android.view.KeyEvent); method public boolean dispatchMediaKeyEventAsSystemService(@NonNull android.media.session.MediaSession.Token, @NonNull android.view.KeyEvent); @@ -129,6 +144,14 @@ package android.os { } +package android.provider { + + public final class DeviceConfig { + field public static final String NAMESPACE_DEVICE_IDLE = "device_idle"; + } + +} + package android.util { public class AtomicFile { diff --git a/api/system-current.txt b/api/system-current.txt index dbe2e318a7ba..b908cae38ca1 100755..100644 --- a/api/system-current.txt +++ b/api/system-current.txt @@ -205,6 +205,7 @@ package android { field public static final String REVOKE_RUNTIME_PERMISSIONS = "android.permission.REVOKE_RUNTIME_PERMISSIONS"; field public static final String SCORE_NETWORKS = "android.permission.SCORE_NETWORKS"; field public static final String SECURE_ELEMENT_PRIVILEGED_OPERATION = "android.permission.SECURE_ELEMENT_PRIVILEGED_OPERATION"; + field public static final String SEND_CATEGORY_CAR_NOTIFICATIONS = "android.permission.SEND_CATEGORY_CAR_NOTIFICATIONS"; field public static final String SEND_DEVICE_CUSTOMIZATION_READY = "android.permission.SEND_DEVICE_CUSTOMIZATION_READY"; field public static final String SEND_SHOW_SUSPENDED_APP_DETAILS = "android.permission.SEND_SHOW_SUSPENDED_APP_DETAILS"; field public static final String SEND_SMS_NO_CONFIRMATION = "android.permission.SEND_SMS_NO_CONFIRMATION"; @@ -4199,8 +4200,10 @@ package android.media { public class AudioManager { method @Deprecated public int abandonAudioFocus(android.media.AudioManager.OnAudioFocusChangeListener, android.media.AudioAttributes); method @Deprecated @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public void addOnPreferredDeviceForStrategyChangedListener(@NonNull java.util.concurrent.Executor, @NonNull android.media.AudioManager.OnPreferredDeviceForStrategyChangedListener) throws java.lang.SecurityException; + method @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public void addOnPreferredDevicesForCapturePresetChangedListener(@NonNull java.util.concurrent.Executor, @NonNull android.media.AudioManager.OnPreferredDevicesForCapturePresetChangedListener) throws java.lang.SecurityException; method @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public void addOnPreferredDevicesForStrategyChangedListener(@NonNull java.util.concurrent.Executor, @NonNull android.media.AudioManager.OnPreferredDevicesForStrategyChangedListener) throws java.lang.SecurityException; method public void clearAudioServerStateCallback(); + method @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public boolean clearPreferredDevicesForCapturePreset(int); method @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public int dispatchAudioFocusChange(@NonNull android.media.AudioFocusInfo, int, @NonNull android.media.audiopolicy.AudioPolicy); method @IntRange(from=0) public long getAdditionalOutputDeviceDelay(@NonNull android.media.AudioDeviceInfo); method @NonNull @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public static java.util.List<android.media.audiopolicy.AudioProductStrategy> getAudioProductStrategies(); @@ -4211,6 +4214,7 @@ package android.media { method @IntRange(from=0) @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public int getMaxVolumeIndexForAttributes(@NonNull android.media.AudioAttributes); method @IntRange(from=0) @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public int getMinVolumeIndexForAttributes(@NonNull android.media.AudioAttributes); method @Nullable @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public android.media.AudioDeviceAttributes getPreferredDeviceForStrategy(@NonNull android.media.audiopolicy.AudioProductStrategy); + method @NonNull @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public java.util.List<android.media.AudioDeviceAttributes> getPreferredDevicesForCapturePreset(int); method @NonNull @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public java.util.List<android.media.AudioDeviceAttributes> getPreferredDevicesForStrategy(@NonNull android.media.audiopolicy.AudioProductStrategy); method @NonNull @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public int[] getSupportedSystemUsages(); method @IntRange(from=0) @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public int getVolumeIndexForAttributes(@NonNull android.media.AudioAttributes); @@ -4219,6 +4223,7 @@ package android.media { method @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public int registerAudioPolicy(@NonNull android.media.audiopolicy.AudioPolicy); method public void registerVolumeGroupCallback(@NonNull java.util.concurrent.Executor, @NonNull android.media.AudioManager.VolumeGroupCallback); method @Deprecated @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public void removeOnPreferredDeviceForStrategyChangedListener(@NonNull android.media.AudioManager.OnPreferredDeviceForStrategyChangedListener); + method @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public void removeOnPreferredDevicesForCapturePresetChangedListener(@NonNull android.media.AudioManager.OnPreferredDevicesForCapturePresetChangedListener); method @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public void removeOnPreferredDevicesForStrategyChangedListener(@NonNull android.media.AudioManager.OnPreferredDevicesForStrategyChangedListener); method @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public boolean removePreferredDeviceForStrategy(@NonNull android.media.audiopolicy.AudioProductStrategy); method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public int requestAudioFocus(android.media.AudioManager.OnAudioFocusChangeListener, @NonNull android.media.AudioAttributes, int, int) throws java.lang.IllegalArgumentException; @@ -4228,6 +4233,7 @@ package android.media { method public void setAudioServerStateCallback(@NonNull java.util.concurrent.Executor, @NonNull android.media.AudioManager.AudioServerStateCallback); method @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public void setDeviceVolumeBehavior(@NonNull android.media.AudioDeviceAttributes, int); method @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public void setFocusRequestResult(@NonNull android.media.AudioFocusInfo, int, @NonNull android.media.audiopolicy.AudioPolicy); + method @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public boolean setPreferredDeviceForCapturePreset(int, @NonNull android.media.AudioDeviceAttributes); method @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public boolean setPreferredDeviceForStrategy(@NonNull android.media.audiopolicy.AudioProductStrategy, @NonNull android.media.AudioDeviceAttributes); method @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public boolean setPreferredDevicesForStrategy(@NonNull android.media.audiopolicy.AudioProductStrategy, @NonNull java.util.List<android.media.AudioDeviceAttributes>); method @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public void setSupportedSystemUsages(@NonNull int[]); @@ -4257,6 +4263,10 @@ package android.media { method @Deprecated public void onPreferredDeviceForStrategyChanged(@NonNull android.media.audiopolicy.AudioProductStrategy, @Nullable android.media.AudioDeviceAttributes); } + public static interface AudioManager.OnPreferredDevicesForCapturePresetChangedListener { + method public void onPreferredDevicesForCapturePresetChanged(int, @NonNull java.util.List<android.media.AudioDeviceAttributes>); + } + public static interface AudioManager.OnPreferredDevicesForStrategyChangedListener { method public void onPreferredDevicesForStrategyChanged(@NonNull android.media.audiopolicy.AudioProductStrategy, @NonNull java.util.List<android.media.AudioDeviceAttributes>); } @@ -4334,11 +4344,8 @@ package android.media { field @RequiresPermission(android.Manifest.permission.CAPTURE_AUDIO_OUTPUT) public static final int RADIO_TUNER = 1998; // 0x7ce } - public final class MediaTranscodeManager implements java.lang.AutoCloseable { - method public void close(); + public final class MediaTranscodeManager { method @NonNull public android.media.MediaTranscodeManager.TranscodingJob enqueueRequest(@NonNull android.media.MediaTranscodeManager.TranscodingRequest, @NonNull java.util.concurrent.Executor, @NonNull android.media.MediaTranscodeManager.OnTranscodingFinishedListener) throws java.io.FileNotFoundException; - method protected void finalize(); - field public static final int PRIORITY_OFFLINE = 2; // 0x2 field public static final int PRIORITY_REALTIME = 1; // 0x1 field public static final int TRANSCODING_TYPE_VIDEO = 1; // 0x1 } @@ -4367,7 +4374,7 @@ package android.media { } @java.lang.FunctionalInterface public static interface MediaTranscodeManager.TranscodingJob.OnProgressUpdateListener { - method public void onProgressUpdate(@IntRange(from=0, to=100) int); + method public void onProgressUpdate(@NonNull android.media.MediaTranscodeManager.TranscodingJob, @IntRange(from=0, to=100) int); } public static final class MediaTranscodeManager.TranscodingRequest { @@ -4388,6 +4395,14 @@ package android.media { method @NonNull public android.media.MediaTranscodeManager.TranscodingRequest.Builder setVideoTrackFormat(@NonNull android.media.MediaFormat); } + public static class MediaTranscodeManager.TranscodingRequest.MediaFormatResolver { + ctor public MediaTranscodeManager.TranscodingRequest.MediaFormatResolver(); + method @Nullable public android.media.MediaFormat resolveVideoFormat(); + method @NonNull public android.media.MediaTranscodeManager.TranscodingRequest.MediaFormatResolver setSourceVideoFormatHint(@NonNull android.media.MediaFormat); + method public boolean shouldTranscode(); + field public static final String CAPS_SUPPORTS_HEVC = "support-hevc"; + } + public class PlayerProxy { method public void pause(); method public void setPan(float); @@ -7329,6 +7344,7 @@ package android.net.wifi { method @Deprecated @Nullable @RequiresPermission(android.Manifest.permission.ACCESS_WIFI_STATE) public android.net.wifi.WifiConfiguration getWifiApConfiguration(); method @RequiresPermission(android.Manifest.permission.ACCESS_WIFI_STATE) public int getWifiApState(); method @NonNull @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.NETWORK_SETUP_WIZARD}) public java.util.List<android.net.wifi.WifiConfiguration> getWifiConfigForMatchedNetworkSuggestionsSharedWithUser(@NonNull java.util.List<android.net.wifi.ScanResult>); + method public boolean is60GHzBandSupported(); method public boolean isApMacRandomizationSupported(); method public boolean isConnectedMacRandomizationSupported(); method @Deprecated public boolean isDeviceToDeviceRttSupported(); @@ -7568,6 +7584,7 @@ package android.net.wifi { field public static final int WIFI_BAND_5_GHZ = 2; // 0x2 field public static final int WIFI_BAND_5_GHZ_DFS_ONLY = 4; // 0x4 field public static final int WIFI_BAND_5_GHZ_WITH_DFS = 6; // 0x6 + field public static final int WIFI_BAND_60_GHZ = 16; // 0x10 field public static final int WIFI_BAND_6_GHZ = 8; // 0x8 field public static final int WIFI_BAND_BOTH = 3; // 0x3 field public static final int WIFI_BAND_BOTH_WITH_DFS = 7; // 0x7 @@ -7807,6 +7824,8 @@ package android.net.wifi.nl80211 { field public static final int BSS_CAPABILITY_CF_POLL_REQUEST = 8; // 0x8 field public static final int BSS_CAPABILITY_CHANNEL_AGILITY = 128; // 0x80 field public static final int BSS_CAPABILITY_DELAYED_BLOCK_ACK = 16384; // 0x4000 + field public static final int BSS_CAPABILITY_DMG_ESS = 3; // 0x3 + field public static final int BSS_CAPABILITY_DMG_IBSS = 1; // 0x1 field public static final int BSS_CAPABILITY_DSSS_OFDM = 8192; // 0x2000 field public static final int BSS_CAPABILITY_ESS = 1; // 0x1 field public static final int BSS_CAPABILITY_IBSS = 2; // 0x2 @@ -7876,7 +7895,7 @@ package android.net.wifi.nl80211 { method @NonNull public java.util.List<android.net.wifi.nl80211.NativeScanResult> getScanResults(@NonNull String, int); method @Nullable public android.net.wifi.nl80211.WifiNl80211Manager.TxPacketCounters getTxPacketCounters(@NonNull String); method @Nullable public static android.net.wifi.nl80211.WifiNl80211Manager.OemSecurityType parseOemSecurityTypeElement(int, int, @NonNull byte[]); - method public boolean registerApCallback(@NonNull String, @NonNull java.util.concurrent.Executor, @NonNull android.net.wifi.nl80211.WifiNl80211Manager.SoftApCallback); + method @Deprecated public boolean registerApCallback(@NonNull String, @NonNull java.util.concurrent.Executor, @NonNull android.net.wifi.nl80211.WifiNl80211Manager.SoftApCallback); method public void sendMgmtFrame(@NonNull String, @NonNull byte[], int, @NonNull java.util.concurrent.Executor, @NonNull android.net.wifi.nl80211.WifiNl80211Manager.SendMgmtFrameCallback); method public void setOnServiceDeadCallback(@NonNull Runnable); method public boolean setupInterfaceForClientMode(@NonNull String, @NonNull java.util.concurrent.Executor, @NonNull android.net.wifi.nl80211.WifiNl80211Manager.ScanEventCallback, @NonNull android.net.wifi.nl80211.WifiNl80211Manager.ScanEventCallback); @@ -7927,10 +7946,10 @@ package android.net.wifi.nl80211 { field public final int txBitrateMbps; } - public static interface WifiNl80211Manager.SoftApCallback { - method public void onConnectedClientsChanged(@NonNull android.net.wifi.nl80211.NativeWifiClient, boolean); - method public void onFailure(); - method public void onSoftApChannelSwitched(int, int); + @Deprecated public static interface WifiNl80211Manager.SoftApCallback { + method @Deprecated public void onConnectedClientsChanged(@NonNull android.net.wifi.nl80211.NativeWifiClient, boolean); + method @Deprecated public void onFailure(); + method @Deprecated public void onSoftApChannelSwitched(int, int); } public static class WifiNl80211Manager.TxPacketCounters { @@ -10876,6 +10895,7 @@ package android.telephony { method @Deprecated public void onOutgoingEmergencyCall(@NonNull android.telephony.emergency.EmergencyNumber); method public void onOutgoingEmergencyCall(@NonNull android.telephony.emergency.EmergencyNumber, int); method public void onOutgoingEmergencySms(@NonNull android.telephony.emergency.EmergencyNumber); + method public void onPhysicalChannelConfigurationChanged(@NonNull java.util.List<android.telephony.PhysicalChannelConfig>); method @RequiresPermission("android.permission.READ_PRECISE_PHONE_STATE") public void onPreciseCallStateChanged(@NonNull android.telephony.PreciseCallState); method public void onRadioPowerStateChanged(int); method public void onSrvccStateChanged(int); @@ -10883,12 +10903,29 @@ package android.telephony { field @RequiresPermission("android.permission.READ_PRECISE_PHONE_STATE") public static final int LISTEN_CALL_ATTRIBUTES_CHANGED = 67108864; // 0x4000000 field @RequiresPermission(android.Manifest.permission.READ_ACTIVE_EMERGENCY_SESSION) public static final int LISTEN_OUTGOING_EMERGENCY_CALL = 268435456; // 0x10000000 field @RequiresPermission(android.Manifest.permission.READ_ACTIVE_EMERGENCY_SESSION) public static final int LISTEN_OUTGOING_EMERGENCY_SMS = 536870912; // 0x20000000 + field @RequiresPermission(android.Manifest.permission.READ_PRECISE_PHONE_STATE) public static final long LISTEN_PHYSICAL_CHANNEL_CONFIGURATION = 4294967296L; // 0x100000000L field @RequiresPermission("android.permission.READ_PRECISE_PHONE_STATE") public static final int LISTEN_PRECISE_CALL_STATE = 2048; // 0x800 field @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public static final int LISTEN_RADIO_POWER_STATE_CHANGED = 8388608; // 0x800000 field @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public static final int LISTEN_SRVCC_STATE_CHANGED = 16384; // 0x4000 field @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public static final int LISTEN_VOICE_ACTIVATION_STATE = 131072; // 0x20000 } + public final class PhysicalChannelConfig implements android.os.Parcelable { + method public int describeContents(); + method public int getCellBandwidthDownlink(); + method public int getChannelNumber(); + method public int getConnectionStatus(); + method public int getNetworkType(); + method @IntRange(from=0, to=1007) public int getPhysicalCellId(); + method public void writeToParcel(@NonNull android.os.Parcel, int); + field public static final int CHANNEL_NUMBER_UNKNOWN = -1; // 0xffffffff + field public static final int CONNECTION_PRIMARY_SERVING = 1; // 0x1 + field public static final int CONNECTION_SECONDARY_SERVING = 2; // 0x2 + field public static final int CONNECTION_UNKNOWN = -1; // 0xffffffff + field @NonNull public static final android.os.Parcelable.Creator<android.telephony.PhysicalChannelConfig> CREATOR; + field public static final int PHYSICAL_CELL_ID_UNKNOWN = -1; // 0xffffffff + } + public final class PreciseCallState implements android.os.Parcelable { ctor public PreciseCallState(int, int, int, int, int); method public int describeContents(); diff --git a/api/test-current.txt b/api/test-current.txt index 2dd740924275..de2919b8936a 100644 --- a/api/test-current.txt +++ b/api/test-current.txt @@ -133,7 +133,6 @@ package android.app { public class ActivityTaskManager { method @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS) public void clearLaunchParamsForPackages(java.util.List<java.lang.String>); method public static boolean currentUiModeSupportsErrorDialogs(@NonNull android.content.Context); - method @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS) public String listAllStacks(); method @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS) public void moveTaskToStack(int, int, boolean); method @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS) public boolean moveTopActivityToPinnedStack(int, android.graphics.Rect); method @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS) public void removeStacksInWindowingModes(int[]) throws java.lang.SecurityException; @@ -1819,11 +1818,8 @@ package android.media { method @NonNull public String getOriginalId(); } - public final class MediaTranscodeManager implements java.lang.AutoCloseable { - method public void close(); + public final class MediaTranscodeManager { method @NonNull public android.media.MediaTranscodeManager.TranscodingJob enqueueRequest(@NonNull android.media.MediaTranscodeManager.TranscodingRequest, @NonNull java.util.concurrent.Executor, @NonNull android.media.MediaTranscodeManager.OnTranscodingFinishedListener) throws java.io.FileNotFoundException; - method protected void finalize(); - field public static final int PRIORITY_OFFLINE = 2; // 0x2 field public static final int PRIORITY_REALTIME = 1; // 0x1 field public static final int TRANSCODING_TYPE_VIDEO = 1; // 0x1 } @@ -1852,7 +1848,7 @@ package android.media { } @java.lang.FunctionalInterface public static interface MediaTranscodeManager.TranscodingJob.OnProgressUpdateListener { - method public void onProgressUpdate(@IntRange(from=0, to=100) int); + method public void onProgressUpdate(@NonNull android.media.MediaTranscodeManager.TranscodingJob, @IntRange(from=0, to=100) int); } public static final class MediaTranscodeManager.TranscodingRequest { @@ -1873,6 +1869,14 @@ package android.media { method @NonNull public android.media.MediaTranscodeManager.TranscodingRequest.Builder setVideoTrackFormat(@NonNull android.media.MediaFormat); } + public static class MediaTranscodeManager.TranscodingRequest.MediaFormatResolver { + ctor public MediaTranscodeManager.TranscodingRequest.MediaFormatResolver(); + method @Nullable public android.media.MediaFormat resolveVideoFormat(); + method @NonNull public android.media.MediaTranscodeManager.TranscodingRequest.MediaFormatResolver setSourceVideoFormatHint(@NonNull android.media.MediaFormat); + method public boolean shouldTranscode(); + field public static final String CAPS_SUPPORTS_HEVC = "support-hevc"; + } + public final class PlaybackParams implements android.os.Parcelable { method public int getAudioStretchMode(); method public android.media.PlaybackParams setAudioStretchMode(int); @@ -3294,6 +3298,7 @@ package android.provider { field public static final String NAMESPACE_AUTOFILL = "autofill"; field public static final String NAMESPACE_BIOMETRICS = "biometrics"; field public static final String NAMESPACE_CONTENT_CAPTURE = "content_capture"; + field public static final String NAMESPACE_DEVICE_IDLE = "device_idle"; field public static final String NAMESPACE_JOB_SCHEDULER = "jobscheduler"; field public static final String NAMESPACE_PERMISSIONS = "permissions"; field public static final String NAMESPACE_PRIVACY = "privacy"; @@ -5623,18 +5628,18 @@ package android.window { public class TaskOrganizer extends android.window.WindowOrganizer { ctor public TaskOrganizer(); - method @Nullable @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS) public static android.app.ActivityManager.RunningTaskInfo createRootTask(int, int); - method @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS) public static boolean deleteRootTask(@NonNull android.window.WindowContainerToken); - method @Nullable @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS) public static java.util.List<android.app.ActivityManager.RunningTaskInfo> getChildTasks(@NonNull android.window.WindowContainerToken, @NonNull int[]); - method @Nullable @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS) public static android.window.WindowContainerToken getImeTarget(int); - method @Nullable @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS) public static java.util.List<android.app.ActivityManager.RunningTaskInfo> getRootTasks(int, @NonNull int[]); + method @Nullable @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS) public android.app.ActivityManager.RunningTaskInfo createRootTask(int, int); + method @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS) public boolean deleteRootTask(@NonNull android.window.WindowContainerToken); + method @Nullable @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS) public java.util.List<android.app.ActivityManager.RunningTaskInfo> getChildTasks(@NonNull android.window.WindowContainerToken, @NonNull int[]); + method @Nullable @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS) public android.window.WindowContainerToken getImeTarget(int); + method @Nullable @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS) public java.util.List<android.app.ActivityManager.RunningTaskInfo> getRootTasks(int, @NonNull int[]); method @BinderThread public void onBackPressedOnTaskRoot(@NonNull android.app.ActivityManager.RunningTaskInfo); method @BinderThread public void onTaskAppeared(@NonNull android.app.ActivityManager.RunningTaskInfo, @NonNull android.view.SurfaceControl); method @BinderThread public void onTaskInfoChanged(@NonNull android.app.ActivityManager.RunningTaskInfo); method @BinderThread public void onTaskVanished(@NonNull android.app.ActivityManager.RunningTaskInfo); method @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS) public final void registerOrganizer(); method @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS) public void setInterceptBackPressedOnTaskRoot(@NonNull android.window.WindowContainerToken, boolean); - method @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS) public static void setLaunchRoot(int, @NonNull android.window.WindowContainerToken); + method @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS) public void setLaunchRoot(int, @NonNull android.window.WindowContainerToken); method @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS) public final void unregisterOrganizer(); } @@ -5671,7 +5676,7 @@ package android.window { public class WindowOrganizer { ctor public WindowOrganizer(); method @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS) public int applySyncTransaction(@NonNull android.window.WindowContainerTransaction, @NonNull android.window.WindowContainerTransactionCallback); - method @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS) public static void applyTransaction(@NonNull android.window.WindowContainerTransaction); + method @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS) public void applyTransaction(@NonNull android.window.WindowContainerTransaction); } } diff --git a/cmds/hid/jni/com_android_commands_hid_Device.cpp b/cmds/hid/jni/com_android_commands_hid_Device.cpp index 1e200c52a207..437a87e8df54 100644 --- a/cmds/hid/jni/com_android_commands_hid_Device.cpp +++ b/cmds/hid/jni/com_android_commands_hid_Device.cpp @@ -27,9 +27,9 @@ #include <cstring> #include <memory> -#include <android/log.h> #include <android/looper.h> #include <jni.h> +#include <log/log.h> #include <nativehelper/JNIHelp.h> #include <nativehelper/ScopedLocalRef.h> #include <nativehelper/ScopedPrimitiveArray.h> @@ -37,10 +37,8 @@ #include <android-base/stringprintf.h> -#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR,LOG_TAG,__VA_ARGS__) -#define LOGW(...) __android_log_print(ANDROID_LOG_WARN,LOG_TAG,__VA_ARGS__) -#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG,LOG_TAG,__VA_ARGS__) -#define LOGI(...) __android_log_print(ANDROID_LOG_INFO,LOG_TAG,__VA_ARGS__) +// Log debug messages about the output. +static constexpr bool DEBUG_OUTPUT = false; namespace android { namespace uhid { @@ -61,7 +59,7 @@ static int handleLooperEvents(int /* fd */, int events, void* data) { static void checkAndClearException(JNIEnv* env, const char* methodName) { if (env->ExceptionCheck()) { - LOGE("An exception was thrown by callback '%s'.", methodName); + ALOGE("An exception was thrown by callback '%s'.", methodName); env->ExceptionClear(); } } @@ -115,9 +113,9 @@ void DeviceCallback::onDeviceGetReport(uint32_t requestId, uint8_t reportId) { checkAndClearException(env, "onDeviceGetReport"); } -void DeviceCallback::onDeviceOutput(const std::vector<uint8_t>& data) { +void DeviceCallback::onDeviceOutput(uint8_t rType, const std::vector<uint8_t>& data) { JNIEnv* env = getJNIEnv(); - env->CallVoidMethod(mCallbackObject, gDeviceCallbackClassInfo.onDeviceOutput, + env->CallVoidMethod(mCallbackObject, gDeviceCallbackClassInfo.onDeviceOutput, rType, toJbyteArray(env, data).get()); checkAndClearException(env, "onDeviceOutput"); } @@ -133,13 +131,13 @@ std::unique_ptr<Device> Device::open(int32_t id, const char* name, int32_t vid, std::unique_ptr<DeviceCallback> callback) { size_t size = descriptor.size(); if (size > HID_MAX_DESCRIPTOR_SIZE) { - LOGE("Received invalid hid report with descriptor size %zu, skipping", size); + ALOGE("Received invalid hid report with descriptor size %zu, skipping", size); return nullptr; } android::base::unique_fd fd(::open(UHID_PATH, O_RDWR | O_CLOEXEC)); if (!fd.ok()) { - LOGE("Failed to open uhid: %s", strerror(errno)); + ALOGE("Failed to open uhid: %s", strerror(errno)); return nullptr; } @@ -159,14 +157,14 @@ std::unique_ptr<Device> Device::open(int32_t id, const char* name, int32_t vid, errno = 0; ssize_t ret = TEMP_FAILURE_RETRY(::write(fd, &ev, sizeof(ev))); if (ret < 0 || ret != sizeof(ev)) { - LOGE("Failed to create uhid node: %s", strerror(errno)); + ALOGE("Failed to create uhid node: %s", strerror(errno)); return nullptr; } // Wait for the device to actually be created. ret = TEMP_FAILURE_RETRY(::read(fd, &ev, sizeof(ev))); if (ret < 0 || ev.type != UHID_START) { - LOGE("uhid node failed to start: %s", strerror(errno)); + ALOGE("uhid node failed to start: %s", strerror(errno)); return nullptr; } // using 'new' to access non-public constructor @@ -177,7 +175,7 @@ Device::Device(int32_t id, android::base::unique_fd fd, std::unique_ptr<DeviceCa : mId(id), mFd(std::move(fd)), mDeviceCallback(std::move(callback)) { ALooper* aLooper = ALooper_forThread(); if (aLooper == NULL) { - LOGE("Could not get ALooper, ALooper_forThread returned NULL"); + ALOGE("Could not get ALooper, ALooper_forThread returned NULL"); aLooper = ALooper_prepare(ALOOPER_PREPARE_ALLOW_NON_CALLBACKS); } ALooper_addFd(aLooper, mFd, 0, ALOOPER_EVENT_INPUT, handleLooperEvents, @@ -189,7 +187,7 @@ Device::~Device() { if (looper != NULL) { ALooper_removeFd(looper, mFd); } else { - LOGE("Could not remove fd, ALooper_forThread() returned NULL!"); + ALOGE("Could not remove fd, ALooper_forThread() returned NULL!"); } struct uhid_event ev = {}; ev.type = UHID_DESTROY; @@ -200,13 +198,13 @@ Device::~Device() { static void writeEvent(int fd, struct uhid_event& ev, const char* messageType) { ssize_t ret = TEMP_FAILURE_RETRY(::write(fd, &ev, sizeof(ev))); if (ret < 0 || ret != sizeof(ev)) { - LOGE("Failed to send uhid_event %s: %s", messageType, strerror(errno)); + ALOGE("Failed to send uhid_event %s: %s", messageType, strerror(errno)); } } void Device::sendReport(const std::vector<uint8_t>& report) const { if (report.size() > UHID_DATA_MAX) { - LOGE("Received invalid report of size %zu, skipping", report.size()); + ALOGE("Received invalid report of size %zu, skipping", report.size()); return; } @@ -230,14 +228,14 @@ void Device::sendGetFeatureReportReply(uint32_t id, const std::vector<uint8_t>& int Device::handleEvents(int events) { if (events & (ALOOPER_EVENT_ERROR | ALOOPER_EVENT_HANGUP)) { - LOGE("uhid node was closed or an error occurred. events=0x%x", events); + ALOGE("uhid node was closed or an error occurred. events=0x%x", events); mDeviceCallback->onDeviceError(); return 0; } struct uhid_event ev; ssize_t ret = TEMP_FAILURE_RETRY(::read(mFd, &ev, sizeof(ev))); if (ret < 0) { - LOGE("Failed to read from uhid node: %s", strerror(errno)); + ALOGE("Failed to read from uhid node: %s", strerror(errno)); mDeviceCallback->onDeviceError(); return 0; } @@ -254,23 +252,28 @@ int Device::handleEvents(int events) { case UHID_SET_REPORT: { const struct uhid_set_report_req& set_report = ev.u.set_report; if (set_report.size > UHID_DATA_MAX) { - LOGE("SET_REPORT contains too much data: size = %" PRIu16, set_report.size); + ALOGE("SET_REPORT contains too much data: size = %" PRIu16, set_report.size); return 0; } std::vector<uint8_t> data(set_report.data, set_report.data + set_report.size); - LOGI("Received SET_REPORT: id=%" PRIu32 " rnum=%" PRIu8 " data=%s", set_report.id, - set_report.rnum, toString(data).c_str()); + if (DEBUG_OUTPUT) { + ALOGD("Received SET_REPORT: id=%" PRIu32 " rnum=%" PRIu8 " data=%s", set_report.id, + set_report.rnum, toString(data).c_str()); + } break; } case UHID_OUTPUT: { struct uhid_output_req& output = ev.u.output; std::vector<uint8_t> data(output.data, output.data + output.size); - mDeviceCallback->onDeviceOutput(data); + if (DEBUG_OUTPUT) { + ALOGD("UHID_OUTPUT rtype=%" PRIu8 " data=%s", output.rtype, toString(data).c_str()); + } + mDeviceCallback->onDeviceOutput(output.rtype, data); break; } default: { - LOGI("Unhandled event type: %" PRIu32, ev.type); + ALOGI("Unhandled event type: %" PRIu32, ev.type); break; } } @@ -318,7 +321,7 @@ static void sendReport(JNIEnv* env, jclass /* clazz */, jlong ptr, jbyteArray ra if (d) { d->sendReport(report); } else { - LOGE("Could not send report, Device* is null!"); + ALOGE("Could not send report, Device* is null!"); } } @@ -329,7 +332,7 @@ static void sendGetFeatureReportReply(JNIEnv* env, jclass /* clazz */, jlong ptr std::vector<uint8_t> report = getData(env, rawReport); d->sendGetFeatureReportReply(id, report); } else { - LOGE("Could not send get feature report reply, Device* is null!"); + ALOGE("Could not send get feature report reply, Device* is null!"); } } @@ -354,7 +357,7 @@ static JNINativeMethod sMethods[] = { int register_com_android_commands_hid_Device(JNIEnv* env) { jclass clazz = env->FindClass("com/android/commands/hid/Device$DeviceCallback"); if (clazz == NULL) { - LOGE("Unable to find class 'DeviceCallback'"); + ALOGE("Unable to find class 'DeviceCallback'"); return JNI_ERR; } uhid::gDeviceCallbackClassInfo.onDeviceOpen = @@ -362,12 +365,12 @@ int register_com_android_commands_hid_Device(JNIEnv* env) { uhid::gDeviceCallbackClassInfo.onDeviceGetReport = env->GetMethodID(clazz, "onDeviceGetReport", "(II)V"); uhid::gDeviceCallbackClassInfo.onDeviceOutput = - env->GetMethodID(clazz, "onDeviceOutput", "([B)V"); + env->GetMethodID(clazz, "onDeviceOutput", "(B[B)V"); uhid::gDeviceCallbackClassInfo.onDeviceError = env->GetMethodID(clazz, "onDeviceError", "()V"); if (uhid::gDeviceCallbackClassInfo.onDeviceOpen == NULL || uhid::gDeviceCallbackClassInfo.onDeviceError == NULL) { - LOGE("Unable to obtain onDeviceOpen or onDeviceError methods"); + ALOGE("Unable to obtain onDeviceOpen or onDeviceError methods"); return JNI_ERR; } diff --git a/cmds/hid/jni/com_android_commands_hid_Device.h b/cmds/hid/jni/com_android_commands_hid_Device.h index 7202b45adcde..5483b40831a0 100644 --- a/cmds/hid/jni/com_android_commands_hid_Device.h +++ b/cmds/hid/jni/com_android_commands_hid_Device.h @@ -31,7 +31,7 @@ public: void onDeviceOpen(); void onDeviceGetReport(uint32_t requestId, uint8_t reportId); - void onDeviceOutput(const std::vector<uint8_t>& data); + void onDeviceOutput(uint8_t rType, const std::vector<uint8_t>& data); void onDeviceError(); private: diff --git a/cmds/hid/src/com/android/commands/hid/Device.java b/cmds/hid/src/com/android/commands/hid/Device.java index dade41511ae6..20b4bd86baec 100644 --- a/cmds/hid/src/com/android/commands/hid/Device.java +++ b/cmds/hid/src/com/android/commands/hid/Device.java @@ -26,6 +26,12 @@ import android.util.SparseArray; import com.android.internal.os.SomeArgs; +import org.json.JSONArray; +import org.json.JSONException; +import org.json.JSONObject; + +import java.io.IOException; +import java.io.OutputStream; import java.nio.ByteBuffer; import java.util.Arrays; import java.util.Map; @@ -38,12 +44,16 @@ public class Device { private static final int MSG_SEND_GET_FEATURE_REPORT_REPLY = 3; private static final int MSG_CLOSE_DEVICE = 4; + // Sync with linux uhid_event_type::UHID_OUTPUT + private static final byte UHID_EVENT_TYPE_UHID_OUTPUT = 6; + private final int mId; private final HandlerThread mThread; private final DeviceHandler mHandler; // mFeatureReports is limited to 256 entries, because the report number is 8-bit private final SparseArray<byte[]> mFeatureReports; private final Map<ByteBuffer, byte[]> mOutputs; + private final OutputStream mOutputStream; private long mTimeToSend; private final Object mCond = new Object(); @@ -66,6 +76,7 @@ public class Device { mHandler = new DeviceHandler(mThread.getLooper()); mFeatureReports = featureReports; mOutputs = outputs; + mOutputStream = System.out; SomeArgs args = SomeArgs.obtain(); args.argi1 = id; args.argi2 = vid; @@ -188,7 +199,27 @@ public class Device { } // native callback - public void onDeviceOutput(byte[] data) { + public void onDeviceOutput(byte rtype, byte[] data) { + JSONObject json = new JSONObject(); + try { + json.put("eventId", UHID_EVENT_TYPE_UHID_OUTPUT); + json.put("deviceId", mId); + json.put("reportType", rtype); + JSONArray dataArray = new JSONArray(); + for (int i = 0; i < data.length; i++) { + dataArray.put(data[i] & 0xFF); + } + json.put("reportData", dataArray); + } catch (JSONException e) { + throw new RuntimeException("Could not create JSON object ", e); + } + try { + mOutputStream.write(json.toString().getBytes()); + mOutputStream.flush(); + } catch (IOException e) { + throw new RuntimeException(e); + } + if (mOutputs == null) { Log.e(TAG, "Received OUTPUT request, but 'outputs' section is not found"); return; diff --git a/cmds/screencap/screencap.cpp b/cmds/screencap/screencap.cpp index dec4a567fc81..5c08704a6623 100644 --- a/cmds/screencap/screencap.cpp +++ b/cmds/screencap/screencap.cpp @@ -30,8 +30,9 @@ #include <binder/ProcessState.h> -#include <gui/SurfaceComposerClient.h> #include <gui/ISurfaceComposer.h> +#include <gui/SurfaceComposerClient.h> +#include <gui/SyncScreenCaptureListener.h> #include <ui/DisplayInfo.h> #include <ui/GraphicTypes.h> @@ -181,13 +182,18 @@ int main(int argc, char** argv) ProcessState::self()->setThreadPoolMaxThreadCount(0); ProcessState::self()->startThreadPool(); - ScreenCaptureResults captureResults; - status_t result = ScreenshotClient::captureDisplay(displayId->value, captureResults); + sp<SyncScreenCaptureListener> captureListener = new SyncScreenCaptureListener(); + status_t result = ScreenshotClient::captureDisplay(displayId->value, captureListener); if (result != NO_ERROR) { close(fd); return 1; } + ScreenCaptureResults captureResults = captureListener->waitForResults(); + if (captureResults.result != NO_ERROR) { + close(fd); + return 1; + } ui::Dataspace dataspace = captureResults.capturedDataspace; sp<GraphicBuffer> buffer = captureResults.buffer; diff --git a/core/java/android/app/ActivityManager.aidl b/core/java/android/app/ActivityManager.aidl index 29260e996663..45a0e87ea2d8 100644 --- a/core/java/android/app/ActivityManager.aidl +++ b/core/java/android/app/ActivityManager.aidl @@ -24,8 +24,6 @@ parcelable ActivityManager.RunningAppProcessInfo; parcelable ActivityManager.RunningServiceInfo; parcelable ActivityManager.RunningTaskInfo; /** @hide */ -parcelable ActivityManager.StackInfo; -/** @hide */ parcelable ActivityManager.TaskThumbnail; /** @hide */ parcelable ActivityManager.TaskSnapshot;
\ No newline at end of file diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java index a88c6a890844..5aecb61b62b1 100644 --- a/core/java/android/app/ActivityManager.java +++ b/core/java/android/app/ActivityManager.java @@ -76,7 +76,6 @@ import android.util.DisplayMetrics; import android.util.Singleton; import android.util.Size; import android.view.Surface; -import android.window.WindowContainerToken; import com.android.internal.app.LocalePicker; import com.android.internal.app.procstats.ProcessStats; @@ -2815,160 +2814,6 @@ public class ActivityManager { } /** - * Information you can retrieve about an ActivityStack in the system. - * @hide - */ - public static class StackInfo implements Parcelable { - @UnsupportedAppUsage - public int stackId; - @UnsupportedAppUsage - public Rect bounds = new Rect(); - @UnsupportedAppUsage - public int[] taskIds; - @UnsupportedAppUsage - public String[] taskNames; - @UnsupportedAppUsage - public Rect[] taskBounds; - @UnsupportedAppUsage - public int[] taskUserIds; - @UnsupportedAppUsage - public ComponentName topActivity; - @UnsupportedAppUsage - public int displayId; - @UnsupportedAppUsage - public int userId; - @UnsupportedAppUsage - public boolean visible; - // Index of the stack in the display's stack list, can be used for comparison of stack order - // TODO: Can be removed since no one is using it. - @UnsupportedAppUsage - @Deprecated - public int position; - public WindowContainerToken stackToken; - /** - * The full configuration the stack is currently running in. - * @hide - */ - final public Configuration configuration = new Configuration(); - - @Override - public int describeContents() { - return 0; - } - - @Override - public void writeToParcel(Parcel dest, int flags) { - dest.writeInt(stackId); - dest.writeInt(bounds.left); - dest.writeInt(bounds.top); - dest.writeInt(bounds.right); - dest.writeInt(bounds.bottom); - dest.writeIntArray(taskIds); - dest.writeStringArray(taskNames); - final int boundsCount = taskBounds == null ? 0 : taskBounds.length; - dest.writeInt(boundsCount); - for (int i = 0; i < boundsCount; i++) { - dest.writeInt(taskBounds[i].left); - dest.writeInt(taskBounds[i].top); - dest.writeInt(taskBounds[i].right); - dest.writeInt(taskBounds[i].bottom); - } - dest.writeIntArray(taskUserIds); - dest.writeInt(displayId); - dest.writeInt(userId); - dest.writeInt(visible ? 1 : 0); - dest.writeInt(position); - stackToken.writeToParcel(dest, 0); - if (topActivity != null) { - dest.writeInt(1); - topActivity.writeToParcel(dest, 0); - } else { - dest.writeInt(0); - } - configuration.writeToParcel(dest, flags); - } - - public void readFromParcel(Parcel source) { - stackId = source.readInt(); - bounds = new Rect( - source.readInt(), source.readInt(), source.readInt(), source.readInt()); - taskIds = source.createIntArray(); - taskNames = source.createStringArray(); - final int boundsCount = source.readInt(); - if (boundsCount > 0) { - taskBounds = new Rect[boundsCount]; - for (int i = 0; i < boundsCount; i++) { - taskBounds[i] = new Rect(); - taskBounds[i].set( - source.readInt(), source.readInt(), source.readInt(), source.readInt()); - } - } else { - taskBounds = null; - } - taskUserIds = source.createIntArray(); - displayId = source.readInt(); - userId = source.readInt(); - visible = source.readInt() > 0; - position = source.readInt(); - stackToken = WindowContainerToken.CREATOR.createFromParcel(source); - if (source.readInt() > 0) { - topActivity = ComponentName.readFromParcel(source); - } - configuration.readFromParcel(source); - } - - public static final @android.annotation.NonNull Creator<StackInfo> CREATOR = new Creator<StackInfo>() { - @Override - public StackInfo createFromParcel(Parcel source) { - return new StackInfo(source); - } - @Override - public StackInfo[] newArray(int size) { - return new StackInfo[size]; - } - }; - - public StackInfo() { - } - - private StackInfo(Parcel source) { - readFromParcel(source); - } - - @UnsupportedAppUsage - public String toString(String prefix) { - StringBuilder sb = new StringBuilder(256); - sb.append(prefix); sb.append("Stack id="); sb.append(stackId); - sb.append(" bounds="); sb.append(bounds.toShortString()); - sb.append(" displayId="); sb.append(displayId); - sb.append(" userId="); sb.append(userId); - sb.append("\n"); - sb.append(" configuration="); sb.append(configuration); - sb.append("\n"); - prefix = prefix + " "; - for (int i = 0; i < taskIds.length; ++i) { - sb.append(prefix); sb.append("taskId="); sb.append(taskIds[i]); - sb.append(": "); sb.append(taskNames[i]); - if (taskBounds != null) { - sb.append(" bounds="); sb.append(taskBounds[i].toShortString()); - } - sb.append(" userId=").append(taskUserIds[i]); - sb.append(" visible=").append(visible); - if (topActivity != null) { - sb.append(" topActivity=").append(topActivity); - } - sb.append("\n"); - } - return sb.toString(); - } - - @Override - public String toString() { - return toString(""); - } - } - - /** * @hide */ @RequiresPermission(anyOf={Manifest.permission.CLEAR_APP_USER_DATA, diff --git a/core/java/android/app/ActivityTaskManager.aidl b/core/java/android/app/ActivityTaskManager.aidl new file mode 100644 index 000000000000..a12bcd536af7 --- /dev/null +++ b/core/java/android/app/ActivityTaskManager.aidl @@ -0,0 +1,20 @@ +/** + * Copyright (c) 2020, The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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.app; + +/** @hide */ +parcelable ActivityTaskManager.RootTaskInfo;
\ No newline at end of file diff --git a/core/java/android/app/ActivityTaskManager.java b/core/java/android/app/ActivityTaskManager.java index 4283d7ad2a62..3e4d5eee34fe 100644 --- a/core/java/android/app/ActivityTaskManager.java +++ b/core/java/android/app/ActivityTaskManager.java @@ -29,6 +29,8 @@ import android.graphics.Rect; import android.os.Build; import android.os.Handler; import android.os.IBinder; +import android.os.Parcel; +import android.os.Parcelable; import android.os.RemoteException; import android.os.ServiceManager; import android.util.DisplayMetrics; @@ -391,27 +393,6 @@ public class ActivityTaskManager { } /** - * List all activity stacks information. - */ - @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS) - public String listAllStacks() { - final List<ActivityManager.StackInfo> stacks; - try { - stacks = getService().getAllStackInfos(); - } catch (RemoteException e) { - throw e.rethrowFromSystemServer(); - } - - final StringBuilder sb = new StringBuilder(); - if (stacks != null) { - for (ActivityManager.StackInfo info : stacks) { - sb.append(info).append("\n"); - } - } - return sb.toString(); - } - - /** * Clears launch params for the given package. * @param packageNames the names of the packages of which the launch params are to be cleared */ @@ -468,4 +449,96 @@ public class ActivityTaskManager { final Configuration config = context.getResources().getConfiguration(); return currentUiModeSupportsErrorDialogs(config); } + + /** + * Information you can retrieve about a root task in the system. + * @hide + */ + public static class RootTaskInfo extends TaskInfo implements Parcelable { + // TODO(b/148895075): Move some of the fields to TaskInfo. + public Rect bounds = new Rect(); + public int[] childTaskIds; + public String[] childTaskNames; + public Rect[] childTaskBounds; + public int[] childTaskUserIds; + public boolean visible; + // Index of the stack in the display's stack list, can be used for comparison of stack order + public int position; + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(Parcel dest, int flags) { + dest.writeTypedObject(bounds, flags); + dest.writeIntArray(childTaskIds); + dest.writeStringArray(childTaskNames); + dest.writeTypedArray(childTaskBounds, flags); + dest.writeIntArray(childTaskUserIds); + dest.writeInt(visible ? 1 : 0); + dest.writeInt(position); + super.writeToParcel(dest, flags); + } + + @Override + void readFromParcel(Parcel source) { + bounds = source.readTypedObject(Rect.CREATOR); + childTaskIds = source.createIntArray(); + childTaskNames = source.createStringArray(); + childTaskBounds = source.createTypedArray(Rect.CREATOR); + childTaskUserIds = source.createIntArray(); + visible = source.readInt() > 0; + position = source.readInt(); + super.readFromParcel(source); + } + + public static final @NonNull Creator<RootTaskInfo> CREATOR = new Creator<>() { + @Override + public RootTaskInfo createFromParcel(Parcel source) { + return new RootTaskInfo(source); + } + + @Override + public RootTaskInfo[] newArray(int size) { + return new RootTaskInfo[size]; + } + }; + + public RootTaskInfo() { + } + + private RootTaskInfo(Parcel source) { + readFromParcel(source); + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(256); + sb.append("RootTask id="); sb.append(taskId); + sb.append(" bounds="); sb.append(bounds.toShortString()); + sb.append(" displayId="); sb.append(displayId); + sb.append(" userId="); sb.append(userId); + sb.append("\n"); + + sb.append(" configuration="); sb.append(configuration); + sb.append("\n"); + + for (int i = 0; i < childTaskIds.length; ++i) { + sb.append(" taskId="); sb.append(childTaskIds[i]); + sb.append(": "); sb.append(childTaskNames[i]); + if (childTaskBounds != null) { + sb.append(" bounds="); sb.append(childTaskBounds[i].toShortString()); + } + sb.append(" userId=").append(childTaskUserIds[i]); + sb.append(" visible=").append(visible); + if (topActivity != null) { + sb.append(" topActivity=").append(topActivity); + } + sb.append("\n"); + } + return sb.toString(); + } + } } diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java index caca05a9e3b3..763ce6c6fd17 100644 --- a/core/java/android/app/ActivityThread.java +++ b/core/java/android/app/ActivityThread.java @@ -5418,13 +5418,12 @@ public final class ActivityThread extends ClientTransactionHandler { final int prevState = r.getLifecycleState(); - if (prevState < ON_RESUME || prevState > ON_STOP) { - Log.w(TAG, "Activity state must be in [ON_RESUME..ON_STOP] in order to be relaunched," + if (prevState < ON_START || prevState > ON_STOP) { + Log.w(TAG, "Activity state must be in [ON_START..ON_STOP] in order to be relaunched," + "current state is " + prevState); return; } - // Initialize a relaunch request. final MergedConfiguration mergedConfiguration = new MergedConfiguration( r.createdConfig != null ? r.createdConfig : mConfiguration, diff --git a/core/java/android/app/IActivityManager.aidl b/core/java/android/app/IActivityManager.aidl index cd9e02d30d05..45b25a3bf317 100644 --- a/core/java/android/app/IActivityManager.aidl +++ b/core/java/android/app/IActivityManager.aidl @@ -17,6 +17,7 @@ package android.app; import android.app.ActivityManager; +import android.app.ActivityTaskManager; import android.app.ApplicationErrorReport; import android.app.ApplicationExitInfo; import android.app.ContentProviderHolder; @@ -99,7 +100,6 @@ interface IActivityManager { void unregisterUidObserver(in IUidObserver observer); boolean isUidActive(int uid, String callingPackage); int getUidProcessState(int uid, in String callingPackage); - boolean setSchedPolicyCgroup(int tid, int group); // =============== End of transactions used on native side as well ============================ // Special low-level communication with activity manager. @@ -449,12 +449,11 @@ interface IActivityManager { @UnsupportedAppUsage void hang(in IBinder who, boolean allowRestart); - @UnsupportedAppUsage - List<ActivityManager.StackInfo> getAllStackInfos(); + List<ActivityTaskManager.RootTaskInfo> getAllRootTaskInfos(); @UnsupportedAppUsage void moveTaskToStack(int taskId, int stackId, boolean toTop); void setFocusedStack(int stackId); - ActivityManager.StackInfo getFocusedStackInfo(); + ActivityTaskManager.RootTaskInfo getFocusedRootTaskInfo(); @UnsupportedAppUsage void restart(); void performIdleMaintenance(); diff --git a/core/java/android/app/IActivityTaskManager.aidl b/core/java/android/app/IActivityTaskManager.aidl index 72a3637d8e07..f3c7fe9412c9 100644 --- a/core/java/android/app/IActivityTaskManager.aidl +++ b/core/java/android/app/IActivityTaskManager.aidl @@ -17,6 +17,7 @@ package android.app; import android.app.ActivityManager; +import android.app.ActivityTaskManager; import android.app.ApplicationErrorReport; import android.app.ContentProviderHolder; import android.app.GrantedUriPermission; @@ -186,7 +187,7 @@ interface IActivityTaskManager { in AssistStructure structure, in AssistContent content, in Uri referrer); void setFocusedStack(int stackId); - ActivityManager.StackInfo getFocusedStackInfo(); + ActivityTaskManager.RootTaskInfo getFocusedRootTaskInfo(); Rect getTaskBounds(int taskId); void cancelRecentsAnimation(boolean restoreHomeStackPosition); @@ -260,11 +261,10 @@ interface IActivityTaskManager { /** Removes stack of the activity types from the system. */ void removeStacksWithActivityTypes(in int[] activityTypes); - List<ActivityManager.StackInfo> getAllStackInfos(); - ActivityManager.StackInfo getStackInfo(int windowingMode, int activityType); - List<ActivityManager.StackInfo> getAllStackInfosOnDisplay(int displayId); - ActivityManager.StackInfo getStackInfoOnDisplay(int windowingMode, int activityType, - int displayId); + List<ActivityTaskManager.RootTaskInfo> getAllRootTaskInfos(); + ActivityTaskManager.RootTaskInfo getRootTaskInfo(int windowingMode, int activityType); + List<ActivityTaskManager.RootTaskInfo> getAllRootTaskInfosOnDisplay(int displayId); + ActivityTaskManager.RootTaskInfo getRootTaskInfoOnDisplay(int windowingMode, int activityType, int displayId); /** * Informs ActivityTaskManagerService that the keyguard is showing. diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java index 6737972dc34e..1ff48f6baa6a 100644 --- a/core/java/android/app/Notification.java +++ b/core/java/android/app/Notification.java @@ -207,7 +207,7 @@ public class Notification implements Parcelable * <p> * Avoids spamming the system with overly large strings such as full e-mails. */ - private static final int MAX_CHARSEQUENCE_LENGTH = 5 * 1024; + private static final int MAX_CHARSEQUENCE_LENGTH = 1024; /** * Maximum entries of reply text that are accepted by Builder and friends. @@ -7863,7 +7863,7 @@ public class Notification implements Parcelable */ public Message(@NonNull CharSequence text, long timestamp, @Nullable Person sender, boolean remoteInputHistory) { - mText = text; + mText = safeCharSequence(text); mTimestamp = timestamp; mSender = sender; mRemoteInputHistory = remoteInputHistory; @@ -7977,7 +7977,7 @@ public class Notification implements Parcelable bundle.putLong(KEY_TIMESTAMP, mTimestamp); if (mSender != null) { // Legacy listeners need this - bundle.putCharSequence(KEY_SENDER, mSender.getName()); + bundle.putCharSequence(KEY_SENDER, safeCharSequence(mSender.getName())); bundle.putParcelable(KEY_SENDER_PERSON, mSender); } if (mDataMimeType != null) { diff --git a/core/java/android/app/PictureInPictureParams.java b/core/java/android/app/PictureInPictureParams.java index 67d94dec88c5..18c4d70dd9b0 100644 --- a/core/java/android/app/PictureInPictureParams.java +++ b/core/java/android/app/PictureInPictureParams.java @@ -16,6 +16,7 @@ package android.app; +import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.TestApi; import android.graphics.Rect; @@ -46,6 +47,8 @@ public final class PictureInPictureParams implements Parcelable { @Nullable private Rect mSourceRectHint; + private boolean mAutoEnterAllowed; + /** * Sets the aspect ratio. This aspect ratio is defined as the desired width / height, and * does not change upon device rotation. @@ -103,6 +106,25 @@ public final class PictureInPictureParams implements Parcelable { } /** + * Sets whether the system is allowed to automatically put the activity in + * picture-in-picture mode without needing/waiting for the activity to call + * {@link Activity#enterPictureInPictureMode(PictureInPictureParams)}. + * + * If true, {@link Activity#onPictureInPictureRequested()} will never be called. + * + * This property is false by default. + * @param autoEnterAllowed {@code true} if the system is allowed to automatically put the + * activity in picture-in-picture mode. + * + * @return this builder instance. + */ + @NonNull + public Builder setAutoEnterAllowed(boolean autoEnterAllowed) { + mAutoEnterAllowed = autoEnterAllowed; + return this; + } + + /** * @return an immutable {@link PictureInPictureParams} to be used when entering or updating * the activity in picture-in-picture. * @@ -111,7 +133,7 @@ public final class PictureInPictureParams implements Parcelable { */ public PictureInPictureParams build() { PictureInPictureParams params = new PictureInPictureParams(mAspectRatio, mUserActions, - mSourceRectHint); + mSourceRectHint, mAutoEnterAllowed); return params; } } @@ -136,6 +158,11 @@ public final class PictureInPictureParams implements Parcelable { @Nullable private Rect mSourceRectHint; + /** + * Whether the system is allowed to automatically put the activity in picture-in-picture mode. + */ + private boolean mAutoEnterAllowed; + /** {@hide} */ PictureInPictureParams() { } @@ -152,14 +179,18 @@ public final class PictureInPictureParams implements Parcelable { if (in.readInt() != 0) { mSourceRectHint = Rect.CREATOR.createFromParcel(in); } + if (in.readInt() != 0) { + mAutoEnterAllowed = in.readBoolean(); + } } /** {@hide} */ PictureInPictureParams(Rational aspectRatio, List<RemoteAction> actions, - Rect sourceRectHint) { + Rect sourceRectHint, boolean autoEnterAllowed) { mAspectRatio = aspectRatio; mUserActions = actions; mSourceRectHint = sourceRectHint; + mAutoEnterAllowed = autoEnterAllowed; } /** @@ -176,6 +207,7 @@ public final class PictureInPictureParams implements Parcelable { if (otherArgs.hasSourceBoundsHint()) { mSourceRectHint = new Rect(otherArgs.getSourceRectHint()); } + mAutoEnterAllowed = otherArgs.mAutoEnterAllowed; } /** @@ -248,11 +280,20 @@ public final class PictureInPictureParams implements Parcelable { } /** + * @return whether auto pip allowed. + * @hide + */ + public boolean isAutoEnterAllowed() { + return mAutoEnterAllowed; + } + + /** * @return True if no parameters are set * @hide */ public boolean empty() { - return !hasSourceBoundsHint() && !hasSetActions() && !hasSetAspectRatio(); + return !hasSourceBoundsHint() && !hasSetActions() && !hasSetAspectRatio() + && !mAutoEnterAllowed; } @Override @@ -281,6 +322,8 @@ public final class PictureInPictureParams implements Parcelable { } else { out.writeInt(0); } + out.writeInt(1); + out.writeBoolean(mAutoEnterAllowed); } public static final @android.annotation.NonNull Creator<PictureInPictureParams> CREATOR = diff --git a/core/java/android/app/TaskInfo.java b/core/java/android/app/TaskInfo.java index f3f00e50715b..4718cf1545ce 100644 --- a/core/java/android/app/TaskInfo.java +++ b/core/java/android/app/TaskInfo.java @@ -36,7 +36,8 @@ public class TaskInfo { private static final String TAG = "TaskInfo"; /** - * The id of the user the task was running as. + * The id of the user the task was running as if this is a leaf task. The id of the current + * running user of the system otherwise. * @hide */ @UnsupportedAppUsage diff --git a/core/java/android/app/assist/AssistStructure.java b/core/java/android/app/assist/AssistStructure.java index 22d8c87e9268..b5234f8e2e17 100644 --- a/core/java/android/app/assist/AssistStructure.java +++ b/core/java/android/app/assist/AssistStructure.java @@ -36,8 +36,6 @@ import android.view.WindowManagerGlobal; import android.view.autofill.AutofillId; import android.view.autofill.AutofillValue; -import com.android.internal.util.Preconditions; - import java.util.ArrayList; import java.util.Arrays; import java.util.List; @@ -1676,8 +1674,9 @@ public class AssistStructure implements Parcelable { } /** - * Returns the maximum length of the text associated with this node node, or {@code -1} - * if not supported by the node or not set. + * Returns the maximum length of the text associated with this node, or {@code -1} if not + * supported by the node or not set. System may set a default value if the text length is + * not set. * * <p>It's only relevant when the {@link AssistStructure} is used for autofill purposes, * not for assist purposes. diff --git a/core/java/android/app/servertransaction/TransactionExecutorHelper.java b/core/java/android/app/servertransaction/TransactionExecutorHelper.java index a34be5c3edc7..56bf59b52f74 100644 --- a/core/java/android/app/servertransaction/TransactionExecutorHelper.java +++ b/core/java/android/app/servertransaction/TransactionExecutorHelper.java @@ -185,6 +185,9 @@ public class TransactionExecutorHelper { final ActivityLifecycleItem lifecycleItem; switch (prevState) { // TODO(lifecycler): Extend to support all possible states. + case ON_START: + lifecycleItem = StartActivityItem.obtain(); + break; case ON_PAUSE: lifecycleItem = PauseActivityItem.obtain(); break; diff --git a/core/java/android/app/timezonedetector/TimeZoneConfiguration.java b/core/java/android/app/timezonedetector/TimeZoneConfiguration.java index 95db0a26cc6e..e879091cd68e 100644 --- a/core/java/android/app/timezonedetector/TimeZoneConfiguration.java +++ b/core/java/android/app/timezonedetector/TimeZoneConfiguration.java @@ -162,9 +162,9 @@ public final class TimeZoneConfiguration implements Parcelable { @Override public String toString() { - return "TimeZoneDetectorConfiguration{" + return "TimeZoneConfiguration{" + "mUserId=" + mUserId - + "mBundle=" + mBundle + + ", mBundle=" + mBundle + '}'; } diff --git a/core/java/android/app/usage/UsageEvents.java b/core/java/android/app/usage/UsageEvents.java index 0e6a0637d801..3522b1b8aff5 100644 --- a/core/java/android/app/usage/UsageEvents.java +++ b/core/java/android/app/usage/UsageEvents.java @@ -199,7 +199,7 @@ public final class UsageEvents implements Parcelable { public static final int NOTIFICATION_INTERRUPTION = 12; /** - * A Slice was pinned by the default assistant. + * A Slice was pinned by the default launcher or the default assistant. * @hide */ @SystemApi diff --git a/core/java/android/content/PermissionChecker.java b/core/java/android/content/PermissionChecker.java index b4340729a220..eec7c9cc5a63 100644 --- a/core/java/android/content/PermissionChecker.java +++ b/core/java/android/content/PermissionChecker.java @@ -343,20 +343,22 @@ public final class PermissionChecker { * @param permission The permission to check. * @return The permission check result which is either {@link #PERMISSION_GRANTED} * or {@link #PERMISSION_SOFT_DENIED} or {@link #PERMISSION_HARD_DENIED}. - * @param attributionTag attribution tag of caller (if not self) + * @param callingPackageName package name tag of caller (if not self) + * @param callingAttributionTag attribution tag of caller (if not self) * @param message A message describing the reason the permission was checked * * @see #checkCallingOrSelfPermissionForPreflight(Context, String) */ @PermissionResult public static int checkCallingOrSelfPermissionForDataDelivery(@NonNull Context context, - @NonNull String permission, @Nullable String attributionTag, @Nullable String message) { - String packageName = (Binder.getCallingPid() == Process.myPid()) - ? context.getPackageName() : null; - attributionTag = (Binder.getCallingPid() == Process.myPid()) - ? context.getAttributionTag() : attributionTag; + @NonNull String permission, @Nullable String callingPackageName, + @Nullable String callingAttributionTag, @Nullable String message) { + callingPackageName = (Binder.getCallingPid() == Process.myPid()) + ? context.getPackageName() : callingPackageName; + callingAttributionTag = (Binder.getCallingPid() == Process.myPid()) + ? context.getAttributionTag() : callingAttributionTag; return checkPermissionForDataDelivery(context, permission, Binder.getCallingPid(), - Binder.getCallingUid(), packageName, attributionTag, message); + Binder.getCallingUid(), callingPackageName, callingAttributionTag, message); } /** @@ -375,15 +377,15 @@ public final class PermissionChecker { * app's fg/gb state) and this check will not leave a trace that permission protected * data was delivered. When you are about to deliver the location data to a registered * listener you should use {@link #checkCallingOrSelfPermissionForDataDelivery(Context, - * String, String, String)} which will evaluate the permission access based on the current - * fg/bg state of the app and leave a record that the data was accessed. + * String, String, String, String)} which will evaluate the permission access based on the + * current fg/bg state of the app and leave a record that the data was accessed. * * @param context Context for accessing resources. * @param permission The permission to check. * @return The permission check result which is either {@link #PERMISSION_GRANTED} * or {@link #PERMISSION_SOFT_DENIED} or {@link #PERMISSION_HARD_DENIED}. * - * @see #checkCallingOrSelfPermissionForDataDelivery(Context, String, String, String) + * @see #checkCallingOrSelfPermissionForDataDelivery(Context, String, String, String, String) */ @PermissionResult public static int checkCallingOrSelfPermissionForPreflight(@NonNull Context context, diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java index 0f1f276ce0f9..e108451b54fb 100644 --- a/core/java/android/content/pm/PackageParser.java +++ b/core/java/android/content/pm/PackageParser.java @@ -30,7 +30,6 @@ import static android.content.pm.ApplicationInfo.FLAG_SUSPENDED; import static android.content.pm.ApplicationInfo.PRIVATE_FLAG_ACTIVITIES_RESIZE_MODE_RESIZEABLE; import static android.content.pm.ApplicationInfo.PRIVATE_FLAG_ACTIVITIES_RESIZE_MODE_RESIZEABLE_VIA_SDK_VERSION; import static android.content.pm.ApplicationInfo.PRIVATE_FLAG_ACTIVITIES_RESIZE_MODE_UNRESIZEABLE; -import static android.content.pm.PackageManager.FEATURE_WATCH; import static android.content.pm.PackageManager.INSTALL_PARSE_FAILED_BAD_MANIFEST; import static android.content.pm.PackageManager.INSTALL_PARSE_FAILED_BAD_PACKAGE_NAME; import static android.content.pm.PackageManager.INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES; @@ -159,8 +158,6 @@ public class PackageParser { SystemProperties.getBoolean(PROPERTY_CHILD_PACKAGES_ENABLED, false); public static final float DEFAULT_PRE_O_MAX_ASPECT_RATIO = 1.86f; - public static final float DEFAULT_PRE_Q_MIN_ASPECT_RATIO = 1.333f; - public static final float DEFAULT_PRE_Q_MIN_ASPECT_RATIO_WATCH = 1f; private static final int DEFAULT_MIN_SDK_VERSION = 1; private static final int DEFAULT_TARGET_SDK_VERSION = 0; @@ -4683,20 +4680,8 @@ public class PackageParser { * ratio set. */ private void setMinAspectRatio(Package owner) { - final float minAspectRatio; - if (owner.applicationInfo.minAspectRatio != 0) { - // Use the application max aspect ration as default if set. - minAspectRatio = owner.applicationInfo.minAspectRatio; - } else { - // Default to (1.33) 4:3 aspect ratio for pre-Q apps and unset for Q and greater. - // NOTE: 4:3 was the min aspect ratio Android devices can support pre-Q per the CDD, - // except for watches which always supported 1:1. - minAspectRatio = owner.applicationInfo.targetSdkVersion >= Build.VERSION_CODES.Q - ? 0 - : (mCallback != null && mCallback.hasFeature(FEATURE_WATCH)) - ? DEFAULT_PRE_Q_MIN_ASPECT_RATIO_WATCH - : DEFAULT_PRE_Q_MIN_ASPECT_RATIO; - } + // Use the application max aspect ration as default if set. + final float minAspectRatio = owner.applicationInfo.minAspectRatio; for (Activity activity : owner.activities) { if (activity.hasMinAspectRatio()) { diff --git a/core/java/android/content/pm/parsing/ApkLiteParseUtils.java b/core/java/android/content/pm/parsing/ApkLiteParseUtils.java index 4914601b0b5a..6d92d3e0d219 100644 --- a/core/java/android/content/pm/parsing/ApkLiteParseUtils.java +++ b/core/java/android/content/pm/parsing/ApkLiteParseUtils.java @@ -53,7 +53,7 @@ import java.util.List; /** @hide */ public class ApkLiteParseUtils { - private static final String TAG = ParsingPackageUtils.TAG; + private static final String TAG = ParsingUtils.TAG; // TODO(b/135203078): Consolidate constants private static final int DEFAULT_MIN_SDK_VERSION = 1; @@ -67,7 +67,7 @@ public class ApkLiteParseUtils { * Automatically detects if the package is a monolithic style (single APK * file) or cluster style (directory of APKs). * <p> - * This performs sanity checking on cluster style packages, such as + * This performs validity checking on cluster style packages, such as * requiring identical package name and version codes, a single base APK, * and unique split names. * diff --git a/core/java/android/content/pm/parsing/PackageInfoWithoutStateUtils.java b/core/java/android/content/pm/parsing/PackageInfoWithoutStateUtils.java index e4507483c08f..e57353922115 100644 --- a/core/java/android/content/pm/parsing/PackageInfoWithoutStateUtils.java +++ b/core/java/android/content/pm/parsing/PackageInfoWithoutStateUtils.java @@ -579,8 +579,8 @@ public class PackageInfoWithoutStateUtils { ii.handleProfiling = i.isHandleProfiling(); ii.functionalTest = i.isFunctionalTest(); - ii.sourceDir = pkg.getBaseCodePath(); - ii.publicSourceDir = pkg.getBaseCodePath(); + ii.sourceDir = pkg.getBaseApkPath(); + ii.publicSourceDir = pkg.getBaseApkPath(); ii.splitNames = pkg.getSplitNames(); ii.splitSourceDirs = pkg.getSplitCodePaths(); ii.splitPublicSourceDirs = pkg.getSplitCodePaths(); diff --git a/core/java/android/content/pm/parsing/ParsingPackageImpl.java b/core/java/android/content/pm/parsing/ParsingPackageImpl.java index 0c0dc313087e..ed12a17ad493 100644 --- a/core/java/android/content/pm/parsing/ParsingPackageImpl.java +++ b/core/java/android/content/pm/parsing/ParsingPackageImpl.java @@ -145,7 +145,7 @@ public class ParsingPackageImpl implements ParsingPackage, Parcelable { private String realPackage; @NonNull - protected String baseCodePath; + protected String mBaseApkPath; private boolean requiredForAllUsers; @Nullable @@ -280,7 +280,7 @@ public class ParsingPackageImpl implements ParsingPackage, Parcelable { @NonNull @DataClass.ParcelWith(ForInternedString.class) - protected String codePath; + protected String mPath; private boolean use32BitAbi; private boolean visibleToInstantApps; @@ -429,11 +429,11 @@ public class ParsingPackageImpl implements ParsingPackage, Parcelable { private ArraySet<String> mimeGroups; @VisibleForTesting - public ParsingPackageImpl(@NonNull String packageName, @NonNull String baseCodePath, - @NonNull String codePath, @Nullable TypedArray manifestArray) { + public ParsingPackageImpl(@NonNull String packageName, @NonNull String baseApkPath, + @NonNull String path, @Nullable TypedArray manifestArray) { this.packageName = TextUtils.safeIntern(packageName); - this.baseCodePath = baseCodePath; - this.codePath = codePath; + this.mBaseApkPath = baseApkPath; + this.mPath = path; if (manifestArray != null) { versionCode = manifestArray.getInteger(R.styleable.AndroidManifest_versionCode, 0); @@ -888,6 +888,9 @@ public class ParsingPackageImpl implements ParsingPackage, Parcelable { public ApplicationInfo toAppInfoWithoutStateWithoutFlags() { ApplicationInfo appInfo = new ApplicationInfo(); + // Lines that are commented below are state related and should not be assigned here. + // They are left in as placeholders, since there is no good backwards compatible way to + // separate these. appInfo.appComponentFactory = appComponentFactory; appInfo.backupAgentName = backupAgentName; appInfo.banner = banner; @@ -897,13 +900,17 @@ public class ParsingPackageImpl implements ParsingPackage, Parcelable { appInfo.compatibleWidthLimitDp = compatibleWidthLimitDp; appInfo.compileSdkVersion = compileSdkVersion; appInfo.compileSdkVersionCodename = compileSdkVersionCodeName; -// appInfo.credentialProtectedDataDir = credentialProtectedDataDir; -// appInfo.dataDir = dataDir; +// appInfo.credentialProtectedDataDir + appInfo.crossProfile = isCrossProfile(); +// appInfo.dataDir appInfo.descriptionRes = descriptionRes; -// appInfo.deviceProtectedDataDir = deviceProtectedDataDir; +// appInfo.deviceProtectedDataDir appInfo.enabled = enabled; +// appInfo.enabledSetting appInfo.fullBackupContent = fullBackupContent; -// appInfo.hiddenUntilInstalled = hiddenUntilInstalled; + // TODO(b/135203078): See ParsingPackageImpl#getHiddenApiEnforcementPolicy +// appInfo.mHiddenApiPolicy +// appInfo.hiddenUntilInstalled appInfo.icon = (PackageParser.sUseRoundIcon && roundIconRes != 0) ? roundIconRes : iconRes; appInfo.iconRes = iconRes; appInfo.roundIconRes = roundIconRes; @@ -920,9 +927,9 @@ public class ParsingPackageImpl implements ParsingPackage, Parcelable { if (appInfo.name != null) { appInfo.name = appInfo.name.trim(); } -// appInfo.nativeLibraryDir = nativeLibraryDir; -// appInfo.nativeLibraryRootDir = nativeLibraryRootDir; -// appInfo.nativeLibraryRootRequiresIsa = nativeLibraryRootRequiresIsa; +// appInfo.nativeLibraryDir +// appInfo.nativeLibraryRootDir +// appInfo.nativeLibraryRootRequiresIsa appInfo.networkSecurityConfigRes = networkSecurityConfigRes; appInfo.nonLocalizedLabel = nonLocalizedLabel; if (appInfo.nonLocalizedLabel != null) { @@ -930,16 +937,17 @@ public class ParsingPackageImpl implements ParsingPackage, Parcelable { } appInfo.packageName = packageName; appInfo.permission = permission; -// appInfo.primaryCpuAbi = primaryCpuAbi; +// appInfo.primaryCpuAbi appInfo.processName = getProcessName(); appInfo.requiresSmallestWidthDp = requiresSmallestWidthDp; -// appInfo.secondaryCpuAbi = secondaryCpuAbi; -// appInfo.secondaryNativeLibraryDir = secondaryNativeLibraryDir; -// appInfo.seInfo = seInfo; -// appInfo.seInfoUser = seInfoUser; -// appInfo.sharedLibraryFiles = usesLibraryFiles.isEmpty() -// ? null : usesLibraryFiles.toArray(new String[0]); -// appInfo.sharedLibraryInfos = usesLibraryInfos.isEmpty() ? null : usesLibraryInfos; +// appInfo.resourceDirs +// appInfo.secondaryCpuAbi +// appInfo.secondaryNativeLibraryDir +// appInfo.seInfo +// appInfo.seInfoUser +// appInfo.sharedLibraryFiles +// appInfo.sharedLibraryInfos +// appInfo.showUserIcon appInfo.splitClassLoaderNames = splitClassLoaderNames; appInfo.splitDependencies = splitDependencies; appInfo.splitNames = splitNames; @@ -948,29 +956,19 @@ public class ParsingPackageImpl implements ParsingPackage, Parcelable { appInfo.targetSdkVersion = targetSdkVersion; appInfo.taskAffinity = taskAffinity; appInfo.theme = theme; -// appInfo.uid = uid; +// appInfo.uid appInfo.uiOptions = uiOptions; appInfo.volumeUuid = volumeUuid; appInfo.zygotePreloadName = zygotePreloadName; - appInfo.crossProfile = isCrossProfile(); appInfo.setGwpAsanMode(gwpAsanMode); - appInfo.setBaseCodePath(baseCodePath); - appInfo.setBaseResourcePath(baseCodePath); - appInfo.setCodePath(codePath); - appInfo.setResourcePath(codePath); + appInfo.setBaseCodePath(mBaseApkPath); + appInfo.setBaseResourcePath(mBaseApkPath); + appInfo.setCodePath(mPath); + appInfo.setResourcePath(mPath); appInfo.setSplitCodePaths(splitCodePaths); appInfo.setSplitResourcePaths(splitCodePaths); appInfo.setVersionCode(PackageInfo.composeLongVersionCode(versionCodeMajor, versionCode)); - // TODO(b/135203078): Can this be removed? Looks only used in ActivityInfo. -// appInfo.showUserIcon = pkg.getShowUserIcon(); - // TODO(b/135203078): Unused? -// appInfo.resourceDirs = pkg.getResourceDirs(); - // TODO(b/135203078): Unused? -// appInfo.enabledSetting = pkg.getEnabledSetting(); - // TODO(b/135203078): See ParsingPackageImpl#getHiddenApiEnforcementPolicy -// appInfo.mHiddenApiPolicy = pkg.getHiddenApiPolicy(); - return appInfo; } @@ -995,7 +993,7 @@ public class ParsingPackageImpl implements ParsingPackage, Parcelable { dest.writeString(this.compileSdkVersionCodeName); sForInternedString.parcel(this.packageName, dest, flags); dest.writeString(this.realPackage); - dest.writeString(this.baseCodePath); + dest.writeString(this.mBaseApkPath); dest.writeBoolean(this.requiredForAllUsers); dest.writeString(this.restrictedAccountType); dest.writeString(this.requiredAccountType); @@ -1050,7 +1048,7 @@ public class ParsingPackageImpl implements ParsingPackage, Parcelable { dest.writeBundle(this.metaData); sForInternedString.parcel(this.volumeUuid, dest, flags); dest.writeParcelable(this.signingDetails, flags); - dest.writeString(this.codePath); + dest.writeString(this.mPath); dest.writeBoolean(this.use32BitAbi); dest.writeBoolean(this.visibleToInstantApps); dest.writeBoolean(this.forceQueryable); @@ -1159,7 +1157,7 @@ public class ParsingPackageImpl implements ParsingPackage, Parcelable { this.compileSdkVersionCodeName = in.readString(); this.packageName = sForInternedString.unparcel(in); this.realPackage = in.readString(); - this.baseCodePath = in.readString(); + this.mBaseApkPath = in.readString(); this.requiredForAllUsers = in.readBoolean(); this.restrictedAccountType = in.readString(); this.requiredAccountType = in.readString(); @@ -1214,7 +1212,7 @@ public class ParsingPackageImpl implements ParsingPackage, Parcelable { this.metaData = in.readBundle(boot); this.volumeUuid = sForInternedString.unparcel(in); this.signingDetails = in.readParcelable(boot); - this.codePath = in.readString(); + this.mPath = in.readString(); this.use32BitAbi = in.readBoolean(); this.visibleToInstantApps = in.readBoolean(); this.forceQueryable = in.readBoolean(); @@ -1363,8 +1361,8 @@ public class ParsingPackageImpl implements ParsingPackage, Parcelable { @NonNull @Override - public String getBaseCodePath() { - return baseCodePath; + public String getBaseApkPath() { + return mBaseApkPath; } @Override @@ -1649,8 +1647,8 @@ public class ParsingPackageImpl implements ParsingPackage, Parcelable { @NonNull @Override - public String getCodePath() { - return codePath; + public String getPath() { + return mPath; } @Override diff --git a/core/java/android/content/pm/parsing/ParsingPackageRead.java b/core/java/android/content/pm/parsing/ParsingPackageRead.java index 7e0fe7dc41bf..dbd15f544bcd 100644 --- a/core/java/android/content/pm/parsing/ParsingPackageRead.java +++ b/core/java/android/content/pm/parsing/ParsingPackageRead.java @@ -548,7 +548,7 @@ public interface ParsingPackageRead extends Parcelable { String getPackageName(); /** Path of base APK */ - String getBaseCodePath(); + String getBaseApkPath(); /** * Path where this package was found on disk. For monolithic packages @@ -556,7 +556,7 @@ public interface ParsingPackageRead extends Parcelable { * path to the cluster directory. */ @NonNull - String getCodePath(); + String getPath(); /** * @see ApplicationInfo#compatibleWidthLimitDp diff --git a/core/java/android/content/pm/parsing/ParsingPackageUtils.java b/core/java/android/content/pm/parsing/ParsingPackageUtils.java index e1f08f3e55a1..bce75cde20c2 100644 --- a/core/java/android/content/pm/parsing/ParsingPackageUtils.java +++ b/core/java/android/content/pm/parsing/ParsingPackageUtils.java @@ -18,7 +18,6 @@ package android.content.pm.parsing; import static android.content.pm.ActivityInfo.FLAG_SUPPORTS_PICTURE_IN_PICTURE; import static android.content.pm.ActivityInfo.RESIZE_MODE_UNRESIZEABLE; -import static android.content.pm.PackageManager.FEATURE_WATCH; import static android.content.pm.PackageManager.INSTALL_PARSE_FAILED_BAD_MANIFEST; import static android.content.pm.PackageManager.INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES; import static android.content.pm.PackageManager.INSTALL_PARSE_FAILED_ONLY_COREAPP_ALLOWED; @@ -128,7 +127,7 @@ import java.util.StringTokenizer; */ public class ParsingPackageUtils { - public static final String TAG = ParsingUtils.TAG; + private static final String TAG = ParsingUtils.TAG; /** * @see #parseDefault(ParseInput, File, int, boolean) @@ -163,10 +162,10 @@ public class ParsingPackageUtils { @Override public ParsingPackage startParsingPackage( @NonNull String packageName, - @NonNull String baseCodePath, - @NonNull String codePath, + @NonNull String baseApkPath, + @NonNull String path, @NonNull TypedArray manifestArray, boolean isCoreApp) { - return new ParsingPackageImpl(packageName, baseCodePath, codePath, manifestArray); + return new ParsingPackageImpl(packageName, baseApkPath, path, manifestArray); } }); try { @@ -211,7 +210,7 @@ public class ParsingPackageUtils { * package is a monolithic style (single APK file) or cluster style * (directory of APKs). * <p> - * This performs sanity checking on cluster style packages, such as + * This performs validity checking on cluster style packages, such as * requiring identical package name and version codes, a single base APK, * and unique split names. * <p> @@ -237,7 +236,7 @@ public class ParsingPackageUtils { /** * Parse all APKs contained in the given directory, treating them as a - * single package. This also performs sanity checking, such as requiring + * single package. This also performs validity checking, such as requiring * identical package name and version codes, a single base APK, and unique * split names. * <p> @@ -740,7 +739,6 @@ public class ParsingPackageUtils { String tagName = parser.getName(); final ParseResult result; - // TODO(b/135203078): Convert to instance methods to share variables // <application> has special logic, so it's handled outside the general method if (PackageParser.TAG_APPLICATION.equals(tagName)) { if (foundApp) { @@ -1215,9 +1213,9 @@ public class ParsingPackageUtils { features = ArrayUtils.add(features, featureInfo); } else { Slog.w(TAG, - "Unknown element under <feature-group>: " + innerTagName + - " at " + pkg.getBaseCodePath() + " " + - parser.getPositionDescription()); + "Unknown element under <feature-group>: " + innerTagName + + " at " + pkg.getBaseApkPath() + " " + + parser.getPositionDescription()); } } @@ -1720,10 +1718,6 @@ public class ParsingPackageUtils { pkg.setPersistent(requiredFeature == null || mCallback.hasFeature(requiredFeature)); } - // TODO(b/135203078): Should parsing code be responsible for this? Maybe move to a - // util or just have PackageImpl return true if either flag is set - pkg.setProfileableByShell(pkg.isProfileableByShell()); - if (sa.hasValueOrEmpty(R.styleable.AndroidManifestApplication_resizeableActivity)) { pkg.setResizeableActivity(sa.getBoolean( R.styleable.AndroidManifestApplication_resizeableActivity, true)); @@ -2375,21 +2369,8 @@ public class ParsingPackageUtils { * ratio set. */ private void setMinAspectRatio(ParsingPackage pkg) { - final float minAspectRatio; - float packageMinAspectRatio = pkg.getMinAspectRatio(); - if (packageMinAspectRatio != 0) { - // Use the application max aspect ration as default if set. - minAspectRatio = packageMinAspectRatio; - } else { - // Default to (1.33) 4:3 aspect ratio for pre-Q apps and unset for Q and greater. - // NOTE: 4:3 was the min aspect ratio Android devices can support pre-Q per the CDD, - // except for watches which always supported 1:1. - minAspectRatio = pkg.getTargetSdkVersion() >= Build.VERSION_CODES.Q - ? 0 - : (mCallback != null && mCallback.hasFeature(FEATURE_WATCH)) - ? PackageParser.DEFAULT_PRE_Q_MIN_ASPECT_RATIO_WATCH - : PackageParser.DEFAULT_PRE_Q_MIN_ASPECT_RATIO; - } + // Use the application max aspect ration as default if set. + final float minAspectRatio = pkg.getMinAspectRatio(); List<ParsedActivity> activities = pkg.getActivities(); int activitiesSize = activities.size(); @@ -2438,7 +2419,7 @@ public class ParsingPackageUtils { R.styleable.AndroidManifestResourceOverlay_requiredSystemPropertyValue); if (!PackageParser.checkRequiredSystemProperties(propName, propValue)) { String message = "Skipping target and overlay pair " + target + " and " - + pkg.getBaseCodePath() + + pkg.getBaseApkPath() + ": overlay ignored due to required system property: " + propName + " with value: " + propValue; Slog.i(TAG, message); @@ -2693,7 +2674,7 @@ public class ParsingPackageUtils { "<meta-data> only supports string, integer, float, color, " + "boolean, and resource reference types: " + parser.getName() + " at " - + pkg.getBaseCodePath() + " " + + pkg.getBaseApkPath() + " " + parser.getPositionDescription()); } else { return input.error("<meta-data> only supports string, integer, float, " @@ -2730,7 +2711,7 @@ public class ParsingPackageUtils { try { ParseResult<SigningDetails> result = getSigningDetails( input, - pkg.getBaseCodePath(), + pkg.getBaseApkPath(), skipVerify, pkg.isStaticSharedLibrary(), signingDetails, @@ -2876,7 +2857,7 @@ public class ParsingPackageUtils { boolean hasFeature(String feature); ParsingPackage startParsingPackage(@NonNull String packageName, - @NonNull String baseCodePath, @NonNull String codePath, + @NonNull String baseApkPath, @NonNull String path, @NonNull TypedArray manifestArray, boolean isCoreApp); } } diff --git a/core/java/android/content/pm/parsing/ParsingUtils.java b/core/java/android/content/pm/parsing/ParsingUtils.java index ba61de1cf950..5da5fbf4d8a7 100644 --- a/core/java/android/content/pm/parsing/ParsingUtils.java +++ b/core/java/android/content/pm/parsing/ParsingUtils.java @@ -33,7 +33,6 @@ import java.io.IOException; /** @hide **/ public class ParsingUtils { - // TODO(b/135203078): Consolidate log tags public static final String TAG = "PackageParsing"; @Nullable @@ -62,7 +61,7 @@ public class ParsingUtils { return input.error("Bad element under " + parentTag + ": " + parser.getName()); } Slog.w(TAG, "Unknown element under " + parentTag + ": " - + parser.getName() + " at " + pkg.getBaseCodePath() + " " + + parser.getName() + " at " + pkg.getBaseApkPath() + " " + parser.getPositionDescription()); XmlUtils.skipCurrentTag(parser); return input.success(null); // Type doesn't matter diff --git a/core/java/android/content/pm/parsing/component/ComponentParseUtils.java b/core/java/android/content/pm/parsing/component/ComponentParseUtils.java index c4caedcb87ff..cfefc016d4a4 100644 --- a/core/java/android/content/pm/parsing/component/ComponentParseUtils.java +++ b/core/java/android/content/pm/parsing/component/ComponentParseUtils.java @@ -24,15 +24,13 @@ import android.content.pm.PackageParser; import android.content.pm.PackageUserState; import android.content.pm.parsing.ParsingPackage; import android.content.pm.parsing.ParsingUtils; +import android.content.pm.parsing.result.ParseInput; +import android.content.pm.parsing.result.ParseResult; import android.content.res.Resources; import android.content.res.TypedArray; import android.content.res.XmlResourceParser; import android.text.TextUtils; -import android.content.pm.parsing.ParsingPackageUtils; -import android.content.pm.parsing.result.ParseInput; -import android.content.pm.parsing.result.ParseResult; - import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParserException; @@ -41,8 +39,6 @@ import java.io.IOException; /** @hide */ public class ComponentParseUtils { - private static final String TAG = ParsingPackageUtils.TAG; - public static boolean isImplicitlyExposedIntent(ParsedIntentInfo intentInfo) { return intentInfo.hasCategory(Intent.CATEGORY_BROWSABLE) || intentInfo.hasAction(Intent.ACTION_SEND) diff --git a/core/java/android/content/pm/parsing/component/ParsedActivityUtils.java b/core/java/android/content/pm/parsing/component/ParsedActivityUtils.java index 6927f3b8a97d..8c0bfef19d0f 100644 --- a/core/java/android/content/pm/parsing/component/ParsedActivityUtils.java +++ b/core/java/android/content/pm/parsing/component/ParsedActivityUtils.java @@ -24,7 +24,6 @@ import android.app.ActivityTaskManager; import android.content.pm.ActivityInfo; import android.content.pm.PackageParser; import android.content.pm.parsing.ParsingPackage; -import android.content.pm.parsing.ParsingPackageUtils; import android.content.pm.parsing.ParsingUtils; import android.content.pm.parsing.result.ParseInput; import android.content.pm.parsing.result.ParseInput.DeferredError; @@ -55,7 +54,7 @@ import java.util.Objects; /** @hide */ public class ParsedActivityUtils { - private static final String TAG = ParsingPackageUtils.TAG; + private static final String TAG = ParsingUtils.TAG; @NonNull @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE) diff --git a/core/java/android/content/pm/parsing/component/ParsedComponentUtils.java b/core/java/android/content/pm/parsing/component/ParsedComponentUtils.java index 6811e06fbe7e..dd2fb5bd2d78 100644 --- a/core/java/android/content/pm/parsing/component/ParsedComponentUtils.java +++ b/core/java/android/content/pm/parsing/component/ParsedComponentUtils.java @@ -36,8 +36,6 @@ import com.android.internal.annotations.VisibleForTesting; /** @hide */ class ParsedComponentUtils { - private static final String TAG = ParsingPackageUtils.TAG; - @NonNull @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE) static <Component extends ParsedComponent> ParseResult<Component> parseComponent( diff --git a/core/java/android/content/pm/parsing/component/ParsedIntentInfo.java b/core/java/android/content/pm/parsing/component/ParsedIntentInfo.java index 0ba92cc4fef7..6b797bcb6ab2 100644 --- a/core/java/android/content/pm/parsing/component/ParsedIntentInfo.java +++ b/core/java/android/content/pm/parsing/component/ParsedIntentInfo.java @@ -22,7 +22,6 @@ import android.os.Parcel; import android.os.Parcelable; import android.util.Pair; -import com.android.internal.util.DataClass; import com.android.internal.util.Parcelling; import java.util.ArrayList; @@ -163,7 +162,7 @@ public final class ParsedIntentInfo extends IntentFilter { } public String toString() { - return "ProviderIntentInfo{" + return "ParsedIntentInfo{" + Integer.toHexString(System.identityHashCode(this)) + '}'; } diff --git a/core/java/android/content/pm/parsing/component/ParsedIntentInfoUtils.java b/core/java/android/content/pm/parsing/component/ParsedIntentInfoUtils.java index 390f76968e7c..c0536bb7eb10 100644 --- a/core/java/android/content/pm/parsing/component/ParsedIntentInfoUtils.java +++ b/core/java/android/content/pm/parsing/component/ParsedIntentInfoUtils.java @@ -21,7 +21,6 @@ import android.content.Intent; import android.content.IntentFilter; import android.content.pm.PackageParser; import android.content.pm.parsing.ParsingPackage; -import android.content.pm.parsing.ParsingPackageUtils; import android.content.pm.parsing.ParsingUtils; import android.content.pm.parsing.result.ParseInput; import android.content.pm.parsing.result.ParseResult; @@ -43,7 +42,7 @@ import java.util.Iterator; /** @hide */ public class ParsedIntentInfoUtils { - private static final String TAG = ParsingPackageUtils.TAG; + private static final String TAG = ParsingUtils.TAG; @NonNull public static ParseResult<ParsedIntentInfo> parseIntentInfo(String className, diff --git a/core/java/android/content/pm/parsing/component/ParsedMainComponentUtils.java b/core/java/android/content/pm/parsing/component/ParsedMainComponentUtils.java index f4c9914cb69f..f70d62b56d49 100644 --- a/core/java/android/content/pm/parsing/component/ParsedMainComponentUtils.java +++ b/core/java/android/content/pm/parsing/component/ParsedMainComponentUtils.java @@ -20,7 +20,7 @@ import android.annotation.NonNull; import android.annotation.Nullable; import android.content.IntentFilter; import android.content.pm.parsing.ParsingPackage; -import android.content.pm.parsing.ParsingPackageUtils; +import android.content.pm.parsing.ParsingUtils; import android.content.pm.parsing.result.ParseInput; import android.content.pm.parsing.result.ParseResult; import android.content.res.Configuration; @@ -39,7 +39,7 @@ import java.io.IOException; /** @hide */ class ParsedMainComponentUtils { - private static final String TAG = ParsingPackageUtils.TAG; + private static final String TAG = ParsingUtils.TAG; @NonNull @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE) @@ -113,7 +113,7 @@ class ParsedMainComponentUtils { ParsedIntentInfo intent = intentResult.getResult(); int actionCount = intent.countActions(); if (actionCount == 0 && failOnNoActions) { - Slog.w(TAG, "No actions in " + parser.getName() + " at " + pkg.getBaseCodePath() + " " + Slog.w(TAG, "No actions in " + parser.getName() + " at " + pkg.getBaseApkPath() + " " + parser.getPositionDescription()); // Backward-compat, do not actually fail return input.success(null); diff --git a/core/java/android/content/pm/parsing/component/ParsedPermissionUtils.java b/core/java/android/content/pm/parsing/component/ParsedPermissionUtils.java index 1884a1e27832..894849ada213 100644 --- a/core/java/android/content/pm/parsing/component/ParsedPermissionUtils.java +++ b/core/java/android/content/pm/parsing/component/ParsedPermissionUtils.java @@ -19,15 +19,15 @@ package android.content.pm.parsing.component; import android.annotation.NonNull; import android.content.pm.PermissionInfo; import android.content.pm.parsing.ParsingPackage; +import android.content.pm.parsing.ParsingUtils; +import android.content.pm.parsing.result.ParseInput; +import android.content.pm.parsing.result.ParseResult; import android.content.res.Resources; import android.content.res.TypedArray; import android.content.res.XmlResourceParser; import android.util.Slog; import com.android.internal.R; -import android.content.pm.parsing.ParsingPackageUtils; -import android.content.pm.parsing.result.ParseInput; -import android.content.pm.parsing.result.ParseResult; import org.xmlpull.v1.XmlPullParserException; @@ -36,7 +36,7 @@ import java.io.IOException; /** @hide */ public class ParsedPermissionUtils { - private static final String TAG = ParsingPackageUtils.TAG; + private static final String TAG = ParsingUtils.TAG; @NonNull public static ParseResult<ParsedPermission> parsePermission(ParsingPackage pkg, Resources res, @@ -106,11 +106,6 @@ public class ParsedPermissionUtils { sa.recycle(); } - // TODO(b/135203078): This is impossible because of default value in above getInt - if (permission.protectionLevel == -1) { - return input.error("<permission> does not specify protectionLevel"); - } - permission.protectionLevel = PermissionInfo.fixProtectionLevel(permission.protectionLevel); if (permission.getProtectionFlags() != 0) { diff --git a/core/java/android/content/pm/parsing/component/ParsedProcessUtils.java b/core/java/android/content/pm/parsing/component/ParsedProcessUtils.java index 837270721078..9bff719e45dd 100644 --- a/core/java/android/content/pm/parsing/component/ParsedProcessUtils.java +++ b/core/java/android/content/pm/parsing/component/ParsedProcessUtils.java @@ -40,8 +40,6 @@ import java.util.Set; /** @hide */ public class ParsedProcessUtils { - private static final String TAG = ParsingUtils.TAG; - @NonNull private static ParseResult<Set<String>> parseDenyPermission(Set<String> perms, Resources res, XmlResourceParser parser, ParseInput input) diff --git a/core/java/android/content/pm/parsing/component/ParsedProviderUtils.java b/core/java/android/content/pm/parsing/component/ParsedProviderUtils.java index aa5ea8d4295a..37cbeca1d23a 100644 --- a/core/java/android/content/pm/parsing/component/ParsedProviderUtils.java +++ b/core/java/android/content/pm/parsing/component/ParsedProviderUtils.java @@ -23,7 +23,6 @@ import android.content.pm.PackageParser; import android.content.pm.PathPermission; import android.content.pm.ProviderInfo; import android.content.pm.parsing.ParsingPackage; -import android.content.pm.parsing.ParsingPackageUtils; import android.content.pm.parsing.ParsingUtils; import android.content.pm.parsing.result.ParseInput; import android.content.pm.parsing.result.ParseResult; @@ -45,7 +44,7 @@ import java.util.Objects; /** @hide */ public class ParsedProviderUtils { - private static final String TAG = ParsingPackageUtils.TAG; + private static final String TAG = ParsingUtils.TAG; @NonNull public static ParseResult<ParsedProvider> parseProvider(String[] separateProcesses, @@ -247,7 +246,7 @@ public class ParsedProviderUtils { } Slog.w(TAG, "Unknown element under <path-permission>: " + name + " at " - + pkg.getBaseCodePath() + " " + parser.getPositionDescription()); + + pkg.getBaseApkPath() + " " + parser.getPositionDescription()); } return input.success(provider); @@ -293,7 +292,8 @@ public class ParsedProviderUtils { "No readPermission or writePermission for <path-permission>"); } Slog.w(TAG, "No readPermission or writePermission for <path-permission>: " - + name + " at " + pkg.getBaseCodePath() + " " + parser.getPositionDescription()); + + name + " at " + pkg.getBaseApkPath() + " " + + parser.getPositionDescription()); return input.success(provider); } @@ -342,7 +342,7 @@ public class ParsedProviderUtils { } Slog.w(TAG, "No path, pathPrefix, or pathPattern for <path-permission>: " - + name + " at " + pkg.getBaseCodePath() + + name + " at " + pkg.getBaseApkPath() + " " + parser.getPositionDescription()); } diff --git a/core/java/android/content/pm/parsing/component/ParsedServiceUtils.java b/core/java/android/content/pm/parsing/component/ParsedServiceUtils.java index a8d2d671e5e6..afe3c5494fcb 100644 --- a/core/java/android/content/pm/parsing/component/ParsedServiceUtils.java +++ b/core/java/android/content/pm/parsing/component/ParsedServiceUtils.java @@ -22,7 +22,6 @@ import android.annotation.NonNull; import android.content.pm.ActivityInfo; import android.content.pm.ServiceInfo; import android.content.pm.parsing.ParsingPackage; -import android.content.pm.parsing.ParsingPackageUtils; import android.content.pm.parsing.ParsingUtils; import android.content.pm.parsing.result.ParseInput; import android.content.pm.parsing.result.ParseInput.DeferredError; @@ -43,8 +42,6 @@ import java.util.Objects; /** @hide */ public class ParsedServiceUtils { - private static final String TAG = ParsingPackageUtils.TAG; - @NonNull public static ParseResult<ParsedService> parseService(String[] separateProcesses, ParsingPackage pkg, Resources res, XmlResourceParser parser, int flags, diff --git a/core/java/android/content/pm/parsing/result/ParseTypeImpl.java b/core/java/android/content/pm/parsing/result/ParseTypeImpl.java index 14992fb2a4d1..0f90b5371965 100644 --- a/core/java/android/content/pm/parsing/result/ParseTypeImpl.java +++ b/core/java/android/content/pm/parsing/result/ParseTypeImpl.java @@ -95,7 +95,7 @@ public class ParseTypeImpl implements ParseInput, ParseResult<Object> { return platformCompat.isChangeEnabled(changeId, appInfo); } catch (Exception e) { // This shouldn't happen, but assume enforcement if it does - Slog.wtf(ParsingUtils.TAG, "IPlatformCompat query failed", e); + Slog.wtf(TAG, "IPlatformCompat query failed", e); return true; } }); @@ -125,7 +125,7 @@ public class ParseTypeImpl implements ParseInput, ParseResult<Object> { @Override public <ResultType> ParseResult<ResultType> success(ResultType result) { if (mErrorCode != PackageManager.INSTALL_SUCCEEDED) { - Slog.wtf(ParsingUtils.TAG, "Cannot set to success after set to error, was " + Slog.wtf(TAG, "Cannot set to success after set to error, was " + mErrorMessage, mException); } mResult = result; diff --git a/core/java/android/os/Binder.java b/core/java/android/os/Binder.java index 515704ca77f4..bec96f98dbcd 100644 --- a/core/java/android/os/Binder.java +++ b/core/java/android/os/Binder.java @@ -1102,7 +1102,6 @@ public class Binder implements IBinder { } private static native long getNativeBBinderHolder(); - private static native long getFinalizer(); /** * By default, we use the calling uid since we can always trust it. diff --git a/core/java/android/os/LocaleList.java b/core/java/android/os/LocaleList.java index ab4bb0b9f2cd..9c0bc45a346e 100644 --- a/core/java/android/os/LocaleList.java +++ b/core/java/android/os/LocaleList.java @@ -25,6 +25,7 @@ import android.icu.util.ULocale; import com.android.internal.annotations.GuardedBy; +import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.HashSet; @@ -151,18 +152,18 @@ public final class LocaleList implements Parcelable { /** * Creates a new {@link LocaleList}. * + * If two or more same locales are passed, the repeated locales will be dropped. * <p>For empty lists of {@link Locale} items it is better to use {@link #getEmptyLocaleList()}, * which returns a pre-constructed empty list.</p> * * @throws NullPointerException if any of the input locales is <code>null</code>. - * @throws IllegalArgumentException if any of the input locales repeat. */ public LocaleList(@NonNull Locale... list) { if (list.length == 0) { mList = sEmptyList; mStringRepresentation = ""; } else { - final Locale[] localeList = new Locale[list.length]; + final ArrayList<Locale> localeList = new ArrayList<>(); final HashSet<Locale> seenLocales = new HashSet<Locale>(); final StringBuilder sb = new StringBuilder(); for (int i = 0; i < list.length; i++) { @@ -170,10 +171,10 @@ public final class LocaleList implements Parcelable { if (l == null) { throw new NullPointerException("list[" + i + "] is null"); } else if (seenLocales.contains(l)) { - throw new IllegalArgumentException("list[" + i + "] is a repetition"); + // Dropping duplicated locale entries. } else { final Locale localeClone = (Locale) l.clone(); - localeList[i] = localeClone; + localeList.add(localeClone); sb.append(localeClone.toLanguageTag()); if (i < list.length - 1) { sb.append(','); @@ -181,7 +182,7 @@ public final class LocaleList implements Parcelable { seenLocales.add(localeClone); } } - mList = localeList; + mList = localeList.toArray(new Locale[localeList.size()]); mStringRepresentation = sb.toString(); } } diff --git a/core/java/android/os/storage/StorageManagerInternal.java b/core/java/android/os/storage/StorageManagerInternal.java index e05991b33796..a79a1cfcd64f 100644 --- a/core/java/android/os/storage/StorageManagerInternal.java +++ b/core/java/android/os/storage/StorageManagerInternal.java @@ -118,7 +118,7 @@ public abstract class StorageManagerInternal { * affects them. */ public abstract void onAppOpsChanged(int code, int uid, - @Nullable String packageName, int mode); + @Nullable String packageName, int mode, int previousMode); /** * Asks the StorageManager to reset all state for the provided user; this will result diff --git a/core/java/android/provider/DeviceConfig.java b/core/java/android/provider/DeviceConfig.java index 859b70382328..7a03953f2e9b 100644 --- a/core/java/android/provider/DeviceConfig.java +++ b/core/java/android/provider/DeviceConfig.java @@ -145,6 +145,15 @@ public final class DeviceConfig { public static final String NAMESPACE_CONTENT_CAPTURE = "content_capture"; /** + * Namespace for device idle configurations. + * + * @hide + */ + @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) + @TestApi + public static final String NAMESPACE_DEVICE_IDLE = "device_idle"; + + /** * Namespace for how dex runs. The feature requires a reboot to reach a clean state. * * @deprecated No longer used diff --git a/core/java/android/provider/DocumentsProvider.java b/core/java/android/provider/DocumentsProvider.java index d55fc511fc77..4e1f81919c7d 100644 --- a/core/java/android/provider/DocumentsProvider.java +++ b/core/java/android/provider/DocumentsProvider.java @@ -239,6 +239,10 @@ public abstract class DocumentsProvider extends ContentProvider { } } + private Uri validateIncomingNullableUri(@Nullable Uri uri) { + return uri == null ? null : validateIncomingUri(uri); + } + /** * Create a new document and return its newly generated * {@link Document#COLUMN_DOCUMENT_ID}. You must allocate a new @@ -1086,11 +1090,18 @@ public abstract class DocumentsProvider extends ContentProvider { // If the URI is a tree URI performs some validation. enforceTreeForExtraUris(extras); + final Uri extraUri = validateIncomingNullableUri( + extras.getParcelable(DocumentsContract.EXTRA_URI)); + final Uri extraTargetUri = validateIncomingNullableUri( + extras.getParcelable(DocumentsContract.EXTRA_TARGET_URI)); + final Uri extraParentUri = validateIncomingNullableUri( + extras.getParcelable(DocumentsContract.EXTRA_PARENT_URI)); + if (METHOD_EJECT_ROOT.equals(method)) { // Given that certain system apps can hold MOUNT_UNMOUNT permission, but only apps // signed with platform signature can hold MANAGE_DOCUMENTS, we are going to check for // MANAGE_DOCUMENTS or associated URI permission here instead - final Uri rootUri = extras.getParcelable(DocumentsContract.EXTRA_URI); + final Uri rootUri = extraUri; enforceWritePermissionInner(rootUri, getCallingPackage(), getCallingAttributionTag(), null); @@ -1100,7 +1111,7 @@ public abstract class DocumentsProvider extends ContentProvider { return out; } - final Uri documentUri = extras.getParcelable(DocumentsContract.EXTRA_URI); + final Uri documentUri = extraUri; final String authority = documentUri.getAuthority(); final String documentId = DocumentsContract.getDocumentId(documentUri); @@ -1113,7 +1124,7 @@ public abstract class DocumentsProvider extends ContentProvider { enforceReadPermissionInner(documentUri, getCallingPackage(), getCallingAttributionTag(), null); - final Uri childUri = extras.getParcelable(DocumentsContract.EXTRA_TARGET_URI); + final Uri childUri = extraTargetUri; final String childAuthority = childUri.getAuthority(); final String childId = DocumentsContract.getDocumentId(childUri); @@ -1180,7 +1191,7 @@ public abstract class DocumentsProvider extends ContentProvider { revokeDocumentPermission(documentId); } else if (METHOD_COPY_DOCUMENT.equals(method)) { - final Uri targetUri = extras.getParcelable(DocumentsContract.EXTRA_TARGET_URI); + final Uri targetUri = extraTargetUri; final String targetId = DocumentsContract.getDocumentId(targetUri); enforceReadPermissionInner(documentUri, getCallingPackage(), @@ -1204,9 +1215,9 @@ public abstract class DocumentsProvider extends ContentProvider { } } else if (METHOD_MOVE_DOCUMENT.equals(method)) { - final Uri parentSourceUri = extras.getParcelable(DocumentsContract.EXTRA_PARENT_URI); + final Uri parentSourceUri = extraParentUri; final String parentSourceId = DocumentsContract.getDocumentId(parentSourceUri); - final Uri targetUri = extras.getParcelable(DocumentsContract.EXTRA_TARGET_URI); + final Uri targetUri = extraTargetUri; final String targetId = DocumentsContract.getDocumentId(targetUri); enforceWritePermissionInner(documentUri, getCallingPackage(), @@ -1232,7 +1243,7 @@ public abstract class DocumentsProvider extends ContentProvider { } } else if (METHOD_REMOVE_DOCUMENT.equals(method)) { - final Uri parentSourceUri = extras.getParcelable(DocumentsContract.EXTRA_PARENT_URI); + final Uri parentSourceUri = extraParentUri; final String parentSourceId = DocumentsContract.getDocumentId(parentSourceUri); enforceReadPermissionInner(parentSourceUri, getCallingPackage(), diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java index 03cf0cf2ca78..18337b661844 100644 --- a/core/java/android/provider/Settings.java +++ b/core/java/android/provider/Settings.java @@ -6801,6 +6801,13 @@ public final class Settings { public static final String KEYGUARD_SLICE_URI = "keyguard_slice_uri"; /** + * Whether to draw text in bold. + * + * @hide + */ + public static final String FORCE_BOLD_TEXT = "force_bold_text"; + + /** * Whether to speak passwords while in accessibility mode. * * @deprecated The speaking of passwords is controlled by individual accessibility services. @@ -11534,38 +11541,6 @@ public final class Settings { public static final String APP_OPS_CONSTANTS = "app_ops_constants"; /** - * Device Idle (Doze) specific settings. - * This is encoded as a key=value list, separated by commas. Ex: - * - * "inactive_to=60000,sensing_to=400000" - * - * The following keys are supported: - * - * <pre> - * inactive_to (long) - * sensing_to (long) - * motion_inactive_to (long) - * idle_after_inactive_to (long) - * idle_pending_to (long) - * max_idle_pending_to (long) - * idle_pending_factor (float) - * quick_doze_delay_to (long) - * idle_to (long) - * max_idle_to (long) - * idle_factor (float) - * min_time_to_alarm (long) - * max_temp_app_whitelist_duration (long) - * notification_whitelist_duration (long) - * </pre> - * - * <p> - * Type: string - * @hide - * @see com.android.server.DeviceIdleController.Constants - */ - public static final String DEVICE_IDLE_CONSTANTS = "device_idle_constants"; - - /** * Battery Saver specific settings * This is encoded as a key=value list, separated by commas. Ex: * diff --git a/core/java/android/service/wallpaper/WallpaperService.java b/core/java/android/service/wallpaper/WallpaperService.java index e083417644e3..19860eb45fbf 100644 --- a/core/java/android/service/wallpaper/WallpaperService.java +++ b/core/java/android/service/wallpaper/WallpaperService.java @@ -71,6 +71,7 @@ import android.view.ViewGroup; import android.view.WindowInsets; import android.view.WindowManager; import android.view.WindowManagerGlobal; +import android.window.ClientWindowFrames; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.os.HandlerCaller; @@ -186,17 +187,11 @@ public abstract class WallpaperService extends Service { int mCurWindowFlags = mWindowFlags; int mCurWindowPrivateFlags = mWindowPrivateFlags; Rect mPreviewSurfacePosition; - final Rect mVisibleInsets = new Rect(); - final Rect mWinFrame = new Rect(); - final Rect mContentInsets = new Rect(); - final Rect mStableInsets = new Rect(); + final ClientWindowFrames mWinFrames = new ClientWindowFrames(); final Rect mDispatchedContentInsets = new Rect(); final Rect mDispatchedStableInsets = new Rect(); final Rect mFinalSystemInsets = new Rect(); final Rect mFinalStableInsets = new Rect(); - final Rect mBackdropFrame = new Rect(); - final DisplayCutout.ParcelableWrapper mDisplayCutout = - new DisplayCutout.ParcelableWrapper(); DisplayCutout mDispatchedDisplayCutout = DisplayCutout.NO_CUTOUT; final InsetsState mInsetsState = new InsetsState(); final InsetsSourceControl[] mTempControls = new InsetsSourceControl[0]; @@ -332,11 +327,9 @@ public abstract class WallpaperService extends Service { final BaseIWindow mWindow = new BaseIWindow() { @Override - public void resized(Rect frame, Rect contentInsets, - Rect visibleInsets, Rect stableInsets, boolean reportDraw, - MergedConfiguration mergedConfiguration, Rect backDropRect, boolean forceLayout, - boolean alwaysConsumeSystemBars, int displayId, - DisplayCutout.ParcelableWrapper displayCutout) { + public void resized(ClientWindowFrames frames, boolean reportDraw, + MergedConfiguration mergedConfiguration, boolean forceLayout, + boolean alwaysConsumeSystemBars, int displayId) { Message msg = mCaller.obtainMessageI(MSG_WINDOW_RESIZED, reportDraw ? 1 : 0); mCaller.sendMessage(msg); @@ -749,10 +742,7 @@ public abstract class WallpaperService extends Service { out.print(" mCurWindowFlags="); out.println(mCurWindowFlags); out.print(prefix); out.print("mWindowPrivateFlags="); out.print(mWindowPrivateFlags); out.print(" mCurWindowPrivateFlags="); out.println(mCurWindowPrivateFlags); - out.print(prefix); out.print("mVisibleInsets="); - out.print(mVisibleInsets.toShortString()); - out.print(" mWinFrame="); out.print(mWinFrame.toShortString()); - out.print(" mContentInsets="); out.println(mContentInsets.toShortString()); + out.print(prefix); out.println("mWinFrames="); out.println(mWinFrames); out.print(prefix); out.print("mConfiguration="); out.println(mMergedConfiguration.getMergedConfiguration()); out.print(prefix); out.print("mLayout="); out.println(mLayout); @@ -890,8 +880,8 @@ public abstract class WallpaperService extends Service { InputChannel inputChannel = new InputChannel(); if (mSession.addToDisplay(mWindow, mWindow.mSeq, mLayout, View.VISIBLE, - mDisplay.getDisplayId(), mWinFrame, mContentInsets, mStableInsets, - mDisplayCutout, inputChannel, + mDisplay.getDisplayId(), mWinFrames.frame, mWinFrames.contentInsets, + mWinFrames.stableInsets, mWinFrames.displayCutout, inputChannel, mInsetsState, mTempControls) < 0) { Log.w(TAG, "Failed to add window while updating wallpaper surface."); return; @@ -914,34 +904,32 @@ public abstract class WallpaperService extends Service { final int relayoutResult = mSession.relayout( mWindow, mWindow.mSeq, mLayout, mWidth, mHeight, - View.VISIBLE, 0, -1, mWinFrame, mContentInsets, - mVisibleInsets, mStableInsets, mBackdropFrame, - mDisplayCutout, mMergedConfiguration, mSurfaceControl, + View.VISIBLE, 0, -1, mWinFrames, mMergedConfiguration, mSurfaceControl, mInsetsState, mTempControls, mSurfaceSize, mTmpSurfaceControl); if (mSurfaceControl.isValid()) { mSurfaceHolder.mSurface.copyFrom(mSurfaceControl); } if (DEBUG) Log.v(TAG, "New surface: " + mSurfaceHolder.mSurface - + ", frame=" + mWinFrame); + + ", frame=" + mWinFrames); - int w = mWinFrame.width(); - int h = mWinFrame.height(); + int w = mWinFrames.frame.width(); + int h = mWinFrames.frame.height(); if (!fixedSize) { final Rect padding = mIWallpaperEngine.mDisplayPadding; w += padding.left + padding.right; h += padding.top + padding.bottom; - mContentInsets.left += padding.left; - mContentInsets.top += padding.top; - mContentInsets.right += padding.right; - mContentInsets.bottom += padding.bottom; - mStableInsets.left += padding.left; - mStableInsets.top += padding.top; - mStableInsets.right += padding.right; - mStableInsets.bottom += padding.bottom; - mDisplayCutout.set(mDisplayCutout.get().inset(-padding.left, -padding.top, - -padding.right, -padding.bottom)); + mWinFrames.contentInsets.left += padding.left; + mWinFrames.contentInsets.top += padding.top; + mWinFrames.contentInsets.right += padding.right; + mWinFrames.contentInsets.bottom += padding.bottom; + mWinFrames.stableInsets.left += padding.left; + mWinFrames.stableInsets.top += padding.top; + mWinFrames.stableInsets.right += padding.right; + mWinFrames.stableInsets.bottom += padding.bottom; + mWinFrames.displayCutout.set(mWinFrames.displayCutout.get().inset( + -padding.left, -padding.top, -padding.right, -padding.bottom)); } else { w = myWidth; h = myHeight; @@ -960,9 +948,10 @@ public abstract class WallpaperService extends Service { Log.v(TAG, "Wallpaper size has changed: (" + mCurWidth + ", " + mCurHeight); } - insetsChanged |= !mDispatchedContentInsets.equals(mContentInsets); - insetsChanged |= !mDispatchedStableInsets.equals(mStableInsets); - insetsChanged |= !mDispatchedDisplayCutout.equals(mDisplayCutout.get()); + final DisplayCutout displayCutout = mWinFrames.displayCutout.get(); + insetsChanged |= !mDispatchedContentInsets.equals(mWinFrames.contentInsets); + insetsChanged |= !mDispatchedStableInsets.equals(mWinFrames.stableInsets); + insetsChanged |= !mDispatchedDisplayCutout.equals(displayCutout); mSurfaceHolder.setSurfaceFrameSize(w, h); mSurfaceHolder.mSurfaceLock.unlock(); @@ -1021,9 +1010,9 @@ public abstract class WallpaperService extends Service { } if (insetsChanged) { - mDispatchedContentInsets.set(mContentInsets); - mDispatchedStableInsets.set(mStableInsets); - mDispatchedDisplayCutout = mDisplayCutout.get(); + mDispatchedContentInsets.set(mWinFrames.contentInsets); + mDispatchedStableInsets.set(mWinFrames.stableInsets); + mDispatchedDisplayCutout = displayCutout; mFinalStableInsets.set(mDispatchedStableInsets); WindowInsets insets = new WindowInsets(mFinalSystemInsets, mFinalStableInsets, diff --git a/core/java/android/speech/RecognitionService.java b/core/java/android/speech/RecognitionService.java index 4b42209be653..5fd192afed00 100644 --- a/core/java/android/speech/RecognitionService.java +++ b/core/java/android/speech/RecognitionService.java @@ -183,10 +183,9 @@ public abstract class RecognitionService extends Service { @NonNull String packageName, @Nullable String featureId) { if (DBG) Log.d(TAG, "checkPermissions"); if (forDataDelivery) { - if (PermissionChecker.checkCallingPermissionForDataDelivery(this, + if (PermissionChecker.checkCallingOrSelfPermissionForDataDelivery(this, android.Manifest.permission.RECORD_AUDIO, packageName, featureId, - null /*message*/) - == PermissionChecker.PERMISSION_GRANTED) { + null /*message*/) == PermissionChecker.PERMISSION_GRANTED) { return true; } } else { diff --git a/core/java/android/telephony/PhoneStateListener.java b/core/java/android/telephony/PhoneStateListener.java index cbc304b3293a..8f31d77ac180 100644 --- a/core/java/android/telephony/PhoneStateListener.java +++ b/core/java/android/telephony/PhoneStateListener.java @@ -486,6 +486,16 @@ public class PhoneStateListener { @RequiresPermission(Manifest.permission.READ_PRECISE_PHONE_STATE) public static final int LISTEN_BARRING_INFO = 0x80000000; + /** + * Listen for changes to the physical channel configuration. + * + * @see #onPhysicalChannelConfigurationChanged + * @hide + */ + @SystemApi + @RequiresPermission(android.Manifest.permission.READ_PRECISE_PHONE_STATE) + public static final long LISTEN_PHYSICAL_CHANNEL_CONFIGURATION = 0x100000000L; + /* * Subscription used to listen to the phone state changes * @hide @@ -1145,6 +1155,18 @@ public class PhoneStateListener { } /** + * Callback invoked when the current physical channel configuration has changed + * + * @param configs List of the current {@link PhysicalChannelConfig}s + * @hide + */ + @SystemApi + public void onPhysicalChannelConfigurationChanged( + @NonNull List<PhysicalChannelConfig> configs) { + // default implementation empty + } + + /** * The callback methods need to be called on the handler thread where * this object was created. If the binder did that for us it'd be nice. * @@ -1447,6 +1469,15 @@ public class PhoneStateListener { Binder.withCleanCallingIdentity( () -> mExecutor.execute(() -> psl.onBarringInfoChanged(barringInfo))); } + + public void onPhysicalChannelConfigurationChanged(List<PhysicalChannelConfig> configs) { + PhoneStateListener psl = mPhoneStateListenerWeakRef.get(); + if (psl == null) return; + + Binder.withCleanCallingIdentity( + () -> mExecutor.execute( + () -> psl.onPhysicalChannelConfigurationChanged(configs))); + } } diff --git a/core/java/android/telephony/TelephonyRegistryManager.java b/core/java/android/telephony/TelephonyRegistryManager.java index a720601d81ff..6d48dc36ceb4 100644 --- a/core/java/android/telephony/TelephonyRegistryManager.java +++ b/core/java/android/telephony/TelephonyRegistryManager.java @@ -211,7 +211,7 @@ public class TelephonyRegistryManager { * @param notifyNow Whether to notify instantly */ public void listenForSubscriber(int subId, @NonNull String pkg, @NonNull String featureId, - @NonNull PhoneStateListener listener, int events, boolean notifyNow) { + @NonNull PhoneStateListener listener, long events, boolean notifyNow) { try { // subId from PhoneStateListener is deprecated Q on forward, use the subId from // TelephonyManager instance. Keep using subId from PhoneStateListener for pre-Q. @@ -754,4 +754,19 @@ public class TelephonyRegistryManager { } } + /** + * Notify {@link PhysicalChannelConfig} has changed for a specific subscription. + * + * @param subId the subId + * @param configs a list of {@link PhysicalChannelConfig}, the configs of physical channel. + */ + public void notifyPhysicalChannelConfigurationForSubscriber( + int subId, List<PhysicalChannelConfig> configs) { + try { + sRegistry.notifyPhysicalChannelConfigurationForSubscriber(subId, configs); + } catch (RemoteException ex) { + // system server crash + } + } + } diff --git a/core/java/android/util/FeatureFlagUtils.java b/core/java/android/util/FeatureFlagUtils.java index e338fd977f27..09736085954c 100644 --- a/core/java/android/util/FeatureFlagUtils.java +++ b/core/java/android/util/FeatureFlagUtils.java @@ -65,6 +65,7 @@ public class FeatureFlagUtils { DEFAULT_FLAGS.put(SETTINGS_DO_NOT_RESTORE_PRESERVED, "true"); DEFAULT_FLAGS.put("settings_tether_all_in_one", "false"); + DEFAULT_FLAGS.put("settings_silky_home", "false"); } /** diff --git a/core/java/android/view/BatchedInputEventReceiver.java b/core/java/android/view/BatchedInputEventReceiver.java index 30e3ec135065..7023e4bd0134 100644 --- a/core/java/android/view/BatchedInputEventReceiver.java +++ b/core/java/android/view/BatchedInputEventReceiver.java @@ -24,7 +24,8 @@ import android.os.Looper; * @hide */ public class BatchedInputEventReceiver extends InputEventReceiver { - Choreographer mChoreographer; + private Choreographer mChoreographer; + private boolean mBatchingEnabled; private boolean mBatchedInputScheduled; @UnsupportedAppUsage @@ -32,19 +33,37 @@ public class BatchedInputEventReceiver extends InputEventReceiver { InputChannel inputChannel, Looper looper, Choreographer choreographer) { super(inputChannel, looper); mChoreographer = choreographer; + mBatchingEnabled = true; } @Override public void onBatchedInputEventPending(int source) { - scheduleBatchedInput(); + if (mBatchingEnabled) { + scheduleBatchedInput(); + } else { + consumeBatchedInputEvents(-1); + } } @Override public void dispose() { unscheduleBatchedInput(); + consumeBatchedInputEvents(-1); super.dispose(); } + /** + * Sets whether to enable batching on this input event receiver. + * @hide + */ + public void setBatchingEnabled(boolean batchingEnabled) { + mBatchingEnabled = batchingEnabled; + if (!batchingEnabled) { + unscheduleBatchedInput(); + consumeBatchedInputEvents(-1); + } + } + void doConsumeBatchedInput(long frameTimeNanos) { if (mBatchedInputScheduled) { mBatchedInputScheduled = false; diff --git a/core/java/android/view/IWindow.aidl b/core/java/android/view/IWindow.aidl index e09bf9d2e80a..94e641c62b25 100644 --- a/core/java/android/view/IWindow.aidl +++ b/core/java/android/view/IWindow.aidl @@ -29,6 +29,7 @@ import android.view.InsetsState; import android.view.IScrollCaptureController; import android.view.KeyEvent; import android.view.MotionEvent; +import android.window.ClientWindowFrames; import com.android.internal.os.IResultReceiver; @@ -52,11 +53,9 @@ oneway interface IWindow { */ void executeCommand(String command, String parameters, in ParcelFileDescriptor descriptor); - void resized(in Rect frame, in Rect contentInsets, - in Rect visibleInsets, in Rect stableInsets, boolean reportDraw, - in MergedConfiguration newMergedConfiguration, in Rect backDropFrame, - boolean forceLayout, boolean alwaysConsumeSystemBars, int displayId, - in DisplayCutout.ParcelableWrapper displayCutout); + void resized(in ClientWindowFrames frames, boolean reportDraw, + in MergedConfiguration newMergedConfiguration, + boolean forceLayout, boolean alwaysConsumeSystemBars, int displayId); /** * Called when the window location in parent display has changed. The offset will only be a diff --git a/core/java/android/view/IWindowManager.aidl b/core/java/android/view/IWindowManager.aidl index 00fc67214f75..8e875d7a889d 100644 --- a/core/java/android/view/IWindowManager.aidl +++ b/core/java/android/view/IWindowManager.aidl @@ -393,11 +393,6 @@ interface IWindowManager oneway void setRecentsVisibility(boolean visible); /** - * Called by System UI to notify of changes to the visibility of PIP. - */ - oneway void setPipVisibility(boolean visible); - - /** * Called by System UI to enable or disable haptic feedback on the navigation bar buttons. */ @UnsupportedAppUsage diff --git a/core/java/android/view/IWindowSession.aidl b/core/java/android/view/IWindowSession.aidl index 819e89b67b38..70850d855161 100644 --- a/core/java/android/view/IWindowSession.aidl +++ b/core/java/android/view/IWindowSession.aidl @@ -34,6 +34,7 @@ import android.view.InsetsState; import android.view.Surface; import android.view.SurfaceControl; import android.view.SurfaceControl.Transaction; +import android.window.ClientWindowFrames; import java.util.List; @@ -107,10 +108,7 @@ interface IWindowSession { */ int relayout(IWindow window, int seq, in WindowManager.LayoutParams attrs, int requestedWidth, int requestedHeight, int viewVisibility, - int flags, long frameNumber, out Rect outFrame, - out Rect outContentInsets, out Rect outVisibleInsets, out Rect outStableInsets, - out Rect outBackdropFrame, - out DisplayCutout.ParcelableWrapper displayCutout, + int flags, long frameNumber, out ClientWindowFrames outFrames, out MergedConfiguration outMergedConfiguration, out SurfaceControl outSurfaceControl, out InsetsState insetsState, out InsetsSourceControl[] activeControls, out Point outSurfaceSize, out SurfaceControl outBlastSurfaceControl); @@ -152,12 +150,6 @@ interface IWindowSession { in Rect visibleInsets, in Region touchableRegion); /** - * Return the current display size in which the window is being laid out, - * accounting for screen decorations around it. - */ - void getDisplayFrame(IWindow window, out Rect outDisplayFrame); - - /** * Called when the client has finished drawing the surface, if needed. * * @param postDrawTransaction transaction filled by the client that can be diff --git a/core/java/android/view/InsetsAnimationControlImpl.java b/core/java/android/view/InsetsAnimationControlImpl.java index 69220722fc05..6ffd892e4351 100644 --- a/core/java/android/view/InsetsAnimationControlImpl.java +++ b/core/java/android/view/InsetsAnimationControlImpl.java @@ -16,6 +16,7 @@ package android.view; +import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED; import static android.view.InsetsController.ANIMATION_TYPE_SHOW; import static android.view.InsetsController.AnimationType; import static android.view.InsetsController.DEBUG; @@ -24,6 +25,7 @@ import static android.view.InsetsState.ISIDE_LEFT; import static android.view.InsetsState.ISIDE_RIGHT; import static android.view.InsetsState.ISIDE_TOP; import static android.view.InsetsState.ITYPE_IME; +import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION; import static com.android.internal.annotations.VisibleForTesting.Visibility.PACKAGE; @@ -308,8 +310,8 @@ public class InsetsAnimationControlImpl implements WindowInsetsAnimationControll false /* isScreenRound */, false /* alwaysConsumeSystemBars */, null /* displayCutout */, LayoutParams.SOFT_INPUT_ADJUST_RESIZE /* legacySoftInputMode*/, - 0 /* legacyWindowFlags */, 0 /* legacySystemUiFlags */, typeSideMap) - .getInsets(mTypes); + 0 /* legacyWindowFlags */, 0 /* legacySystemUiFlags */, TYPE_APPLICATION, + WINDOWING_MODE_UNDEFINED, typeSideMap).getInsets(mTypes); } private Insets sanitize(Insets insets) { diff --git a/core/java/android/view/InsetsController.java b/core/java/android/view/InsetsController.java index 403ac3ab29c0..92eade3affaa 100644 --- a/core/java/android/view/InsetsController.java +++ b/core/java/android/view/InsetsController.java @@ -500,9 +500,11 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation /** Pending control request that is waiting on IME to be ready to be shown */ private PendingControlRequest mPendingImeControlRequest; + private int mWindowType; private int mLastLegacySoftInputMode; private int mLastLegacyWindowFlags; private int mLastLegacySystemUiFlags; + private int mLastWindowingMode; private DisplayCutout mLastDisplayCutout; private boolean mStartingAnimation; private int mCaptionInsetsHeight = 0; @@ -571,7 +573,8 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation WindowInsets insets = state.calculateInsets(mFrame, mState /* ignoringVisibilityState*/, mLastInsets.isRound(), mLastInsets.shouldAlwaysConsumeSystemBars(), mLastDisplayCutout, mLastLegacySoftInputMode, mLastLegacyWindowFlags, - mLastLegacySystemUiFlags, null /* typeSideMap */); + mLastLegacySystemUiFlags, mWindowType, mLastWindowingMode, + null /* typeSideMap */); mHost.dispatchWindowInsetsAnimationProgress(insets, mUnmodifiableTmpRunningAnims); if (DEBUG) { for (WindowInsetsAnimation anim : mUnmodifiableTmpRunningAnims) { @@ -709,9 +712,11 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation * @see InsetsState#calculateInsets */ @VisibleForTesting - public WindowInsets calculateInsets(boolean isScreenRound, - boolean alwaysConsumeSystemBars, DisplayCutout cutout, + public WindowInsets calculateInsets(boolean isScreenRound, boolean alwaysConsumeSystemBars, + DisplayCutout cutout, int windowType, int windowingMode, int legacySoftInputMode, int legacyWindowFlags, int legacySystemUiFlags) { + mWindowType = windowType; + mLastWindowingMode = windowingMode; mLastLegacySoftInputMode = legacySoftInputMode; mLastLegacyWindowFlags = legacyWindowFlags; mLastLegacySystemUiFlags = legacySystemUiFlags; @@ -719,7 +724,7 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation mLastInsets = mState.calculateInsets(mFrame, null /* ignoringVisibilityState*/, isScreenRound, alwaysConsumeSystemBars, cutout, legacySoftInputMode, legacyWindowFlags, legacySystemUiFlags, - null /* typeSideMap */); + windowType, windowingMode, null /* typeSideMap */); return mLastInsets; } diff --git a/core/java/android/view/InsetsSourceConsumer.java b/core/java/android/view/InsetsSourceConsumer.java index 700dc66fab55..ba40459692f7 100644 --- a/core/java/android/view/InsetsSourceConsumer.java +++ b/core/java/android/view/InsetsSourceConsumer.java @@ -113,13 +113,20 @@ public class InsetsSourceConsumer { InsetsState.typeToString(control.getType()), mController.getHost().getRootViewTitle())); } - // We are loosing control if (mSourceControl == null) { + // We are loosing control mController.notifyControlRevoked(this); - // Restore server visibility. - mState.getSource(getType()).setVisible( - mController.getLastDispatchedState().getSource(getType()).isVisible()); + // Check if we need to restore server visibility. + final InsetsSource source = mState.getSource(mType); + final boolean serverVisibility = + mController.getLastDispatchedState().getSourceOrDefaultVisibility(mType); + if (source.isVisible() != serverVisibility) { + source.setVisible(serverVisibility); + mController.notifyVisibilityChanged(); + } + + // For updateCompatSysUiVisibility applyLocalVisibilityOverride(); } else { // We are gaining control, and need to run an animation since previous state diff --git a/core/java/android/view/InsetsState.java b/core/java/android/view/InsetsState.java index 593b37af26ad..373a0963dc2f 100644 --- a/core/java/android/view/InsetsState.java +++ b/core/java/android/view/InsetsState.java @@ -30,11 +30,15 @@ import static android.view.WindowInsets.Type.isVisibleInsetsType; import static android.view.WindowInsets.Type.statusBars; import static android.view.WindowInsets.Type.systemBars; import static android.view.WindowManager.LayoutParams.FLAG_FULLSCREEN; +import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS; import static android.view.WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE; import static android.view.WindowManager.LayoutParams.SOFT_INPUT_MASK_ADJUST; +import static android.view.WindowManager.LayoutParams.TYPE_SYSTEM_ERROR; +import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER; import android.annotation.IntDef; import android.annotation.Nullable; +import android.app.WindowConfiguration; import android.graphics.Insets; import android.graphics.Rect; import android.os.Parcel; @@ -174,6 +178,7 @@ public class InsetsState implements Parcelable { public WindowInsets calculateInsets(Rect frame, @Nullable InsetsState ignoringVisibilityState, boolean isScreenRound, boolean alwaysConsumeSystemBars, DisplayCutout cutout, int legacySoftInputMode, int legacyWindowFlags, int legacySystemUiFlags, + int windowType, @WindowConfiguration.WindowingMode int windowingMode, @Nullable @InternalInsetsSide SparseIntArray typeSideMap) { Insets[] typeInsetsMap = new Insets[Type.SIZE]; Insets[] typeMaxInsetsMap = new Insets[Type.SIZE]; @@ -228,6 +233,9 @@ public class InsetsState implements Parcelable { if ((legacyWindowFlags & FLAG_FULLSCREEN) != 0) { compatInsetsTypes &= ~statusBars(); } + if (clearCompatInsets(windowType, legacyWindowFlags, windowingMode)) { + compatInsetsTypes = 0; + } return new WindowInsets(typeInsetsMap, typeMaxInsetsMap, typeVisibilityMap, isScreenRound, alwaysConsumeSystemBars, cutout, compatInsetsTypes, @@ -449,6 +457,12 @@ public class InsetsState implements Parcelable { mSources[source.getType()] = source; } + public static boolean clearCompatInsets(int windowType, int windowFlags, int windowingMode) { + return (windowFlags & FLAG_LAYOUT_NO_LIMITS) != 0 + && windowType != TYPE_WALLPAPER && windowType != TYPE_SYSTEM_ERROR + && !WindowConfiguration.inMultiWindowMode(windowingMode); + } + public static @InternalInsetsType ArraySet<Integer> toInternalType(@InsetsType int types) { final ArraySet<Integer> result = new ArraySet<>(); if ((types & Type.STATUS_BARS) != 0) { diff --git a/core/java/android/view/SurfaceControl.java b/core/java/android/view/SurfaceControl.java index 6ef086b55c41..67681dabf3f0 100644 --- a/core/java/android/view/SurfaceControl.java +++ b/core/java/android/view/SurfaceControl.java @@ -65,6 +65,9 @@ import java.nio.ByteBuffer; import java.nio.ByteOrder; import java.util.ArrayList; import java.util.Objects; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicReference; /** * Handle to an on-screen Surface managed by the system compositor. The SurfaceControl is @@ -87,10 +90,10 @@ public final class SurfaceControl implements Parcelable { private static native void nativeWriteToParcel(long nativeObject, Parcel out); private static native void nativeRelease(long nativeObject); private static native void nativeDisconnect(long nativeObject); - private static native ScreenshotHardwareBuffer nativeCaptureDisplay( - DisplayCaptureArgs captureArgs); - private static native ScreenshotHardwareBuffer nativeCaptureLayers( - LayerCaptureArgs captureArgs); + private static native int nativeCaptureDisplay(DisplayCaptureArgs captureArgs, + ScreenCaptureListener captureListener); + private static native int nativeCaptureLayers(LayerCaptureArgs captureArgs, + ScreenCaptureListener captureListener); private static native long nativeMirrorSurface(long mirrorOfObject); private static native long nativeCreateTransaction(); private static native long nativeGetNativeTransactionFinalizer(); @@ -221,6 +224,8 @@ public final class SurfaceControl implements Parcelable { private static native void nativeReleaseFrameRateFlexibilityToken(long token); private static native void nativeSetFixedTransformHint(long transactionObj, long nativeObject, int transformHint); + private static native void nativeSetFocusedWindow(long transactionObj, IBinder toToken, + IBinder focusedToken, int displayId); @Nullable @GuardedBy("mLock") @@ -493,6 +498,8 @@ public final class SurfaceControl implements Parcelable { private static final int INTERNAL_DATASPACE_DISPLAY_P3 = 143261696; private static final int INTERNAL_DATASPACE_SCRGB = 411107328; + private static final int SCREENSHOT_WAIT_TIME_S = 1; + private void assignNativeObject(long nativeObject, String callsite) { if (mNativeObject != 0) { release(); @@ -611,6 +618,13 @@ public final class SurfaceControl implements Parcelable { } /** + * @hide + */ + public abstract static class ScreenCaptureListener { + abstract void onScreenCaptureComplete(ScreenshotHardwareBuffer hardwareBuffer); + } + + /** * A common arguments class used for various screenshot requests. This contains arguments that * are shared between {@link DisplayCaptureArgs} and {@link LayerCaptureArgs} * @hide @@ -685,7 +699,7 @@ public final class SurfaceControl implements Parcelable { /** * The arguments class used to make display capture requests. * - * @see #nativeCaptureDisplay(DisplayCaptureArgs) + * @see #nativeCaptureDisplay(DisplayCaptureArgs, ScreenCaptureListener) * @hide */ public static class DisplayCaptureArgs extends CaptureArgs { @@ -2226,13 +2240,46 @@ public final class SurfaceControl implements Parcelable { } /** + * @param captureArgs Arguments about how to take the screenshot + * @param captureListener A listener to receive the screenshot callback + * @hide + */ + public static int captureDisplay(@NonNull DisplayCaptureArgs captureArgs, + @NonNull ScreenCaptureListener captureListener) { + return nativeCaptureDisplay(captureArgs, captureListener); + } + + /** * Captures all the surfaces in a display and returns a {@link ScreenshotHardwareBuffer} with * the content. * * @hide */ public static ScreenshotHardwareBuffer captureDisplay(DisplayCaptureArgs captureArgs) { - return nativeCaptureDisplay(captureArgs); + final AtomicReference<ScreenshotHardwareBuffer> outHardwareBuffer = + new AtomicReference<>(null); + + final CountDownLatch countDownLatch = new CountDownLatch(1); + ScreenCaptureListener screenCaptureListener = new ScreenCaptureListener() { + @Override + void onScreenCaptureComplete(ScreenshotHardwareBuffer hardwareBuffer) { + outHardwareBuffer.set(hardwareBuffer); + countDownLatch.countDown(); + } + }; + + int status = captureDisplay(captureArgs, screenCaptureListener); + if (status != 0) { + return null; + } + + try { + countDownLatch.await(SCREENSHOT_WAIT_TIME_S, TimeUnit.SECONDS); + } catch (Exception e) { + Log.e(TAG, "Failed to wait for captureDisplay result", e); + } + + return outHardwareBuffer.get(); } /** @@ -2277,14 +2324,37 @@ public final class SurfaceControl implements Parcelable { .setPixelFormat(format) .build(); - return nativeCaptureLayers(captureArgs); + return captureLayers(captureArgs); } /** * @hide */ public static ScreenshotHardwareBuffer captureLayers(LayerCaptureArgs captureArgs) { - return nativeCaptureLayers(captureArgs); + final AtomicReference<ScreenshotHardwareBuffer> outHardwareBuffer = + new AtomicReference<>(null); + + final CountDownLatch countDownLatch = new CountDownLatch(1); + ScreenCaptureListener screenCaptureListener = new ScreenCaptureListener() { + @Override + void onScreenCaptureComplete(ScreenshotHardwareBuffer hardwareBuffer) { + outHardwareBuffer.set(hardwareBuffer); + countDownLatch.countDown(); + } + }; + + int status = captureLayers(captureArgs, screenCaptureListener); + if (status != 0) { + return null; + } + + try { + countDownLatch.await(SCREENSHOT_WAIT_TIME_S, TimeUnit.SECONDS); + } catch (Exception e) { + Log.e(TAG, "Failed to wait for captureLayers result", e); + } + + return outHardwareBuffer.get(); } /** @@ -2301,7 +2371,17 @@ public final class SurfaceControl implements Parcelable { .setExcludeLayers(exclude) .build(); - return nativeCaptureLayers(captureArgs); + return captureLayers(captureArgs); + } + + /** + * @param captureArgs Arguments about how to take the screenshot + * @param captureListener A listener to receive the screenshot callback + * @hide + */ + public static int captureLayers(@NonNull LayerCaptureArgs captureArgs, + @NonNull ScreenCaptureListener captureListener) { + return nativeCaptureLayers(captureArgs, captureListener); } /** @@ -3184,6 +3264,39 @@ public final class SurfaceControl implements Parcelable { } /** + * Sets focus on the window identified by the input {@code token} if the window is focusable + * otherwise the request is dropped. + * + * If the window is not visible, the request will be queued until the window becomes + * visible or the request is overrriden by another request. The currently focused window + * will lose focus immediately. This is to send the newly focused window any focus + * dispatched events that occur while it is completing its first draw. + * + * @hide + */ + public Transaction setFocusedWindow(@NonNull IBinder token, int displayId) { + nativeSetFocusedWindow(mNativeObject, token, null /* focusedToken */, displayId); + return this; + } + + /** + * Set focus on the window identified by the input {@code token} if the window identified by + * the input {@code focusedToken} is currently focused. If the {@code focusedToken} does not + * have focus, the request is dropped. + * + * This is used by forward focus transfer requests from clients that host embedded windows, + * and want to transfer focus to/from them. + * + * @hide + */ + public Transaction requestFocusTransfer(@NonNull IBinder token, + @NonNull IBinder focusedToken, + int displayId) { + nativeSetFocusedWindow(mNativeObject, token, focusedToken, displayId); + return this; + } + + /** * Merge the other transaction into this transaction, clearing the * other transaction as if it had been applied. * diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java index 89178217366f..92a0f633aba0 100644 --- a/core/java/android/view/View.java +++ b/core/java/android/view/View.java @@ -14940,20 +14940,12 @@ public class View implements Drawable.Callback, KeyEvent.Callback, * inside. In effect, this tells you the available area where content can * be placed and remain visible to users. * - * <p>This function requires an IPC back to the window manager to retrieve - * the requested information, so should not be used in performance critical - * code like drawing. - * * @param outRect Filled in with the visible display frame. If the view * is not attached to a window, this is simply the raw display size. */ public void getWindowVisibleDisplayFrame(Rect outRect) { if (mAttachInfo != null) { - try { - mAttachInfo.mSession.getDisplayFrame(mAttachInfo.mWindow, outRect); - } catch (RemoteException e) { - return; - } + mAttachInfo.mViewRootImpl.getDisplayFrame(outRect); // XXX This is really broken, and probably all needs to be done // in the window manager, and we need to know more about whether // we want the area behind or in front of the IME. @@ -14979,11 +14971,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, @UnsupportedAppUsage public void getWindowDisplayFrame(Rect outRect) { if (mAttachInfo != null) { - try { - mAttachInfo.mSession.getDisplayFrame(mAttachInfo.mWindow, outRect); - } catch (RemoteException e) { - return; - } + mAttachInfo.mViewRootImpl.getDisplayFrame(outRect); return; } // The view is not attached to a display so we don't have a context. diff --git a/core/java/android/view/ViewConfiguration.java b/core/java/android/view/ViewConfiguration.java index ccf1fb07d0bb..abf76ece1f3d 100644 --- a/core/java/android/view/ViewConfiguration.java +++ b/core/java/android/view/ViewConfiguration.java @@ -100,7 +100,7 @@ public class ViewConfiguration { * Defines the duration in milliseconds a user needs to hold down the * appropriate buttons (power + volume down) to trigger the screenshot chord. */ - private static final int SCREENSHOT_CHORD_KEY_TIMEOUT = 500; + private static final int SCREENSHOT_CHORD_KEY_TIMEOUT = 0; /** * Defines the duration in milliseconds a user needs to hold down the diff --git a/core/java/android/view/ViewDebug.java b/core/java/android/view/ViewDebug.java index 8a5be75b6c31..4303d705f945 100644 --- a/core/java/android/view/ViewDebug.java +++ b/core/java/android/view/ViewDebug.java @@ -33,7 +33,6 @@ import android.os.Debug; import android.os.Handler; import android.os.Looper; import android.os.Message; -import android.os.RemoteException; import android.util.DisplayMetrics; import android.util.Log; import android.util.TypedValue; @@ -755,11 +754,7 @@ public class ViewDebug { try { Rect outRect = new Rect(); - try { - root.mAttachInfo.mSession.getDisplayFrame(root.mAttachInfo.mWindow, outRect); - } catch (RemoteException e) { - // Ignore - } + root.mAttachInfo.mViewRootImpl.getDisplayFrame(outRect); clientStream.writeInt(outRect.width()); clientStream.writeInt(outRect.height()); diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java index 03071cd5e814..af839d4481f7 100644 --- a/core/java/android/view/ViewRootImpl.java +++ b/core/java/android/view/ViewRootImpl.java @@ -137,7 +137,6 @@ import android.view.View.MeasureSpec; import android.view.Window.OnContentApplyWindowInsetsListener; import android.view.WindowInsets.Type; import android.view.WindowInsets.Type.InsetsType; -import android.view.WindowManager.LayoutParams; import android.view.WindowManager.LayoutParams.SoftInputModeFlags; import android.view.accessibility.AccessibilityEvent; import android.view.accessibility.AccessibilityManager; @@ -160,6 +159,7 @@ import android.view.contentcapture.ContentCaptureSession; import android.view.contentcapture.MainContentCaptureSession; import android.view.inputmethod.InputMethodManager; import android.widget.Scroller; +import android.window.ClientWindowFrames; import com.android.internal.R; import com.android.internal.annotations.GuardedBy; @@ -465,6 +465,7 @@ public final class ViewRootImpl implements ViewParent, // used in relayout to get SurfaceControl size // for BLAST adapter surface setup private final Point mSurfaceSize = new Point(); + private final Point mLastSurfaceSize = new Point(); final Rect mTempRect; // used in the transaction to not thrash the heap. final Rect mVisRect; // used to retrieve visible rect of focused view. @@ -559,8 +560,11 @@ public final class ViewRootImpl implements ViewParent, boolean mAdded; boolean mAddedTouchMode; - final Rect mTmpFrame = new Rect(); - final Rect mTmpRect = new Rect(); + /** + * It usually keeps the latest layout result from {@link IWindow#resized} or + * {@link IWindowSession#relayout}. + */ + private final ClientWindowFrames mTmpFrames = new ClientWindowFrames(); // These are accessed by multiple threads. final Rect mWinFrame; // frame given by window manager. @@ -1032,11 +1036,11 @@ public final class ViewRootImpl implements ViewParent, collectViewAttributes(); adjustLayoutParamsForCompatibility(mWindowAttributes); res = mWindowSession.addToDisplayAsUser(mWindow, mSeq, mWindowAttributes, - getHostVisibility(), mDisplay.getDisplayId(), userId, mTmpFrame, + getHostVisibility(), mDisplay.getDisplayId(), userId, mTmpFrames.frame, mAttachInfo.mContentInsets, mAttachInfo.mStableInsets, mAttachInfo.mDisplayCutout, inputChannel, mTempInsets, mTempControls); - setFrame(mTmpFrame); + setFrame(mTmpFrames.frame); } catch (RemoteException e) { mAdded = false; mView = null; @@ -1448,7 +1452,7 @@ public final class ViewRootImpl implements ViewParent, & ~SOFT_INPUT_MASK_ADJUST) | (oldSoftInputMode & SOFT_INPUT_MASK_ADJUST); } - if ((changes & LayoutParams.SOFT_INPUT_MODE_CHANGED) != 0) { + if (mWindowAttributes.softInputMode != oldSoftInputMode) { requestFitSystemWindows(); } @@ -1474,6 +1478,55 @@ public final class ViewRootImpl implements ViewParent, scheduleTraversals(); } + /** Handles messages {@link #MSG_RESIZED} and {@link #MSG_RESIZED_REPORT}. */ + private void handleResized(int msg, SomeArgs args) { + if (!mAdded) { + return; + } + + final ClientWindowFrames frames = (ClientWindowFrames) args.arg1; + final MergedConfiguration mergedConfiguration = (MergedConfiguration) args.arg2; + final boolean forceNextWindowRelayout = args.argi1 != 0; + final int displayId = args.argi3; + final Rect backdropFrame = frames.backdropFrame; + final DisplayCutout displayCutout = frames.displayCutout.get(); + + final boolean frameChanged = !mWinFrame.equals(frames.frame); + final boolean cutoutChanged = !mPendingDisplayCutout.get().equals(displayCutout); + final boolean backdropFrameChanged = !mPendingBackDropFrame.equals(backdropFrame); + final boolean configChanged = !mLastReportedMergedConfiguration.equals(mergedConfiguration); + final boolean displayChanged = mDisplay.getDisplayId() != displayId; + if (msg == MSG_RESIZED && !frameChanged && !cutoutChanged && !backdropFrameChanged + && !configChanged && !displayChanged && !forceNextWindowRelayout) { + return; + } + + if (configChanged) { + // If configuration changed - notify about that and, maybe, about move to display. + performConfigurationChange(mergedConfiguration, false /* force */, + displayChanged ? displayId : INVALID_DISPLAY /* same display */); + } else if (displayChanged) { + // Moved to display without config change - report last applied one. + onMovedToDisplay(displayId, mLastConfigurationFromResources); + } + + setFrame(frames.frame); + mTmpFrames.displayFrame.set(frames.displayFrame); + mPendingDisplayCutout.set(displayCutout); + mPendingBackDropFrame.set(backdropFrame); + mForceNextWindowRelayout = forceNextWindowRelayout; + mPendingAlwaysConsumeSystemBars = args.argi2 != 0; + + if (msg == MSG_RESIZED_REPORT) { + reportNextDraw(); + } + + if (mView != null && (frameChanged || cutoutChanged || configChanged)) { + forceLayout(mView); + } + requestLayout(); + } + private final DisplayListener mDisplayListener = new DisplayListener() { @Override public void onDisplayChanged(int displayId) { @@ -2253,9 +2306,11 @@ public final class ViewRootImpl implements ViewParent, /* package */ WindowInsets getWindowInsets(boolean forceConstruct) { if (mLastWindowInsets == null || forceConstruct) { + final Configuration config = mContext.getResources().getConfiguration(); mLastWindowInsets = mInsetsController.calculateInsets( - mContext.getResources().getConfiguration().isScreenRound(), - mAttachInfo.mAlwaysConsumeSystemBars, mPendingDisplayCutout.get(), + config.isScreenRound(), mAttachInfo.mAlwaysConsumeSystemBars, + mPendingDisplayCutout.get(), mWindowAttributes.type, + config.windowConfiguration.getWindowingMode(), mWindowAttributes.softInputMode, mWindowAttributes.flags, (mWindowAttributes.systemUiVisibility | mWindowAttributes.subtreeSystemUiVisibility)); @@ -2639,9 +2694,12 @@ public final class ViewRootImpl implements ViewParent, } cutoutChanged = !mPendingDisplayCutout.equals(mAttachInfo.mDisplayCutout); - surfaceSizeChanged = (relayoutResult - & WindowManagerGlobal.RELAYOUT_RES_SURFACE_RESIZED) != 0; - final boolean alwaysConsumeSystemBarsChanged = + surfaceSizeChanged = false; + if (!mLastSurfaceSize.equals(mSurfaceSize)) { + surfaceSizeChanged = true; + mLastSurfaceSize.set(mSurfaceSize.x, mSurfaceSize.y); + } + final boolean alwaysConsumeSystemBarsChanged = mPendingAlwaysConsumeSystemBars != mAttachInfo.mAlwaysConsumeSystemBars; updateColorModeIfNeeded(lp.getColorMode()); surfaceCreated = !hadSurface && mSurface.isValid(); @@ -4917,60 +4975,13 @@ public final class ViewRootImpl implements ViewParent, case MSG_DISPATCH_GET_NEW_SURFACE: handleGetNewSurface(); break; - case MSG_RESIZED: { - // Recycled in the fall through... - SomeArgs args = (SomeArgs) msg.obj; - if (mWinFrame.equals(args.arg1) - && mPendingDisplayCutout.get().equals(args.arg9) - && mPendingBackDropFrame.equals(args.arg8) - && mLastReportedMergedConfiguration.equals(args.arg4) - && args.argi1 == 0 - && mDisplay.getDisplayId() == args.argi3) { - break; - } - } // fall through... - case MSG_RESIZED_REPORT: - if (mAdded) { - SomeArgs args = (SomeArgs) msg.obj; - - final int displayId = args.argi3; - MergedConfiguration mergedConfiguration = (MergedConfiguration) args.arg4; - final boolean displayChanged = mDisplay.getDisplayId() != displayId; - boolean configChanged = false; - - if (!mLastReportedMergedConfiguration.equals(mergedConfiguration)) { - // If configuration changed - notify about that and, maybe, - // about move to display. - performConfigurationChange(mergedConfiguration, false /* force */, - displayChanged - ? displayId : INVALID_DISPLAY /* same display */); - configChanged = true; - } else if (displayChanged) { - // Moved to display without config change - report last applied one. - onMovedToDisplay(displayId, mLastConfigurationFromResources); - } - - final boolean framesChanged = !mWinFrame.equals(args.arg1) - || !mPendingDisplayCutout.get().equals(args.arg9); - - setFrame((Rect) args.arg1); - mPendingDisplayCutout.set((DisplayCutout) args.arg9); - mPendingBackDropFrame.set((Rect) args.arg8); - mForceNextWindowRelayout = args.argi1 != 0; - mPendingAlwaysConsumeSystemBars = args.argi2 != 0; - - args.recycle(); - - if (msg.what == MSG_RESIZED_REPORT) { - reportNextDraw(); - } - - if (mView != null && (framesChanged || configChanged)) { - forceLayout(mView); - } - requestLayout(); - } + case MSG_RESIZED: + case MSG_RESIZED_REPORT: { + final SomeArgs args = (SomeArgs) msg.obj; + handleResized(msg.what, args); + args.recycle(); break; + } case MSG_INSETS_CHANGED: mInsetsController.onStateChanged((InsetsState) msg.obj); break; @@ -5005,11 +5016,11 @@ public final class ViewRootImpl implements ViewParent, final int h = mWinFrame.height(); final int l = msg.arg1; final int t = msg.arg2; - mTmpFrame.left = l; - mTmpFrame.right = l + w; - mTmpFrame.top = t; - mTmpFrame.bottom = t + h; - setFrame(mTmpFrame); + mTmpFrames.frame.left = l; + mTmpFrames.frame.right = l + w; + mTmpFrames.frame.top = t; + mTmpFrames.frame.bottom = t + h; + setFrame(mTmpFrames.frame); mPendingBackDropFrame.set(mWinFrame); maybeHandleWindowMove(mWinFrame); @@ -7416,9 +7427,10 @@ public final class ViewRootImpl implements ViewParent, (int) (mView.getMeasuredWidth() * appScale + 0.5f), (int) (mView.getMeasuredHeight() * appScale + 0.5f), viewVisibility, insetsPending ? WindowManagerGlobal.RELAYOUT_INSETS_PENDING : 0, frameNumber, - mTmpFrame, mTmpRect, mTmpRect, mTmpRect, mPendingBackDropFrame, - mPendingDisplayCutout, mPendingMergedConfiguration, mSurfaceControl, mTempInsets, + mTmpFrames, mPendingMergedConfiguration, mSurfaceControl, mTempInsets, mTempControls, mSurfaceSize, mBlastSurfaceControl); + mPendingDisplayCutout.set(mTmpFrames.displayCutout); + mPendingBackDropFrame.set(mTmpFrames.backdropFrame); if (mSurfaceControl.isValid()) { if (!useBLAST()) { mSurface.copyFrom(mSurfaceControl); @@ -7444,9 +7456,9 @@ public final class ViewRootImpl implements ViewParent, } if (mTranslator != null) { - mTranslator.translateRectInScreenToAppWinFrame(mTmpFrame); + mTranslator.translateRectInScreenToAppWinFrame(mTmpFrames.frame); } - setFrame(mTmpFrame); + setFrame(mTmpFrames.frame); mInsetsController.onStateChanged(mTempInsets); mInsetsController.onControlsChanged(mTempControls); return relayoutResult; @@ -7458,6 +7470,14 @@ public final class ViewRootImpl implements ViewParent, } /** + * Gets the current display size in which the window is being laid out, accounting for screen + * decorations around it. + */ + void getDisplayFrame(Rect outFrame) { + outFrame.set(mTmpFrames.displayFrame); + } + + /** * {@inheritDoc} */ @Override @@ -7740,11 +7760,14 @@ public final class ViewRootImpl implements ViewParent, } @UnsupportedAppUsage - private void dispatchResized(Rect frame, Rect contentInsets, - Rect visibleInsets, Rect stableInsets, boolean reportDraw, - MergedConfiguration mergedConfiguration, Rect backDropFrame, boolean forceLayout, - boolean alwaysConsumeSystemBars, int displayId, - DisplayCutout.ParcelableWrapper displayCutout) { + private void dispatchResized(ClientWindowFrames frames, boolean reportDraw, + MergedConfiguration mergedConfiguration, boolean forceLayout, + boolean alwaysConsumeSystemBars, int displayId) { + final Rect frame = frames.frame; + final Rect contentInsets = frames.contentInsets; + final Rect visibleInsets = frames.visibleInsets; + final Rect stableInsets = frames.stableInsets; + final Rect backDropFrame = frames.backdropFrame; if (DEBUG_LAYOUT) Log.v(mTag, "Resizing " + this + ": frame=" + frame.toShortString() + " contentInsets=" + contentInsets.toShortString() + " visibleInsets=" + visibleInsets.toShortString() @@ -7771,14 +7794,9 @@ public final class ViewRootImpl implements ViewParent, } SomeArgs args = SomeArgs.obtain(); final boolean sameProcessCall = (Binder.getCallingPid() == android.os.Process.myPid()); - args.arg1 = sameProcessCall ? new Rect(frame) : frame; - args.arg2 = sameProcessCall ? new Rect(contentInsets) : contentInsets; - args.arg3 = sameProcessCall ? new Rect(visibleInsets) : visibleInsets; - args.arg4 = sameProcessCall && mergedConfiguration != null + args.arg1 = sameProcessCall ? new ClientWindowFrames(frames) : frames; + args.arg2 = sameProcessCall && mergedConfiguration != null ? new MergedConfiguration(mergedConfiguration) : mergedConfiguration; - args.arg6 = sameProcessCall ? new Rect(stableInsets) : stableInsets; - args.arg8 = sameProcessCall ? new Rect(backDropFrame) : backDropFrame; - args.arg9 = displayCutout.get(); // DisplayCutout is immutable. args.argi1 = forceLayout ? 1 : 0; args.argi2 = alwaysConsumeSystemBars ? 1 : 0; args.argi3 = displayId; @@ -9072,17 +9090,13 @@ public final class ViewRootImpl implements ViewParent, } @Override - public void resized(Rect frame, Rect contentInsets, - Rect visibleInsets, Rect stableInsets, boolean reportDraw, - MergedConfiguration mergedConfiguration, Rect backDropFrame, boolean forceLayout, - boolean alwaysConsumeSystemBars, int displayId, - DisplayCutout.ParcelableWrapper displayCutout) { + public void resized(ClientWindowFrames frames, boolean reportDraw, + MergedConfiguration mergedConfiguration, boolean forceLayout, + boolean alwaysConsumeSystemBars, int displayId) { final ViewRootImpl viewAncestor = mViewAncestor.get(); if (viewAncestor != null) { - viewAncestor.dispatchResized(frame, contentInsets, - visibleInsets, stableInsets, reportDraw, mergedConfiguration, - backDropFrame, forceLayout, alwaysConsumeSystemBars, displayId, - displayCutout); + viewAncestor.dispatchResized(frames, reportDraw, mergedConfiguration, forceLayout, + alwaysConsumeSystemBars, displayId); } } diff --git a/core/java/android/view/WindowInsetsController.java b/core/java/android/view/WindowInsetsController.java index 1a9003581078..e879bb4bff95 100644 --- a/core/java/android/view/WindowInsetsController.java +++ b/core/java/android/view/WindowInsetsController.java @@ -32,8 +32,6 @@ import java.lang.annotation.RetentionPolicy; /** * Interface to control windows that generate insets. - * - * TODO(118118435): Needs more information and examples once the API is more baked. */ public interface WindowInsetsController { diff --git a/core/java/android/view/WindowManagerImpl.java b/core/java/android/view/WindowManagerImpl.java index 27fbfb6d4d17..5d53ad7ef186 100644 --- a/core/java/android/view/WindowManagerImpl.java +++ b/core/java/android/view/WindowManagerImpl.java @@ -29,6 +29,7 @@ import android.annotation.UiContext; import android.app.ResourcesManager; import android.compat.annotation.UnsupportedAppUsage; import android.content.Context; +import android.content.res.Configuration; import android.graphics.Insets; import android.graphics.Rect; import android.graphics.Region; @@ -271,13 +272,14 @@ public final class WindowManagerImpl implements WindowManager { final boolean alwaysConsumeSystemBars = WindowManagerGlobal.getWindowManagerService() .getWindowInsets(attrs, mContext.getDisplayId(), systemWindowInsets, stableInsets, displayCutout, insetsState); - final boolean isScreenRound = - mContext.getResources().getConfiguration().isScreenRound(); + final Configuration config = mContext.getResources().getConfiguration(); + final boolean isScreenRound = config.isScreenRound(); + final int windowingMode = config.windowConfiguration.getWindowingMode(); if (ViewRootImpl.sNewInsetsMode == NEW_INSETS_MODE_FULL) { return insetsState.calculateInsets(bounds, null /* ignoringVisibilityState*/, isScreenRound, alwaysConsumeSystemBars, displayCutout.get(), - SOFT_INPUT_ADJUST_NOTHING, attrs.flags, - SYSTEM_UI_FLAG_VISIBLE, null /* typeSideMap */); + SOFT_INPUT_ADJUST_NOTHING, attrs.flags, SYSTEM_UI_FLAG_VISIBLE, attrs.type, + windowingMode, null /* typeSideMap */); } else { return new WindowInsets.Builder() .setAlwaysConsumeSystemBars(alwaysConsumeSystemBars) diff --git a/core/java/android/view/WindowlessWindowManager.java b/core/java/android/view/WindowlessWindowManager.java index 060311ec3da8..368918d28f80 100644 --- a/core/java/android/view/WindowlessWindowManager.java +++ b/core/java/android/view/WindowlessWindowManager.java @@ -26,6 +26,7 @@ import android.os.IBinder; import android.os.RemoteException; import android.util.Log; import android.util.MergedConfiguration; +import android.window.ClientWindowFrames; import java.util.HashMap; import java.util.Objects; @@ -224,9 +225,7 @@ public class WindowlessWindowManager implements IWindowSession { @Override public int relayout(IWindow window, int seq, WindowManager.LayoutParams inAttrs, int requestedWidth, int requestedHeight, int viewFlags, int flags, long frameNumber, - Rect outFrame, Rect outContentInsets, Rect outVisibleInsets, - Rect outStableInsets, Rect outBackdropFrame, - DisplayCutout.ParcelableWrapper cutout, MergedConfiguration mergedConfiguration, + ClientWindowFrames outFrames, MergedConfiguration mergedConfiguration, SurfaceControl outSurfaceControl, InsetsState outInsetsState, InsetsSourceControl[] outActiveControls, Point outSurfaceSize, SurfaceControl outBLASTSurfaceControl) { @@ -255,7 +254,8 @@ public class WindowlessWindowManager implements IWindowSession { t.hide(sc).apply(); outSurfaceControl.release(); } - outFrame.set(0, 0, attrs.width, attrs.height); + outFrames.frame.set(0, 0, attrs.width, attrs.height); + outFrames.displayFrame.set(outFrames.frame); mergedConfiguration.setConfiguration(mConfiguration, mConfiguration); @@ -292,11 +292,6 @@ public class WindowlessWindowManager implements IWindowSession { } @Override - public void getDisplayFrame(android.view.IWindow window, - android.graphics.Rect outDisplayFrame) { - } - - @Override public void finishDrawing(android.view.IWindow window, android.view.SurfaceControl.Transaction postDrawTransaction) { synchronized (this) { diff --git a/core/java/android/view/accessibility/MagnificationAnimationCallback.java b/core/java/android/view/accessibility/MagnificationAnimationCallback.java new file mode 100644 index 000000000000..491f7fb32a8c --- /dev/null +++ b/core/java/android/view/accessibility/MagnificationAnimationCallback.java @@ -0,0 +1,31 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.view.accessibility; + +/** + * A callback for magnification animation result. + * @hide + */ +public interface MagnificationAnimationCallback { + /** + * Called when the animation is finished or interrupted during animating. + * + * @param success {@code true} if animating successfully with given spec or the spec did not + * change. Otherwise {@code false} + */ + void onResult(boolean success); +} diff --git a/core/java/android/widget/TEST_MAPPING b/core/java/android/widget/TEST_MAPPING index df3024eda4b6..b5beac99d4e2 100644 --- a/core/java/android/widget/TEST_MAPPING +++ b/core/java/android/widget/TEST_MAPPING @@ -36,17 +36,6 @@ "name": "CtsAutoFillServiceTestCases", "options": [ { - "include-filter": "android.autofillservice.cts.AutofillValueTest" - }, - { - "exclude-annotation": "androidx.test.filters.FlakyTest" - } - ] - }, - { - "name": "CtsAutoFillServiceTestCases", - "options": [ - { "include-filter": "android.autofillservice.cts.CheckoutActivityTest" }, { diff --git a/core/java/android/window/ClientWindowFrames.aidl b/core/java/android/window/ClientWindowFrames.aidl new file mode 100644 index 000000000000..22bbea90d35a --- /dev/null +++ b/core/java/android/window/ClientWindowFrames.aidl @@ -0,0 +1,19 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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.window; + +parcelable ClientWindowFrames; diff --git a/core/java/android/window/ClientWindowFrames.java b/core/java/android/window/ClientWindowFrames.java new file mode 100644 index 000000000000..0523e64f3e7a --- /dev/null +++ b/core/java/android/window/ClientWindowFrames.java @@ -0,0 +1,125 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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.window; + +import android.annotation.NonNull; +import android.graphics.Rect; +import android.os.Parcel; +import android.os.Parcelable; +import android.view.DisplayCutout; + +/** + * The window frame container class used by client side for layout. + * @hide + */ +public class ClientWindowFrames implements Parcelable { + /** The actual window bounds. */ + public final @NonNull Rect frame; + + /** + * The container frame that is usually the same as display size. It may exclude the area of + * insets if the window layout parameter has specified fit-insets-sides. + */ + public final @NonNull Rect displayFrame; + + /** The background area while the window is resizing. */ + public final @NonNull Rect backdropFrame; + + /** The area cut from the display. */ + public final @NonNull DisplayCutout.ParcelableWrapper displayCutout; + + // TODO(b/149813814): Remove legacy insets. + public final Rect contentInsets; + public final Rect visibleInsets; + public final Rect stableInsets; + + public ClientWindowFrames() { + frame = new Rect(); + displayFrame = new Rect(); + backdropFrame = new Rect(); + displayCutout = new DisplayCutout.ParcelableWrapper(); + contentInsets = new Rect(); + visibleInsets = new Rect(); + stableInsets = new Rect(); + } + + public ClientWindowFrames(ClientWindowFrames other) { + frame = new Rect(other.frame); + displayFrame = new Rect(other.displayFrame); + backdropFrame = new Rect(other.backdropFrame); + displayCutout = new DisplayCutout.ParcelableWrapper(other.displayCutout.get()); + contentInsets = new Rect(other.contentInsets); + visibleInsets = new Rect(other.visibleInsets); + stableInsets = new Rect(other.stableInsets); + } + + private ClientWindowFrames(Parcel in) { + frame = Rect.CREATOR.createFromParcel(in); + displayFrame = Rect.CREATOR.createFromParcel(in); + backdropFrame = Rect.CREATOR.createFromParcel(in); + displayCutout = DisplayCutout.ParcelableWrapper.CREATOR.createFromParcel(in); + contentInsets = Rect.CREATOR.createFromParcel(in); + visibleInsets = Rect.CREATOR.createFromParcel(in); + stableInsets = Rect.CREATOR.createFromParcel(in); + } + + /** Needed for AIDL out parameters. */ + public void readFromParcel(Parcel in) { + frame.set(Rect.CREATOR.createFromParcel(in)); + displayFrame.set(Rect.CREATOR.createFromParcel(in)); + backdropFrame.set(Rect.CREATOR.createFromParcel(in)); + displayCutout.set(DisplayCutout.ParcelableWrapper.CREATOR.createFromParcel(in)); + contentInsets.set(Rect.CREATOR.createFromParcel(in)); + visibleInsets.set(Rect.CREATOR.createFromParcel(in)); + stableInsets.set(Rect.CREATOR.createFromParcel(in)); + } + + @Override + public void writeToParcel(Parcel dest, int flags) { + frame.writeToParcel(dest, flags); + displayFrame.writeToParcel(dest, flags); + backdropFrame.writeToParcel(dest, flags); + displayCutout.writeToParcel(dest, flags); + contentInsets.writeToParcel(dest, flags); + visibleInsets.writeToParcel(dest, flags); + stableInsets.writeToParcel(dest, flags); + } + + @Override + public String toString() { + final StringBuilder sb = new StringBuilder(32); + return "ClientWindowFrames{frame=" + frame.toShortString(sb) + + " display=" + displayFrame.toShortString(sb) + + " backdrop=" + backdropFrame.toShortString(sb) + + " cutout=" + displayCutout + "}"; + } + + @Override + public int describeContents() { + return 0; + } + + public static final Creator<ClientWindowFrames> CREATOR = new Creator<ClientWindowFrames>() { + public ClientWindowFrames createFromParcel(Parcel in) { + return new ClientWindowFrames(in); + } + + public ClientWindowFrames[] newArray(int size) { + return new ClientWindowFrames[size]; + } + }; +} diff --git a/core/java/android/window/DisplayAreaOrganizer.java b/core/java/android/window/DisplayAreaOrganizer.java index f035d36a0f71..78fa30358d74 100644 --- a/core/java/android/window/DisplayAreaOrganizer.java +++ b/core/java/android/window/DisplayAreaOrganizer.java @@ -20,7 +20,6 @@ import android.annotation.NonNull; import android.annotation.RequiresPermission; import android.annotation.TestApi; import android.os.RemoteException; -import android.util.Singleton; import android.view.SurfaceControl; /** @@ -135,22 +134,12 @@ public class DisplayAreaOrganizer extends WindowOrganizer { } }; - private static IDisplayAreaOrganizerController getController() { - return IDisplayAreaOrganizerControllerSingleton.get(); + private IDisplayAreaOrganizerController getController() { + try { + return getWindowOrganizerController().getDisplayAreaOrganizerController(); + } catch (RemoteException e) { + return null; + } } - private static final Singleton<IDisplayAreaOrganizerController> - IDisplayAreaOrganizerControllerSingleton = - new Singleton<IDisplayAreaOrganizerController>() { - @Override - protected IDisplayAreaOrganizerController create() { - try { - return getWindowOrganizerController() - .getDisplayAreaOrganizerController(); - } catch (RemoteException e) { - return null; - } - } - }; - } diff --git a/core/java/android/window/TaskOrganizer.java b/core/java/android/window/TaskOrganizer.java index 38fb023a0822..d8f2bb248fd1 100644 --- a/core/java/android/window/TaskOrganizer.java +++ b/core/java/android/window/TaskOrganizer.java @@ -23,9 +23,10 @@ import android.annotation.RequiresPermission; import android.annotation.TestApi; import android.app.ActivityManager; import android.os.RemoteException; -import android.util.Singleton; import android.view.SurfaceControl; +import com.android.internal.annotations.VisibleForTesting; + import java.util.List; /** @@ -35,13 +36,25 @@ import java.util.List; @TestApi public class TaskOrganizer extends WindowOrganizer { + private ITaskOrganizerController mTaskOrganizerController; + + public TaskOrganizer() { + mTaskOrganizerController = getController(); + } + + /** @hide */ + @VisibleForTesting + public TaskOrganizer(ITaskOrganizerController taskOrganizerController) { + mTaskOrganizerController = taskOrganizerController; + } + /** * Register a TaskOrganizer to manage tasks as they enter a supported windowing mode. */ @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS) public final void registerOrganizer() { try { - getController().registerTaskOrganizer(mInterface); + mTaskOrganizerController.registerTaskOrganizer(mInterface); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -51,7 +64,7 @@ public class TaskOrganizer extends WindowOrganizer { @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS) public final void unregisterOrganizer() { try { - getController().unregisterTaskOrganizer(mInterface); + mTaskOrganizerController.unregisterTaskOrganizer(mInterface); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -78,9 +91,9 @@ public class TaskOrganizer extends WindowOrganizer { /** Creates a persistent root task in WM for a particular windowing-mode. */ @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS) @Nullable - public static ActivityManager.RunningTaskInfo createRootTask(int displayId, int windowingMode) { + public ActivityManager.RunningTaskInfo createRootTask(int displayId, int windowingMode) { try { - return getController().createRootTask(displayId, windowingMode); + return mTaskOrganizerController.createRootTask(displayId, windowingMode); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -88,9 +101,9 @@ public class TaskOrganizer extends WindowOrganizer { /** Deletes a persistent root task in WM */ @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS) - public static boolean deleteRootTask(@NonNull WindowContainerToken task) { + public boolean deleteRootTask(@NonNull WindowContainerToken task) { try { - return getController().deleteRootTask(task); + return mTaskOrganizerController.deleteRootTask(task); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -99,10 +112,10 @@ public class TaskOrganizer extends WindowOrganizer { /** Gets direct child tasks (ordered from top-to-bottom) */ @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS) @Nullable - public static List<ActivityManager.RunningTaskInfo> getChildTasks( + public List<ActivityManager.RunningTaskInfo> getChildTasks( @NonNull WindowContainerToken parent, @NonNull int[] activityTypes) { try { - return getController().getChildTasks(parent, activityTypes); + return mTaskOrganizerController.getChildTasks(parent, activityTypes); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -111,10 +124,10 @@ public class TaskOrganizer extends WindowOrganizer { /** Gets all root tasks on a display (ordered from top-to-bottom) */ @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS) @Nullable - public static List<ActivityManager.RunningTaskInfo> getRootTasks( + public List<ActivityManager.RunningTaskInfo> getRootTasks( int displayId, @NonNull int[] activityTypes) { try { - return getController().getRootTasks(displayId, activityTypes); + return mTaskOrganizerController.getRootTasks(displayId, activityTypes); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -123,9 +136,9 @@ public class TaskOrganizer extends WindowOrganizer { /** Get the root task which contains the current ime target */ @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS) @Nullable - public static WindowContainerToken getImeTarget(int display) { + public WindowContainerToken getImeTarget(int display) { try { - return getController().getImeTarget(display); + return mTaskOrganizerController.getImeTarget(display); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -136,9 +149,9 @@ public class TaskOrganizer extends WindowOrganizer { * root and thus new tasks just end up directly on the display. */ @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS) - public static void setLaunchRoot(int displayId, @NonNull WindowContainerToken root) { + public void setLaunchRoot(int displayId, @NonNull WindowContainerToken root) { try { - getController().setLaunchRoot(displayId, root); + mTaskOrganizerController.setLaunchRoot(displayId, root); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -152,7 +165,7 @@ public class TaskOrganizer extends WindowOrganizer { public void setInterceptBackPressedOnTaskRoot(@NonNull WindowContainerToken task, boolean interceptBackPressed) { try { - getController().setInterceptBackPressedOnTaskRoot(task, interceptBackPressed); + mTaskOrganizerController.setInterceptBackPressedOnTaskRoot(task, interceptBackPressed); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -181,19 +194,11 @@ public class TaskOrganizer extends WindowOrganizer { } }; - private static ITaskOrganizerController getController() { - return ITaskOrganizerControllerSingleton.get(); + private ITaskOrganizerController getController() { + try { + return getWindowOrganizerController().getTaskOrganizerController(); + } catch (RemoteException e) { + return null; + } } - - private static final Singleton<ITaskOrganizerController> ITaskOrganizerControllerSingleton = - new Singleton<ITaskOrganizerController>() { - @Override - protected ITaskOrganizerController create() { - try { - return getWindowOrganizerController().getTaskOrganizerController(); - } catch (RemoteException e) { - return null; - } - } - }; } diff --git a/core/java/android/window/TaskOrganizerTaskEmbedder.java b/core/java/android/window/TaskOrganizerTaskEmbedder.java index eb9dfed7f644..1e293df38cf8 100644 --- a/core/java/android/window/TaskOrganizerTaskEmbedder.java +++ b/core/java/android/window/TaskOrganizerTaskEmbedder.java @@ -109,7 +109,7 @@ public class TaskOrganizerTaskEmbedder extends TaskEmbedder { } WindowContainerTransaction wct = new WindowContainerTransaction(); wct.setHidden(mTaskToken, false /* hidden */); - WindowOrganizer.applyTransaction(wct); + mTaskOrganizer.applyTransaction(wct); // TODO(b/151449487): Only call callback once we enable synchronization if (mListener != null) { mListener.onTaskVisibilityChanged(getTaskId(), true); @@ -133,7 +133,7 @@ public class TaskOrganizerTaskEmbedder extends TaskEmbedder { } WindowContainerTransaction wct = new WindowContainerTransaction(); wct.setHidden(mTaskToken, true /* hidden */); - WindowOrganizer.applyTransaction(wct); + mTaskOrganizer.applyTransaction(wct); // TODO(b/151449487): Only call callback once we enable synchronization if (mListener != null) { mListener.onTaskVisibilityChanged(getTaskId(), false); @@ -165,7 +165,7 @@ public class TaskOrganizerTaskEmbedder extends TaskEmbedder { WindowContainerTransaction wct = new WindowContainerTransaction(); wct.setBounds(mTaskToken, screenBounds); // TODO(b/151449487): Enable synchronization - WindowOrganizer.applyTransaction(wct); + mTaskOrganizer.applyTransaction(wct); } /** diff --git a/core/java/android/window/VirtualDisplayTaskEmbedder.java b/core/java/android/window/VirtualDisplayTaskEmbedder.java index 9013da36007e..db27d6255de7 100644 --- a/core/java/android/window/VirtualDisplayTaskEmbedder.java +++ b/core/java/android/window/VirtualDisplayTaskEmbedder.java @@ -25,6 +25,7 @@ import static android.view.Display.INVALID_DISPLAY; import android.app.ActivityManager; import android.app.ActivityOptions; import android.app.ActivityTaskManager; +import android.app.ActivityTaskManager.RootTaskInfo; import android.app.ActivityView; import android.app.TaskStackListener; import android.content.ComponentName; @@ -357,40 +358,40 @@ public class VirtualDisplayTaskEmbedder extends TaskEmbedder { private class TaskStackListenerImpl extends TaskStackListener { @Override - public void onTaskDescriptionChanged(ActivityManager.RunningTaskInfo taskInfo) + public void onTaskDescriptionChanged(ActivityManager.RunningTaskInfo runningTaskInfo) throws RemoteException { if (!isInitialized()) { return; } - if (taskInfo.displayId != getDisplayId()) { + if (runningTaskInfo.displayId != getDisplayId()) { return; } - ActivityManager.StackInfo stackInfo = getTopMostStackInfo(); - if (stackInfo == null) { + RootTaskInfo taskInfo = getTopMostRootTaskInfo(); + if (taskInfo == null) { return; } // Found the topmost stack on target display. Now check if the topmost task's // description changed. - if (taskInfo.taskId == stackInfo.taskIds[stackInfo.taskIds.length - 1]) { + if (runningTaskInfo.taskId == taskInfo.childTaskIds[taskInfo.childTaskIds.length - 1]) { mHost.post(()-> mHost.onTaskBackgroundColorChanged(VirtualDisplayTaskEmbedder.this, - taskInfo.taskDescription.getBackgroundColor())); + runningTaskInfo.taskDescription.getBackgroundColor())); } } @Override - public void onTaskMovedToFront(ActivityManager.RunningTaskInfo taskInfo) + public void onTaskMovedToFront(ActivityManager.RunningTaskInfo runningTaskInfo) throws RemoteException { if (!isInitialized() || mListener == null - || taskInfo.displayId != getDisplayId()) { + || runningTaskInfo.displayId != getDisplayId()) { return; } - ActivityManager.StackInfo stackInfo = getTopMostStackInfo(); - // if StackInfo was null or unrelated to the "move to front" then there's no use + RootTaskInfo taskInfo = getTopMostRootTaskInfo(); + // if TaskInfo was null or unrelated to the "move to front" then there's no use // notifying the callback - if (stackInfo != null - && taskInfo.taskId == stackInfo.taskIds[stackInfo.taskIds.length - 1]) { - mListener.onTaskMovedToFront(taskInfo.taskId); + if (taskInfo != null && runningTaskInfo.taskId == taskInfo.childTaskIds[ + taskInfo.childTaskIds.length - 1]) { + mListener.onTaskMovedToFront(runningTaskInfo.taskId); } } @@ -400,11 +401,11 @@ public class VirtualDisplayTaskEmbedder extends TaskEmbedder { return; } - ActivityManager.StackInfo stackInfo = getTopMostStackInfo(); - // if StackInfo was null or unrelated to the task creation then there's no use + RootTaskInfo taskInfo = getTopMostRootTaskInfo(); + // if TaskInfo was null or unrelated to the task creation then there's no use // notifying the callback - if (stackInfo != null - && taskId == stackInfo.taskIds[stackInfo.taskIds.length - 1]) { + if (taskInfo != null + && taskId == taskInfo.childTaskIds[taskInfo.childTaskIds.length - 1]) { mListener.onTaskCreated(taskId, componentName); } } @@ -420,16 +421,16 @@ public class VirtualDisplayTaskEmbedder extends TaskEmbedder { mListener.onTaskRemovalStarted(taskInfo.taskId); } - private ActivityManager.StackInfo getTopMostStackInfo() throws RemoteException { + private RootTaskInfo getTopMostRootTaskInfo() throws RemoteException { // Find the topmost task on our virtual display - it will define the background // color of the surface view during resizing. final int displayId = getDisplayId(); - final List<ActivityManager.StackInfo> stackInfoList = - mActivityTaskManager.getAllStackInfosOnDisplay(displayId); - if (stackInfoList.isEmpty()) { + final List<RootTaskInfo> taskInfoList = + mActivityTaskManager.getAllRootTaskInfosOnDisplay(displayId); + if (taskInfoList.isEmpty()) { return null; } - return stackInfoList.get(0); + return taskInfoList.get(0); } } } diff --git a/core/java/android/window/WindowOrganizer.java b/core/java/android/window/WindowOrganizer.java index ff40ddac134e..97a97d9984f9 100644 --- a/core/java/android/window/WindowOrganizer.java +++ b/core/java/android/window/WindowOrganizer.java @@ -38,7 +38,7 @@ public class WindowOrganizer { * @param t The transaction to apply. */ @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS) - public static void applyTransaction(@NonNull WindowContainerTransaction t) { + public void applyTransaction(@NonNull WindowContainerTransaction t) { try { getWindowOrganizerController().applyTransaction(t); } catch (RemoteException e) { @@ -74,7 +74,7 @@ public class WindowOrganizer { */ @Nullable @RequiresPermission(android.Manifest.permission.READ_FRAME_BUFFER) - public static SurfaceControl takeScreenshot(@NonNull WindowContainerToken token) { + public SurfaceControl takeScreenshot(@NonNull WindowContainerToken token) { try { SurfaceControl surfaceControl = new SurfaceControl(); if (getWindowOrganizerController().takeScreenshot(token, surfaceControl)) { @@ -88,7 +88,7 @@ public class WindowOrganizer { } @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS) - static IWindowOrganizerController getWindowOrganizerController() { + IWindowOrganizerController getWindowOrganizerController() { return IWindowOrganizerControllerSingleton.get(); } diff --git a/core/java/com/android/internal/config/sysui/SystemUiDeviceConfigFlags.java b/core/java/com/android/internal/config/sysui/SystemUiDeviceConfigFlags.java index da26930ca727..8b4fddbec03c 100644 --- a/core/java/com/android/internal/config/sysui/SystemUiDeviceConfigFlags.java +++ b/core/java/com/android/internal/config/sysui/SystemUiDeviceConfigFlags.java @@ -390,9 +390,9 @@ public final class SystemUiDeviceConfigFlags { public static final String CHOOSER_TARGET_RANKING_ENABLED = "chooser_target_ranking_enabled"; /** - * (boolean) Whether to enable user-drag resizing for PIP. + * (boolean) Whether to enable pinch resizing for PIP. */ - public static final String PIP_USER_RESIZE = "pip_user_resize"; + public static final String PIP_PINCH_RESIZE = "pip_pinch_resize"; /** * (float) Bottom height in DP for Back Gesture. diff --git a/core/java/com/android/internal/content/om/OverlayConfig.java b/core/java/com/android/internal/content/om/OverlayConfig.java index 3b5cf487c8da..b38f623e3a6d 100644 --- a/core/java/com/android/internal/content/om/OverlayConfig.java +++ b/core/java/com/android/internal/content/om/OverlayConfig.java @@ -296,7 +296,7 @@ public class OverlayConfig { if (p.getOverlayTarget() != null && isSystem) { overlays.add(new ParsedOverlayInfo(p.getPackageName(), p.getOverlayTarget(), p.getTargetSdkVersion(), p.isOverlayIsStatic(), p.getOverlayPriority(), - new File(p.getBaseCodePath()))); + new File(p.getBaseApkPath()))); } }); return overlays; diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java index 84981515e133..41bf74ce9d61 100644 --- a/core/java/com/android/internal/os/BatteryStatsImpl.java +++ b/core/java/com/android/internal/os/BatteryStatsImpl.java @@ -256,7 +256,7 @@ public class BatteryStatsImpl extends BatteryStats { @GuardedBy("this") private long mNumBatchedSingleUidCpuTimeReads; @GuardedBy("this") - private long mCpuTimeReadsTrackingStartTime = SystemClock.uptimeMillis(); + private long mCpuTimeReadsTrackingStartTimeMs = SystemClock.uptimeMillis(); @GuardedBy("this") private int mNumUidsRemoved; @GuardedBy("this") @@ -290,7 +290,7 @@ public class BatteryStatsImpl extends BatteryStats { public final class UidToRemove { int startUid; int endUid; - long timeAddedInQueue; + long mTimeAddedInQueueMs; /** Remove just one UID */ public UidToRemove(int uid, long timestamp) { @@ -301,7 +301,7 @@ public class BatteryStatsImpl extends BatteryStats { public UidToRemove(int startUid, int endUid, long timestamp) { this.startUid = startUid; this.endUid = endUid; - timeAddedInQueue = timestamp; + mTimeAddedInQueueMs = timestamp; } void remove() { @@ -382,9 +382,9 @@ public class BatteryStatsImpl extends BatteryStats { } boolean changed = setChargingLocked(true); if (changed) { - final long uptime = mClocks.uptimeMillis(); - final long elapsedRealtime = mClocks.elapsedRealtime(); - addHistoryRecordLocked(elapsedRealtime, uptime); + final long uptimeMs = mClocks.uptimeMillis(); + final long elapsedRealtimeMs = mClocks.elapsedRealtime(); + addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs); } } } @@ -502,9 +502,9 @@ public class BatteryStatsImpl extends BatteryStats { } public void clearPendingRemovedUids() { - long cutOffTime = mClocks.elapsedRealtime() - mConstants.UID_REMOVE_DELAY_MS; + long cutOffTimeMs = mClocks.elapsedRealtime() - mConstants.UID_REMOVE_DELAY_MS; while (!mPendingRemovedUids.isEmpty() - && mPendingRemovedUids.peek().timeAddedInQueue < cutOffTime) { + && mPendingRemovedUids.peek().mTimeAddedInQueueMs < cutOffTimeMs) { mPendingRemovedUids.poll().remove(); } } @@ -572,7 +572,7 @@ public class BatteryStatsImpl extends BatteryStats { } @VisibleForTesting - public long[] addCpuTimes(long[] timesA, long[] timesB) { + public static long[] addCpuTimes(long[] timesA, long[] timesB) { if (timesA != null && timesB != null) { for (int i = timesA.length - 1; i >= 0; --i) { timesA[i] += timesB[i]; @@ -700,7 +700,7 @@ public class BatteryStatsImpl extends BatteryStats { final HistoryEventTracker mActiveEvents = new HistoryEventTracker(); - long mHistoryBaseTime; + long mHistoryBaseTimeMs; protected boolean mHaveBatteryLevel = false; protected boolean mRecordingHistory = false; int mNumHistoryItems; @@ -719,9 +719,9 @@ public class BatteryStatsImpl extends BatteryStats { int mHistoryBufferLastPos = -1; int mActiveHistoryStates = 0xffffffff; int mActiveHistoryStates2 = 0xffffffff; - long mLastHistoryElapsedRealtime = 0; - long mTrackRunningHistoryElapsedRealtime = 0; - long mTrackRunningHistoryUptime = 0; + long mLastHistoryElapsedRealtimeMs = 0; + long mTrackRunningHistoryElapsedRealtimeMs = 0; + long mTrackRunningHistoryUptimeMs = 0; final BatteryStatsHistory mBatteryStatsHistory; @@ -742,28 +742,28 @@ public class BatteryStatsImpl extends BatteryStats { /** * Total time (in milliseconds) spent executing in user code. */ - long mLastStepCpuUserTime; - long mCurStepCpuUserTime; + long mLastStepCpuUserTimeMs; + long mCurStepCpuUserTimeMs; /** * Total time (in milliseconds) spent executing in kernel code. */ - long mLastStepCpuSystemTime; - long mCurStepCpuSystemTime; + long mLastStepCpuSystemTimeMs; + long mCurStepCpuSystemTimeMs; /** * Times from /proc/stat (but measured in milliseconds). */ - long mLastStepStatUserTime; - long mLastStepStatSystemTime; - long mLastStepStatIOWaitTime; - long mLastStepStatIrqTime; - long mLastStepStatSoftIrqTime; - long mLastStepStatIdleTime; - long mCurStepStatUserTime; - long mCurStepStatSystemTime; - long mCurStepStatIOWaitTime; - long mCurStepStatIrqTime; - long mCurStepStatSoftIrqTime; - long mCurStepStatIdleTime; + long mLastStepStatUserTimeMs; + long mLastStepStatSystemTimeMs; + long mLastStepStatIOWaitTimeMs; + long mLastStepStatIrqTimeMs; + long mLastStepStatSoftIrqTimeMs; + long mLastStepStatIdleTimeMs; + long mCurStepStatUserTimeMs; + long mCurStepStatSystemTimeMs; + long mCurStepStatIOWaitTimeMs; + long mCurStepStatIrqTimeMs; + long mCurStepStatSoftIrqTimeMs; + long mCurStepStatIdleTimeMs; private HistoryItem mHistoryIterator; private boolean mReadOverflow; @@ -771,14 +771,14 @@ public class BatteryStatsImpl extends BatteryStats { int mStartCount; - long mStartClockTime; + long mStartClockTimeMs; String mStartPlatformVersion; String mEndPlatformVersion; - long mUptime; - long mUptimeStart; - long mRealtime; - long mRealtimeStart; + long mUptimeUs; + long mUptimeStartUs; + long mRealtimeUs; + long mRealtimeStartUs; int mWakeLockNesting; boolean mWakeLockImportant; @@ -810,9 +810,9 @@ public class BatteryStatsImpl extends BatteryStats { StopwatchTimer mDeviceLightIdlingTimer; int mDeviceIdleMode; - long mLastIdleTimeStart; - long mLongestLightIdleTime; - long mLongestFullIdleTime; + long mLastIdleTimeStartMs; + long mLongestLightIdleTimeMs; + long mLongestFullIdleTimeMs; StopwatchTimer mDeviceIdleModeLightTimer; StopwatchTimer mDeviceIdleModeFullTimer; @@ -921,7 +921,7 @@ public class BatteryStatsImpl extends BatteryStats { protected StopwatchTimer mBluetoothScanTimer; int mMobileRadioPowerState = DataConnectionRealTimeInfo.DC_POWER_STATE_LOW; - long mMobileRadioActiveStartTime; + long mMobileRadioActiveStartTimeMs; StopwatchTimer mMobileRadioActiveTimer; StopwatchTimer mMobileRadioActivePerAppTimer; LongSamplingCounter mMobileRadioActiveAdjustedTime; @@ -989,13 +989,13 @@ public class BatteryStatsImpl extends BatteryStats { static final int MAX_DAILY_ITEMS = 10; - long mDailyStartTime = 0; - long mNextMinDailyDeadline = 0; - long mNextMaxDailyDeadline = 0; + long mDailyStartTimeMs = 0; + long mNextMinDailyDeadlineMs = 0; + long mNextMaxDailyDeadlineMs = 0; final ArrayList<DailyItem> mDailyItems = new ArrayList<>(); - long mLastWriteTime = 0; // Milliseconds + long mLastWriteTimeMs = 0; // Milliseconds private int mPhoneServiceState = -1; private int mPhoneServiceStateRaw = -1; @@ -1131,8 +1131,8 @@ public class BatteryStatsImpl extends BatteryStats { * TimeBase observer. */ public interface TimeBaseObs { - void onTimeStarted(long elapsedRealtime, long baseUptime, long baseRealtime); - void onTimeStopped(long elapsedRealtime, long baseUptime, long baseRealtime); + void onTimeStarted(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs); + void onTimeStopped(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs); /** * Reset the observer's state, returns true if the timer/counter is inactive @@ -1140,7 +1140,18 @@ public class BatteryStatsImpl extends BatteryStats { * @param detachIfReset detach if true, no-op if false. * @return Returns true if the timer/counter is inactive and can be destroyed. */ - boolean reset(boolean detachIfReset); + default boolean reset(boolean detachIfReset) { + return reset(detachIfReset, SystemClock.elapsedRealtime() * 1000); + } + + /** + * @see #reset(boolean) + * @param detachIfReset detach if true, no-op if false. + * @param elapsedRealtimeUs the timestamp when this reset is actually reequested + * @return Returns true if the timer/counter is inactive and can be destroyed. + */ + boolean reset(boolean detachIfReset, long elapsedRealtimeUs); + /** * Detach the observer from TimeBase. */ @@ -1150,17 +1161,19 @@ public class BatteryStatsImpl extends BatteryStats { // methods are protected not private to be VisibleForTesting public static class TimeBase { protected final Collection<TimeBaseObs> mObservers; - protected long mUptime; - protected long mRealtime; + + // All below time metrics are in microseconds. + protected long mUptimeUs; + protected long mRealtimeUs; protected boolean mRunning; - protected long mPastUptime; - protected long mUptimeStart; - protected long mPastRealtime; - protected long mRealtimeStart; - protected long mUnpluggedUptime; - protected long mUnpluggedRealtime; + protected long mPastUptimeUs; + protected long mUptimeStartUs; + protected long mPastRealtimeUs; + protected long mRealtimeStartUs; + protected long mUnpluggedUptimeUs; + protected long mUnpluggedRealtimeUs; public void dump(PrintWriter pw, String prefix) { StringBuilder sb = new StringBuilder(128); @@ -1168,26 +1181,26 @@ public class BatteryStatsImpl extends BatteryStats { sb.setLength(0); sb.append(prefix); sb.append("mUptime="); - formatTimeMs(sb, mUptime / 1000); + formatTimeMs(sb, mUptimeUs / 1000); pw.println(sb.toString()); sb.setLength(0); sb.append(prefix); sb.append("mRealtime="); - formatTimeMs(sb, mRealtime / 1000); + formatTimeMs(sb, mRealtimeUs / 1000); pw.println(sb.toString()); sb.setLength(0); sb.append(prefix); sb.append("mPastUptime="); - formatTimeMs(sb, mPastUptime / 1000); sb.append("mUptimeStart="); - formatTimeMs(sb, mUptimeStart / 1000); - sb.append("mUnpluggedUptime="); formatTimeMs(sb, mUnpluggedUptime / 1000); + formatTimeMs(sb, mPastUptimeUs / 1000); sb.append("mUptimeStart="); + formatTimeMs(sb, mUptimeStartUs / 1000); + sb.append("mUnpluggedUptime="); formatTimeMs(sb, mUnpluggedUptimeUs / 1000); pw.println(sb.toString()); sb.setLength(0); sb.append(prefix); sb.append("mPastRealtime="); - formatTimeMs(sb, mPastRealtime / 1000); sb.append("mRealtimeStart="); - formatTimeMs(sb, mRealtimeStart / 1000); - sb.append("mUnpluggedRealtime="); formatTimeMs(sb, mUnpluggedRealtime / 1000); + formatTimeMs(sb, mPastRealtimeUs / 1000); sb.append("mRealtimeStart="); + formatTimeMs(sb, mRealtimeStartUs / 1000); + sb.append("mUnpluggedRealtime="); formatTimeMs(sb, mUnpluggedRealtimeUs / 1000); pw.println(sb.toString()); } /** @@ -1219,94 +1232,96 @@ public class BatteryStatsImpl extends BatteryStats { return mObservers.contains(observer); } - public void init(long uptime, long realtime) { - mRealtime = 0; - mUptime = 0; - mPastUptime = 0; - mPastRealtime = 0; - mUptimeStart = uptime; - mRealtimeStart = realtime; - mUnpluggedUptime = getUptime(mUptimeStart); - mUnpluggedRealtime = getRealtime(mRealtimeStart); + public void init(long uptimeUs, long elapsedRealtimeUs) { + mRealtimeUs = 0; + mUptimeUs = 0; + mPastUptimeUs = 0; + mPastRealtimeUs = 0; + mUptimeStartUs = uptimeUs; + mRealtimeStartUs = elapsedRealtimeUs; + mUnpluggedUptimeUs = getUptime(mUptimeStartUs); + mUnpluggedRealtimeUs = getRealtime(mRealtimeStartUs); } - public void reset(long uptime, long realtime) { + public void reset(long uptimeUs, long elapsedRealtimeUs) { if (!mRunning) { - mPastUptime = 0; - mPastRealtime = 0; - } else { - mUptimeStart = uptime; - mRealtimeStart = realtime; - // TODO: Since mUptimeStart was just reset and we are running, getUptime will - // just return mPastUptime. Also, are we sure we don't want to reset that? - mUnpluggedUptime = getUptime(uptime); + mPastUptimeUs = 0; + mPastRealtimeUs = 0; + } else { + mUptimeStartUs = uptimeUs; + mRealtimeStartUs = elapsedRealtimeUs; + // TODO: Since mUptimeStartUs was just reset and we are running, getUptime will + // just return mPastUptimeUs. Also, are we sure we don't want to reset that? + mUnpluggedUptimeUs = getUptime(uptimeUs); // TODO: likewise. - mUnpluggedRealtime = getRealtime(realtime); + mUnpluggedRealtimeUs = getRealtime(elapsedRealtimeUs); } } - public long computeUptime(long curTime, int which) { - return mUptime + getUptime(curTime); + public long computeUptime(long curTimeUs, int which) { + return mUptimeUs + getUptime(curTimeUs); } - public long computeRealtime(long curTime, int which) { - return mRealtime + getRealtime(curTime); + public long computeRealtime(long curTimeUs, int which) { + return mRealtimeUs + getRealtime(curTimeUs); } - public long getUptime(long curTime) { - long time = mPastUptime; + public long getUptime(long curTimeUs) { + long time = mPastUptimeUs; if (mRunning) { - time += curTime - mUptimeStart; + time += curTimeUs - mUptimeStartUs; } return time; } - public long getRealtime(long curTime) { - long time = mPastRealtime; + public long getRealtime(long curTimeUs) { + long time = mPastRealtimeUs; if (mRunning) { - time += curTime - mRealtimeStart; + time += curTimeUs - mRealtimeStartUs; } return time; } public long getUptimeStart() { - return mUptimeStart; + return mUptimeStartUs; } public long getRealtimeStart() { - return mRealtimeStart; + return mRealtimeStartUs; } public boolean isRunning() { return mRunning; } - public boolean setRunning(boolean running, long uptime, long realtime) { + public boolean setRunning(boolean running, long uptimeUs, long elapsedRealtimeUs) { if (mRunning != running) { mRunning = running; if (running) { - mUptimeStart = uptime; - mRealtimeStart = realtime; - long batteryUptime = mUnpluggedUptime = getUptime(uptime); - long batteryRealtime = mUnpluggedRealtime = getRealtime(realtime); + mUptimeStartUs = uptimeUs; + mRealtimeStartUs = elapsedRealtimeUs; + long batteryUptimeUs = mUnpluggedUptimeUs = getUptime(uptimeUs); + long batteryRealtimeUs = mUnpluggedRealtimeUs = getRealtime(elapsedRealtimeUs); // Normally we do not use Iterator in framework code to avoid alloc/dealloc // Iterator object, here is an exception because mObservers' type is Collection // instead of list. final Iterator<TimeBaseObs> iter = mObservers.iterator(); while (iter.hasNext()) { - iter.next().onTimeStarted(realtime, batteryUptime, batteryRealtime); + iter.next().onTimeStarted( + elapsedRealtimeUs, batteryUptimeUs, batteryRealtimeUs); } } else { - mPastUptime += uptime - mUptimeStart; - mPastRealtime += realtime - mRealtimeStart; - long batteryUptime = getUptime(uptime); - long batteryRealtime = getRealtime(realtime); + mPastUptimeUs += uptimeUs - mUptimeStartUs; + mPastRealtimeUs += elapsedRealtimeUs - mRealtimeStartUs; + long batteryUptimeUs = getUptime(uptimeUs); + long batteryRealtimeUs = getRealtime(elapsedRealtimeUs); // Normally we do not use Iterator in framework code to avoid alloc/dealloc // Iterator object, here is an exception because mObservers' type is Collection // instead of list. final Iterator<TimeBaseObs> iter = mObservers.iterator(); while (iter.hasNext()) { - iter.next().onTimeStopped(realtime, batteryUptime, batteryRealtime); + iter.next().onTimeStopped( + elapsedRealtimeUs, batteryUptimeUs, batteryRealtimeUs); } } return true; @@ -1315,38 +1330,38 @@ public class BatteryStatsImpl extends BatteryStats { } public void readSummaryFromParcel(Parcel in) { - mUptime = in.readLong(); - mRealtime = in.readLong(); + mUptimeUs = in.readLong(); + mRealtimeUs = in.readLong(); } - public void writeSummaryToParcel(Parcel out, long uptime, long realtime) { - out.writeLong(computeUptime(uptime, STATS_SINCE_CHARGED)); - out.writeLong(computeRealtime(realtime, STATS_SINCE_CHARGED)); + public void writeSummaryToParcel(Parcel out, long uptimeUs, long elapsedRealtimeUs) { + out.writeLong(computeUptime(uptimeUs, STATS_SINCE_CHARGED)); + out.writeLong(computeRealtime(elapsedRealtimeUs, STATS_SINCE_CHARGED)); } public void readFromParcel(Parcel in) { mRunning = false; - mUptime = in.readLong(); - mPastUptime = in.readLong(); - mUptimeStart = in.readLong(); - mRealtime = in.readLong(); - mPastRealtime = in.readLong(); - mRealtimeStart = in.readLong(); - mUnpluggedUptime = in.readLong(); - mUnpluggedRealtime = in.readLong(); - } - - public void writeToParcel(Parcel out, long uptime, long realtime) { - final long runningUptime = getUptime(uptime); - final long runningRealtime = getRealtime(realtime); - out.writeLong(mUptime); + mUptimeUs = in.readLong(); + mPastUptimeUs = in.readLong(); + mUptimeStartUs = in.readLong(); + mRealtimeUs = in.readLong(); + mPastRealtimeUs = in.readLong(); + mRealtimeStartUs = in.readLong(); + mUnpluggedUptimeUs = in.readLong(); + mUnpluggedRealtimeUs = in.readLong(); + } + + public void writeToParcel(Parcel out, long uptimeUs, long elapsedRealtimeUs) { + final long runningUptime = getUptime(uptimeUs); + final long runningRealtime = getRealtime(elapsedRealtimeUs); + out.writeLong(mUptimeUs); out.writeLong(runningUptime); - out.writeLong(mUptimeStart); - out.writeLong(mRealtime); + out.writeLong(mUptimeStartUs); + out.writeLong(mRealtimeUs); out.writeLong(runningRealtime); - out.writeLong(mRealtimeStart); - out.writeLong(mUnpluggedUptime); - out.writeLong(mUnpluggedRealtime); + out.writeLong(mRealtimeStartUs); + out.writeLong(mUnpluggedUptimeUs); + out.writeLong(mUnpluggedRealtimeUs); } } @@ -1374,11 +1389,11 @@ public class BatteryStatsImpl extends BatteryStats { } @Override - public void onTimeStarted(long elapsedRealtime, long baseUptime, long baseRealtime) { + public void onTimeStarted(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs) { } @Override - public void onTimeStopped(long elapsedRealtime, long baseUptime, long baseRealtime) { + public void onTimeStopped(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs) { } /** @@ -1436,7 +1451,7 @@ public class BatteryStatsImpl extends BatteryStats { * Clear state of this counter. */ @Override - public boolean reset(boolean detachIfReset) { + public boolean reset(boolean detachIfReset, long elapsedRealtimeUs /* unused */) { mCount.set(0); if (detachIfReset) { detach(); @@ -1481,11 +1496,11 @@ public class BatteryStatsImpl extends BatteryStats { } @Override - public void onTimeStarted(long elapsedRealTime, long baseUptime, long baseRealtime) { + public void onTimeStarted(long elapsedRealTimeUs, long baseUptimeUs, long baseRealtimeUs) { } @Override - public void onTimeStopped(long elapsedRealtime, long baseUptime, long baseRealtime) { + public void onTimeStopped(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs) { } @Override @@ -1524,7 +1539,7 @@ public class BatteryStatsImpl extends BatteryStats { * Clear state of this counter. */ @Override - public boolean reset(boolean detachIfReset) { + public boolean reset(boolean detachIfReset, long elapsedRealtimeUs /* unused */) { if (mCounts != null) { Arrays.fill(mCounts, 0); } @@ -1608,11 +1623,11 @@ public class BatteryStatsImpl extends BatteryStats { } @Override - public void onTimeStarted(long elapsedRealtime, long baseUptime, long baseRealtime) { + public void onTimeStarted(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs) { } @Override - public void onTimeStopped(long elapsedRealtime, long baseUptime, long baseRealtime) { + public void onTimeStopped(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs) { } public long getCountLocked(int which) { @@ -1638,7 +1653,7 @@ public class BatteryStatsImpl extends BatteryStats { * Clear state of this counter. */ @Override - public boolean reset(boolean detachIfReset) { + public boolean reset(boolean detachIfReset, long elapsedRealtimeUs /* unused */) { mCount = 0; if (detachIfReset) { detach(); @@ -1678,13 +1693,13 @@ public class BatteryStatsImpl extends BatteryStats { * boot, to the last time something interesting happened in the * current run. */ - protected long mTotalTime; + protected long mTotalTimeUs; /** * The total time this timer has been running until the latest mark has been set. - * Subtract this from mTotalTime to get the time spent running since the mark was set. + * Subtract this from mTotalTimeUs to get the time spent running since the mark was set. */ - protected long mTimeBeforeMark; + protected long mTimeBeforeMarkUs; /** * Constructs from a parcel. @@ -1698,10 +1713,10 @@ public class BatteryStatsImpl extends BatteryStats { mTimeBase = timeBase; mCount = in.readInt(); - mTotalTime = in.readLong(); - mTimeBeforeMark = in.readLong(); + mTotalTimeUs = in.readLong(); + mTimeBeforeMarkUs = in.readLong(); timeBase.add(this); - if (DEBUG) Log.i(TAG, "**** READ TIMER #" + mType + ": mTotalTime=" + mTotalTime); + if (DEBUG) Log.i(TAG, "**** READ TIMER #" + mType + ": mTotalTime=" + mTotalTimeUs); } public Timer(Clocks clocks, int type, TimeBase timeBase) { @@ -1714,14 +1729,17 @@ public class BatteryStatsImpl extends BatteryStats { public void writeToParcel(Parcel out, long elapsedRealtimeUs) { if (DEBUG) { Log.i(TAG, "**** WRITING TIMER #" + mType + ": mTotalTime=" - + computeRunTimeLocked(mTimeBase.getRealtime(elapsedRealtimeUs))); + + computeRunTimeLocked(mTimeBase.getRealtime(elapsedRealtimeUs), + elapsedRealtimeUs)); } out.writeInt(computeCurrentCountLocked()); - out.writeLong(computeRunTimeLocked(mTimeBase.getRealtime(elapsedRealtimeUs))); - out.writeLong(mTimeBeforeMark); + out.writeLong(computeRunTimeLocked(mTimeBase.getRealtime(elapsedRealtimeUs), + elapsedRealtimeUs)); + out.writeLong(mTimeBeforeMarkUs); } - protected abstract long computeRunTimeLocked(long curBatteryRealtime); + protected abstract long computeRunTimeLocked(long curBatteryRealtime, + long elapsedRealtimeUs); protected abstract int computeCurrentCountLocked(); @@ -1731,7 +1749,12 @@ public class BatteryStatsImpl extends BatteryStats { */ @Override public boolean reset(boolean detachIfReset) { - mTotalTime = mTimeBeforeMark = 0; + return reset(detachIfReset, mClocks.elapsedRealtime() * 1000); + } + + @Override + public boolean reset(boolean detachIfReset, long elapsedRealtimeUs /* unused */) { + mTotalTimeUs = mTimeBeforeMarkUs = 0; mCount = 0; if (detachIfReset) { detach(); @@ -1745,19 +1768,20 @@ public class BatteryStatsImpl extends BatteryStats { } @Override - public void onTimeStarted(long elapsedRealtime, long timeBaseUptime, long baseRealtime) { + public void onTimeStarted(long elapsedRealtimeUs, long timeBaseUptimeUs, + long baseRealtimeUs) { } @Override - public void onTimeStopped(long elapsedRealtime, long baseUptime, long baseRealtime) { + public void onTimeStopped(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs) { if (DEBUG && mType < 0) { - Log.v(TAG, "plug #" + mType + ": realtime=" + baseRealtime - + " old mTotalTime=" + mTotalTime); + Log.v(TAG, "plug #" + mType + ": realtime=" + baseRealtimeUs + + " old mTotalTime=" + mTotalTimeUs); } - mTotalTime = computeRunTimeLocked(baseRealtime); + mTotalTimeUs = computeRunTimeLocked(baseRealtimeUs, elapsedRealtimeUs); mCount = computeCurrentCountLocked(); if (DEBUG && mType < 0) { - Log.v(TAG, "plug #" + mType + ": new mTotalTime=" + mTotalTime); + Log.v(TAG, "plug #" + mType + ": new mTotalTime=" + mTotalTimeUs); } } @@ -1780,7 +1804,8 @@ public class BatteryStatsImpl extends BatteryStats { @Override @UnsupportedAppUsage public long getTotalTimeLocked(long elapsedRealtimeUs, int which) { - return computeRunTimeLocked(mTimeBase.getRealtime(elapsedRealtimeUs)); + return computeRunTimeLocked(mTimeBase.getRealtime(elapsedRealtimeUs), + elapsedRealtimeUs); } @Override @@ -1791,29 +1816,31 @@ public class BatteryStatsImpl extends BatteryStats { @Override public long getTimeSinceMarkLocked(long elapsedRealtimeUs) { - long val = computeRunTimeLocked(mTimeBase.getRealtime(elapsedRealtimeUs)); - return val - mTimeBeforeMark; + long val = computeRunTimeLocked(mTimeBase.getRealtime(elapsedRealtimeUs), + elapsedRealtimeUs); + return val - mTimeBeforeMarkUs; } @Override public void logState(Printer pw, String prefix) { pw.println(prefix + "mCount=" + mCount); - pw.println(prefix + "mTotalTime=" + mTotalTime); + pw.println(prefix + "mTotalTime=" + mTotalTimeUs); } public void writeSummaryFromParcelLocked(Parcel out, long elapsedRealtimeUs) { - long runTime = computeRunTimeLocked(mTimeBase.getRealtime(elapsedRealtimeUs)); - out.writeLong(runTime); + long runTimeUs = computeRunTimeLocked(mTimeBase.getRealtime(elapsedRealtimeUs), + elapsedRealtimeUs); + out.writeLong(runTimeUs); out.writeInt(computeCurrentCountLocked()); } public void readSummaryFromParcelLocked(Parcel in) { // Multiply by 1000 for backwards compatibility - mTotalTime = in.readLong(); + mTotalTimeUs = in.readLong(); mCount = in.readInt(); // When reading the summary, we set the mark to be the latest information. - mTimeBeforeMark = mTotalTime; + mTimeBeforeMarkUs = mTotalTimeUs; } } @@ -1843,14 +1870,14 @@ public class BatteryStatsImpl extends BatteryStats { /** * The most recent reported total_time from /proc/wakelocks. */ - long mCurrentReportedTotalTime; + long mCurrentReportedTotalTimeUs; /** * The reported total_time from /proc/wakelocks when unplug() was last * called. */ - long mUnpluggedReportedTotalTime; + long mUnpluggedReportedTotalTimeUs; /** * Whether we are currently in a discharge cycle. @@ -1872,8 +1899,8 @@ public class BatteryStatsImpl extends BatteryStats { super(clocks, 0, timeBase, in); mCurrentReportedCount = in.readInt(); mUnpluggedReportedCount = in.readInt(); - mCurrentReportedTotalTime = in.readLong(); - mUnpluggedReportedTotalTime = in.readLong(); + mCurrentReportedTotalTimeUs = in.readLong(); + mUnpluggedReportedTotalTimeUs = in.readLong(); mTrackingReportedValues = in.readInt() == 1; mTimeBaseRunning = timeBase.isRunning(); } @@ -1890,9 +1917,16 @@ public class BatteryStatsImpl extends BatteryStats { * be less than the values used for a previous invocation. */ public void endSample() { - mTotalTime = computeRunTimeLocked(0 /* unused by us */); + endSample(mClocks.elapsedRealtime() * 1000); + } + + /** + * @see #endSample() + */ + public void endSample(long elapsedRealtimeUs) { + mTotalTimeUs = computeRunTimeLocked(0 /* unused by us */, elapsedRealtimeUs); mCount = computeCurrentCountLocked(); - mUnpluggedReportedTotalTime = mCurrentReportedTotalTime = 0; + mUnpluggedReportedTotalTimeUs = mCurrentReportedTotalTimeUs = 0; mUnpluggedReportedCount = mCurrentReportedCount = 0; mTrackingReportedValues = false; } @@ -1911,26 +1945,33 @@ public class BatteryStatsImpl extends BatteryStats { * * If the values being recorded have been reset, the monotonically increasing requirement * will be broken. In this case, {@link #endSample()} is automatically called and - * the total value of totalTime and count are recorded, starting a new monotonically + * the total value of totalTimeUs and count are recorded, starting a new monotonically * increasing sample. * - * @param totalTime total time of sample in microseconds. + * @param totalTimeUs total time of sample in microseconds. * @param count total number of times the event being sampled occurred. */ - public void update(long totalTime, int count) { + public void updated(long totalTimeUs, int count) { + update(totalTimeUs, count, mClocks.elapsedRealtime() * 1000); + } + + /** + * @see #update(long, int) + */ + public void update(long totalTimeUs, int count, long elapsedRealtimeUs) { if (mTimeBaseRunning && !mTrackingReportedValues) { // Updating the reported value for the first time. - mUnpluggedReportedTotalTime = totalTime; + mUnpluggedReportedTotalTimeUs = totalTimeUs; mUnpluggedReportedCount = count; } mTrackingReportedValues = true; - if (totalTime < mCurrentReportedTotalTime || count < mCurrentReportedCount) { - endSample(); + if (totalTimeUs < mCurrentReportedTotalTimeUs || count < mCurrentReportedCount) { + endSample(elapsedRealtimeUs); } - mCurrentReportedTotalTime = totalTime; + mCurrentReportedTotalTimeUs = totalTimeUs; mCurrentReportedCount = count; } @@ -1940,23 +1981,31 @@ public class BatteryStatsImpl extends BatteryStats { * @param deltaTime additional time recorded since the last sampled event, in microseconds. * @param deltaCount additional number of times the event being sampled occurred. */ - public void add(long deltaTime, int deltaCount) { - update(mCurrentReportedTotalTime + deltaTime, mCurrentReportedCount + deltaCount); + public void add(long deltaTimeUs, int deltaCount) { + add(deltaTimeUs, deltaCount, mClocks.elapsedRealtime() * 1000); + } + + /** + * @see #add(long, int) + */ + public void add(long deltaTimeUs, int deltaCount, long elapsedRealtimeUs) { + update(mCurrentReportedTotalTimeUs + deltaTimeUs, mCurrentReportedCount + deltaCount, + elapsedRealtimeUs); } @Override - public void onTimeStarted(long elapsedRealtime, long baseUptime, long baseRealtime) { - super.onTimeStarted(elapsedRealtime, baseUptime, baseRealtime); + public void onTimeStarted(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs) { + super.onTimeStarted(elapsedRealtimeUs, baseUptimeUs, baseRealtimeUs); if (mTrackingReportedValues) { - mUnpluggedReportedTotalTime = mCurrentReportedTotalTime; + mUnpluggedReportedTotalTimeUs = mCurrentReportedTotalTimeUs; mUnpluggedReportedCount = mCurrentReportedCount; } mTimeBaseRunning = true; } @Override - public void onTimeStopped(long elapsedRealtime, long baseUptime, long baseRealtime) { - super.onTimeStopped(elapsedRealtime, baseUptime, baseRealtime); + public void onTimeStopped(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs) { + super.onTimeStopped(elapsedRealtimeUs, baseUptimeUs, baseRealtimeUs); mTimeBaseRunning = false; } @@ -1965,14 +2014,14 @@ public class BatteryStatsImpl extends BatteryStats { super.logState(pw, prefix); pw.println(prefix + "mCurrentReportedCount=" + mCurrentReportedCount + " mUnpluggedReportedCount=" + mUnpluggedReportedCount - + " mCurrentReportedTotalTime=" + mCurrentReportedTotalTime - + " mUnpluggedReportedTotalTime=" + mUnpluggedReportedTotalTime); + + " mCurrentReportedTotalTime=" + mCurrentReportedTotalTimeUs + + " mUnpluggedReportedTotalTime=" + mUnpluggedReportedTotalTimeUs); } @Override - protected long computeRunTimeLocked(long curBatteryRealtime) { - return mTotalTime + (mTimeBaseRunning && mTrackingReportedValues - ? mCurrentReportedTotalTime - mUnpluggedReportedTotalTime : 0); + protected long computeRunTimeLocked(long curBatteryRealtime, long elapsedRealtimeUs) { + return mTotalTimeUs + (mTimeBaseRunning && mTrackingReportedValues + ? mCurrentReportedTotalTimeUs - mUnpluggedReportedTotalTimeUs : 0); } @Override @@ -1986,16 +2035,16 @@ public class BatteryStatsImpl extends BatteryStats { super.writeToParcel(out, elapsedRealtimeUs); out.writeInt(mCurrentReportedCount); out.writeInt(mUnpluggedReportedCount); - out.writeLong(mCurrentReportedTotalTime); - out.writeLong(mUnpluggedReportedTotalTime); + out.writeLong(mCurrentReportedTotalTimeUs); + out.writeLong(mUnpluggedReportedTotalTimeUs); out.writeInt(mTrackingReportedValues ? 1 : 0); } @Override - public boolean reset(boolean detachIfReset) { - super.reset(detachIfReset); + public boolean reset(boolean detachIfReset, long elapsedRealtimeUs) { + super.reset(detachIfReset, elapsedRealtimeUs); mTrackingReportedValues = false; - mUnpluggedReportedTotalTime = 0; + mUnpluggedReportedTotalTimeUs = 0; mUnpluggedReportedCount = 0; return true; } @@ -2011,12 +2060,12 @@ public class BatteryStatsImpl extends BatteryStats { /** * The last time at which we updated the timer. This is in elapsed realtime microseconds. */ - long mLastAddedTime; + long mLastAddedTimeUs; /** * The last duration that we added to the timer. This is in microseconds. */ - long mLastAddedDuration; + long mLastAddedDurationUs; /** * Whether we are currently in a discharge cycle. @@ -2026,8 +2075,8 @@ public class BatteryStatsImpl extends BatteryStats { BatchTimer(Clocks clocks, Uid uid, int type, TimeBase timeBase, Parcel in) { super(clocks, type, timeBase, in); mUid = uid; - mLastAddedTime = in.readLong(); - mLastAddedDuration = in.readLong(); + mLastAddedTimeUs = in.readLong(); + mLastAddedDurationUs = in.readLong(); mInDischarge = timeBase.isRunning(); } @@ -2040,74 +2089,82 @@ public class BatteryStatsImpl extends BatteryStats { @Override public void writeToParcel(Parcel out, long elapsedRealtimeUs) { super.writeToParcel(out, elapsedRealtimeUs); - out.writeLong(mLastAddedTime); - out.writeLong(mLastAddedDuration); + out.writeLong(mLastAddedTimeUs); + out.writeLong(mLastAddedDurationUs); } @Override - public void onTimeStopped(long elapsedRealtime, long baseUptime, long baseRealtime) { - recomputeLastDuration(mClocks.elapsedRealtime() * 1000, false); + public void onTimeStopped(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs) { + recomputeLastDuration(elapsedRealtimeUs, false); mInDischarge = false; - super.onTimeStopped(elapsedRealtime, baseUptime, baseRealtime); + super.onTimeStopped(elapsedRealtimeUs, baseUptimeUs, baseRealtimeUs); } @Override - public void onTimeStarted(long elapsedRealtime, long baseUptime, long baseRealtime) { - recomputeLastDuration(elapsedRealtime, false); + public void onTimeStarted(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs) { + recomputeLastDuration(elapsedRealtimeUs, false); mInDischarge = true; // If we are still within the last added duration, then re-added whatever remains. - if (mLastAddedTime == elapsedRealtime) { - mTotalTime += mLastAddedDuration; + if (mLastAddedTimeUs == elapsedRealtimeUs) { + mTotalTimeUs += mLastAddedDurationUs; } - super.onTimeStarted(elapsedRealtime, baseUptime, baseRealtime); + super.onTimeStarted(elapsedRealtimeUs, baseUptimeUs, baseRealtimeUs); } @Override public void logState(Printer pw, String prefix) { super.logState(pw, prefix); - pw.println(prefix + "mLastAddedTime=" + mLastAddedTime - + " mLastAddedDuration=" + mLastAddedDuration); + pw.println(prefix + "mLastAddedTime=" + mLastAddedTimeUs + + " mLastAddedDuration=" + mLastAddedDurationUs); } - private long computeOverage(long curTime) { - if (mLastAddedTime > 0) { - return mLastAddedDuration - curTime; + private long computeOverage(long curTimeUs) { + if (mLastAddedTimeUs > 0) { + return mLastAddedDurationUs - curTimeUs; } return 0; } - private void recomputeLastDuration(long curTime, boolean abort) { - final long overage = computeOverage(curTime); + private void recomputeLastDuration(long curTimeUs, boolean abort) { + final long overage = computeOverage(curTimeUs); if (overage > 0) { // Aborting before the duration ran out -- roll back the remaining // duration. Only do this if currently discharging; otherwise we didn't // actually add the time. if (mInDischarge) { - mTotalTime -= overage; + mTotalTimeUs -= overage; } if (abort) { - mLastAddedTime = 0; + mLastAddedTimeUs = 0; } else { - mLastAddedTime = curTime; - mLastAddedDuration -= overage; + mLastAddedTimeUs = curTimeUs; + mLastAddedDurationUs -= overage; } } } - public void addDuration(BatteryStatsImpl stats, long durationMillis) { - final long now = mClocks.elapsedRealtime() * 1000; - recomputeLastDuration(now, true); - mLastAddedTime = now; - mLastAddedDuration = durationMillis * 1000; + public void addDuration(BatteryStatsImpl stats, long durationMs) { + addDuration(stats, durationMs, mClocks.elapsedRealtime()); + } + + public void addDuration(BatteryStatsImpl stats, long durationMs, long elapsedRealtimeMs) { + final long nowUs = elapsedRealtimeMs * 1000; + recomputeLastDuration(nowUs, true); + mLastAddedTimeUs = nowUs; + mLastAddedDurationUs = durationMs * 1000; if (mInDischarge) { - mTotalTime += mLastAddedDuration; + mTotalTimeUs += mLastAddedDurationUs; mCount++; } } public void abortLastDuration(BatteryStatsImpl stats) { - final long now = mClocks.elapsedRealtime() * 1000; - recomputeLastDuration(now, true); + abortLastDuration(stats, mClocks.elapsedRealtime()); + } + + public void abortLastDuration(BatteryStatsImpl stats, long elapsedRealtimeMs) { + final long nowUs = elapsedRealtimeMs * 1000; + recomputeLastDuration(nowUs, true); } @Override @@ -2116,20 +2173,19 @@ public class BatteryStatsImpl extends BatteryStats { } @Override - protected long computeRunTimeLocked(long curBatteryRealtime) { - final long overage = computeOverage(mClocks.elapsedRealtime() * 1000); + protected long computeRunTimeLocked(long curBatteryRealtimeUs, long elapsedRealtimeUs) { + final long overage = computeOverage(elapsedRealtimeUs); if (overage > 0) { - return mTotalTime = overage; + return mTotalTimeUs = overage; } - return mTotalTime; + return mTotalTimeUs; } @Override - public boolean reset(boolean detachIfReset) { - final long now = mClocks.elapsedRealtime() * 1000; - recomputeLastDuration(now, true); - boolean stillActive = mLastAddedTime == now; - super.reset(!stillActive && detachIfReset); + public boolean reset(boolean detachIfReset, long elapsedRealtimeUs) { + recomputeLastDuration(elapsedRealtimeUs, true); + boolean stillActive = mLastAddedTimeUs == elapsedRealtimeUs; + super.reset(!stillActive && detachIfReset, elapsedRealtimeUs); return !stillActive; } } @@ -2225,10 +2281,10 @@ public class BatteryStatsImpl extends BatteryStats { * * If the timer is also running, store the start time. */ - public void onTimeStarted(long elapsedRealtimeUs, long baseUptime, long baseRealtime) { - super.onTimeStarted(elapsedRealtimeUs, baseUptime, baseRealtime); + public void onTimeStarted(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs) { + super.onTimeStarted(elapsedRealtimeUs, baseUptimeUs, baseRealtimeUs); if (mNesting > 0) { - mStartTimeMs = baseRealtime / 1000; + mStartTimeMs = baseRealtimeUs / 1000; } } @@ -2238,8 +2294,8 @@ public class BatteryStatsImpl extends BatteryStats { * If the timer is running, add the duration into mCurrentDurationMs. */ @Override - public void onTimeStopped(long elapsedRealtimeUs, long baseUptime, long baseRealtimeUs) { - super.onTimeStopped(elapsedRealtimeUs, baseUptime, baseRealtimeUs); + public void onTimeStopped(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs) { + super.onTimeStopped(elapsedRealtimeUs, baseUptimeUs, baseRealtimeUs); if (mNesting > 0) { // baseRealtimeUs has already been converted to the timebase's realtime. mCurrentDurationMs += (baseRealtimeUs / 1000) - mStartTimeMs; @@ -2284,13 +2340,13 @@ public class BatteryStatsImpl extends BatteryStats { } @Override - public boolean reset(boolean detachIfReset) { - boolean result = super.reset(detachIfReset); + public boolean reset(boolean detachIfReset, long elapsedRealtimeUs) { + boolean result = super.reset(detachIfReset, elapsedRealtimeUs); mMaxDurationMs = 0; mTotalDurationMs = 0; mCurrentDurationMs = 0; if (mNesting > 0) { - mStartTimeMs = mTimeBase.getRealtime(mClocks.elapsedRealtime() * 1000) / 1000; + mStartTimeMs = mTimeBase.getRealtime(elapsedRealtimeUs) / 1000; } else { mStartTimeMs = -1; } @@ -2364,16 +2420,16 @@ public class BatteryStatsImpl extends BatteryStats { * subtract this from the current battery time to find the amount of * time we have been running since we last computed an update. */ - long mUpdateTime; + long mUpdateTimeUs; /** * The total time at which the timer was acquired, to determine if it * was actually held for an interesting duration. If time base was not running when timer * was acquired, will be -1. */ - long mAcquireTime = -1; + long mAcquireTimeUs = -1; - long mTimeout; + long mTimeoutUs; /** * For partial wake locks, keep track of whether we are in the list @@ -2387,7 +2443,7 @@ public class BatteryStatsImpl extends BatteryStats { super(clocks, type, timeBase, in); mUid = uid; mTimerPool = timerPool; - mUpdateTime = in.readLong(); + mUpdateTimeUs = in.readLong(); } public StopwatchTimer(Clocks clocks, Uid uid, int type, ArrayList<StopwatchTimer> timerPool, @@ -2397,56 +2453,56 @@ public class BatteryStatsImpl extends BatteryStats { mTimerPool = timerPool; } - public void setTimeout(long timeout) { - mTimeout = timeout; + public void setTimeout(long timeoutUs) { + mTimeoutUs = timeoutUs; } public void writeToParcel(Parcel out, long elapsedRealtimeUs) { super.writeToParcel(out, elapsedRealtimeUs); - out.writeLong(mUpdateTime); + out.writeLong(mUpdateTimeUs); } - public void onTimeStopped(long elapsedRealtime, long baseUptime, long baseRealtime) { + public void onTimeStopped(long elapsedRealtimeUs, long baseUptimeUs, long baseRealtimeUs) { if (mNesting > 0) { if (DEBUG && mType < 0) { - Log.v(TAG, "old mUpdateTime=" + mUpdateTime); + Log.v(TAG, "old mUpdateTime=" + mUpdateTimeUs); } - super.onTimeStopped(elapsedRealtime, baseUptime, baseRealtime); - mUpdateTime = baseRealtime; + super.onTimeStopped(elapsedRealtimeUs, baseUptimeUs, baseRealtimeUs); + mUpdateTimeUs = baseRealtimeUs; if (DEBUG && mType < 0) { - Log.v(TAG, "new mUpdateTime=" + mUpdateTime); + Log.v(TAG, "new mUpdateTime=" + mUpdateTimeUs); } } } public void logState(Printer pw, String prefix) { super.logState(pw, prefix); - pw.println(prefix + "mNesting=" + mNesting + " mUpdateTime=" + mUpdateTime - + " mAcquireTime=" + mAcquireTime); + pw.println(prefix + "mNesting=" + mNesting + " mUpdateTime=" + mUpdateTimeUs + + " mAcquireTime=" + mAcquireTimeUs); } public void startRunningLocked(long elapsedRealtimeMs) { if (mNesting++ == 0) { - final long batteryRealtime = mTimeBase.getRealtime(elapsedRealtimeMs * 1000); - mUpdateTime = batteryRealtime; + final long batteryRealtimeUs = mTimeBase.getRealtime(elapsedRealtimeMs * 1000); + mUpdateTimeUs = batteryRealtimeUs; if (mTimerPool != null) { // Accumulate time to all currently active timers before adding // this new one to the pool. - refreshTimersLocked(batteryRealtime, mTimerPool, null); + refreshTimersLocked(batteryRealtimeUs, mTimerPool, null); // Add this timer to the active pool mTimerPool.add(this); } if (mTimeBase.isRunning()) { // Increment the count mCount++; - mAcquireTime = mTotalTime; + mAcquireTimeUs = mTotalTimeUs; } else { - mAcquireTime = -1; + mAcquireTimeUs = -1; } if (DEBUG && mType < 0) { - Log.v(TAG, "start #" + mType + ": mUpdateTime=" + mUpdateTime - + " mTotalTime=" + mTotalTime + " mCount=" + mCount - + " mAcquireTime=" + mAcquireTime); + Log.v(TAG, "start #" + mType + ": mUpdateTime=" + mUpdateTimeUs + + " mTotalTime=" + mTotalTimeUs + " mCount=" + mCount + + " mAcquireTime=" + mAcquireTimeUs); } } } @@ -2461,26 +2517,27 @@ public class BatteryStatsImpl extends BatteryStats { return; } if (--mNesting == 0) { - final long batteryRealtime = mTimeBase.getRealtime(elapsedRealtimeMs * 1000); + final long batteryRealtimeUs = mTimeBase.getRealtime(elapsedRealtimeMs * 1000); if (mTimerPool != null) { // Accumulate time to all active counters, scaled by the total // active in the pool, before taking this one out of the pool. - refreshTimersLocked(batteryRealtime, mTimerPool, null); + refreshTimersLocked(batteryRealtimeUs, mTimerPool, null); // Remove this timer from the active pool mTimerPool.remove(this); } else { mNesting = 1; - mTotalTime = computeRunTimeLocked(batteryRealtime); + mTotalTimeUs = computeRunTimeLocked(batteryRealtimeUs, + elapsedRealtimeMs * 1000); mNesting = 0; } if (DEBUG && mType < 0) { - Log.v(TAG, "stop #" + mType + ": mUpdateTime=" + mUpdateTime - + " mTotalTime=" + mTotalTime + " mCount=" + mCount - + " mAcquireTime=" + mAcquireTime); + Log.v(TAG, "stop #" + mType + ": mUpdateTime=" + mUpdateTimeUs + + " mTotalTime=" + mTotalTimeUs + " mCount=" + mCount + + " mAcquireTime=" + mAcquireTimeUs); } - if (mAcquireTime >= 0 && mTotalTime == mAcquireTime) { + if (mAcquireTimeUs >= 0 && mTotalTimeUs == mAcquireTimeUs) { // If there was no change in the time, then discard this // count. A somewhat cheezy strategy, but hey. mCount--; @@ -2497,32 +2554,32 @@ public class BatteryStatsImpl extends BatteryStats { // Update the total time for all other running Timers with the same type as this Timer // due to a change in timer count - private static long refreshTimersLocked(long batteryRealtime, + private static long refreshTimersLocked(long batteryRealtimeUs, final ArrayList<StopwatchTimer> pool, StopwatchTimer self) { - long selfTime = 0; + long selfTimeUs = 0; final int N = pool.size(); for (int i=N-1; i>= 0; i--) { final StopwatchTimer t = pool.get(i); - long heldTime = batteryRealtime - t.mUpdateTime; - if (heldTime > 0) { - final long myTime = heldTime / N; + long heldTimeUs = batteryRealtimeUs - t.mUpdateTimeUs; + if (heldTimeUs > 0) { + final long myTimeUs = heldTimeUs / N; if (t == self) { - selfTime = myTime; + selfTimeUs = myTimeUs; } - t.mTotalTime += myTime; + t.mTotalTimeUs += myTimeUs; } - t.mUpdateTime = batteryRealtime; + t.mUpdateTimeUs = batteryRealtimeUs; } - return selfTime; + return selfTimeUs; } @Override - protected long computeRunTimeLocked(long curBatteryRealtime) { - if (mTimeout > 0 && curBatteryRealtime > mUpdateTime + mTimeout) { - curBatteryRealtime = mUpdateTime + mTimeout; + protected long computeRunTimeLocked(long curBatteryRealtimeUs, long elapsedRealtimeUs) { + if (mTimeoutUs > 0 && curBatteryRealtimeUs > mUpdateTimeUs + mTimeoutUs) { + curBatteryRealtimeUs = mUpdateTimeUs + mTimeoutUs; } - return mTotalTime + (mNesting > 0 - ? (curBatteryRealtime - mUpdateTime) + return mTotalTimeUs + (mNesting > 0 + ? (curBatteryRealtimeUs - mUpdateTimeUs) / (mTimerPool != null ? mTimerPool.size() : 1) : 0); } @@ -2533,13 +2590,14 @@ public class BatteryStatsImpl extends BatteryStats { } @Override - public boolean reset(boolean detachIfReset) { + public boolean reset(boolean detachIfReset, long elapsedRealtimeUs) { boolean canDetach = mNesting <= 0; - super.reset(canDetach && detachIfReset); + super.reset(canDetach && detachIfReset, elapsedRealtimeUs); if (mNesting > 0) { - mUpdateTime = mTimeBase.getRealtime(mClocks.elapsedRealtime() * 1000); + mUpdateTimeUs = mTimeBase.getRealtime(elapsedRealtimeUs); } - mAcquireTime = -1; // to ensure mCount isn't decreased to -1 if timer is stopped later. + // To ensure mCount isn't decreased to -1 if timer is stopped later. + mAcquireTimeUs = -1; return canDetach; } @@ -2565,17 +2623,17 @@ public class BatteryStatsImpl extends BatteryStats { * @param elapsedRealtimeMs the current elapsed realtime in milliseconds. */ public void setMark(long elapsedRealtimeMs) { - final long batteryRealtime = mTimeBase.getRealtime(elapsedRealtimeMs * 1000); + final long batteryRealtimeUs = mTimeBase.getRealtime(elapsedRealtimeMs * 1000); if (mNesting > 0) { // We are running. if (mTimerPool != null) { - refreshTimersLocked(batteryRealtime, mTimerPool, this); + refreshTimersLocked(batteryRealtimeUs, mTimerPool, this); } else { - mTotalTime += batteryRealtime - mUpdateTime; - mUpdateTime = batteryRealtime; + mTotalTimeUs += batteryRealtimeUs - mUpdateTimeUs; + mUpdateTimeUs = batteryRealtimeUs; } } - mTimeBeforeMark = mTotalTime; + mTimeBeforeMarkUs = mTotalTimeUs; } } @@ -2641,11 +2699,11 @@ public class BatteryStatsImpl extends BatteryStats { } @Override - public boolean reset(boolean detachIfReset) { + public boolean reset(boolean detachIfReset, long elapsedRealtimeUs) { boolean active = false; // Do not detach the subTimer explicitly since that'll be done by DualTimer.detach(). - active |= !mSubTimer.reset(false); - active |= !super.reset(detachIfReset); + active |= !mSubTimer.reset(false, elapsedRealtimeUs); + active |= !super.reset(detachIfReset, elapsedRealtimeUs); return !active; } @@ -2682,10 +2740,10 @@ public class BatteryStatsImpl extends BatteryStats { final ArrayMap<String, T> mMap = new ArrayMap<>(); T mCurOverflow; ArrayMap<String, MutableInt> mActiveOverflow; - long mLastOverflowTime; - long mLastOverflowFinishTime; - long mLastClearTime; - long mLastCleanupTime; + long mLastOverflowTimeMs; + long mLastOverflowFinishTimeMs; + long mLastClearTimeMs; + long mLastCleanupTimeMs; public OverflowArrayMap(int uid) { mUid = uid; @@ -2696,7 +2754,7 @@ public class BatteryStatsImpl extends BatteryStats { } public void clear() { - mLastClearTime = SystemClock.elapsedRealtime(); + mLastClearTimeMs = SystemClock.elapsedRealtime(); mMap.clear(); mCurOverflow = null; mActiveOverflow = null; @@ -2712,8 +2770,8 @@ public class BatteryStatsImpl extends BatteryStats { } } - public void cleanup() { - mLastCleanupTime = SystemClock.elapsedRealtime(); + public void cleanup(long elapsedRealtimeMs) { + mLastCleanupTimeMs = elapsedRealtimeMs; if (mActiveOverflow != null) { if (mActiveOverflow.size() == 0) { mActiveOverflow = null; @@ -2737,7 +2795,7 @@ public class BatteryStatsImpl extends BatteryStats { } } - public T startObject(String name) { + public T startObject(String name, long elapsedRealtimeMs) { if (name == null) { name = ""; } @@ -2780,7 +2838,7 @@ public class BatteryStatsImpl extends BatteryStats { mActiveOverflow = new ArrayMap<>(); } mActiveOverflow.put(name, new MutableInt(1)); - mLastOverflowTime = SystemClock.elapsedRealtime(); + mLastOverflowTimeMs = elapsedRealtimeMs; return obj; } @@ -2790,7 +2848,7 @@ public class BatteryStatsImpl extends BatteryStats { return obj; } - public T stopObject(String name) { + public T stopObject(String name, long elapsedRealtimeMs) { if (name == null) { name = ""; } @@ -2810,7 +2868,7 @@ public class BatteryStatsImpl extends BatteryStats { over.value--; if (over.value <= 0) { mActiveOverflow.remove(name); - mLastOverflowFinishTime = SystemClock.elapsedRealtime(); + mLastOverflowFinishTimeMs = elapsedRealtimeMs; } return obj; } @@ -2830,22 +2888,22 @@ public class BatteryStatsImpl extends BatteryStats { sb.append(mActiveOverflow); sb.append(" curoverflow="); sb.append(mCurOverflow); - long now = SystemClock.elapsedRealtime(); - if (mLastOverflowTime != 0) { + long now = elapsedRealtimeMs; + if (mLastOverflowTimeMs != 0) { sb.append(" lastOverflowTime="); - TimeUtils.formatDuration(mLastOverflowTime-now, sb); + TimeUtils.formatDuration(mLastOverflowTimeMs - now, sb); } - if (mLastOverflowFinishTime != 0) { + if (mLastOverflowFinishTimeMs != 0) { sb.append(" lastOverflowFinishTime="); - TimeUtils.formatDuration(mLastOverflowFinishTime-now, sb); + TimeUtils.formatDuration(mLastOverflowFinishTimeMs - now, sb); } - if (mLastClearTime != 0) { + if (mLastClearTimeMs != 0) { sb.append(" lastClearTime="); - TimeUtils.formatDuration(mLastClearTime-now, sb); + TimeUtils.formatDuration(mLastClearTimeMs - now, sb); } - if (mLastCleanupTime != 0) { + if (mLastCleanupTimeMs != 0) { sb.append(" lastCleanupTime="); - TimeUtils.formatDuration(mLastCleanupTime-now, sb); + TimeUtils.formatDuration(mLastCleanupTimeMs - now, sb); } Slog.wtf(TAG, sb.toString()); return null; @@ -2943,16 +3001,16 @@ public class BatteryStatsImpl extends BatteryStats { mMonitoredRailChargeConsumedMaMs.writeToParcel(dest); } - public void reset(boolean detachIfReset) { - mIdleTimeMillis.reset(detachIfReset); - mScanTimeMillis.reset(detachIfReset); - mSleepTimeMillis.reset(detachIfReset); - mRxTimeMillis.reset(detachIfReset); + public void reset(boolean detachIfReset, long elapsedRealtimeUs) { + mIdleTimeMillis.reset(detachIfReset, elapsedRealtimeUs); + mScanTimeMillis.reset(detachIfReset, elapsedRealtimeUs); + mSleepTimeMillis.reset(detachIfReset, elapsedRealtimeUs); + mRxTimeMillis.reset(detachIfReset, elapsedRealtimeUs); for (LongSamplingCounter counter : mTxTimeMillis) { - counter.reset(detachIfReset); + counter.reset(detachIfReset, elapsedRealtimeUs); } - mPowerDrainMaMs.reset(detachIfReset); - mMonitoredRailChargeConsumedMaMs.reset(detachIfReset); + mPowerDrainMaMs.reset(detachIfReset, elapsedRealtimeUs); + mMonitoredRailChargeConsumedMaMs.reset(detachIfReset, elapsedRealtimeUs); } public void detach() { @@ -3416,82 +3474,82 @@ public class BatteryStatsImpl extends BatteryStats { final int NU = mUidStats.size(); for (int i=0; i<NU; i++) { final BatteryStatsImpl.Uid uid = mUidStats.valueAt(i); - uid.mLastStepUserTime = uid.mCurStepUserTime; - uid.mLastStepSystemTime = uid.mCurStepSystemTime; - } - mLastStepCpuUserTime = mCurStepCpuUserTime; - mLastStepCpuSystemTime = mCurStepCpuSystemTime; - mLastStepStatUserTime = mCurStepStatUserTime; - mLastStepStatSystemTime = mCurStepStatSystemTime; - mLastStepStatIOWaitTime = mCurStepStatIOWaitTime; - mLastStepStatIrqTime = mCurStepStatIrqTime; - mLastStepStatSoftIrqTime = mCurStepStatSoftIrqTime; - mLastStepStatIdleTime = mCurStepStatIdleTime; + uid.mLastStepUserTimeMs = uid.mCurStepUserTimeMs; + uid.mLastStepSystemTimeMs = uid.mCurStepSystemTimeMs; + } + mLastStepCpuUserTimeMs = mCurStepCpuUserTimeMs; + mLastStepCpuSystemTimeMs = mCurStepCpuSystemTimeMs; + mLastStepStatUserTimeMs = mCurStepStatUserTimeMs; + mLastStepStatSystemTimeMs = mCurStepStatSystemTimeMs; + mLastStepStatIOWaitTimeMs = mCurStepStatIOWaitTimeMs; + mLastStepStatIrqTimeMs = mCurStepStatIrqTimeMs; + mLastStepStatSoftIrqTimeMs = mCurStepStatSoftIrqTimeMs; + mLastStepStatIdleTimeMs = mCurStepStatIdleTimeMs; tmp.clear(); return; } if (DEBUG) { - Slog.d(TAG, "Step stats last: user=" + mLastStepCpuUserTime + " sys=" - + mLastStepStatSystemTime + " io=" + mLastStepStatIOWaitTime - + " irq=" + mLastStepStatIrqTime + " sirq=" - + mLastStepStatSoftIrqTime + " idle=" + mLastStepStatIdleTime); - Slog.d(TAG, "Step stats cur: user=" + mCurStepCpuUserTime + " sys=" - + mCurStepStatSystemTime + " io=" + mCurStepStatIOWaitTime - + " irq=" + mCurStepStatIrqTime + " sirq=" - + mCurStepStatSoftIrqTime + " idle=" + mCurStepStatIdleTime); - } - out.userTime = (int)(mCurStepCpuUserTime - mLastStepCpuUserTime); - out.systemTime = (int)(mCurStepCpuSystemTime - mLastStepCpuSystemTime); - out.statUserTime = (int)(mCurStepStatUserTime - mLastStepStatUserTime); - out.statSystemTime = (int)(mCurStepStatSystemTime - mLastStepStatSystemTime); - out.statIOWaitTime = (int)(mCurStepStatIOWaitTime - mLastStepStatIOWaitTime); - out.statIrqTime = (int)(mCurStepStatIrqTime - mLastStepStatIrqTime); - out.statSoftIrqTime = (int)(mCurStepStatSoftIrqTime - mLastStepStatSoftIrqTime); - out.statIdlTime = (int)(mCurStepStatIdleTime - mLastStepStatIdleTime); + Slog.d(TAG, "Step stats last: user=" + mLastStepCpuUserTimeMs + " sys=" + + mLastStepStatSystemTimeMs + " io=" + mLastStepStatIOWaitTimeMs + + " irq=" + mLastStepStatIrqTimeMs + " sirq=" + + mLastStepStatSoftIrqTimeMs + " idle=" + mLastStepStatIdleTimeMs); + Slog.d(TAG, "Step stats cur: user=" + mCurStepCpuUserTimeMs + " sys=" + + mCurStepStatSystemTimeMs + " io=" + mCurStepStatIOWaitTimeMs + + " irq=" + mCurStepStatIrqTimeMs + " sirq=" + + mCurStepStatSoftIrqTimeMs + " idle=" + mCurStepStatIdleTimeMs); + } + out.userTime = (int) (mCurStepCpuUserTimeMs - mLastStepCpuUserTimeMs); + out.systemTime = (int) (mCurStepCpuSystemTimeMs - mLastStepCpuSystemTimeMs); + out.statUserTime = (int) (mCurStepStatUserTimeMs - mLastStepStatUserTimeMs); + out.statSystemTime = (int) (mCurStepStatSystemTimeMs - mLastStepStatSystemTimeMs); + out.statIOWaitTime = (int) (mCurStepStatIOWaitTimeMs - mLastStepStatIOWaitTimeMs); + out.statIrqTime = (int) (mCurStepStatIrqTimeMs - mLastStepStatIrqTimeMs); + out.statSoftIrqTime = (int) (mCurStepStatSoftIrqTimeMs - mLastStepStatSoftIrqTimeMs); + out.statIdlTime = (int) (mCurStepStatIdleTimeMs - mLastStepStatIdleTimeMs); out.appCpuUid1 = out.appCpuUid2 = out.appCpuUid3 = -1; out.appCpuUTime1 = out.appCpuUTime2 = out.appCpuUTime3 = 0; out.appCpuSTime1 = out.appCpuSTime2 = out.appCpuSTime3 = 0; final int NU = mUidStats.size(); for (int i=0; i<NU; i++) { final BatteryStatsImpl.Uid uid = mUidStats.valueAt(i); - final int totalUTime = (int)(uid.mCurStepUserTime - uid.mLastStepUserTime); - final int totalSTime = (int)(uid.mCurStepSystemTime - uid.mLastStepSystemTime); - final int totalTime = totalUTime + totalSTime; - uid.mLastStepUserTime = uid.mCurStepUserTime; - uid.mLastStepSystemTime = uid.mCurStepSystemTime; - if (totalTime <= (out.appCpuUTime3+out.appCpuSTime3)) { + final int totalUTimeMs = (int) (uid.mCurStepUserTimeMs - uid.mLastStepUserTimeMs); + final int totalSTimeMs = (int) (uid.mCurStepSystemTimeMs - uid.mLastStepSystemTimeMs); + final int totalTimeMs = totalUTimeMs + totalSTimeMs; + uid.mLastStepUserTimeMs = uid.mCurStepUserTimeMs; + uid.mLastStepSystemTimeMs = uid.mCurStepSystemTimeMs; + if (totalTimeMs <= (out.appCpuUTime3 + out.appCpuSTime3)) { continue; } - if (totalTime <= (out.appCpuUTime2+out.appCpuSTime2)) { + if (totalTimeMs <= (out.appCpuUTime2 + out.appCpuSTime2)) { out.appCpuUid3 = uid.mUid; - out.appCpuUTime3 = totalUTime; - out.appCpuSTime3 = totalSTime; + out.appCpuUTime3 = totalUTimeMs; + out.appCpuSTime3 = totalSTimeMs; } else { out.appCpuUid3 = out.appCpuUid2; out.appCpuUTime3 = out.appCpuUTime2; out.appCpuSTime3 = out.appCpuSTime2; - if (totalTime <= (out.appCpuUTime1+out.appCpuSTime1)) { + if (totalTimeMs <= (out.appCpuUTime1 + out.appCpuSTime1)) { out.appCpuUid2 = uid.mUid; - out.appCpuUTime2 = totalUTime; - out.appCpuSTime2 = totalSTime; + out.appCpuUTime2 = totalUTimeMs; + out.appCpuSTime2 = totalSTimeMs; } else { out.appCpuUid2 = out.appCpuUid1; out.appCpuUTime2 = out.appCpuUTime1; out.appCpuSTime2 = out.appCpuSTime1; out.appCpuUid1 = uid.mUid; - out.appCpuUTime1 = totalUTime; - out.appCpuSTime1 = totalSTime; + out.appCpuUTime1 = totalUTimeMs; + out.appCpuSTime1 = totalSTimeMs; } } } - mLastStepCpuUserTime = mCurStepCpuUserTime; - mLastStepCpuSystemTime = mCurStepCpuSystemTime; - mLastStepStatUserTime = mCurStepStatUserTime; - mLastStepStatSystemTime = mCurStepStatSystemTime; - mLastStepStatIOWaitTime = mCurStepStatIOWaitTime; - mLastStepStatIrqTime = mCurStepStatIrqTime; - mLastStepStatSoftIrqTime = mCurStepStatSoftIrqTime; - mLastStepStatIdleTime = mCurStepStatIdleTime; + mLastStepCpuUserTimeMs = mCurStepCpuUserTimeMs; + mLastStepCpuSystemTimeMs = mCurStepCpuSystemTimeMs; + mLastStepStatUserTimeMs = mCurStepStatUserTimeMs; + mLastStepStatSystemTimeMs = mCurStepStatSystemTimeMs; + mLastStepStatIOWaitTimeMs = mCurStepStatIOWaitTimeMs; + mLastStepStatIrqTimeMs = mCurStepStatIrqTimeMs; + mLastStepStatSoftIrqTimeMs = mCurStepStatSoftIrqTimeMs; + mLastStepStatIdleTimeMs = mCurStepStatIdleTimeMs; } public void readHistoryDelta(Parcel src, HistoryItem cur) { @@ -3631,29 +3689,35 @@ public class BatteryStatsImpl extends BatteryStats { } public void createFakeHistoryEvents(long numEvents) { + final long elapsedRealtimeMs = mClocks.elapsedRealtime(); + final long uptimeMs = mClocks.uptimeMillis(); for(long i = 0; i < numEvents; i++) { - noteLongPartialWakelockStart("name1", "historyName1", 1000); - noteLongPartialWakelockFinish("name1", "historyName1", 1000); + noteLongPartialWakelockStart("name1", "historyName1", 1000, + elapsedRealtimeMs, uptimeMs); + noteLongPartialWakelockFinish("name1", "historyName1", 1000, + elapsedRealtimeMs, uptimeMs); } } - void addHistoryBufferLocked(long elapsedRealtimeMs, HistoryItem cur) { + void addHistoryBufferLocked(long elapsedRealtimeMs, long uptimeMs, HistoryItem cur) { if (!mHaveBatteryLevel || !mRecordingHistory) { return; } - final long timeDiff = (mHistoryBaseTime+elapsedRealtimeMs) - mHistoryLastWritten.time; + final long timeDiffMs = (mHistoryBaseTimeMs + elapsedRealtimeMs) - mHistoryLastWritten.time; final int diffStates = mHistoryLastWritten.states^(cur.states&mActiveHistoryStates); final int diffStates2 = mHistoryLastWritten.states2^(cur.states2&mActiveHistoryStates2); final int lastDiffStates = mHistoryLastWritten.states^mHistoryLastLastWritten.states; final int lastDiffStates2 = mHistoryLastWritten.states2^mHistoryLastLastWritten.states2; - if (DEBUG) Slog.i(TAG, "ADD: tdelta=" + timeDiff + " diff=" - + Integer.toHexString(diffStates) + " lastDiff=" - + Integer.toHexString(lastDiffStates) + " diff2=" - + Integer.toHexString(diffStates2) + " lastDiff2=" - + Integer.toHexString(lastDiffStates2)); + if (DEBUG) { + Slog.i(TAG, "ADD: tdelta=" + timeDiffMs + " diff=" + + Integer.toHexString(diffStates) + " lastDiff=" + + Integer.toHexString(lastDiffStates) + " diff2=" + + Integer.toHexString(diffStates2) + " lastDiff2=" + + Integer.toHexString(lastDiffStates2)); + } if (mHistoryBufferLastPos >= 0 && mHistoryLastWritten.cmd == HistoryItem.CMD_UPDATE - && timeDiff < 1000 && (diffStates&lastDiffStates) == 0 + && timeDiffMs < 1000 && (diffStates & lastDiffStates) == 0 && (diffStates2&lastDiffStates2) == 0 && (mHistoryLastWritten.wakelockTag == null || cur.wakelockTag == null) && (mHistoryLastWritten.wakeReasonTag == null || cur.wakeReasonTag == null) @@ -3674,7 +3738,7 @@ public class BatteryStatsImpl extends BatteryStats { mHistoryBuffer.setDataSize(mHistoryBufferLastPos); mHistoryBuffer.setDataPosition(mHistoryBufferLastPos); mHistoryBufferLastPos = -1; - elapsedRealtimeMs = mHistoryLastWritten.time - mHistoryBaseTime; + elapsedRealtimeMs = mHistoryLastWritten.time - mHistoryBaseTimeMs; // If the last written history had a wakelock tag, we need to retain it. // Note that the condition above made sure that we aren't in a case where // both it and the current history item have a wakelock tag. @@ -3714,11 +3778,9 @@ public class BatteryStatsImpl extends BatteryStats { mHistoryBuffer.setDataPosition(0); mHistoryBuffer.setDataCapacity(mConstants.MAX_HISTORY_BUFFER / 2); mHistoryBufferLastPos = -1; - final long elapsedRealtime = mClocks.elapsedRealtime(); - final long uptime = mClocks.uptimeMillis(); HistoryItem newItem = new HistoryItem(); newItem.setTo(cur); - startRecordingHistory(elapsedRealtime, uptime, false); + startRecordingHistory(elapsedRealtimeMs, uptimeMs, false); addHistoryBufferLocked(elapsedRealtimeMs, HistoryItem.CMD_UPDATE, newItem); return; } @@ -3737,11 +3799,11 @@ public class BatteryStatsImpl extends BatteryStats { } mHistoryBufferLastPos = mHistoryBuffer.dataPosition(); mHistoryLastLastWritten.setTo(mHistoryLastWritten); - mHistoryLastWritten.setTo(mHistoryBaseTime + elapsedRealtimeMs, cmd, cur); + mHistoryLastWritten.setTo(mHistoryBaseTimeMs + elapsedRealtimeMs, cmd, cur); mHistoryLastWritten.states &= mActiveHistoryStates; mHistoryLastWritten.states2 &= mActiveHistoryStates2; writeHistoryDelta(mHistoryBuffer, mHistoryLastWritten, mHistoryLastLastWritten); - mLastHistoryElapsedRealtime = elapsedRealtimeMs; + mLastHistoryElapsedRealtimeMs = elapsedRealtimeMs; cur.wakelockTag = null; cur.wakeReasonTag = null; cur.eventCode = HistoryItem.EVENT_NONE; @@ -3755,27 +3817,27 @@ public class BatteryStatsImpl extends BatteryStats { int mChangedStates2 = 0; void addHistoryRecordLocked(long elapsedRealtimeMs, long uptimeMs) { - if (mTrackRunningHistoryElapsedRealtime != 0) { - final long diffElapsed = elapsedRealtimeMs - mTrackRunningHistoryElapsedRealtime; - final long diffUptime = uptimeMs - mTrackRunningHistoryUptime; - if (diffUptime < (diffElapsed-20)) { - final long wakeElapsedTime = elapsedRealtimeMs - (diffElapsed - diffUptime); + if (mTrackRunningHistoryElapsedRealtimeMs != 0) { + final long diffElapsedMs = elapsedRealtimeMs - mTrackRunningHistoryElapsedRealtimeMs; + final long diffUptimeMs = uptimeMs - mTrackRunningHistoryUptimeMs; + if (diffUptimeMs < (diffElapsedMs - 20)) { + final long wakeElapsedTimeMs = elapsedRealtimeMs - (diffElapsedMs - diffUptimeMs); mHistoryAddTmp.setTo(mHistoryLastWritten); mHistoryAddTmp.wakelockTag = null; mHistoryAddTmp.wakeReasonTag = null; mHistoryAddTmp.eventCode = HistoryItem.EVENT_NONE; mHistoryAddTmp.states &= ~HistoryItem.STATE_CPU_RUNNING_FLAG; - addHistoryRecordInnerLocked(wakeElapsedTime, mHistoryAddTmp); + addHistoryRecordInnerLocked(wakeElapsedTimeMs, uptimeMs, mHistoryAddTmp); } } mHistoryCur.states |= HistoryItem.STATE_CPU_RUNNING_FLAG; - mTrackRunningHistoryElapsedRealtime = elapsedRealtimeMs; - mTrackRunningHistoryUptime = uptimeMs; - addHistoryRecordInnerLocked(elapsedRealtimeMs, mHistoryCur); + mTrackRunningHistoryElapsedRealtimeMs = elapsedRealtimeMs; + mTrackRunningHistoryUptimeMs = uptimeMs; + addHistoryRecordInnerLocked(elapsedRealtimeMs, uptimeMs, mHistoryCur); } - void addHistoryRecordInnerLocked(long elapsedRealtimeMs, HistoryItem cur) { - addHistoryBufferLocked(elapsedRealtimeMs, cur); + void addHistoryRecordInnerLocked(long elapsedRealtimeMs, long uptimeMs, HistoryItem cur) { + addHistoryBufferLocked(elapsedRealtimeMs, uptimeMs, cur); if (!USE_OLD_HISTORY) { return; @@ -3790,13 +3852,13 @@ public class BatteryStatsImpl extends BatteryStats { // are now resetting back to their original value, then just collapse // into one record. if (mHistoryEnd != null && mHistoryEnd.cmd == HistoryItem.CMD_UPDATE - && (mHistoryBaseTime+elapsedRealtimeMs) < (mHistoryEnd.time+1000) + && (mHistoryBaseTimeMs + elapsedRealtimeMs) < (mHistoryEnd.time + 1000) && ((mHistoryEnd.states^cur.states)&mChangedStates&mActiveHistoryStates) == 0 && ((mHistoryEnd.states2^cur.states2)&mChangedStates2&mActiveHistoryStates2) == 0) { // If the current is the same as the one before, then we no // longer need the entry. if (mHistoryLastEnd != null && mHistoryLastEnd.cmd == HistoryItem.CMD_UPDATE - && (mHistoryBaseTime+elapsedRealtimeMs) < (mHistoryEnd.time+500) + && (mHistoryBaseTimeMs + elapsedRealtimeMs) < (mHistoryEnd.time + 500) && mHistoryLastEnd.sameNonEvent(cur)) { mHistoryLastEnd.next = null; mHistoryEnd.next = mHistoryCache; @@ -3832,7 +3894,7 @@ public class BatteryStatsImpl extends BatteryStats { } else { rec = new HistoryItem(); } - rec.setTo(mHistoryBaseTime + elapsedRealtimeMs, cmd, cur); + rec.setTo(mHistoryBaseTimeMs + elapsedRealtimeMs, cmd, cur); addHistoryRecordLocked(rec); } @@ -3860,10 +3922,10 @@ public class BatteryStatsImpl extends BatteryStats { mNumHistoryItems = 0; } - mHistoryBaseTime = 0; - mLastHistoryElapsedRealtime = 0; - mTrackRunningHistoryElapsedRealtime = 0; - mTrackRunningHistoryUptime = 0; + mHistoryBaseTimeMs = 0; + mLastHistoryElapsedRealtimeMs = 0; + mTrackRunningHistoryElapsedRealtimeMs = 0; + mTrackRunningHistoryUptimeMs = 0; mHistoryBuffer.setDataSize(0); mHistoryBuffer.setDataPosition(0); @@ -3879,8 +3941,8 @@ public class BatteryStatsImpl extends BatteryStats { } @GuardedBy("this") - public void updateTimeBasesLocked(boolean unplugged, int screenState, long uptime, - long realtime) { + public void updateTimeBasesLocked(boolean unplugged, int screenState, long uptimeUs, + long realtimeUs) { final boolean screenOff = !isScreenOn(screenState); final boolean updateOnBatteryTimeBase = unplugged != mOnBatteryTimeBase.isRunning(); final boolean updateOnBatteryScreenOffTimeBase = @@ -3888,14 +3950,15 @@ public class BatteryStatsImpl extends BatteryStats { if (updateOnBatteryScreenOffTimeBase || updateOnBatteryTimeBase) { if (updateOnBatteryScreenOffTimeBase) { - updateKernelWakelocksLocked(); + updateKernelWakelocksLocked(realtimeUs); updateBatteryPropertiesLocked(); } // This if{} is only necessary due to SCREEN_OFF_RPM_STATS_ENABLED, which exists because // updateRpmStatsLocked is too slow to run each screen change. When the speed is // improved, remove the surrounding if{}. if (SCREEN_OFF_RPM_STATS_ENABLED || updateOnBatteryTimeBase) { - updateRpmStatsLocked(); // if either OnBattery or OnBatteryScreenOff timebase changes. + // if either OnBattery or OnBatteryScreenOfftimebase changes. + updateRpmStatsLocked(realtimeUs); } if (DEBUG_ENERGY_CPU) { Slog.d(TAG, "Updating cpu time because screen is now " @@ -3903,16 +3966,17 @@ public class BatteryStatsImpl extends BatteryStats { + " and battery is " + (unplugged ? "on" : "off")); } - mOnBatteryTimeBase.setRunning(unplugged, uptime, realtime); + mOnBatteryTimeBase.setRunning(unplugged, uptimeUs, realtimeUs); if (updateOnBatteryTimeBase) { for (int i = mUidStats.size() - 1; i >= 0; --i) { - mUidStats.valueAt(i).updateOnBatteryBgTimeBase(uptime, realtime); + mUidStats.valueAt(i).updateOnBatteryBgTimeBase(uptimeUs, realtimeUs); } } if (updateOnBatteryScreenOffTimeBase) { - mOnBatteryScreenOffTimeBase.setRunning(unplugged && screenOff, uptime, realtime); + mOnBatteryScreenOffTimeBase.setRunning(unplugged && screenOff, + uptimeUs, realtimeUs); for (int i = mUidStats.size() - 1; i >= 0; --i) { - mUidStats.valueAt(i).updateOnBatteryScreenOffBgTimeBase(uptime, realtime); + mUidStats.valueAt(i).updateOnBatteryScreenOffBgTimeBase(uptimeUs, realtimeUs); } } } @@ -3931,8 +3995,14 @@ public class BatteryStatsImpl extends BatteryStats { } public void addIsolatedUidLocked(int isolatedUid, int appUid) { + addIsolatedUidLocked(isolatedUid, appUid, + mClocks.elapsedRealtime(), mClocks.uptimeMillis()); + } + + public void addIsolatedUidLocked(int isolatedUid, int appUid, + long elapsedRealtimeMs, long uptimeMs) { mIsolatedUids.put(isolatedUid, appUid); - final Uid u = getUidStatsLocked(appUid); + final Uid u = getUidStatsLocked(appUid, elapsedRealtimeMs, uptimeMs); u.addIsolatedUid(isolatedUid); } @@ -3955,14 +4025,22 @@ public class BatteryStatsImpl extends BatteryStats { */ @GuardedBy("this") public void removeIsolatedUidLocked(int isolatedUid) { + removeIsolatedUidLocked(isolatedUid, mClocks.elapsedRealtime(), mClocks.uptimeMillis()); + } + + /** + * @see #removeIsolatedUidLocked(int) + */ + @GuardedBy("this") + public void removeIsolatedUidLocked(int isolatedUid, long elapsedRealtimeMs, long uptimeMs) { final int idx = mIsolatedUids.indexOfKey(isolatedUid); if (idx >= 0) { final int ownerUid = mIsolatedUids.valueAt(idx); - final Uid u = getUidStatsLocked(ownerUid); + final Uid u = getUidStatsLocked(ownerUid, elapsedRealtimeMs, uptimeMs); u.removeIsolatedUid(isolatedUid); mIsolatedUids.removeAt(idx); } - mPendingRemovedUids.add(new UidToRemove(isolatedUid, mClocks.elapsedRealtime())); + mPendingRemovedUids.add(new UidToRemove(isolatedUid, elapsedRealtimeMs)); } public int mapUid(int uid) { @@ -3971,26 +4049,39 @@ public class BatteryStatsImpl extends BatteryStats { } public void noteEventLocked(int code, String name, int uid) { + noteEventLocked(code, name, uid, mClocks.elapsedRealtime(), mClocks.uptimeMillis()); + } + + public void noteEventLocked(int code, String name, int uid, + long elapsedRealtimeMs, long uptimeMs) { uid = mapUid(uid); if (!mActiveEvents.updateState(code, name, uid, 0)) { return; } - final long elapsedRealtime = mClocks.elapsedRealtime(); - final long uptime = mClocks.uptimeMillis(); - addHistoryEventLocked(elapsedRealtime, uptime, code, name, uid); + addHistoryEventLocked(elapsedRealtimeMs, uptimeMs, code, name, uid); } public void noteCurrentTimeChangedLocked() { final long currentTime = System.currentTimeMillis(); final long elapsedRealtime = mClocks.elapsedRealtime(); final long uptime = mClocks.uptimeMillis(); - recordCurrentTimeChangeLocked(currentTime, elapsedRealtime, uptime); + noteCurrentTimeChangedLocked(currentTime, elapsedRealtime, uptime); + } + + public void noteCurrentTimeChangedLocked(long currentTimeMs, + long elapsedRealtimeMs, long uptimeMs) { + recordCurrentTimeChangeLocked(currentTimeMs, elapsedRealtimeMs, uptimeMs); } public void noteProcessStartLocked(String name, int uid) { + noteProcessStartLocked(name, uid, mClocks.elapsedRealtime(), mClocks.uptimeMillis()); + } + + public void noteProcessStartLocked(String name, int uid, + long elapsedRealtimeMs, long uptimeMs) { uid = mapUid(uid); if (isOnBattery()) { - Uid u = getUidStatsLocked(uid); + Uid u = getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs); u.getProcessStatsLocked(name).incStartsLocked(); } if (!mActiveEvents.updateState(HistoryItem.EVENT_PROC_START, name, uid, 0)) { @@ -3999,28 +4090,40 @@ public class BatteryStatsImpl extends BatteryStats { if (!mRecordAllHistory) { return; } - final long elapsedRealtime = mClocks.elapsedRealtime(); - final long uptime = mClocks.uptimeMillis(); - addHistoryEventLocked(elapsedRealtime, uptime, HistoryItem.EVENT_PROC_START, name, uid); + addHistoryEventLocked(elapsedRealtimeMs, uptimeMs, HistoryItem.EVENT_PROC_START, name, uid); } public void noteProcessCrashLocked(String name, int uid) { + noteProcessCrashLocked(name, uid, mClocks.elapsedRealtime(), mClocks.uptimeMillis()); + } + + public void noteProcessCrashLocked(String name, int uid, + long elapsedRealtimeMs, long uptimeMs) { uid = mapUid(uid); if (isOnBattery()) { - Uid u = getUidStatsLocked(uid); + Uid u = getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs); u.getProcessStatsLocked(name).incNumCrashesLocked(); } } public void noteProcessAnrLocked(String name, int uid) { + noteProcessAnrLocked(name, uid, mClocks.elapsedRealtime(), mClocks.uptimeMillis()); + } + + public void noteProcessAnrLocked(String name, int uid, long elapsedRealtimeMs, long uptimeMs) { uid = mapUid(uid); if (isOnBattery()) { - Uid u = getUidStatsLocked(uid); + Uid u = getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs); u.getProcessStatsLocked(name).incNumAnrsLocked(); } } public void noteUidProcessStateLocked(int uid, int state) { + noteUidProcessStateLocked(uid, state, mClocks.elapsedRealtime(), mClocks.uptimeMillis()); + } + + public void noteUidProcessStateLocked(int uid, int state, + long elapsedRealtimeMs, long uptimeMs) { int parentUid = mapUid(uid); if (uid != parentUid) { // Isolated UIDs process state is already rolled up into parent, so no need to track @@ -4032,10 +4135,16 @@ public class BatteryStatsImpl extends BatteryStats { // and isolated uids rather than only the parent uid. FrameworkStatsLog.write(FrameworkStatsLog.UID_PROCESS_STATE_CHANGED, uid, ActivityManager.processStateAmToProto(state)); - getUidStatsLocked(uid).updateUidProcessStateLocked(state); + getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs) + .updateUidProcessStateLocked(state, elapsedRealtimeMs, uptimeMs); } public void noteProcessFinishLocked(String name, int uid) { + noteProcessFinishLocked(name, uid, mClocks.elapsedRealtime(), mClocks.uptimeMillis()); + } + + public void noteProcessFinishLocked(String name, int uid, + long elapsedRealtimeMs, long uptimeMs) { uid = mapUid(uid); if (!mActiveEvents.updateState(HistoryItem.EVENT_PROC_FINISH, name, uid, 0)) { return; @@ -4043,82 +4152,120 @@ public class BatteryStatsImpl extends BatteryStats { if (!mRecordAllHistory) { return; } - final long elapsedRealtime = mClocks.elapsedRealtime(); - final long uptime = mClocks.uptimeMillis(); - addHistoryEventLocked(elapsedRealtime, uptime, HistoryItem.EVENT_PROC_FINISH, name, uid); + addHistoryEventLocked(elapsedRealtimeMs, uptimeMs, HistoryItem.EVENT_PROC_FINISH, + name, uid); } public void noteSyncStartLocked(String name, int uid) { + noteSyncStartLocked(name, uid, mClocks.elapsedRealtime(), mClocks.uptimeMillis()); + } + + public void noteSyncStartLocked(String name, int uid, long elapsedRealtimeMs, long uptimeMs) { uid = mapUid(uid); - final long elapsedRealtime = mClocks.elapsedRealtime(); - final long uptime = mClocks.uptimeMillis(); - getUidStatsLocked(uid).noteStartSyncLocked(name, elapsedRealtime); + getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs) + .noteStartSyncLocked(name, elapsedRealtimeMs); if (!mActiveEvents.updateState(HistoryItem.EVENT_SYNC_START, name, uid, 0)) { return; } - addHistoryEventLocked(elapsedRealtime, uptime, HistoryItem.EVENT_SYNC_START, name, uid); + addHistoryEventLocked(elapsedRealtimeMs, uptimeMs, HistoryItem.EVENT_SYNC_START, name, uid); } public void noteSyncFinishLocked(String name, int uid) { + noteSyncFinishLocked(name, uid, mClocks.elapsedRealtime(), mClocks.uptimeMillis()); + } + + public void noteSyncFinishLocked(String name, int uid, long elapsedRealtimeMs, long uptimeMs) { uid = mapUid(uid); - final long elapsedRealtime = mClocks.elapsedRealtime(); - final long uptime = mClocks.uptimeMillis(); - getUidStatsLocked(uid).noteStopSyncLocked(name, elapsedRealtime); + getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs) + .noteStopSyncLocked(name, elapsedRealtimeMs); if (!mActiveEvents.updateState(HistoryItem.EVENT_SYNC_FINISH, name, uid, 0)) { return; } - addHistoryEventLocked(elapsedRealtime, uptime, HistoryItem.EVENT_SYNC_FINISH, name, uid); + addHistoryEventLocked(elapsedRealtimeMs, uptimeMs, HistoryItem.EVENT_SYNC_FINISH, + name, uid); } public void noteJobStartLocked(String name, int uid) { + noteJobStartLocked(name, uid, mClocks.elapsedRealtime(), mClocks.uptimeMillis()); + } + + public void noteJobStartLocked(String name, int uid, long elapsedRealtimeMs, long uptimeMs) { uid = mapUid(uid); - final long elapsedRealtime = mClocks.elapsedRealtime(); - final long uptime = mClocks.uptimeMillis(); - getUidStatsLocked(uid).noteStartJobLocked(name, elapsedRealtime); + getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs) + .noteStartJobLocked(name, elapsedRealtimeMs); if (!mActiveEvents.updateState(HistoryItem.EVENT_JOB_START, name, uid, 0)) { return; } - addHistoryEventLocked(elapsedRealtime, uptime, HistoryItem.EVENT_JOB_START, name, uid); + addHistoryEventLocked(elapsedRealtimeMs, uptimeMs, HistoryItem.EVENT_JOB_START, name, uid); } public void noteJobFinishLocked(String name, int uid, int stopReason) { + noteJobFinishLocked(name, uid, stopReason, + mClocks.elapsedRealtime(), mClocks.uptimeMillis()); + } + + public void noteJobFinishLocked(String name, int uid, int stopReason, + long elapsedRealtimeMs, long uptimeMs) { uid = mapUid(uid); - final long elapsedRealtime = mClocks.elapsedRealtime(); - final long uptime = mClocks.uptimeMillis(); - getUidStatsLocked(uid).noteStopJobLocked(name, elapsedRealtime, stopReason); + getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs) + .noteStopJobLocked(name, elapsedRealtimeMs, stopReason); if (!mActiveEvents.updateState(HistoryItem.EVENT_JOB_FINISH, name, uid, 0)) { return; } - addHistoryEventLocked(elapsedRealtime, uptime, HistoryItem.EVENT_JOB_FINISH, name, uid); + addHistoryEventLocked(elapsedRealtimeMs, uptimeMs, HistoryItem.EVENT_JOB_FINISH, name, uid); } public void noteJobsDeferredLocked(int uid, int numDeferred, long sinceLast) { + noteJobsDeferredLocked(uid, numDeferred, sinceLast, + mClocks.elapsedRealtime(), mClocks.uptimeMillis()); + } + + public void noteJobsDeferredLocked(int uid, int numDeferred, long sinceLast, + long elapsedRealtimeMs, long uptimeMs) { uid = mapUid(uid); - getUidStatsLocked(uid).noteJobsDeferredLocked(numDeferred, sinceLast); + getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs) + .noteJobsDeferredLocked(numDeferred, sinceLast); } public void noteAlarmStartLocked(String name, WorkSource workSource, int uid) { - noteAlarmStartOrFinishLocked(HistoryItem.EVENT_ALARM_START, name, workSource, uid); + noteAlarmStartLocked(name, workSource, uid, + mClocks.elapsedRealtime(), mClocks.uptimeMillis()); + } + + public void noteAlarmStartLocked(String name, WorkSource workSource, int uid, + long elapsedRealtimeMs, long uptimeMs) { + noteAlarmStartOrFinishLocked(HistoryItem.EVENT_ALARM_START, name, workSource, uid, + elapsedRealtimeMs, uptimeMs); } public void noteAlarmFinishLocked(String name, WorkSource workSource, int uid) { - noteAlarmStartOrFinishLocked(HistoryItem.EVENT_ALARM_FINISH, name, workSource, uid); + noteAlarmFinishLocked(name, workSource, uid, + mClocks.elapsedRealtime(), mClocks.uptimeMillis()); + } + + public void noteAlarmFinishLocked(String name, WorkSource workSource, int uid, + long elapsedRealtimeMs, long uptimeMs) { + noteAlarmStartOrFinishLocked(HistoryItem.EVENT_ALARM_FINISH, name, workSource, uid, + elapsedRealtimeMs, uptimeMs); } private void noteAlarmStartOrFinishLocked(int historyItem, String name, WorkSource workSource, int uid) { + noteAlarmStartOrFinishLocked(historyItem, name, workSource, uid, + mClocks.elapsedRealtime(), mClocks.uptimeMillis()); + } + + private void noteAlarmStartOrFinishLocked(int historyItem, String name, WorkSource workSource, + int uid, long elapsedRealtimeMs, long uptimeMs) { if (!mRecordAllHistory) { return; } - final long elapsedRealtime = mClocks.elapsedRealtime(); - final long uptime = mClocks.uptimeMillis(); - if (workSource != null) { for (int i = 0; i < workSource.size(); ++i) { uid = mapUid(workSource.getUid(i)); if (mActiveEvents.updateState(historyItem, name, uid, 0)) { - addHistoryEventLocked(elapsedRealtime, uptime, historyItem, name, uid); + addHistoryEventLocked(elapsedRealtimeMs, uptimeMs, historyItem, name, uid); } } @@ -4127,7 +4274,7 @@ public class BatteryStatsImpl extends BatteryStats { for (int i = 0; i < workChains.size(); ++i) { uid = mapUid(workChains.get(i).getAttributionUid()); if (mActiveEvents.updateState(historyItem, name, uid, 0)) { - addHistoryEventLocked(elapsedRealtime, uptime, historyItem, name, uid); + addHistoryEventLocked(elapsedRealtimeMs, uptimeMs, historyItem, name, uid); } } } @@ -4135,13 +4282,19 @@ public class BatteryStatsImpl extends BatteryStats { uid = mapUid(uid); if (mActiveEvents.updateState(historyItem, name, uid, 0)) { - addHistoryEventLocked(elapsedRealtime, uptime, historyItem, name, uid); + addHistoryEventLocked(elapsedRealtimeMs, uptimeMs, historyItem, name, uid); } } } public void noteWakupAlarmLocked(String packageName, int uid, WorkSource workSource, String tag) { + noteWakupAlarmLocked(packageName, uid, workSource, tag, + mClocks.elapsedRealtime(), mClocks.uptimeMillis()); + } + + public void noteWakupAlarmLocked(String packageName, int uid, WorkSource workSource, + String tag, long elapsedRealtimeMs, long uptimeMs) { if (workSource != null) { for (int i = 0; i < workSource.size(); ++i) { uid = workSource.getUid(i); @@ -4149,7 +4302,8 @@ public class BatteryStatsImpl extends BatteryStats { if (isOnBattery()) { BatteryStatsImpl.Uid.Pkg pkg = getPackageStatsLocked(uid, - workSourceName != null ? workSourceName : packageName); + workSourceName != null ? workSourceName : packageName, + elapsedRealtimeMs, uptimeMs); pkg.noteWakeupAlarmLocked(tag); } } @@ -4161,14 +4315,16 @@ public class BatteryStatsImpl extends BatteryStats { uid = wc.getAttributionUid(); if (isOnBattery()) { - BatteryStatsImpl.Uid.Pkg pkg = getPackageStatsLocked(uid, packageName); + BatteryStatsImpl.Uid.Pkg pkg = getPackageStatsLocked(uid, packageName, + elapsedRealtimeMs, uptimeMs); pkg.noteWakeupAlarmLocked(tag); } } } } else { if (isOnBattery()) { - BatteryStatsImpl.Uid.Pkg pkg = getPackageStatsLocked(uid, packageName); + BatteryStatsImpl.Uid.Pkg pkg = getPackageStatsLocked(uid, packageName, + elapsedRealtimeMs, uptimeMs); pkg.noteWakeupAlarmLocked(tag); } } @@ -4228,7 +4384,8 @@ public class BatteryStatsImpl extends BatteryStats { public void setPretendScreenOff(boolean pretendScreenOff) { if (mPretendScreenOff != pretendScreenOff) { mPretendScreenOff = pretendScreenOff; - noteScreenStateLocked(pretendScreenOff ? Display.STATE_OFF : Display.STATE_ON); + noteScreenStateLocked(pretendScreenOff ? Display.STATE_OFF : Display.STATE_ON, + mClocks.elapsedRealtime(), mClocks.uptimeMillis(), System.currentTimeMillis()); } } @@ -4236,19 +4393,25 @@ public class BatteryStatsImpl extends BatteryStats { private int mInitialAcquireWakeUid = -1; public void noteStartWakeLocked(int uid, int pid, WorkChain wc, String name, String historyName, - int type, boolean unimportantForLogging, long elapsedRealtime, long uptime) { + int type, boolean unimportantForLogging) { + noteStartWakeLocked(uid, pid, wc, name, historyName, type, unimportantForLogging, + mClocks.elapsedRealtime(), mClocks.uptimeMillis()); + } + + public void noteStartWakeLocked(int uid, int pid, WorkChain wc, String name, String historyName, + int type, boolean unimportantForLogging, long elapsedRealtimeMs, long uptimeMs) { uid = mapUid(uid); if (type == WAKE_TYPE_PARTIAL) { // Only care about partial wake locks, since full wake locks // will be canceled when the user puts the screen to sleep. - aggregateLastWakeupUptimeLocked(uptime); + aggregateLastWakeupUptimeLocked(elapsedRealtimeMs, uptimeMs); if (historyName == null) { historyName = name; } if (mRecordAllHistory) { if (mActiveEvents.updateState(HistoryItem.EVENT_WAKE_LOCK_START, historyName, uid, 0)) { - addHistoryEventLocked(elapsedRealtime, uptime, + addHistoryEventLocked(elapsedRealtimeMs, uptimeMs, HistoryItem.EVENT_WAKE_LOCK_START, historyName, uid); } } @@ -4260,7 +4423,7 @@ public class BatteryStatsImpl extends BatteryStats { mHistoryCur.wakelockTag.string = mInitialAcquireWakeName = historyName; mHistoryCur.wakelockTag.uid = mInitialAcquireWakeUid = uid; mWakeLockImportant = !unimportantForLogging; - addHistoryRecordLocked(elapsedRealtime, uptime); + addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs); } else if (!mWakeLockImportant && !unimportantForLogging && mHistoryLastWritten.cmd == HistoryItem.CMD_UPDATE) { if (mHistoryLastWritten.wakelockTag != null) { @@ -4269,7 +4432,7 @@ public class BatteryStatsImpl extends BatteryStats { mHistoryCur.wakelockTag = mHistoryCur.localWakelockTag; mHistoryCur.wakelockTag.string = mInitialAcquireWakeName = historyName; mHistoryCur.wakelockTag.uid = mInitialAcquireWakeUid = uid; - addHistoryRecordLocked(elapsedRealtime, uptime); + addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs); } mWakeLockImportant = true; } @@ -4285,7 +4448,8 @@ public class BatteryStatsImpl extends BatteryStats { requestWakelockCpuUpdate(); } - getUidStatsLocked(uid).noteStartWakeLocked(pid, name, type, elapsedRealtime); + getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs) + .noteStartWakeLocked(pid, name, type, elapsedRealtimeMs); if (wc != null) { FrameworkStatsLog.write(FrameworkStatsLog.WAKELOCK_STATE_CHANGED, wc.getUids(), @@ -4300,7 +4464,13 @@ public class BatteryStatsImpl extends BatteryStats { } public void noteStopWakeLocked(int uid, int pid, WorkChain wc, String name, String historyName, - int type, long elapsedRealtime, long uptime) { + int type) { + noteStopWakeLocked(uid, pid, wc, name, historyName, type, + mClocks.elapsedRealtime(), mClocks.uptimeMillis()); + } + + public void noteStopWakeLocked(int uid, int pid, WorkChain wc, String name, String historyName, + int type, long elapsedRealtimeMs, long uptimeMs) { uid = mapUid(uid); if (type == WAKE_TYPE_PARTIAL) { mWakeLockNesting--; @@ -4310,7 +4480,7 @@ public class BatteryStatsImpl extends BatteryStats { } if (mActiveEvents.updateState(HistoryItem.EVENT_WAKE_LOCK_FINISH, historyName, uid, 0)) { - addHistoryEventLocked(elapsedRealtime, uptime, + addHistoryEventLocked(elapsedRealtimeMs, uptimeMs, HistoryItem.EVENT_WAKE_LOCK_FINISH, historyName, uid); } } @@ -4320,7 +4490,7 @@ public class BatteryStatsImpl extends BatteryStats { + Integer.toHexString(mHistoryCur.states)); mInitialAcquireWakeName = null; mInitialAcquireWakeUid = -1; - addHistoryRecordLocked(elapsedRealtime, uptime); + addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs); } } if (uid >= 0) { @@ -4331,7 +4501,8 @@ public class BatteryStatsImpl extends BatteryStats { requestWakelockCpuUpdate(); } - getUidStatsLocked(uid).noteStopWakeLocked(pid, name, type, elapsedRealtime); + getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs) + .noteStopWakeLocked(pid, name, type, elapsedRealtimeMs); if (wc != null) { FrameworkStatsLog.write(FrameworkStatsLog.WAKELOCK_STATE_CHANGED, wc.getUids(), wc.getTags(), getPowerManagerWakeLockLevel(type), name, @@ -4377,12 +4548,17 @@ public class BatteryStatsImpl extends BatteryStats { public void noteStartWakeFromSourceLocked(WorkSource ws, int pid, String name, String historyName, int type, boolean unimportantForLogging) { - final long elapsedRealtime = mClocks.elapsedRealtime(); - final long uptime = mClocks.uptimeMillis(); + noteStartWakeFromSourceLocked(ws, pid, name, historyName, type, unimportantForLogging, + mClocks.elapsedRealtime(), mClocks.uptimeMillis()); + } + + public void noteStartWakeFromSourceLocked(WorkSource ws, int pid, String name, + String historyName, int type, boolean unimportantForLogging, + long elapsedRealtimeMs, long uptimeMs) { final int N = ws.size(); for (int i=0; i<N; i++) { noteStartWakeLocked(ws.getUid(i), pid, null, name, historyName, type, - unimportantForLogging, elapsedRealtime, uptime); + unimportantForLogging, elapsedRealtimeMs, uptimeMs); } List<WorkChain> wcs = ws.getWorkChains(); @@ -4390,7 +4566,7 @@ public class BatteryStatsImpl extends BatteryStats { for (int i = 0; i < wcs.size(); ++i) { final WorkChain wc = wcs.get(i); noteStartWakeLocked(wc.getAttributionUid(), pid, wc, name, historyName, type, - unimportantForLogging, elapsedRealtime, uptime); + unimportantForLogging, elapsedRealtimeMs, uptimeMs); } } } @@ -4398,9 +4574,15 @@ public class BatteryStatsImpl extends BatteryStats { public void noteChangeWakelockFromSourceLocked(WorkSource ws, int pid, String name, String historyName, int type, WorkSource newWs, int newPid, String newName, String newHistoryName, int newType, boolean newUnimportantForLogging) { - final long elapsedRealtime = mClocks.elapsedRealtime(); - final long uptime = mClocks.uptimeMillis(); + noteChangeWakelockFromSourceLocked(ws, pid, name, historyName, type, newWs, newPid, + newName, newHistoryName, newType, newUnimportantForLogging, + mClocks.elapsedRealtime(), mClocks.uptimeMillis()); + } + public void noteChangeWakelockFromSourceLocked(WorkSource ws, int pid, String name, + String historyName, int type, WorkSource newWs, int newPid, String newName, + String newHistoryName, int newType, boolean newUnimportantForLogging, + long elapsedRealtimeMs, long uptimeMs) { List<WorkChain>[] wcs = WorkSource.diffChains(ws, newWs); // For correct semantics, we start the need worksources first, so that we won't @@ -4411,7 +4593,7 @@ public class BatteryStatsImpl extends BatteryStats { final int NN = newWs.size(); for (int i=0; i<NN; i++) { noteStartWakeLocked(newWs.getUid(i), newPid, null, newName, newHistoryName, newType, - newUnimportantForLogging, elapsedRealtime, uptime); + newUnimportantForLogging, elapsedRealtimeMs, uptimeMs); } if (wcs != null) { List<WorkChain> newChains = wcs[0]; @@ -4419,8 +4601,8 @@ public class BatteryStatsImpl extends BatteryStats { for (int i = 0; i < newChains.size(); ++i) { final WorkChain newChain = newChains.get(i); noteStartWakeLocked(newChain.getAttributionUid(), newPid, newChain, newName, - newHistoryName, newType, newUnimportantForLogging, elapsedRealtime, - uptime); + newHistoryName, newType, newUnimportantForLogging, elapsedRealtimeMs, + uptimeMs); } } } @@ -4428,8 +4610,8 @@ public class BatteryStatsImpl extends BatteryStats { // Then the stops : final int NO = ws.size(); for (int i=0; i<NO; i++) { - noteStopWakeLocked(ws.getUid(i), pid, null, name, historyName, type, elapsedRealtime, - uptime); + noteStopWakeLocked(ws.getUid(i), pid, null, name, historyName, type, elapsedRealtimeMs, + uptimeMs); } if (wcs != null) { List<WorkChain> goneChains = wcs[1]; @@ -4437,7 +4619,7 @@ public class BatteryStatsImpl extends BatteryStats { for (int i = 0; i < goneChains.size(); ++i) { final WorkChain goneChain = goneChains.get(i); noteStopWakeLocked(goneChain.getAttributionUid(), pid, goneChain, name, - historyName, type, elapsedRealtime, uptime); + historyName, type, elapsedRealtimeMs, uptimeMs); } } } @@ -4445,12 +4627,16 @@ public class BatteryStatsImpl extends BatteryStats { public void noteStopWakeFromSourceLocked(WorkSource ws, int pid, String name, String historyName, int type) { - final long elapsedRealtime = mClocks.elapsedRealtime(); - final long uptime = mClocks.uptimeMillis(); + noteStopWakeFromSourceLocked(ws, pid, name, historyName, type, + mClocks.elapsedRealtime(), mClocks.uptimeMillis()); + } + + public void noteStopWakeFromSourceLocked(WorkSource ws, int pid, String name, + String historyName, int type, long elapsedRealtimeMs, long uptimeMs) { final int N = ws.size(); for (int i=0; i<N; i++) { - noteStopWakeLocked(ws.getUid(i), pid, null, name, historyName, type, elapsedRealtime, - uptime); + noteStopWakeLocked(ws.getUid(i), pid, null, name, historyName, type, elapsedRealtimeMs, + uptimeMs); } List<WorkChain> wcs = ws.getWorkChains(); @@ -4458,22 +4644,35 @@ public class BatteryStatsImpl extends BatteryStats { for (int i = 0; i < wcs.size(); ++i) { final WorkChain wc = wcs.get(i); noteStopWakeLocked(wc.getAttributionUid(), pid, wc, name, historyName, type, - elapsedRealtime, uptime); + elapsedRealtimeMs, uptimeMs); } } } public void noteLongPartialWakelockStart(String name, String historyName, int uid) { + noteLongPartialWakelockStart(name, historyName, uid, + mClocks.elapsedRealtime(), mClocks.uptimeMillis()); + } + + public void noteLongPartialWakelockStart(String name, String historyName, int uid, + long elapsedRealtimeMs, long uptimeMs) { uid = mapUid(uid); - noteLongPartialWakeLockStartInternal(name, historyName, uid); + noteLongPartialWakeLockStartInternal(name, historyName, uid, elapsedRealtimeMs, uptimeMs); } public void noteLongPartialWakelockStartFromSource(String name, String historyName, WorkSource workSource) { + noteLongPartialWakelockStartFromSource(name, historyName, workSource, + mClocks.elapsedRealtime(), mClocks.uptimeMillis()); + } + + public void noteLongPartialWakelockStartFromSource(String name, String historyName, + WorkSource workSource, long elapsedRealtimeMs, long uptimeMs) { final int N = workSource.size(); for (int i = 0; i < N; ++i) { final int uid = mapUid(workSource.getUid(i)); - noteLongPartialWakeLockStartInternal(name, historyName, uid); + noteLongPartialWakeLockStartInternal(name, historyName, uid, + elapsedRealtimeMs, uptimeMs); } final List<WorkChain> workChains = workSource.getWorkChains(); @@ -4481,14 +4680,14 @@ public class BatteryStatsImpl extends BatteryStats { for (int i = 0; i < workChains.size(); ++i) { final WorkChain workChain = workChains.get(i); final int uid = workChain.getAttributionUid(); - noteLongPartialWakeLockStartInternal(name, historyName, uid); + noteLongPartialWakeLockStartInternal(name, historyName, uid, + elapsedRealtimeMs, uptimeMs); } } } - private void noteLongPartialWakeLockStartInternal(String name, String historyName, int uid) { - final long elapsedRealtime = mClocks.elapsedRealtime(); - final long uptime = mClocks.uptimeMillis(); + private void noteLongPartialWakeLockStartInternal(String name, String historyName, int uid, + long elapsedRealtimeMs, long uptimeMs) { if (historyName == null) { historyName = name; } @@ -4496,21 +4695,34 @@ public class BatteryStatsImpl extends BatteryStats { 0)) { return; } - addHistoryEventLocked(elapsedRealtime, uptime, HistoryItem.EVENT_LONG_WAKE_LOCK_START, + addHistoryEventLocked(elapsedRealtimeMs, uptimeMs, HistoryItem.EVENT_LONG_WAKE_LOCK_START, historyName, uid); } public void noteLongPartialWakelockFinish(String name, String historyName, int uid) { + noteLongPartialWakelockFinish(name, historyName, uid, + mClocks.elapsedRealtime(), mClocks.uptimeMillis()); + } + + public void noteLongPartialWakelockFinish(String name, String historyName, int uid, + long elapsedRealtimeMs, long uptimeMs) { uid = mapUid(uid); - noteLongPartialWakeLockFinishInternal(name, historyName, uid); + noteLongPartialWakeLockFinishInternal(name, historyName, uid, elapsedRealtimeMs, uptimeMs); } public void noteLongPartialWakelockFinishFromSource(String name, String historyName, WorkSource workSource) { + noteLongPartialWakelockFinishFromSource(name, historyName, workSource, + mClocks.elapsedRealtime(), mClocks.uptimeMillis()); + } + + public void noteLongPartialWakelockFinishFromSource(String name, String historyName, + WorkSource workSource, long elapsedRealtimeMs, long uptimeMs) { final int N = workSource.size(); for (int i = 0; i < N; ++i) { final int uid = mapUid(workSource.getUid(i)); - noteLongPartialWakeLockFinishInternal(name, historyName, uid); + noteLongPartialWakeLockFinishInternal(name, historyName, uid, + elapsedRealtimeMs, uptimeMs); } final List<WorkChain> workChains = workSource.getWorkChains(); @@ -4518,14 +4730,14 @@ public class BatteryStatsImpl extends BatteryStats { for (int i = 0; i < workChains.size(); ++i) { final WorkChain workChain = workChains.get(i); final int uid = workChain.getAttributionUid(); - noteLongPartialWakeLockFinishInternal(name, historyName, uid); + noteLongPartialWakeLockFinishInternal(name, historyName, uid, + elapsedRealtimeMs, uptimeMs); } } } - private void noteLongPartialWakeLockFinishInternal(String name, String historyName, int uid) { - final long elapsedRealtime = mClocks.elapsedRealtime(); - final long uptime = mClocks.uptimeMillis(); + private void noteLongPartialWakeLockFinishInternal(String name, String historyName, int uid, + long elapsedRealtimeMs, long uptimeMs) { if (historyName == null) { historyName = name; } @@ -4533,33 +4745,35 @@ public class BatteryStatsImpl extends BatteryStats { 0)) { return; } - addHistoryEventLocked(elapsedRealtime, uptime, HistoryItem.EVENT_LONG_WAKE_LOCK_FINISH, + addHistoryEventLocked(elapsedRealtimeMs, uptimeMs, HistoryItem.EVENT_LONG_WAKE_LOCK_FINISH, historyName, uid); } - void aggregateLastWakeupUptimeLocked(long uptimeMs) { + void aggregateLastWakeupUptimeLocked(long elapsedRealtimeMs, long uptimeMs) { if (mLastWakeupReason != null) { - long deltaUptime = uptimeMs - mLastWakeupUptimeMs; + long deltaUptimeMs = uptimeMs - mLastWakeupUptimeMs; SamplingTimer timer = getWakeupReasonTimerLocked(mLastWakeupReason); - timer.add(deltaUptime * 1000, 1); // time in in microseconds + timer.add(deltaUptimeMs * 1000, 1, elapsedRealtimeMs); // time in in microseconds FrameworkStatsLog.write(FrameworkStatsLog.KERNEL_WAKEUP_REPORTED, mLastWakeupReason, - /* duration_usec */ deltaUptime * 1000); + /* duration_usec */ deltaUptimeMs * 1000); mLastWakeupReason = null; } } public void noteWakeupReasonLocked(String reason) { - final long elapsedRealtime = mClocks.elapsedRealtime(); - final long uptime = mClocks.uptimeMillis(); + noteWakeupReasonLocked(reason, mClocks.elapsedRealtime(), mClocks.uptimeMillis()); + } + + public void noteWakeupReasonLocked(String reason, long elapsedRealtimeMs, long uptimeMs) { if (DEBUG_HISTORY) Slog.v(TAG, "Wakeup reason \"" + reason +"\": " + Integer.toHexString(mHistoryCur.states)); - aggregateLastWakeupUptimeLocked(uptime); + aggregateLastWakeupUptimeLocked(elapsedRealtimeMs, uptimeMs); mHistoryCur.wakeReasonTag = mHistoryCur.localWakeReasonTag; mHistoryCur.wakeReasonTag.string = reason; mHistoryCur.wakeReasonTag.uid = 0; mLastWakeupReason = reason; - mLastWakeupUptimeMs = uptime; - addHistoryRecordLocked(elapsedRealtime, uptime); + mLastWakeupUptimeMs = uptimeMs; + addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs); } public boolean startAddingCpuLocked() { @@ -4567,21 +4781,23 @@ public class BatteryStatsImpl extends BatteryStats { return mOnBatteryInternal; } - public void finishAddingCpuLocked(int totalUTime, int totalSTime, int statUserTime, - int statSystemTime, int statIOWaitTime, int statIrqTime, - int statSoftIrqTime, int statIdleTime) { - if (DEBUG) Slog.d(TAG, "Adding cpu: tuser=" + totalUTime + " tsys=" + totalSTime - + " user=" + statUserTime + " sys=" + statSystemTime - + " io=" + statIOWaitTime + " irq=" + statIrqTime - + " sirq=" + statSoftIrqTime + " idle=" + statIdleTime); - mCurStepCpuUserTime += totalUTime; - mCurStepCpuSystemTime += totalSTime; - mCurStepStatUserTime += statUserTime; - mCurStepStatSystemTime += statSystemTime; - mCurStepStatIOWaitTime += statIOWaitTime; - mCurStepStatIrqTime += statIrqTime; - mCurStepStatSoftIrqTime += statSoftIrqTime; - mCurStepStatIdleTime += statIdleTime; + public void finishAddingCpuLocked(int totalUTimeMs, int totalSTimeMs, int statUserTimeMs, + int statSystemTimeMs, int statIOWaitTimeMs, int statIrqTimeMs, + int statSoftIrqTimeMs, int statIdleTimeMs) { + if (DEBUG) { + Slog.d(TAG, "Adding cpu: tuser=" + totalUTimeMs + " tsys=" + totalSTimeMs + + " user=" + statUserTimeMs + " sys=" + statSystemTimeMs + + " io=" + statIOWaitTimeMs + " irq=" + statIrqTimeMs + + " sirq=" + statSoftIrqTimeMs + " idle=" + statIdleTimeMs); + } + mCurStepCpuUserTimeMs += totalUTimeMs; + mCurStepCpuSystemTimeMs += totalSTimeMs; + mCurStepStatUserTimeMs += statUserTimeMs; + mCurStepStatSystemTimeMs += statSystemTimeMs; + mCurStepStatIOWaitTimeMs += statIOWaitTimeMs; + mCurStepStatIrqTimeMs += statIrqTimeMs; + mCurStepStatSoftIrqTimeMs += statSoftIrqTimeMs; + mCurStepStatIdleTimeMs += statIdleTimeMs; } public void noteProcessDiedLocked(int uid, int pid) { @@ -4592,65 +4808,76 @@ public class BatteryStatsImpl extends BatteryStats { } } - public long getProcessWakeTime(int uid, int pid, long realtime) { + public long getProcessWakeTime(int uid, int pid, long realtimeMs) { uid = mapUid(uid); Uid u = mUidStats.get(uid); if (u != null) { Uid.Pid p = u.mPids.get(pid); if (p != null) { - return p.mWakeSumMs + (p.mWakeNesting > 0 ? (realtime - p.mWakeStartMs) : 0); + return p.mWakeSumMs + (p.mWakeNesting > 0 ? (realtimeMs - p.mWakeStartMs) : 0); } } return 0; } - public void reportExcessiveCpuLocked(int uid, String proc, long overTime, long usedTime) { + public void reportExcessiveCpuLocked(int uid, String proc, long overTimeMs, long usedTimeMs) { uid = mapUid(uid); Uid u = mUidStats.get(uid); if (u != null) { - u.reportExcessiveCpuLocked(proc, overTime, usedTime); + u.reportExcessiveCpuLocked(proc, overTimeMs, usedTimeMs); } } int mSensorNesting; public void noteStartSensorLocked(int uid, int sensor) { + noteStartSensorLocked(uid, sensor, mClocks.elapsedRealtime(), mClocks.uptimeMillis()); + } + + public void noteStartSensorLocked(int uid, int sensor, long elapsedRealtimeMs, long uptimeMs) { uid = mapUid(uid); - final long elapsedRealtime = mClocks.elapsedRealtime(); - final long uptime = mClocks.uptimeMillis(); if (mSensorNesting == 0) { mHistoryCur.states |= HistoryItem.STATE_SENSOR_ON_FLAG; if (DEBUG_HISTORY) Slog.v(TAG, "Start sensor to: " + Integer.toHexString(mHistoryCur.states)); - addHistoryRecordLocked(elapsedRealtime, uptime); + addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs); } mSensorNesting++; - getUidStatsLocked(uid).noteStartSensor(sensor, elapsedRealtime); + getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs) + .noteStartSensor(sensor, elapsedRealtimeMs); } public void noteStopSensorLocked(int uid, int sensor) { + noteStopSensorLocked(uid, sensor, mClocks.elapsedRealtime(), mClocks.uptimeMillis()); + } + + public void noteStopSensorLocked(int uid, int sensor, long elapsedRealtimeMs, long uptimeMs) { uid = mapUid(uid); - final long elapsedRealtime = mClocks.elapsedRealtime(); - final long uptime = mClocks.uptimeMillis(); mSensorNesting--; if (mSensorNesting == 0) { mHistoryCur.states &= ~HistoryItem.STATE_SENSOR_ON_FLAG; if (DEBUG_HISTORY) Slog.v(TAG, "Stop sensor to: " + Integer.toHexString(mHistoryCur.states)); - addHistoryRecordLocked(elapsedRealtime, uptime); + addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs); } - getUidStatsLocked(uid).noteStopSensor(sensor, elapsedRealtime); + getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs) + .noteStopSensor(sensor, elapsedRealtimeMs); } int mGpsNesting; public void noteGpsChangedLocked(WorkSource oldWs, WorkSource newWs) { + noteGpsChangedLocked(oldWs, newWs, mClocks.elapsedRealtime(), mClocks.uptimeMillis()); + } + + public void noteGpsChangedLocked(WorkSource oldWs, WorkSource newWs, + long elapsedRealtimeMs, long uptimeMs) { for (int i = 0; i < newWs.size(); ++i) { - noteStartGpsLocked(newWs.getUid(i), null); + noteStartGpsLocked(newWs.getUid(i), null, elapsedRealtimeMs, uptimeMs); } for (int i = 0; i < oldWs.size(); ++i) { - noteStopGpsLocked((oldWs.getUid(i)), null); + noteStopGpsLocked((oldWs.getUid(i)), null, elapsedRealtimeMs, uptimeMs); } List<WorkChain>[] wcs = WorkSource.diffChains(oldWs, newWs); @@ -4658,28 +4885,27 @@ public class BatteryStatsImpl extends BatteryStats { if (wcs[0] != null) { final List<WorkChain> newChains = wcs[0]; for (int i = 0; i < newChains.size(); ++i) { - noteStartGpsLocked(-1, newChains.get(i)); + noteStartGpsLocked(-1, newChains.get(i), elapsedRealtimeMs, uptimeMs); } } if (wcs[1] != null) { final List<WorkChain> goneChains = wcs[1]; for (int i = 0; i < goneChains.size(); ++i) { - noteStopGpsLocked(-1, goneChains.get(i)); + noteStopGpsLocked(-1, goneChains.get(i), elapsedRealtimeMs, uptimeMs); } } } } - private void noteStartGpsLocked(int uid, WorkChain workChain) { + private void noteStartGpsLocked(int uid, WorkChain workChain, + long elapsedRealtimeMs, long uptimeMs) { uid = getAttributionUid(uid, workChain); - final long elapsedRealtime = mClocks.elapsedRealtime(); - final long uptime = mClocks.uptimeMillis(); if (mGpsNesting == 0) { mHistoryCur.states |= HistoryItem.STATE_GPS_ON_FLAG; if (DEBUG_HISTORY) Slog.v(TAG, "Start GPS to: " + Integer.toHexString(mHistoryCur.states)); - addHistoryRecordLocked(elapsedRealtime, uptime); + addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs); } mGpsNesting++; @@ -4692,20 +4918,19 @@ public class BatteryStatsImpl extends BatteryStats { FrameworkStatsLog.GPS_SCAN_STATE_CHANGED__STATE__ON); } - getUidStatsLocked(uid).noteStartGps(elapsedRealtime); + getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs).noteStartGps(elapsedRealtimeMs); } - private void noteStopGpsLocked(int uid, WorkChain workChain) { + private void noteStopGpsLocked(int uid, WorkChain workChain, + long elapsedRealtimeMs, long uptimeMs) { uid = getAttributionUid(uid, workChain); - final long elapsedRealtime = mClocks.elapsedRealtime(); - final long uptime = mClocks.uptimeMillis(); mGpsNesting--; if (mGpsNesting == 0) { mHistoryCur.states &= ~HistoryItem.STATE_GPS_ON_FLAG; if (DEBUG_HISTORY) Slog.v(TAG, "Stop GPS to: " + Integer.toHexString(mHistoryCur.states)); - addHistoryRecordLocked(elapsedRealtime, uptime); - stopAllGpsSignalQualityTimersLocked(-1); + addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs); + stopAllGpsSignalQualityTimersLocked(-1, elapsedRealtimeMs); mGpsSignalQualityBin = -1; } @@ -4717,29 +4942,31 @@ public class BatteryStatsImpl extends BatteryStats { workChain.getTags(), FrameworkStatsLog.GPS_SCAN_STATE_CHANGED__STATE__OFF); } - getUidStatsLocked(uid).noteStopGps(elapsedRealtime); + getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs).noteStopGps(elapsedRealtimeMs); } public void noteGpsSignalQualityLocked(int signalLevel) { + noteGpsSignalQualityLocked(signalLevel, mClocks.elapsedRealtime(), mClocks.uptimeMillis()); + } + + public void noteGpsSignalQualityLocked(int signalLevel, long elapsedRealtimeMs, long uptimeMs) { if (mGpsNesting == 0) { return; } if (signalLevel < 0 || signalLevel >= GnssMetrics.NUM_GPS_SIGNAL_QUALITY_LEVELS) { - stopAllGpsSignalQualityTimersLocked(-1); + stopAllGpsSignalQualityTimersLocked(-1, elapsedRealtimeMs); return; } - final long elapsedRealtime = mClocks.elapsedRealtime(); - final long uptime = mClocks.uptimeMillis(); if (mGpsSignalQualityBin != signalLevel) { if (mGpsSignalQualityBin >= 0) { - mGpsSignalQualityTimer[mGpsSignalQualityBin].stopRunningLocked(elapsedRealtime); + mGpsSignalQualityTimer[mGpsSignalQualityBin].stopRunningLocked(elapsedRealtimeMs); } if(!mGpsSignalQualityTimer[signalLevel].isRunningLocked()) { - mGpsSignalQualityTimer[signalLevel].startRunningLocked(elapsedRealtime); + mGpsSignalQualityTimer[signalLevel].startRunningLocked(elapsedRealtimeMs); } mHistoryCur.states2 = (mHistoryCur.states2&~HistoryItem.STATE2_GPS_SIGNAL_QUALITY_MASK) | (signalLevel << HistoryItem.STATE2_GPS_SIGNAL_QUALITY_SHIFT); - addHistoryRecordLocked(elapsedRealtime, uptime); + addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs); mGpsSignalQualityBin = signalLevel; } return; @@ -4747,6 +4974,13 @@ public class BatteryStatsImpl extends BatteryStats { @GuardedBy("this") public void noteScreenStateLocked(int state) { + noteScreenStateLocked(state, mClocks.elapsedRealtime(), mClocks.uptimeMillis(), + System.currentTimeMillis()); + } + + @GuardedBy("this") + public void noteScreenStateLocked(int state, + long elapsedRealtimeMs, long uptimeMs, long currentTimeMs) { state = mPretendScreenOff ? Display.STATE_OFF : state; // Battery stats relies on there being 4 states. To accommodate this, new states beyond the @@ -4763,7 +4997,7 @@ public class BatteryStatsImpl extends BatteryStats { } if (mScreenState != state) { - recordDailyStatsIfNeededLocked(true); + recordDailyStatsIfNeededLocked(true, currentTimeMs); final int oldState = mScreenState; mScreenState = state; if (DEBUG) Slog.v(TAG, "Screen state: oldState=" + Display.stateToString(oldState) @@ -4779,56 +5013,55 @@ public class BatteryStatsImpl extends BatteryStats { } } - final long elapsedRealtime = mClocks.elapsedRealtime(); - final long uptime = mClocks.uptimeMillis(); - boolean updateHistory = false; if (isScreenDoze(state) && !isScreenDoze(oldState)) { mHistoryCur.states |= HistoryItem.STATE_SCREEN_DOZE_FLAG; - mScreenDozeTimer.startRunningLocked(elapsedRealtime); + mScreenDozeTimer.startRunningLocked(elapsedRealtimeMs); updateHistory = true; } else if (isScreenDoze(oldState) && !isScreenDoze(state)) { mHistoryCur.states &= ~HistoryItem.STATE_SCREEN_DOZE_FLAG; - mScreenDozeTimer.stopRunningLocked(elapsedRealtime); + mScreenDozeTimer.stopRunningLocked(elapsedRealtimeMs); updateHistory = true; } if (isScreenOn(state)) { mHistoryCur.states |= HistoryItem.STATE_SCREEN_ON_FLAG; if (DEBUG_HISTORY) Slog.v(TAG, "Screen on to: " + Integer.toHexString(mHistoryCur.states)); - mScreenOnTimer.startRunningLocked(elapsedRealtime); + mScreenOnTimer.startRunningLocked(elapsedRealtimeMs); if (mScreenBrightnessBin >= 0) { - mScreenBrightnessTimer[mScreenBrightnessBin].startRunningLocked(elapsedRealtime); + mScreenBrightnessTimer[mScreenBrightnessBin] + .startRunningLocked(elapsedRealtimeMs); } updateHistory = true; } else if (isScreenOn(oldState)) { mHistoryCur.states &= ~HistoryItem.STATE_SCREEN_ON_FLAG; if (DEBUG_HISTORY) Slog.v(TAG, "Screen off to: " + Integer.toHexString(mHistoryCur.states)); - mScreenOnTimer.stopRunningLocked(elapsedRealtime); + mScreenOnTimer.stopRunningLocked(elapsedRealtimeMs); if (mScreenBrightnessBin >= 0) { - mScreenBrightnessTimer[mScreenBrightnessBin].stopRunningLocked(elapsedRealtime); + mScreenBrightnessTimer[mScreenBrightnessBin] + .stopRunningLocked(elapsedRealtimeMs); } updateHistory = true; } if (updateHistory) { if (DEBUG_HISTORY) Slog.v(TAG, "Screen state to: " + Display.stateToString(state)); - addHistoryRecordLocked(elapsedRealtime, uptime); + addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs); } mExternalSync.scheduleCpuSyncDueToScreenStateChange( mOnBatteryTimeBase.isRunning(), mOnBatteryScreenOffTimeBase.isRunning()); if (isScreenOn(state)) { updateTimeBasesLocked(mOnBatteryTimeBase.isRunning(), state, - mClocks.uptimeMillis() * 1000, elapsedRealtime * 1000); + uptimeMs * 1000, elapsedRealtimeMs * 1000); // Fake a wake lock, so we consider the device waked as long as the screen is on. noteStartWakeLocked(-1, -1, null, "screen", null, WAKE_TYPE_PARTIAL, false, - elapsedRealtime, uptime); + elapsedRealtimeMs, uptimeMs); } else if (isScreenOn(oldState)) { noteStopWakeLocked(-1, -1, null, "screen", "screen", WAKE_TYPE_PARTIAL, - elapsedRealtime, uptime); + elapsedRealtimeMs, uptimeMs); updateTimeBasesLocked(mOnBatteryTimeBase.isRunning(), state, - mClocks.uptimeMillis() * 1000, elapsedRealtime * 1000); + uptimeMs * 1000, elapsedRealtimeMs * 1000); } // Update discharge amounts. if (mOnBatteryInternal) { @@ -4839,23 +5072,27 @@ public class BatteryStatsImpl extends BatteryStats { @UnsupportedAppUsage public void noteScreenBrightnessLocked(int brightness) { + noteScreenBrightnessLocked(brightness, mClocks.elapsedRealtime(), mClocks.uptimeMillis()); + } + + public void noteScreenBrightnessLocked(int brightness, long elapsedRealtimeMs, long uptimeMs) { // Bin the brightness. int bin = brightness / (256/NUM_SCREEN_BRIGHTNESS_BINS); if (bin < 0) bin = 0; else if (bin >= NUM_SCREEN_BRIGHTNESS_BINS) bin = NUM_SCREEN_BRIGHTNESS_BINS-1; if (mScreenBrightnessBin != bin) { - final long elapsedRealtime = mClocks.elapsedRealtime(); - final long uptime = mClocks.uptimeMillis(); mHistoryCur.states = (mHistoryCur.states&~HistoryItem.STATE_BRIGHTNESS_MASK) | (bin << HistoryItem.STATE_BRIGHTNESS_SHIFT); if (DEBUG_HISTORY) Slog.v(TAG, "Screen brightness " + bin + " to: " + Integer.toHexString(mHistoryCur.states)); - addHistoryRecordLocked(elapsedRealtime, uptime); + addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs); if (mScreenState == Display.STATE_ON) { if (mScreenBrightnessBin >= 0) { - mScreenBrightnessTimer[mScreenBrightnessBin].stopRunningLocked(elapsedRealtime); + mScreenBrightnessTimer[mScreenBrightnessBin] + .stopRunningLocked(elapsedRealtimeMs); } - mScreenBrightnessTimer[bin].startRunningLocked(elapsedRealtime); + mScreenBrightnessTimer[bin] + .startRunningLocked(elapsedRealtimeMs); } mScreenBrightnessBin = bin; } @@ -4863,36 +5100,50 @@ public class BatteryStatsImpl extends BatteryStats { @UnsupportedAppUsage public void noteUserActivityLocked(int uid, int event) { + noteUserActivityLocked(uid, event, mClocks.elapsedRealtime(), mClocks.uptimeMillis()); + } + + public void noteUserActivityLocked(int uid, int event, long elapsedRealtimeMs, long uptimeMs) { if (mOnBatteryInternal) { uid = mapUid(uid); - getUidStatsLocked(uid).noteUserActivityLocked(event); + getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs).noteUserActivityLocked(event); } } public void noteWakeUpLocked(String reason, int reasonUid) { - final long elapsedRealtime = mClocks.elapsedRealtime(); - final long uptime = mClocks.uptimeMillis(); - addHistoryEventLocked(elapsedRealtime, uptime, HistoryItem.EVENT_SCREEN_WAKE_UP, + noteWakeUpLocked(reason, reasonUid, mClocks.elapsedRealtime(), mClocks.uptimeMillis()); + } + + public void noteWakeUpLocked(String reason, int reasonUid, + long elapsedRealtimeMs, long uptimeMs) { + addHistoryEventLocked(elapsedRealtimeMs, uptimeMs, HistoryItem.EVENT_SCREEN_WAKE_UP, reason, reasonUid); } public void noteInteractiveLocked(boolean interactive) { + noteInteractiveLocked(interactive, mClocks.elapsedRealtime()); + } + + public void noteInteractiveLocked(boolean interactive, long elapsedRealtimeMs) { if (mInteractive != interactive) { - final long elapsedRealtime = mClocks.elapsedRealtime(); mInteractive = interactive; if (DEBUG) Slog.v(TAG, "Interactive: " + interactive); if (interactive) { - mInteractiveTimer.startRunningLocked(elapsedRealtime); + mInteractiveTimer.startRunningLocked(elapsedRealtimeMs); } else { - mInteractiveTimer.stopRunningLocked(elapsedRealtime); + mInteractiveTimer.stopRunningLocked(elapsedRealtimeMs); } } } public void noteConnectivityChangedLocked(int type, String extra) { - final long elapsedRealtime = mClocks.elapsedRealtime(); - final long uptime = mClocks.uptimeMillis(); - addHistoryEventLocked(elapsedRealtime, uptime, HistoryItem.EVENT_CONNECTIVITY_CHANGED, + noteConnectivityChangedLocked(type, extra, + mClocks.elapsedRealtime(), mClocks.uptimeMillis()); + } + + public void noteConnectivityChangedLocked(int type, String extra, + long elapsedRealtimeMs, long uptimeMs) { + addHistoryEventLocked(elapsedRealtimeMs, uptimeMs, HistoryItem.EVENT_CONNECTIVITY_CHANGED, extra, type); mNumConnectivityChange++; } @@ -4902,15 +5153,19 @@ public class BatteryStatsImpl extends BatteryStats { uid = mapUid(uid); addHistoryEventLocked(elapsedRealtimeMillis, uptimeMillis, HistoryItem.EVENT_WAKEUP_AP, "", uid); - getUidStatsLocked(uid).noteMobileRadioApWakeupLocked(); + getUidStatsLocked(uid, elapsedRealtimeMillis, uptimeMillis).noteMobileRadioApWakeupLocked(); } /** * Updates the radio power state and returns true if an external stats collection should occur. */ public boolean noteMobileRadioPowerStateLocked(int powerState, long timestampNs, int uid) { - final long elapsedRealtime = mClocks.elapsedRealtime(); - final long uptime = mClocks.uptimeMillis(); + return noteMobileRadioPowerStateLocked(powerState, timestampNs, uid, + mClocks.elapsedRealtime(), mClocks.uptimeMillis()); + } + + public boolean noteMobileRadioPowerStateLocked(int powerState, long timestampNs, int uid, + long elapsedRealtimeMs, long uptimeMs) { if (mMobileRadioPowerState != powerState) { long realElapsedRealtimeMs; final boolean active = @@ -4918,31 +5173,31 @@ public class BatteryStatsImpl extends BatteryStats { || powerState == DataConnectionRealTimeInfo.DC_POWER_STATE_HIGH; if (active) { if (uid > 0) { - noteMobileRadioApWakeupLocked(elapsedRealtime, uptime, uid); + noteMobileRadioApWakeupLocked(elapsedRealtimeMs, uptimeMs, uid); } - mMobileRadioActiveStartTime = realElapsedRealtimeMs = timestampNs / (1000 * 1000); + mMobileRadioActiveStartTimeMs = realElapsedRealtimeMs = timestampNs / (1000 * 1000); mHistoryCur.states |= HistoryItem.STATE_MOBILE_RADIO_ACTIVE_FLAG; } else { realElapsedRealtimeMs = timestampNs / (1000*1000); - long lastUpdateTimeMs = mMobileRadioActiveStartTime; + long lastUpdateTimeMs = mMobileRadioActiveStartTimeMs; if (realElapsedRealtimeMs < lastUpdateTimeMs) { Slog.wtf(TAG, "Data connection inactive timestamp " + realElapsedRealtimeMs + " is before start time " + lastUpdateTimeMs); - realElapsedRealtimeMs = elapsedRealtime; - } else if (realElapsedRealtimeMs < elapsedRealtime) { - mMobileRadioActiveAdjustedTime.addCountLocked(elapsedRealtime + realElapsedRealtimeMs = elapsedRealtimeMs; + } else if (realElapsedRealtimeMs < elapsedRealtimeMs) { + mMobileRadioActiveAdjustedTime.addCountLocked(elapsedRealtimeMs - realElapsedRealtimeMs); } mHistoryCur.states &= ~HistoryItem.STATE_MOBILE_RADIO_ACTIVE_FLAG; } if (DEBUG_HISTORY) Slog.v(TAG, "Mobile network active " + active + " to: " + Integer.toHexString(mHistoryCur.states)); - addHistoryRecordLocked(elapsedRealtime, uptime); + addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs); mMobileRadioPowerState = powerState; if (active) { - mMobileRadioActiveTimer.startRunningLocked(elapsedRealtime); - mMobileRadioActivePerAppTimer.startRunningLocked(elapsedRealtime); + mMobileRadioActiveTimer.startRunningLocked(elapsedRealtimeMs); + mMobileRadioActivePerAppTimer.startRunningLocked(elapsedRealtimeMs); } else { mMobileRadioActiveTimer.stopRunningLocked(realElapsedRealtimeMs); mMobileRadioActivePerAppTimer.stopRunningLocked(realElapsedRealtimeMs); @@ -4954,25 +5209,27 @@ public class BatteryStatsImpl extends BatteryStats { } public void notePowerSaveModeLocked(boolean enabled) { + notePowerSaveModeLocked(enabled, mClocks.elapsedRealtime(), mClocks.uptimeMillis()); + } + + public void notePowerSaveModeLocked(boolean enabled, long elapsedRealtimeMs, long uptimeMs) { if (mPowerSaveModeEnabled != enabled) { int stepState = enabled ? STEP_LEVEL_MODE_POWER_SAVE : 0; mModStepMode |= (mCurStepMode&STEP_LEVEL_MODE_POWER_SAVE) ^ stepState; mCurStepMode = (mCurStepMode&~STEP_LEVEL_MODE_POWER_SAVE) | stepState; - final long elapsedRealtime = mClocks.elapsedRealtime(); - final long uptime = mClocks.uptimeMillis(); mPowerSaveModeEnabled = enabled; if (enabled) { mHistoryCur.states2 |= HistoryItem.STATE2_POWER_SAVE_FLAG; if (DEBUG_HISTORY) Slog.v(TAG, "Power save mode enabled to: " + Integer.toHexString(mHistoryCur.states2)); - mPowerSaveModeEnabledTimer.startRunningLocked(elapsedRealtime); + mPowerSaveModeEnabledTimer.startRunningLocked(elapsedRealtimeMs); } else { mHistoryCur.states2 &= ~HistoryItem.STATE2_POWER_SAVE_FLAG; if (DEBUG_HISTORY) Slog.v(TAG, "Power save mode disabled to: " + Integer.toHexString(mHistoryCur.states2)); - mPowerSaveModeEnabledTimer.stopRunningLocked(elapsedRealtime); + mPowerSaveModeEnabledTimer.stopRunningLocked(elapsedRealtimeMs); } - addHistoryRecordLocked(elapsedRealtime, uptime); + addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs); FrameworkStatsLog.write(FrameworkStatsLog.BATTERY_SAVER_MODE_STATE_CHANGED, enabled ? FrameworkStatsLog.BATTERY_SAVER_MODE_STATE_CHANGED__STATE__ON @@ -4981,8 +5238,12 @@ public class BatteryStatsImpl extends BatteryStats { } public void noteDeviceIdleModeLocked(final int mode, String activeReason, int activeUid) { - final long elapsedRealtime = mClocks.elapsedRealtime(); - final long uptime = mClocks.uptimeMillis(); + noteDeviceIdleModeLocked(mode, activeReason, activeUid, + mClocks.elapsedRealtime(), mClocks.uptimeMillis()); + } + + public void noteDeviceIdleModeLocked(final int mode, String activeReason, int activeUid, + long elapsedRealtimeMs, long uptimeMs) { boolean nowIdling = mode == DEVICE_IDLE_MODE_DEEP; if (mDeviceIdling && !nowIdling && activeReason == null) { // We don't go out of general idling mode until explicitly taken out of @@ -4996,7 +5257,7 @@ public class BatteryStatsImpl extends BatteryStats { nowLightIdling = true; } if (activeReason != null && (mDeviceIdling || mDeviceLightIdling)) { - addHistoryEventLocked(elapsedRealtime, uptime, HistoryItem.EVENT_ACTIVE, + addHistoryEventLocked(elapsedRealtimeMs, uptimeMs, HistoryItem.EVENT_ACTIVE, activeReason, activeUid); } if (mDeviceIdling != nowIdling || mDeviceLightIdling != nowLightIdling) { @@ -5012,17 +5273,17 @@ public class BatteryStatsImpl extends BatteryStats { mModStepMode |= (mCurStepMode&STEP_LEVEL_MODE_DEVICE_IDLE) ^ stepState; mCurStepMode = (mCurStepMode&~STEP_LEVEL_MODE_DEVICE_IDLE) | stepState; if (nowIdling) { - mDeviceIdlingTimer.startRunningLocked(elapsedRealtime); + mDeviceIdlingTimer.startRunningLocked(elapsedRealtimeMs); } else { - mDeviceIdlingTimer.stopRunningLocked(elapsedRealtime); + mDeviceIdlingTimer.stopRunningLocked(elapsedRealtimeMs); } } if (mDeviceLightIdling != nowLightIdling) { mDeviceLightIdling = nowLightIdling; if (nowLightIdling) { - mDeviceLightIdlingTimer.startRunningLocked(elapsedRealtime); + mDeviceLightIdlingTimer.startRunningLocked(elapsedRealtimeMs); } else { - mDeviceLightIdlingTimer.stopRunningLocked(elapsedRealtime); + mDeviceLightIdlingTimer.stopRunningLocked(elapsedRealtimeMs); } } if (mDeviceIdleMode != mode) { @@ -5030,24 +5291,24 @@ public class BatteryStatsImpl extends BatteryStats { | (mode << HistoryItem.STATE2_DEVICE_IDLE_SHIFT); if (DEBUG_HISTORY) Slog.v(TAG, "Device idle mode changed to: " + Integer.toHexString(mHistoryCur.states2)); - addHistoryRecordLocked(elapsedRealtime, uptime); - long lastDuration = elapsedRealtime - mLastIdleTimeStart; - mLastIdleTimeStart = elapsedRealtime; + addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs); + long lastDuration = elapsedRealtimeMs - mLastIdleTimeStartMs; + mLastIdleTimeStartMs = elapsedRealtimeMs; if (mDeviceIdleMode == DEVICE_IDLE_MODE_LIGHT) { - if (lastDuration > mLongestLightIdleTime) { - mLongestLightIdleTime = lastDuration; + if (lastDuration > mLongestLightIdleTimeMs) { + mLongestLightIdleTimeMs = lastDuration; } - mDeviceIdleModeLightTimer.stopRunningLocked(elapsedRealtime); + mDeviceIdleModeLightTimer.stopRunningLocked(elapsedRealtimeMs); } else if (mDeviceIdleMode == DEVICE_IDLE_MODE_DEEP) { - if (lastDuration > mLongestFullIdleTime) { - mLongestFullIdleTime = lastDuration; + if (lastDuration > mLongestFullIdleTimeMs) { + mLongestFullIdleTimeMs = lastDuration; } - mDeviceIdleModeFullTimer.stopRunningLocked(elapsedRealtime); + mDeviceIdleModeFullTimer.stopRunningLocked(elapsedRealtimeMs); } if (mode == DEVICE_IDLE_MODE_LIGHT) { - mDeviceIdleModeLightTimer.startRunningLocked(elapsedRealtime); + mDeviceIdleModeLightTimer.startRunningLocked(elapsedRealtimeMs); } else if (mode == DEVICE_IDLE_MODE_DEEP) { - mDeviceIdleModeFullTimer.startRunningLocked(elapsedRealtime); + mDeviceIdleModeFullTimer.startRunningLocked(elapsedRealtimeMs); } mDeviceIdleMode = mode; FrameworkStatsLog.write(FrameworkStatsLog.DEVICE_IDLE_MODE_STATE_CHANGED, mode); @@ -5055,10 +5316,14 @@ public class BatteryStatsImpl extends BatteryStats { } public void notePackageInstalledLocked(String pkgName, long versionCode) { - final long elapsedRealtime = mClocks.elapsedRealtime(); - final long uptime = mClocks.uptimeMillis(); + notePackageInstalledLocked(pkgName, versionCode, + mClocks.elapsedRealtime(), mClocks.uptimeMillis()); + } + + public void notePackageInstalledLocked(String pkgName, long versionCode, + long elapsedRealtimeMs, long uptimeMs) { // XXX need to figure out what to do with long version codes. - addHistoryEventLocked(elapsedRealtime, uptime, HistoryItem.EVENT_PACKAGE_INSTALLED, + addHistoryEventLocked(elapsedRealtimeMs, uptimeMs, HistoryItem.EVENT_PACKAGE_INSTALLED, pkgName, (int)versionCode); PackageChange pc = new PackageChange(); pc.mPackageName = pkgName; @@ -5068,10 +5333,13 @@ public class BatteryStatsImpl extends BatteryStats { } public void notePackageUninstalledLocked(String pkgName) { - final long elapsedRealtime = mClocks.elapsedRealtime(); - final long uptime = mClocks.uptimeMillis(); - addHistoryEventLocked(elapsedRealtime, uptime, HistoryItem.EVENT_PACKAGE_UNINSTALLED, - pkgName, 0); + notePackageUninstalledLocked(pkgName, mClocks.elapsedRealtime(), mClocks.uptimeMillis()); + } + + public void notePackageUninstalledLocked(String pkgName, + long elapsedRealtimeMs, long uptimeMs) { + addHistoryEventLocked(elapsedRealtimeMs, uptimeMs, + HistoryItem.EVENT_PACKAGE_UNINSTALLED, pkgName, 0); PackageChange pc = new PackageChange(); pc.mPackageName = pkgName; pc.mUpdate = true; @@ -5086,42 +5354,49 @@ public class BatteryStatsImpl extends BatteryStats { } void stopAllGpsSignalQualityTimersLocked(int except) { - final long elapsedRealtime = mClocks.elapsedRealtime(); + stopAllGpsSignalQualityTimersLocked(except, mClocks.elapsedRealtime()); + } + + void stopAllGpsSignalQualityTimersLocked(int except, long elapsedRealtimeMs) { for (int i = 0; i < GnssMetrics.NUM_GPS_SIGNAL_QUALITY_LEVELS; i++) { if (i == except) { continue; } while (mGpsSignalQualityTimer[i].isRunningLocked()) { - mGpsSignalQualityTimer[i].stopRunningLocked(elapsedRealtime); + mGpsSignalQualityTimer[i].stopRunningLocked(elapsedRealtimeMs); } } } @UnsupportedAppUsage public void notePhoneOnLocked() { + notePhoneOnLocked(mClocks.elapsedRealtime(), mClocks.uptimeMillis()); + } + + public void notePhoneOnLocked(long elapsedRealtimeMs, long uptimeMs) { if (!mPhoneOn) { - final long elapsedRealtime = mClocks.elapsedRealtime(); - final long uptime = mClocks.uptimeMillis(); mHistoryCur.states2 |= HistoryItem.STATE2_PHONE_IN_CALL_FLAG; if (DEBUG_HISTORY) Slog.v(TAG, "Phone on to: " + Integer.toHexString(mHistoryCur.states)); - addHistoryRecordLocked(elapsedRealtime, uptime); + addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs); mPhoneOn = true; - mPhoneOnTimer.startRunningLocked(elapsedRealtime); + mPhoneOnTimer.startRunningLocked(elapsedRealtimeMs); } } @UnsupportedAppUsage public void notePhoneOffLocked() { + notePhoneOffLocked(mClocks.elapsedRealtime(), mClocks.uptimeMillis()); + } + + public void notePhoneOffLocked(long elapsedRealtimeMs, long uptimeMs) { if (mPhoneOn) { - final long elapsedRealtime = mClocks.elapsedRealtime(); - final long uptime = mClocks.uptimeMillis(); mHistoryCur.states2 &= ~HistoryItem.STATE2_PHONE_IN_CALL_FLAG; if (DEBUG_HISTORY) Slog.v(TAG, "Phone off to: " + Integer.toHexString(mHistoryCur.states)); - addHistoryRecordLocked(elapsedRealtime, uptime); + addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs); mPhoneOn = false; - mPhoneOnTimer.stopRunningLocked(elapsedRealtime); + mPhoneOnTimer.stopRunningLocked(elapsedRealtimeMs); } } @@ -5133,7 +5408,8 @@ public class BatteryStatsImpl extends BatteryStats { public void onReceive(Context context, Intent intent) { final boolean state = intent.getBooleanExtra(UsbManager.USB_CONNECTED, false); synchronized (BatteryStatsImpl.this) { - noteUsbConnectionStateLocked(state); + noteUsbConnectionStateLocked(state, mClocks.elapsedRealtime(), + mClocks.uptimeMillis()); } } }, usbStateFilter); @@ -5142,12 +5418,14 @@ public class BatteryStatsImpl extends BatteryStats { final Intent usbState = context.registerReceiver(null, usbStateFilter); final boolean initState = usbState != null && usbState.getBooleanExtra( UsbManager.USB_CONNECTED, false); - noteUsbConnectionStateLocked(initState); + noteUsbConnectionStateLocked(initState, mClocks.elapsedRealtime(), + mClocks.uptimeMillis()); } } } - private void noteUsbConnectionStateLocked(boolean connected) { + private void noteUsbConnectionStateLocked(boolean connected, long elapsedRealtimeMs, + long uptimeMs) { int newState = connected ? USB_DATA_CONNECTED : USB_DATA_DISCONNECTED; if (mUsbDataState != newState) { mUsbDataState = newState; @@ -5156,18 +5434,17 @@ public class BatteryStatsImpl extends BatteryStats { } else { mHistoryCur.states2 &= ~HistoryItem.STATE2_USB_DATA_LINK_FLAG; } - addHistoryRecordLocked(mClocks.elapsedRealtime(), mClocks.uptimeMillis()); + addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs); } } - void stopAllPhoneSignalStrengthTimersLocked(int except) { - final long elapsedRealtime = mClocks.elapsedRealtime(); + void stopAllPhoneSignalStrengthTimersLocked(int except, long elapsedRealtimeMs) { for (int i = 0; i < CellSignalStrength.getNumSignalStrengthLevels(); i++) { if (i == except) { continue; } while (mPhoneSignalStrengthsTimer[i].isRunningLocked()) { - mPhoneSignalStrengthsTimer[i].stopRunningLocked(elapsedRealtime); + mPhoneSignalStrengthsTimer[i].stopRunningLocked(elapsedRealtimeMs); } } } @@ -5185,7 +5462,8 @@ public class BatteryStatsImpl extends BatteryStats { return state; } - private void updateAllPhoneStateLocked(int state, int simState, int strengthBin) { + private void updateAllPhoneStateLocked(int state, int simState, int strengthBin, + long elapsedRealtimeMs, long uptimeMs) { boolean scanning = false; boolean newHistory = false; @@ -5193,9 +5471,6 @@ public class BatteryStatsImpl extends BatteryStats { mPhoneSimStateRaw = simState; mPhoneSignalStrengthBinRaw = strengthBin; - final long elapsedRealtime = mClocks.elapsedRealtime(); - final long uptime = mClocks.uptimeMillis(); - if (simState == TelephonyManager.SIM_STATE_ABSENT) { // In this case we will always be STATE_OUT_OF_SERVICE, so need // to infer that we are scanning from other data. @@ -5223,7 +5498,7 @@ public class BatteryStatsImpl extends BatteryStats { newHistory = true; if (DEBUG_HISTORY) Slog.v(TAG, "Phone started scanning to: " + Integer.toHexString(mHistoryCur.states)); - mPhoneSignalScanningTimer.startRunningLocked(elapsedRealtime); + mPhoneSignalScanningTimer.startRunningLocked(elapsedRealtimeMs); FrameworkStatsLog.write(FrameworkStatsLog.PHONE_SERVICE_STATE_CHANGED, state, simState, strengthBin); } @@ -5236,7 +5511,7 @@ public class BatteryStatsImpl extends BatteryStats { if (DEBUG_HISTORY) Slog.v(TAG, "Phone stopped scanning to: " + Integer.toHexString(mHistoryCur.states)); newHistory = true; - mPhoneSignalScanningTimer.stopRunningLocked(elapsedRealtime); + mPhoneSignalScanningTimer.stopRunningLocked(elapsedRealtimeMs); FrameworkStatsLog.write(FrameworkStatsLog.PHONE_SERVICE_STATE_CHANGED, state, simState, strengthBin); } @@ -5254,13 +5529,14 @@ public class BatteryStatsImpl extends BatteryStats { if (mPhoneSignalStrengthBin != strengthBin) { if (mPhoneSignalStrengthBin >= 0) { mPhoneSignalStrengthsTimer[mPhoneSignalStrengthBin].stopRunningLocked( - elapsedRealtime); + elapsedRealtimeMs); } if (strengthBin >= 0) { if (!mPhoneSignalStrengthsTimer[strengthBin].isRunningLocked()) { - mPhoneSignalStrengthsTimer[strengthBin].startRunningLocked(elapsedRealtime); + mPhoneSignalStrengthsTimer[strengthBin].startRunningLocked(elapsedRealtimeMs); } - mHistoryCur.states = (mHistoryCur.states&~HistoryItem.STATE_PHONE_SIGNAL_STRENGTH_MASK) + mHistoryCur.states = + (mHistoryCur.states & ~HistoryItem.STATE_PHONE_SIGNAL_STRENGTH_MASK) | (strengthBin << HistoryItem.STATE_PHONE_SIGNAL_STRENGTH_SHIFT); if (DEBUG_HISTORY) Slog.v(TAG, "Signal strength " + strengthBin + " to: " + Integer.toHexString(mHistoryCur.states)); @@ -5268,13 +5544,13 @@ public class BatteryStatsImpl extends BatteryStats { FrameworkStatsLog.write( FrameworkStatsLog.PHONE_SIGNAL_STRENGTH_CHANGED, strengthBin); } else { - stopAllPhoneSignalStrengthTimersLocked(-1); + stopAllPhoneSignalStrengthTimersLocked(-1, elapsedRealtimeMs); } mPhoneSignalStrengthBin = strengthBin; } if (newHistory) { - addHistoryRecordLocked(elapsedRealtime, uptime); + addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs); } } @@ -5283,18 +5559,37 @@ public class BatteryStatsImpl extends BatteryStats { * @param state phone state from ServiceState.getState() */ public void notePhoneStateLocked(int state, int simState) { - updateAllPhoneStateLocked(state, simState, mPhoneSignalStrengthBinRaw); + notePhoneStateLocked(state, simState, mClocks.elapsedRealtime(), mClocks.uptimeMillis()); + } + + public void notePhoneStateLocked(int state, int simState, + long elapsedRealtimeMs, long uptimeMs) { + updateAllPhoneStateLocked(state, simState, mPhoneSignalStrengthBinRaw, + elapsedRealtimeMs, uptimeMs); } @UnsupportedAppUsage public void notePhoneSignalStrengthLocked(SignalStrength signalStrength) { + notePhoneSignalStrengthLocked(signalStrength, + mClocks.elapsedRealtime(), mClocks.uptimeMillis()); + } + + public void notePhoneSignalStrengthLocked(SignalStrength signalStrength, + long elapsedRealtimeMs, long uptimeMs) { // Bin the strength. int bin = signalStrength.getLevel(); - updateAllPhoneStateLocked(mPhoneServiceStateRaw, mPhoneSimStateRaw, bin); + updateAllPhoneStateLocked(mPhoneServiceStateRaw, mPhoneSimStateRaw, bin, + elapsedRealtimeMs, uptimeMs); } @UnsupportedAppUsage public void notePhoneDataConnectionStateLocked(int dataType, boolean hasData, int serviceType) { + notePhoneDataConnectionStateLocked(dataType, hasData, serviceType, + mClocks.elapsedRealtime(), mClocks.uptimeMillis()); + } + + public void notePhoneDataConnectionStateLocked(int dataType, boolean hasData, int serviceType, + long elapsedRealtimeMs, long uptimeMs) { // BatteryStats uses 0 to represent no network type. // Telephony does not have a concept of no network type, and uses 0 to represent unknown. // Unknown is included in DATA_CONNECTION_OTHER. @@ -5318,312 +5613,374 @@ public class BatteryStatsImpl extends BatteryStats { } if (DEBUG) Log.i(TAG, "Phone Data Connection -> " + dataType + " = " + hasData); if (mPhoneDataConnectionType != bin) { - final long elapsedRealtime = mClocks.elapsedRealtime(); - final long uptime = mClocks.uptimeMillis(); mHistoryCur.states = (mHistoryCur.states&~HistoryItem.STATE_DATA_CONNECTION_MASK) | (bin << HistoryItem.STATE_DATA_CONNECTION_SHIFT); if (DEBUG_HISTORY) Slog.v(TAG, "Data connection " + bin + " to: " + Integer.toHexString(mHistoryCur.states)); - addHistoryRecordLocked(elapsedRealtime, uptime); + addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs); if (mPhoneDataConnectionType >= 0) { mPhoneDataConnectionsTimer[mPhoneDataConnectionType].stopRunningLocked( - elapsedRealtime); + elapsedRealtimeMs); } mPhoneDataConnectionType = bin; - mPhoneDataConnectionsTimer[bin].startRunningLocked(elapsedRealtime); + mPhoneDataConnectionsTimer[bin].startRunningLocked(elapsedRealtimeMs); } } public void noteWifiOnLocked() { + noteWifiOnLocked(mClocks.elapsedRealtime(), mClocks.uptimeMillis()); + } + + public void noteWifiOnLocked(long elapsedRealtimeMs, long uptimeMs) { if (!mWifiOn) { - final long elapsedRealtime = mClocks.elapsedRealtime(); - final long uptime = mClocks.uptimeMillis(); mHistoryCur.states2 |= HistoryItem.STATE2_WIFI_ON_FLAG; if (DEBUG_HISTORY) Slog.v(TAG, "WIFI on to: " + Integer.toHexString(mHistoryCur.states)); - addHistoryRecordLocked(elapsedRealtime, uptime); + addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs); mWifiOn = true; - mWifiOnTimer.startRunningLocked(elapsedRealtime); + mWifiOnTimer.startRunningLocked(elapsedRealtimeMs); scheduleSyncExternalStatsLocked("wifi-off", ExternalStatsSync.UPDATE_WIFI); } } public void noteWifiOffLocked() { - final long elapsedRealtime = mClocks.elapsedRealtime(); - final long uptime = mClocks.uptimeMillis(); + noteWifiOffLocked(mClocks.elapsedRealtime(), mClocks.uptimeMillis()); + } + + public void noteWifiOffLocked(long elapsedRealtimeMs, long uptimeMs) { if (mWifiOn) { mHistoryCur.states2 &= ~HistoryItem.STATE2_WIFI_ON_FLAG; if (DEBUG_HISTORY) Slog.v(TAG, "WIFI off to: " + Integer.toHexString(mHistoryCur.states)); - addHistoryRecordLocked(elapsedRealtime, uptime); + addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs); mWifiOn = false; - mWifiOnTimer.stopRunningLocked(elapsedRealtime); + mWifiOnTimer.stopRunningLocked(elapsedRealtimeMs); scheduleSyncExternalStatsLocked("wifi-on", ExternalStatsSync.UPDATE_WIFI); } } @UnsupportedAppUsage public void noteAudioOnLocked(int uid) { + noteAudioOnLocked(uid, mClocks.elapsedRealtime(), mClocks.uptimeMillis()); + } + + public void noteAudioOnLocked(int uid, long elapsedRealtimeMs, long uptimeMs) { uid = mapUid(uid); - final long elapsedRealtime = mClocks.elapsedRealtime(); - final long uptime = mClocks.uptimeMillis(); if (mAudioOnNesting == 0) { mHistoryCur.states |= HistoryItem.STATE_AUDIO_ON_FLAG; if (DEBUG_HISTORY) Slog.v(TAG, "Audio on to: " + Integer.toHexString(mHistoryCur.states)); - addHistoryRecordLocked(elapsedRealtime, uptime); - mAudioOnTimer.startRunningLocked(elapsedRealtime); + addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs); + mAudioOnTimer.startRunningLocked(elapsedRealtimeMs); } mAudioOnNesting++; - getUidStatsLocked(uid).noteAudioTurnedOnLocked(elapsedRealtime); + getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs) + .noteAudioTurnedOnLocked(elapsedRealtimeMs); } @UnsupportedAppUsage public void noteAudioOffLocked(int uid) { + noteAudioOffLocked(uid, mClocks.elapsedRealtime(), mClocks.uptimeMillis()); + } + + public void noteAudioOffLocked(int uid, long elapsedRealtimeMs, long uptimeMs) { if (mAudioOnNesting == 0) { return; } uid = mapUid(uid); - final long elapsedRealtime = mClocks.elapsedRealtime(); - final long uptime = mClocks.uptimeMillis(); if (--mAudioOnNesting == 0) { mHistoryCur.states &= ~HistoryItem.STATE_AUDIO_ON_FLAG; if (DEBUG_HISTORY) Slog.v(TAG, "Audio off to: " + Integer.toHexString(mHistoryCur.states)); - addHistoryRecordLocked(elapsedRealtime, uptime); - mAudioOnTimer.stopRunningLocked(elapsedRealtime); + addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs); + mAudioOnTimer.stopRunningLocked(elapsedRealtimeMs); } - getUidStatsLocked(uid).noteAudioTurnedOffLocked(elapsedRealtime); + getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs) + .noteAudioTurnedOffLocked(elapsedRealtimeMs); } @UnsupportedAppUsage public void noteVideoOnLocked(int uid) { + noteVideoOnLocked(uid, mClocks.elapsedRealtime(), mClocks.uptimeMillis()); + } + + public void noteVideoOnLocked(int uid, long elapsedRealtimeMs, long uptimeMs) { uid = mapUid(uid); - final long elapsedRealtime = mClocks.elapsedRealtime(); - final long uptime = mClocks.uptimeMillis(); if (mVideoOnNesting == 0) { mHistoryCur.states2 |= HistoryItem.STATE2_VIDEO_ON_FLAG; if (DEBUG_HISTORY) Slog.v(TAG, "Video on to: " + Integer.toHexString(mHistoryCur.states)); - addHistoryRecordLocked(elapsedRealtime, uptime); - mVideoOnTimer.startRunningLocked(elapsedRealtime); + addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs); + mVideoOnTimer.startRunningLocked(elapsedRealtimeMs); } mVideoOnNesting++; - getUidStatsLocked(uid).noteVideoTurnedOnLocked(elapsedRealtime); + getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs) + .noteVideoTurnedOnLocked(elapsedRealtimeMs); } @UnsupportedAppUsage public void noteVideoOffLocked(int uid) { + noteVideoOffLocked(uid, mClocks.elapsedRealtime(), mClocks.uptimeMillis()); + } + + public void noteVideoOffLocked(int uid, long elapsedRealtimeMs, long uptimeMs) { if (mVideoOnNesting == 0) { return; } uid = mapUid(uid); - final long elapsedRealtime = mClocks.elapsedRealtime(); - final long uptime = mClocks.uptimeMillis(); if (--mVideoOnNesting == 0) { mHistoryCur.states2 &= ~HistoryItem.STATE2_VIDEO_ON_FLAG; if (DEBUG_HISTORY) Slog.v(TAG, "Video off to: " + Integer.toHexString(mHistoryCur.states)); - addHistoryRecordLocked(elapsedRealtime, uptime); - mVideoOnTimer.stopRunningLocked(elapsedRealtime); + addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs); + mVideoOnTimer.stopRunningLocked(elapsedRealtimeMs); } - getUidStatsLocked(uid).noteVideoTurnedOffLocked(elapsedRealtime); + getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs) + .noteVideoTurnedOffLocked(elapsedRealtimeMs); } public void noteResetAudioLocked() { + noteResetAudioLocked(mClocks.elapsedRealtime(), mClocks.uptimeMillis()); + } + + public void noteResetAudioLocked(long elapsedRealtimeMs, long uptimeMs) { if (mAudioOnNesting > 0) { - final long elapsedRealtime = mClocks.elapsedRealtime(); - final long uptime = mClocks.uptimeMillis(); mAudioOnNesting = 0; mHistoryCur.states &= ~HistoryItem.STATE_AUDIO_ON_FLAG; if (DEBUG_HISTORY) Slog.v(TAG, "Audio off to: " + Integer.toHexString(mHistoryCur.states)); - addHistoryRecordLocked(elapsedRealtime, uptime); - mAudioOnTimer.stopAllRunningLocked(elapsedRealtime); + addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs); + mAudioOnTimer.stopAllRunningLocked(elapsedRealtimeMs); for (int i=0; i<mUidStats.size(); i++) { BatteryStatsImpl.Uid uid = mUidStats.valueAt(i); - uid.noteResetAudioLocked(elapsedRealtime); + uid.noteResetAudioLocked(elapsedRealtimeMs); } } } public void noteResetVideoLocked() { + noteResetVideoLocked(mClocks.elapsedRealtime(), mClocks.uptimeMillis()); + } + + public void noteResetVideoLocked(long elapsedRealtimeMs, long uptimeMs) { if (mVideoOnNesting > 0) { - final long elapsedRealtime = mClocks.elapsedRealtime(); - final long uptime = mClocks.uptimeMillis(); mVideoOnNesting = 0; mHistoryCur.states2 &= ~HistoryItem.STATE2_VIDEO_ON_FLAG; if (DEBUG_HISTORY) Slog.v(TAG, "Video off to: " + Integer.toHexString(mHistoryCur.states)); - addHistoryRecordLocked(elapsedRealtime, uptime); - mVideoOnTimer.stopAllRunningLocked(elapsedRealtime); + addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs); + mVideoOnTimer.stopAllRunningLocked(elapsedRealtimeMs); for (int i=0; i<mUidStats.size(); i++) { BatteryStatsImpl.Uid uid = mUidStats.valueAt(i); - uid.noteResetVideoLocked(elapsedRealtime); + uid.noteResetVideoLocked(elapsedRealtimeMs); } } } public void noteActivityResumedLocked(int uid) { + noteActivityResumedLocked(uid, mClocks.elapsedRealtime(), mClocks.uptimeMillis()); + } + + public void noteActivityResumedLocked(int uid, long elapsedRealtimeMs, long uptimeMs) { uid = mapUid(uid); - getUidStatsLocked(uid).noteActivityResumedLocked(mClocks.elapsedRealtime()); + getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs) + .noteActivityResumedLocked(elapsedRealtimeMs); } public void noteActivityPausedLocked(int uid) { + noteActivityPausedLocked(uid, mClocks.elapsedRealtime(), mClocks.uptimeMillis()); + } + + public void noteActivityPausedLocked(int uid, long elapsedRealtimeMs, long uptimeMs) { uid = mapUid(uid); - getUidStatsLocked(uid).noteActivityPausedLocked(mClocks.elapsedRealtime()); + getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs) + .noteActivityPausedLocked(elapsedRealtimeMs); } public void noteVibratorOnLocked(int uid, long durationMillis) { + noteVibratorOnLocked(uid, durationMillis, + mClocks.elapsedRealtime(), mClocks.uptimeMillis()); + } + + public void noteVibratorOnLocked(int uid, long durationMillis, + long elapsedRealtimeMs, long uptimeMs) { uid = mapUid(uid); - getUidStatsLocked(uid).noteVibratorOnLocked(durationMillis); + getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs) + .noteVibratorOnLocked(durationMillis, elapsedRealtimeMs); } public void noteVibratorOffLocked(int uid) { + noteVibratorOffLocked(uid, mClocks.elapsedRealtime(), mClocks.uptimeMillis()); + } + + public void noteVibratorOffLocked(int uid, long elapsedRealtimeMs, long uptimeMs) { uid = mapUid(uid); - getUidStatsLocked(uid).noteVibratorOffLocked(); + getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs) + .noteVibratorOffLocked(elapsedRealtimeMs); } public void noteFlashlightOnLocked(int uid) { + noteFlashlightOnLocked(uid, mClocks.elapsedRealtime(), mClocks.uptimeMillis()); + } + + public void noteFlashlightOnLocked(int uid, long elapsedRealtimeMs, long uptimeMs) { uid = mapUid(uid); - final long elapsedRealtime = mClocks.elapsedRealtime(); - final long uptime = mClocks.uptimeMillis(); if (mFlashlightOnNesting++ == 0) { mHistoryCur.states2 |= HistoryItem.STATE2_FLASHLIGHT_FLAG; if (DEBUG_HISTORY) Slog.v(TAG, "Flashlight on to: " + Integer.toHexString(mHistoryCur.states2)); - addHistoryRecordLocked(elapsedRealtime, uptime); - mFlashlightOnTimer.startRunningLocked(elapsedRealtime); + addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs); + mFlashlightOnTimer.startRunningLocked(elapsedRealtimeMs); } - getUidStatsLocked(uid).noteFlashlightTurnedOnLocked(elapsedRealtime); + getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs) + .noteFlashlightTurnedOnLocked(elapsedRealtimeMs); } public void noteFlashlightOffLocked(int uid) { + noteFlashlightOffLocked(uid, mClocks.elapsedRealtime(), mClocks.uptimeMillis()); + } + + public void noteFlashlightOffLocked(int uid, long elapsedRealtimeMs, long uptimeMs) { if (mFlashlightOnNesting == 0) { return; } uid = mapUid(uid); - final long elapsedRealtime = mClocks.elapsedRealtime(); - final long uptime = mClocks.uptimeMillis(); if (--mFlashlightOnNesting == 0) { mHistoryCur.states2 &= ~HistoryItem.STATE2_FLASHLIGHT_FLAG; if (DEBUG_HISTORY) Slog.v(TAG, "Flashlight off to: " + Integer.toHexString(mHistoryCur.states2)); - addHistoryRecordLocked(elapsedRealtime, uptime); - mFlashlightOnTimer.stopRunningLocked(elapsedRealtime); + addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs); + mFlashlightOnTimer.stopRunningLocked(elapsedRealtimeMs); } - getUidStatsLocked(uid).noteFlashlightTurnedOffLocked(elapsedRealtime); + getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs) + .noteFlashlightTurnedOffLocked(elapsedRealtimeMs); } public void noteCameraOnLocked(int uid) { + noteCameraOnLocked(uid, mClocks.elapsedRealtime(), mClocks.uptimeMillis()); + } + + public void noteCameraOnLocked(int uid, long elapsedRealtimeMs, long uptimeMs) { uid = mapUid(uid); - final long elapsedRealtime = mClocks.elapsedRealtime(); - final long uptime = mClocks.uptimeMillis(); if (mCameraOnNesting++ == 0) { mHistoryCur.states2 |= HistoryItem.STATE2_CAMERA_FLAG; if (DEBUG_HISTORY) Slog.v(TAG, "Camera on to: " + Integer.toHexString(mHistoryCur.states2)); - addHistoryRecordLocked(elapsedRealtime, uptime); - mCameraOnTimer.startRunningLocked(elapsedRealtime); + addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs); + mCameraOnTimer.startRunningLocked(elapsedRealtimeMs); } - getUidStatsLocked(uid).noteCameraTurnedOnLocked(elapsedRealtime); + getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs) + .noteCameraTurnedOnLocked(elapsedRealtimeMs); } public void noteCameraOffLocked(int uid) { + noteCameraOffLocked(uid, mClocks.elapsedRealtime(), mClocks.uptimeMillis()); + } + + public void noteCameraOffLocked(int uid, long elapsedRealtimeMs, long uptimeMs) { if (mCameraOnNesting == 0) { return; } uid = mapUid(uid); - final long elapsedRealtime = mClocks.elapsedRealtime(); - final long uptime = mClocks.uptimeMillis(); if (--mCameraOnNesting == 0) { mHistoryCur.states2 &= ~HistoryItem.STATE2_CAMERA_FLAG; if (DEBUG_HISTORY) Slog.v(TAG, "Camera off to: " + Integer.toHexString(mHistoryCur.states2)); - addHistoryRecordLocked(elapsedRealtime, uptime); - mCameraOnTimer.stopRunningLocked(elapsedRealtime); + addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs); + mCameraOnTimer.stopRunningLocked(elapsedRealtimeMs); } - getUidStatsLocked(uid).noteCameraTurnedOffLocked(elapsedRealtime); + getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs) + .noteCameraTurnedOffLocked(elapsedRealtimeMs); } public void noteResetCameraLocked() { + noteResetCameraLocked(mClocks.elapsedRealtime(), mClocks.uptimeMillis()); + } + + public void noteResetCameraLocked(long elapsedRealtimeMs, long uptimeMs) { if (mCameraOnNesting > 0) { - final long elapsedRealtime = mClocks.elapsedRealtime(); - final long uptime = mClocks.uptimeMillis(); mCameraOnNesting = 0; mHistoryCur.states2 &= ~HistoryItem.STATE2_CAMERA_FLAG; if (DEBUG_HISTORY) Slog.v(TAG, "Camera off to: " + Integer.toHexString(mHistoryCur.states2)); - addHistoryRecordLocked(elapsedRealtime, uptime); - mCameraOnTimer.stopAllRunningLocked(elapsedRealtime); + addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs); + mCameraOnTimer.stopAllRunningLocked(elapsedRealtimeMs); for (int i=0; i<mUidStats.size(); i++) { BatteryStatsImpl.Uid uid = mUidStats.valueAt(i); - uid.noteResetCameraLocked(elapsedRealtime); + uid.noteResetCameraLocked(elapsedRealtimeMs); } } } public void noteResetFlashlightLocked() { + noteResetFlashlightLocked(mClocks.elapsedRealtime(), mClocks.uptimeMillis()); + } + + public void noteResetFlashlightLocked(long elapsedRealtimeMs, long uptimeMs) { if (mFlashlightOnNesting > 0) { - final long elapsedRealtime = mClocks.elapsedRealtime(); - final long uptime = mClocks.uptimeMillis(); mFlashlightOnNesting = 0; mHistoryCur.states2 &= ~HistoryItem.STATE2_FLASHLIGHT_FLAG; if (DEBUG_HISTORY) Slog.v(TAG, "Flashlight off to: " + Integer.toHexString(mHistoryCur.states2)); - addHistoryRecordLocked(elapsedRealtime, uptime); - mFlashlightOnTimer.stopAllRunningLocked(elapsedRealtime); + addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs); + mFlashlightOnTimer.stopAllRunningLocked(elapsedRealtimeMs); for (int i=0; i<mUidStats.size(); i++) { BatteryStatsImpl.Uid uid = mUidStats.valueAt(i); - uid.noteResetFlashlightLocked(elapsedRealtime); + uid.noteResetFlashlightLocked(elapsedRealtimeMs); } } } private void noteBluetoothScanStartedLocked(WorkChain workChain, int uid, - boolean isUnoptimized) { + boolean isUnoptimized, long elapsedRealtimeMs, long uptimeMs) { uid = getAttributionUid(uid, workChain); - final long elapsedRealtime = mClocks.elapsedRealtime(); - final long uptime = mClocks.uptimeMillis(); if (mBluetoothScanNesting == 0) { mHistoryCur.states2 |= HistoryItem.STATE2_BLUETOOTH_SCAN_FLAG; if (DEBUG_HISTORY) Slog.v(TAG, "BLE scan started for: " + Integer.toHexString(mHistoryCur.states2)); - addHistoryRecordLocked(elapsedRealtime, uptime); - mBluetoothScanTimer.startRunningLocked(elapsedRealtime); + addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs); + mBluetoothScanTimer.startRunningLocked(elapsedRealtimeMs); } mBluetoothScanNesting++; - getUidStatsLocked(uid).noteBluetoothScanStartedLocked(elapsedRealtime, isUnoptimized); + getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs) + .noteBluetoothScanStartedLocked(elapsedRealtimeMs, isUnoptimized); } public void noteBluetoothScanStartedFromSourceLocked(WorkSource ws, boolean isUnoptimized) { + noteBluetoothScanStartedFromSourceLocked(ws, isUnoptimized, + mClocks.elapsedRealtime(), mClocks.uptimeMillis()); + } + + public void noteBluetoothScanStartedFromSourceLocked(WorkSource ws, boolean isUnoptimized, + long elapsedRealtimeMs, long uptimeMs) { final int N = ws.size(); for (int i = 0; i < N; i++) { - noteBluetoothScanStartedLocked(null, ws.getUid(i), isUnoptimized); + noteBluetoothScanStartedLocked(null, ws.getUid(i), isUnoptimized, + elapsedRealtimeMs, uptimeMs); } final List<WorkChain> workChains = ws.getWorkChains(); if (workChains != null) { for (int i = 0; i < workChains.size(); ++i) { - noteBluetoothScanStartedLocked(workChains.get(i), -1, isUnoptimized); + noteBluetoothScanStartedLocked(workChains.get(i), -1, isUnoptimized, + elapsedRealtimeMs, uptimeMs); } } } private void noteBluetoothScanStoppedLocked(WorkChain workChain, int uid, - boolean isUnoptimized) { + boolean isUnoptimized, long elapsedRealtimeMs, long uptimeMs) { uid = getAttributionUid(uid, workChain); - final long elapsedRealtime = mClocks.elapsedRealtime(); - final long uptime = mClocks.uptimeMillis(); mBluetoothScanNesting--; if (mBluetoothScanNesting == 0) { mHistoryCur.states2 &= ~HistoryItem.STATE2_BLUETOOTH_SCAN_FLAG; if (DEBUG_HISTORY) Slog.v(TAG, "BLE scan stopped for: " + Integer.toHexString(mHistoryCur.states2)); - addHistoryRecordLocked(elapsedRealtime, uptime); - mBluetoothScanTimer.stopRunningLocked(elapsedRealtime); + addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs); + mBluetoothScanTimer.stopRunningLocked(elapsedRealtimeMs); } - getUidStatsLocked(uid).noteBluetoothScanStoppedLocked(elapsedRealtime, isUnoptimized); + getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs) + .noteBluetoothScanStoppedLocked(elapsedRealtimeMs, isUnoptimized); } private int getAttributionUid(int uid, WorkChain workChain) { @@ -5635,41 +5992,58 @@ public class BatteryStatsImpl extends BatteryStats { } public void noteBluetoothScanStoppedFromSourceLocked(WorkSource ws, boolean isUnoptimized) { + noteBluetoothScanStoppedFromSourceLocked(ws, isUnoptimized, + mClocks.elapsedRealtime(), mClocks.uptimeMillis()); + } + + public void noteBluetoothScanStoppedFromSourceLocked(WorkSource ws, boolean isUnoptimized, + long elapsedRealtimeMs, long uptimeMs) { final int N = ws.size(); for (int i = 0; i < N; i++) { - noteBluetoothScanStoppedLocked(null, ws.getUid(i), isUnoptimized); + noteBluetoothScanStoppedLocked(null, ws.getUid(i), isUnoptimized, + elapsedRealtimeMs, uptimeMs); } final List<WorkChain> workChains = ws.getWorkChains(); if (workChains != null) { for (int i = 0; i < workChains.size(); ++i) { - noteBluetoothScanStoppedLocked(workChains.get(i), -1, isUnoptimized); + noteBluetoothScanStoppedLocked(workChains.get(i), -1, isUnoptimized, + elapsedRealtimeMs, uptimeMs); } } } public void noteResetBluetoothScanLocked() { + noteResetBluetoothScanLocked(mClocks.elapsedRealtime(), mClocks.uptimeMillis()); + } + + public void noteResetBluetoothScanLocked(long elapsedRealtimeMs, long uptimeMs) { if (mBluetoothScanNesting > 0) { - final long elapsedRealtime = mClocks.elapsedRealtime(); - final long uptime = mClocks.uptimeMillis(); mBluetoothScanNesting = 0; mHistoryCur.states2 &= ~HistoryItem.STATE2_BLUETOOTH_SCAN_FLAG; if (DEBUG_HISTORY) Slog.v(TAG, "BLE can stopped for: " + Integer.toHexString(mHistoryCur.states2)); - addHistoryRecordLocked(elapsedRealtime, uptime); - mBluetoothScanTimer.stopAllRunningLocked(elapsedRealtime); + addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs); + mBluetoothScanTimer.stopAllRunningLocked(elapsedRealtimeMs); for (int i=0; i<mUidStats.size(); i++) { BatteryStatsImpl.Uid uid = mUidStats.valueAt(i); - uid.noteResetBluetoothScanLocked(elapsedRealtime); + uid.noteResetBluetoothScanLocked(elapsedRealtimeMs); } } } public void noteBluetoothScanResultsFromSourceLocked(WorkSource ws, int numNewResults) { + noteBluetoothScanResultsFromSourceLocked(ws, numNewResults, + mClocks.elapsedRealtime(), mClocks.uptimeMillis()); + } + + public void noteBluetoothScanResultsFromSourceLocked(WorkSource ws, int numNewResults, + long elapsedRealtimeMs, long uptimeMs) { final int N = ws.size(); for (int i = 0; i < N; i++) { int uid = mapUid(ws.getUid(i)); - getUidStatsLocked(uid).noteBluetoothScanResultsLocked(numNewResults); + getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs) + .noteBluetoothScanResultsLocked(numNewResults); } final List<WorkChain> workChains = ws.getWorkChains(); @@ -5677,7 +6051,8 @@ public class BatteryStatsImpl extends BatteryStats { for (int i = 0; i < workChains.size(); ++i) { final WorkChain wc = workChains.get(i); int uid = mapUid(wc.getAttributionUid()); - getUidStatsLocked(uid).noteBluetoothScanResultsLocked(numNewResults); + getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs) + .noteBluetoothScanResultsLocked(numNewResults); } } } @@ -5687,55 +6062,62 @@ public class BatteryStatsImpl extends BatteryStats { uid = mapUid(uid); addHistoryEventLocked(elapsedRealtimeMillis, uptimeMillis, HistoryItem.EVENT_WAKEUP_AP, "", uid); - getUidStatsLocked(uid).noteWifiRadioApWakeupLocked(); + getUidStatsLocked(uid, elapsedRealtimeMillis, uptimeMillis).noteWifiRadioApWakeupLocked(); } public void noteWifiRadioPowerState(int powerState, long timestampNs, int uid) { - final long elapsedRealtime = mClocks.elapsedRealtime(); - final long uptime = mClocks.uptimeMillis(); + noteWifiRadioPowerState(powerState, timestampNs, uid, + mClocks.elapsedRealtime(), mClocks.uptimeMillis()); + } + + public void noteWifiRadioPowerState(int powerState, long timestampNs, int uid, + long elapsedRealtimeMs, long uptimeMs) { if (mWifiRadioPowerState != powerState) { final boolean active = powerState == DataConnectionRealTimeInfo.DC_POWER_STATE_MEDIUM || powerState == DataConnectionRealTimeInfo.DC_POWER_STATE_HIGH; if (active) { if (uid > 0) { - noteWifiRadioApWakeupLocked(elapsedRealtime, uptime, uid); + noteWifiRadioApWakeupLocked(elapsedRealtimeMs, uptimeMs, uid); } mHistoryCur.states |= HistoryItem.STATE_WIFI_RADIO_ACTIVE_FLAG; - mWifiActiveTimer.startRunningLocked(elapsedRealtime); + mWifiActiveTimer.startRunningLocked(elapsedRealtimeMs); } else { mHistoryCur.states &= ~HistoryItem.STATE_WIFI_RADIO_ACTIVE_FLAG; - mWifiActiveTimer.stopRunningLocked( - timestampNs / (1000 * 1000)); + mWifiActiveTimer.stopRunningLocked(timestampNs / (1000 * 1000)); } if (DEBUG_HISTORY) Slog.v(TAG, "Wifi network active " + active + " to: " + Integer.toHexString(mHistoryCur.states)); - addHistoryRecordLocked(elapsedRealtime, uptime); + addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs); mWifiRadioPowerState = powerState; } } public void noteWifiRunningLocked(WorkSource ws) { + noteWifiRunningLocked(ws, mClocks.elapsedRealtime(), mClocks.uptimeMillis()); + } + + public void noteWifiRunningLocked(WorkSource ws, long elapsedRealtimeMs, long uptimeMs) { if (!mGlobalWifiRunning) { - final long elapsedRealtime = mClocks.elapsedRealtime(); - final long uptime = mClocks.uptimeMillis(); mHistoryCur.states2 |= HistoryItem.STATE2_WIFI_RUNNING_FLAG; if (DEBUG_HISTORY) Slog.v(TAG, "WIFI running to: " + Integer.toHexString(mHistoryCur.states)); - addHistoryRecordLocked(elapsedRealtime, uptime); + addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs); mGlobalWifiRunning = true; - mGlobalWifiRunningTimer.startRunningLocked(elapsedRealtime); + mGlobalWifiRunningTimer.startRunningLocked(elapsedRealtimeMs); int N = ws.size(); for (int i=0; i<N; i++) { int uid = mapUid(ws.getUid(i)); - getUidStatsLocked(uid).noteWifiRunningLocked(elapsedRealtime); + getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs) + .noteWifiRunningLocked(elapsedRealtimeMs); } List<WorkChain> workChains = ws.getWorkChains(); if (workChains != null) { for (int i = 0; i < workChains.size(); ++i) { int uid = mapUid(workChains.get(i).getAttributionUid()); - getUidStatsLocked(uid).noteWifiRunningLocked(elapsedRealtime); + getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs) + .noteWifiRunningLocked(elapsedRealtimeMs); } } @@ -5746,33 +6128,42 @@ public class BatteryStatsImpl extends BatteryStats { } public void noteWifiRunningChangedLocked(WorkSource oldWs, WorkSource newWs) { + noteWifiRunningChangedLocked(oldWs, newWs, + mClocks.elapsedRealtime(), mClocks.uptimeMillis()); + } + + public void noteWifiRunningChangedLocked(WorkSource oldWs, WorkSource newWs, + long elapsedRealtimeMs, long uptimeMs) { if (mGlobalWifiRunning) { - final long elapsedRealtime = mClocks.elapsedRealtime(); int N = oldWs.size(); for (int i=0; i<N; i++) { int uid = mapUid(oldWs.getUid(i)); - getUidStatsLocked(uid).noteWifiStoppedLocked(elapsedRealtime); + getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs) + .noteWifiStoppedLocked(elapsedRealtimeMs); } List<WorkChain> workChains = oldWs.getWorkChains(); if (workChains != null) { for (int i = 0; i < workChains.size(); ++i) { int uid = mapUid(workChains.get(i).getAttributionUid()); - getUidStatsLocked(uid).noteWifiStoppedLocked(elapsedRealtime); + getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs) + .noteWifiStoppedLocked(elapsedRealtimeMs); } } N = newWs.size(); for (int i=0; i<N; i++) { int uid = mapUid(newWs.getUid(i)); - getUidStatsLocked(uid).noteWifiRunningLocked(elapsedRealtime); + getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs) + .noteWifiRunningLocked(elapsedRealtimeMs); } workChains = newWs.getWorkChains(); if (workChains != null) { for (int i = 0; i < workChains.size(); ++i) { int uid = mapUid(workChains.get(i).getAttributionUid()); - getUidStatsLocked(uid).noteWifiRunningLocked(elapsedRealtime); + getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs) + .noteWifiRunningLocked(elapsedRealtimeMs); } } } else { @@ -5781,26 +6172,30 @@ public class BatteryStatsImpl extends BatteryStats { } public void noteWifiStoppedLocked(WorkSource ws) { + noteWifiStoppedLocked(ws, mClocks.elapsedRealtime(), mClocks.uptimeMillis()); + } + + public void noteWifiStoppedLocked(WorkSource ws, long elapsedRealtimeMs, long uptimeMs) { if (mGlobalWifiRunning) { - final long elapsedRealtime = mClocks.elapsedRealtime(); - final long uptime = mClocks.uptimeMillis(); mHistoryCur.states2 &= ~HistoryItem.STATE2_WIFI_RUNNING_FLAG; if (DEBUG_HISTORY) Slog.v(TAG, "WIFI stopped to: " + Integer.toHexString(mHistoryCur.states)); - addHistoryRecordLocked(elapsedRealtime, uptime); + addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs); mGlobalWifiRunning = false; - mGlobalWifiRunningTimer.stopRunningLocked(elapsedRealtime); + mGlobalWifiRunningTimer.stopRunningLocked(elapsedRealtimeMs); int N = ws.size(); for (int i=0; i<N; i++) { int uid = mapUid(ws.getUid(i)); - getUidStatsLocked(uid).noteWifiStoppedLocked(elapsedRealtime); + getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs) + .noteWifiStoppedLocked(elapsedRealtimeMs); } List<WorkChain> workChains = ws.getWorkChains(); if (workChains != null) { for (int i = 0; i < workChains.size(); ++i) { int uid = mapUid(workChains.get(i).getAttributionUid()); - getUidStatsLocked(uid).noteWifiStoppedLocked(elapsedRealtime); + getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs) + .noteWifiStoppedLocked(elapsedRealtimeMs); } } @@ -5811,71 +6206,79 @@ public class BatteryStatsImpl extends BatteryStats { } public void noteWifiStateLocked(int wifiState, String accessPoint) { + noteWifiStateLocked(wifiState, accessPoint, mClocks.elapsedRealtime()); + } + + public void noteWifiStateLocked(int wifiState, String accessPoint, long elapsedRealtimeMs) { if (DEBUG) Log.i(TAG, "WiFi state -> " + wifiState); if (mWifiState != wifiState) { - final long elapsedRealtime = mClocks.elapsedRealtime(); if (mWifiState >= 0) { - mWifiStateTimer[mWifiState].stopRunningLocked(elapsedRealtime); + mWifiStateTimer[mWifiState].stopRunningLocked(elapsedRealtimeMs); } mWifiState = wifiState; - mWifiStateTimer[wifiState].startRunningLocked(elapsedRealtime); + mWifiStateTimer[wifiState].startRunningLocked(elapsedRealtimeMs); scheduleSyncExternalStatsLocked("wifi-state", ExternalStatsSync.UPDATE_WIFI); } } public void noteWifiSupplicantStateChangedLocked(int supplState, boolean failedAuth) { + noteWifiSupplicantStateChangedLocked(supplState, failedAuth, + mClocks.elapsedRealtime(), mClocks.uptimeMillis()); + } + + public void noteWifiSupplicantStateChangedLocked(int supplState, boolean failedAuth, + long elapsedRealtimeMs, long uptimeMs) { if (DEBUG) Log.i(TAG, "WiFi suppl state -> " + supplState); if (mWifiSupplState != supplState) { - final long elapsedRealtime = mClocks.elapsedRealtime(); - final long uptime = mClocks.uptimeMillis(); if (mWifiSupplState >= 0) { - mWifiSupplStateTimer[mWifiSupplState].stopRunningLocked(elapsedRealtime); + mWifiSupplStateTimer[mWifiSupplState].stopRunningLocked(elapsedRealtimeMs); } mWifiSupplState = supplState; - mWifiSupplStateTimer[supplState].startRunningLocked(elapsedRealtime); + mWifiSupplStateTimer[supplState].startRunningLocked(elapsedRealtimeMs); mHistoryCur.states2 = (mHistoryCur.states2&~HistoryItem.STATE2_WIFI_SUPPL_STATE_MASK) | (supplState << HistoryItem.STATE2_WIFI_SUPPL_STATE_SHIFT); if (DEBUG_HISTORY) Slog.v(TAG, "Wifi suppl state " + supplState + " to: " + Integer.toHexString(mHistoryCur.states2)); - addHistoryRecordLocked(elapsedRealtime, uptime); + addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs); } } - void stopAllWifiSignalStrengthTimersLocked(int except) { - final long elapsedRealtime = mClocks.elapsedRealtime(); + void stopAllWifiSignalStrengthTimersLocked(int except, long elapsedRealtimeMs) { for (int i = 0; i < NUM_WIFI_SIGNAL_STRENGTH_BINS; i++) { if (i == except) { continue; } while (mWifiSignalStrengthsTimer[i].isRunningLocked()) { - mWifiSignalStrengthsTimer[i].stopRunningLocked(elapsedRealtime); + mWifiSignalStrengthsTimer[i].stopRunningLocked(elapsedRealtimeMs); } } } public void noteWifiRssiChangedLocked(int newRssi) { + noteWifiRssiChangedLocked(newRssi, mClocks.elapsedRealtime(), mClocks.uptimeMillis()); + } + + public void noteWifiRssiChangedLocked(int newRssi, long elapsedRealtimeMs, long uptimeMs) { int strengthBin = WifiManager.calculateSignalLevel(newRssi, NUM_WIFI_SIGNAL_STRENGTH_BINS); if (DEBUG) Log.i(TAG, "WiFi rssi -> " + newRssi + " bin=" + strengthBin); if (mWifiSignalStrengthBin != strengthBin) { - final long elapsedRealtime = mClocks.elapsedRealtime(); - final long uptime = mClocks.uptimeMillis(); if (mWifiSignalStrengthBin >= 0) { mWifiSignalStrengthsTimer[mWifiSignalStrengthBin].stopRunningLocked( - elapsedRealtime); + elapsedRealtimeMs); } if (strengthBin >= 0) { if (!mWifiSignalStrengthsTimer[strengthBin].isRunningLocked()) { - mWifiSignalStrengthsTimer[strengthBin].startRunningLocked(elapsedRealtime); + mWifiSignalStrengthsTimer[strengthBin].startRunningLocked(elapsedRealtimeMs); } mHistoryCur.states2 = (mHistoryCur.states2&~HistoryItem.STATE2_WIFI_SIGNAL_STRENGTH_MASK) | (strengthBin << HistoryItem.STATE2_WIFI_SIGNAL_STRENGTH_SHIFT); if (DEBUG_HISTORY) Slog.v(TAG, "Wifi signal strength " + strengthBin + " to: " + Integer.toHexString(mHistoryCur.states2)); - addHistoryRecordLocked(elapsedRealtime, uptime); + addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs); } else { - stopAllWifiSignalStrengthTimersLocked(-1); + stopAllWifiSignalStrengthTimersLocked(-1, elapsedRealtimeMs); } mWifiSignalStrengthBin = strengthBin; } @@ -5885,121 +6288,155 @@ public class BatteryStatsImpl extends BatteryStats { @UnsupportedAppUsage public void noteFullWifiLockAcquiredLocked(int uid) { - final long elapsedRealtime = mClocks.elapsedRealtime(); - final long uptime = mClocks.uptimeMillis(); + noteFullWifiLockAcquiredLocked(uid, mClocks.elapsedRealtime(), mClocks.uptimeMillis()); + } + + public void noteFullWifiLockAcquiredLocked(int uid, long elapsedRealtimeMs, long uptimeMs) { if (mWifiFullLockNesting == 0) { mHistoryCur.states |= HistoryItem.STATE_WIFI_FULL_LOCK_FLAG; if (DEBUG_HISTORY) Slog.v(TAG, "WIFI full lock on to: " + Integer.toHexString(mHistoryCur.states)); - addHistoryRecordLocked(elapsedRealtime, uptime); + addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs); } mWifiFullLockNesting++; - getUidStatsLocked(uid).noteFullWifiLockAcquiredLocked(elapsedRealtime); + getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs) + .noteFullWifiLockAcquiredLocked(elapsedRealtimeMs); } @UnsupportedAppUsage public void noteFullWifiLockReleasedLocked(int uid) { - final long elapsedRealtime = mClocks.elapsedRealtime(); - final long uptime = mClocks.uptimeMillis(); + noteFullWifiLockReleasedLocked(uid, mClocks.elapsedRealtime(), mClocks.uptimeMillis()); + } + + public void noteFullWifiLockReleasedLocked(int uid, long elapsedRealtimeMs, long uptimeMs) { mWifiFullLockNesting--; if (mWifiFullLockNesting == 0) { mHistoryCur.states &= ~HistoryItem.STATE_WIFI_FULL_LOCK_FLAG; if (DEBUG_HISTORY) Slog.v(TAG, "WIFI full lock off to: " + Integer.toHexString(mHistoryCur.states)); - addHistoryRecordLocked(elapsedRealtime, uptime); + addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs); } - getUidStatsLocked(uid).noteFullWifiLockReleasedLocked(elapsedRealtime); + getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs) + .noteFullWifiLockReleasedLocked(elapsedRealtimeMs); } int mWifiScanNesting = 0; public void noteWifiScanStartedLocked(int uid) { - final long elapsedRealtime = mClocks.elapsedRealtime(); - final long uptime = mClocks.uptimeMillis(); + noteWifiScanStartedLocked(uid, mClocks.elapsedRealtime(), mClocks.uptimeMillis()); + } + + public void noteWifiScanStartedLocked(int uid, long elapsedRealtimeMs, long uptimeMs) { if (mWifiScanNesting == 0) { mHistoryCur.states |= HistoryItem.STATE_WIFI_SCAN_FLAG; if (DEBUG_HISTORY) Slog.v(TAG, "WIFI scan started for: " + Integer.toHexString(mHistoryCur.states)); - addHistoryRecordLocked(elapsedRealtime, uptime); + addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs); } mWifiScanNesting++; - getUidStatsLocked(uid).noteWifiScanStartedLocked(elapsedRealtime); + getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs) + .noteWifiScanStartedLocked(elapsedRealtimeMs); } public void noteWifiScanStoppedLocked(int uid) { - final long elapsedRealtime = mClocks.elapsedRealtime(); - final long uptime = mClocks.uptimeMillis(); + noteWifiScanStoppedLocked(uid, mClocks.elapsedRealtime(), mClocks.uptimeMillis()); + } + + public void noteWifiScanStoppedLocked(int uid, long elapsedRealtimeMs, long uptimeMs) { mWifiScanNesting--; if (mWifiScanNesting == 0) { mHistoryCur.states &= ~HistoryItem.STATE_WIFI_SCAN_FLAG; if (DEBUG_HISTORY) Slog.v(TAG, "WIFI scan stopped for: " + Integer.toHexString(mHistoryCur.states)); - addHistoryRecordLocked(elapsedRealtime, uptime); + addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs); } - getUidStatsLocked(uid).noteWifiScanStoppedLocked(elapsedRealtime); + getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs) + .noteWifiScanStoppedLocked(elapsedRealtimeMs); } public void noteWifiBatchedScanStartedLocked(int uid, int csph) { + noteWifiBatchedScanStartedLocked(uid, csph, + mClocks.elapsedRealtime(), mClocks.uptimeMillis()); + } + + public void noteWifiBatchedScanStartedLocked(int uid, int csph, + long elapsedRealtimeMs, long uptimeMs) { uid = mapUid(uid); - final long elapsedRealtime = mClocks.elapsedRealtime(); - getUidStatsLocked(uid).noteWifiBatchedScanStartedLocked(csph, elapsedRealtime); + getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs) + .noteWifiBatchedScanStartedLocked(csph, elapsedRealtimeMs); } public void noteWifiBatchedScanStoppedLocked(int uid) { + noteWifiBatchedScanStoppedLocked(uid, mClocks.elapsedRealtime(), mClocks.uptimeMillis()); + } + + public void noteWifiBatchedScanStoppedLocked(int uid, long elapsedRealtimeMs, long uptimeMs) { uid = mapUid(uid); - final long elapsedRealtime = mClocks.elapsedRealtime(); - getUidStatsLocked(uid).noteWifiBatchedScanStoppedLocked(elapsedRealtime); + getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs) + .noteWifiBatchedScanStoppedLocked(elapsedRealtimeMs); } int mWifiMulticastNesting = 0; @UnsupportedAppUsage public void noteWifiMulticastEnabledLocked(int uid) { + noteWifiMulticastEnabledLocked(uid, mClocks.elapsedRealtime(), mClocks.uptimeMillis()); + } + + public void noteWifiMulticastEnabledLocked(int uid, long elapsedRealtimeMs, long uptimeMs) { uid = mapUid(uid); - final long elapsedRealtime = mClocks.elapsedRealtime(); - final long uptime = mClocks.uptimeMillis(); if (mWifiMulticastNesting == 0) { mHistoryCur.states |= HistoryItem.STATE_WIFI_MULTICAST_ON_FLAG; if (DEBUG_HISTORY) Slog.v(TAG, "WIFI multicast on to: " + Integer.toHexString(mHistoryCur.states)); - addHistoryRecordLocked(elapsedRealtime, uptime); + addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs); // Start Wifi Multicast overall timer if (!mWifiMulticastWakelockTimer.isRunningLocked()) { if (DEBUG_HISTORY) Slog.v(TAG, "WiFi Multicast Overall Timer Started"); - mWifiMulticastWakelockTimer.startRunningLocked(elapsedRealtime); + mWifiMulticastWakelockTimer.startRunningLocked(elapsedRealtimeMs); } } mWifiMulticastNesting++; - getUidStatsLocked(uid).noteWifiMulticastEnabledLocked(elapsedRealtime); + getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs) + .noteWifiMulticastEnabledLocked(elapsedRealtimeMs); } @UnsupportedAppUsage public void noteWifiMulticastDisabledLocked(int uid) { + noteWifiMulticastDisabledLocked(uid, mClocks.elapsedRealtime(), mClocks.uptimeMillis()); + } + + public void noteWifiMulticastDisabledLocked(int uid, long elapsedRealtimeMs, long uptimeMs) { uid = mapUid(uid); - final long elapsedRealtime = mClocks.elapsedRealtime(); - final long uptime = mClocks.uptimeMillis(); mWifiMulticastNesting--; if (mWifiMulticastNesting == 0) { mHistoryCur.states &= ~HistoryItem.STATE_WIFI_MULTICAST_ON_FLAG; if (DEBUG_HISTORY) Slog.v(TAG, "WIFI multicast off to: " + Integer.toHexString(mHistoryCur.states)); - addHistoryRecordLocked(elapsedRealtime, uptime); + addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs); // Stop Wifi Multicast overall timer if (mWifiMulticastWakelockTimer.isRunningLocked()) { if (DEBUG_HISTORY) Slog.v(TAG, "Multicast Overall Timer Stopped"); - mWifiMulticastWakelockTimer.stopRunningLocked(elapsedRealtime); + mWifiMulticastWakelockTimer.stopRunningLocked(elapsedRealtimeMs); } } - getUidStatsLocked(uid).noteWifiMulticastDisabledLocked(elapsedRealtime); + getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs) + .noteWifiMulticastDisabledLocked(elapsedRealtimeMs); } public void noteFullWifiLockAcquiredFromSourceLocked(WorkSource ws) { + noteFullWifiLockAcquiredFromSourceLocked(ws, + mClocks.elapsedRealtime(), mClocks.uptimeMillis()); + } + + public void noteFullWifiLockAcquiredFromSourceLocked(WorkSource ws, + long elapsedRealtimeMs, long uptimeMs) { int N = ws.size(); for (int i=0; i<N; i++) { final int uid = mapUid(ws.getUid(i)); - noteFullWifiLockAcquiredLocked(uid); + noteFullWifiLockAcquiredLocked(uid, elapsedRealtimeMs, uptimeMs); } final List<WorkChain> workChains = ws.getWorkChains(); @@ -6007,16 +6444,22 @@ public class BatteryStatsImpl extends BatteryStats { for (int i = 0; i < workChains.size(); ++i) { final WorkChain workChain = workChains.get(i); final int uid = mapUid(workChain.getAttributionUid()); - noteFullWifiLockAcquiredLocked(uid); + noteFullWifiLockAcquiredLocked(uid, elapsedRealtimeMs, uptimeMs); } } } public void noteFullWifiLockReleasedFromSourceLocked(WorkSource ws) { + noteFullWifiLockReleasedFromSourceLocked(ws, + mClocks.elapsedRealtime(), mClocks.uptimeMillis()); + } + + public void noteFullWifiLockReleasedFromSourceLocked(WorkSource ws, + long elapsedRealtimeMs, long uptimeMs) { int N = ws.size(); for (int i=0; i<N; i++) { final int uid = mapUid(ws.getUid(i)); - noteFullWifiLockReleasedLocked(uid); + noteFullWifiLockReleasedLocked(uid, elapsedRealtimeMs, uptimeMs); } final List<WorkChain> workChains = ws.getWorkChains(); @@ -6024,16 +6467,21 @@ public class BatteryStatsImpl extends BatteryStats { for (int i = 0; i < workChains.size(); ++i) { final WorkChain workChain = workChains.get(i); final int uid = mapUid(workChain.getAttributionUid()); - noteFullWifiLockReleasedLocked(uid); + noteFullWifiLockReleasedLocked(uid, elapsedRealtimeMs, uptimeMs); } } } public void noteWifiScanStartedFromSourceLocked(WorkSource ws) { + noteWifiScanStartedFromSourceLocked(ws, mClocks.elapsedRealtime(), mClocks.uptimeMillis()); + } + + public void noteWifiScanStartedFromSourceLocked(WorkSource ws, + long elapsedRealtimeMs, long uptimeMs) { int N = ws.size(); for (int i=0; i<N; i++) { final int uid = mapUid(ws.getUid(i)); - noteWifiScanStartedLocked(uid); + noteWifiScanStartedLocked(uid, elapsedRealtimeMs, uptimeMs); } final List<WorkChain> workChains = ws.getWorkChains(); @@ -6041,16 +6489,21 @@ public class BatteryStatsImpl extends BatteryStats { for (int i = 0; i < workChains.size(); ++i) { final WorkChain workChain = workChains.get(i); final int uid = mapUid(workChain.getAttributionUid()); - noteWifiScanStartedLocked(uid); + noteWifiScanStartedLocked(uid, elapsedRealtimeMs, uptimeMs); } } } public void noteWifiScanStoppedFromSourceLocked(WorkSource ws) { + noteWifiScanStoppedFromSourceLocked(ws, mClocks.elapsedRealtime(), mClocks.uptimeMillis()); + } + + public void noteWifiScanStoppedFromSourceLocked(WorkSource ws, + long elapsedRealtimeMs, long uptimeMs) { int N = ws.size(); for (int i=0; i<N; i++) { final int uid = mapUid(ws.getUid(i)); - noteWifiScanStoppedLocked(uid); + noteWifiScanStoppedLocked(uid, elapsedRealtimeMs, uptimeMs); } final List<WorkChain> workChains = ws.getWorkChains(); @@ -6058,35 +6511,48 @@ public class BatteryStatsImpl extends BatteryStats { for (int i = 0; i < workChains.size(); ++i) { final WorkChain workChain = workChains.get(i); final int uid = mapUid(workChain.getAttributionUid()); - noteWifiScanStoppedLocked(uid); + noteWifiScanStoppedLocked(uid, elapsedRealtimeMs, uptimeMs); } } } public void noteWifiBatchedScanStartedFromSourceLocked(WorkSource ws, int csph) { + noteWifiBatchedScanStartedFromSourceLocked(ws, csph, + mClocks.elapsedRealtime(), mClocks.uptimeMillis()); + } + + public void noteWifiBatchedScanStartedFromSourceLocked(WorkSource ws, int csph, + long elapsedRealtimeMs, long uptimeMs) { int N = ws.size(); for (int i=0; i<N; i++) { - noteWifiBatchedScanStartedLocked(ws.getUid(i), csph); + noteWifiBatchedScanStartedLocked(ws.getUid(i), csph, elapsedRealtimeMs, uptimeMs); } final List<WorkChain> workChains = ws.getWorkChains(); if (workChains != null) { for (int i = 0; i < workChains.size(); ++i) { - noteWifiBatchedScanStartedLocked(workChains.get(i).getAttributionUid(), csph); + noteWifiBatchedScanStartedLocked(workChains.get(i).getAttributionUid(), csph, + elapsedRealtimeMs, uptimeMs); } } } public void noteWifiBatchedScanStoppedFromSourceLocked(WorkSource ws) { + noteWifiBatchedScanStoppedFromSourceLocked(ws, + mClocks.elapsedRealtime(), mClocks.uptimeMillis()); + } + public void noteWifiBatchedScanStoppedFromSourceLocked(WorkSource ws, + long elapsedRealtimeMs, long uptimeMs) { int N = ws.size(); for (int i=0; i<N; i++) { - noteWifiBatchedScanStoppedLocked(ws.getUid(i)); + noteWifiBatchedScanStoppedLocked(ws.getUid(i), elapsedRealtimeMs, uptimeMs); } final List<WorkChain> workChains = ws.getWorkChains(); if (workChains != null) { for (int i = 0; i < workChains.size(); ++i) { - noteWifiBatchedScanStoppedLocked(workChains.get(i).getAttributionUid()); + noteWifiBatchedScanStoppedLocked(workChains.get(i).getAttributionUid(), + elapsedRealtimeMs, uptimeMs); } } } @@ -6147,9 +6613,16 @@ public class BatteryStatsImpl extends BatteryStats { */ public void noteBinderCallStats(int workSourceUid, long incrementalCallCount, Collection<BinderCallsStats.CallStat> callStats, int[] binderThreadNativeTids) { + noteBinderCallStats(workSourceUid, incrementalCallCount, callStats, binderThreadNativeTids, + mClocks.elapsedRealtime(), mClocks.uptimeMillis()); + } + + public void noteBinderCallStats(int workSourceUid, long incrementalCallCount, + Collection<BinderCallsStats.CallStat> callStats, int[] binderThreadNativeTids, + long elapsedRealtimeMs, long uptimeMs) { synchronized (this) { - getUidStatsLocked(workSourceUid).noteBinderCallStatsLocked(incrementalCallCount, - callStats); + getUidStatsLocked(workSourceUid, elapsedRealtimeMs, uptimeMs) + .noteBinderCallStatsLocked(incrementalCallCount, callStats); mSystemServerCpuThreadReader.setBinderThreadNativeTids(binderThreadNativeTids); } } @@ -6182,17 +6655,17 @@ public class BatteryStatsImpl extends BatteryStats { for (int i = 0; i < mUidStats.size(); i++) { Uid uid = mUidStats.valueAt(i); - long totalTimeForUid = 0; + long totalTimeForUidUs = 0; int totalCallCountForUid = 0; ArraySet<BinderCallStats> binderCallStats = uid.mBinderCallStats; for (int j = binderCallStats.size() - 1; j >= 0; j--) { BinderCallStats stats = binderCallStats.valueAt(j); totalCallCountForUid += stats.callCount; if (stats.recordedCallCount > 0) { - totalTimeForUid += + totalTimeForUidUs += stats.callCount * stats.recordedCpuTimeMicros / stats.recordedCallCount; } else if (totalRecordedCallCount > 0) { - totalTimeForUid += + totalTimeForUidUs += stats.callCount * totalRecordedCallTimeMicros / totalRecordedCallCount; } } @@ -6200,13 +6673,13 @@ public class BatteryStatsImpl extends BatteryStats { if (totalCallCountForUid < uid.mBinderCallCount && totalRecordedCallCount > 0) { // Estimate remaining calls, which were not tracked because of binder call // stats sampling - totalTimeForUid += + totalTimeForUidUs += (uid.mBinderCallCount - totalCallCountForUid) * totalRecordedCallTimeMicros / totalRecordedCallCount; } - uid.mSystemServiceTimeUs = totalTimeForUid; - totalSystemServiceTimeMicros += totalTimeForUid; + uid.mSystemServiceTimeUs = totalTimeForUidUs; + totalSystemServiceTimeMicros += totalTimeForUidUs; } for (int i = 0; i < mUidStats.size(); i++) { @@ -6296,9 +6769,9 @@ public class BatteryStatsImpl extends BatteryStats { @Override public long getLongestDeviceIdleModeTime(int mode) { switch (mode) { case DEVICE_IDLE_MODE_LIGHT: - return mLongestLightIdleTime; + return mLongestLightIdleTimeMs; case DEVICE_IDLE_MODE_DEEP: - return mLongestFullIdleTime; + return mLongestFullIdleTimeMs; } return 0; } @@ -6328,12 +6801,12 @@ public class BatteryStatsImpl extends BatteryStats { } @Override public long getGpsSignalQualityTime(int strengthBin, - long elapsedRealtimeUs, int which) { + long elapsedRealtimeUs, int which) { if (strengthBin < 0 || strengthBin >= GnssMetrics.NUM_GPS_SIGNAL_QUALITY_LEVELS) { return 0; } return mGpsSignalQualityTimer[strengthBin].getTotalTimeLocked( - elapsedRealtimeUs, which); + elapsedRealtimeUs, which); } @Override public long getGpsBatteryDrainMaMs() { @@ -6344,11 +6817,11 @@ public class BatteryStatsImpl extends BatteryStats { } double energyUsedMaMs = 0.0; final int which = STATS_SINCE_CHARGED; - final long rawRealtime = SystemClock.elapsedRealtime() * 1000; + final long rawRealtimeUs = SystemClock.elapsedRealtime() * 1000; for(int i=0; i < GnssMetrics.NUM_GPS_SIGNAL_QUALITY_LEVELS; i++) { energyUsedMaMs - += mPowerProfile.getAveragePower(PowerProfile.POWER_GPS_SIGNAL_QUALITY_BASED, i) - * (getGpsSignalQualityTime(i, rawRealtime, which) / 1000); + += mPowerProfile.getAveragePower(PowerProfile.POWER_GPS_SIGNAL_QUALITY_BASED, i) + * (getGpsSignalQualityTime(i, rawRealtimeUs, which) / 1000); } return (long) energyUsedMaMs; } @@ -6562,18 +7035,18 @@ public class BatteryStatsImpl extends BatteryStats { } @Override public long getStartClockTime() { - final long currentTime = System.currentTimeMillis(); - if ((currentTime > MILLISECONDS_IN_YEAR - && mStartClockTime < (currentTime - MILLISECONDS_IN_YEAR)) - || (mStartClockTime > currentTime)) { + final long currentTimeMs = System.currentTimeMillis(); + if ((currentTimeMs > MILLISECONDS_IN_YEAR + && mStartClockTimeMs < (currentTimeMs - MILLISECONDS_IN_YEAR)) + || (mStartClockTimeMs > currentTimeMs)) { // If the start clock time has changed by more than a year, then presumably // the previous time was completely bogus. So we are going to figure out a // new time based on how much time has elapsed since we started counting. - recordCurrentTimeChangeLocked(currentTime, mClocks.elapsedRealtime(), + recordCurrentTimeChangeLocked(currentTimeMs, mClocks.elapsedRealtime(), mClocks.uptimeMillis()); - return currentTime - (mClocks.elapsedRealtime() - (mRealtimeStart / 1000)); + return currentTimeMs - (mClocks.elapsedRealtime() - (mRealtimeStartUs / 1000)); } - return mStartClockTime; + return mStartClockTimeMs; } @Override public String getStartPlatformVersion() { @@ -6597,29 +7070,32 @@ public class BatteryStatsImpl extends BatteryStats { return mUidStats; } - private static <T extends TimeBaseObs> boolean resetIfNotNull(T t, boolean detachIfReset) { + private static <T extends TimeBaseObs> boolean resetIfNotNull(T t, boolean detachIfReset, + long elapsedRealtimeUs) { if (t != null) { - return t.reset(detachIfReset); + return t.reset(detachIfReset, elapsedRealtimeUs); } return true; } - private static <T extends TimeBaseObs> boolean resetIfNotNull(T[] t, boolean detachIfReset) { + private static <T extends TimeBaseObs> boolean resetIfNotNull(T[] t, boolean detachIfReset, + long elapsedRealtimeUs) { if (t != null) { boolean ret = true; for (int i = 0; i < t.length; i++) { - ret &= resetIfNotNull(t[i], detachIfReset); + ret &= resetIfNotNull(t[i], detachIfReset, elapsedRealtimeUs); } return ret; } return true; } - private static <T extends TimeBaseObs> boolean resetIfNotNull(T[][] t, boolean detachIfReset) { + private static <T extends TimeBaseObs> boolean resetIfNotNull(T[][] t, boolean detachIfReset, + long elapsedRealtimeUs) { if (t != null) { boolean ret = true; for (int i = 0; i < t.length; i++) { - ret &= resetIfNotNull(t[i], detachIfReset); + ret &= resetIfNotNull(t[i], detachIfReset, elapsedRealtimeUs); } return ret; } @@ -6627,9 +7103,9 @@ public class BatteryStatsImpl extends BatteryStats { } private static boolean resetIfNotNull(ControllerActivityCounterImpl counter, - boolean detachIfReset) { + boolean detachIfReset, long elapsedRealtimeUs) { if (counter != null) { - counter.reset(detachIfReset); + counter.reset(detachIfReset, elapsedRealtimeUs); } return true; } @@ -6812,10 +7288,10 @@ public class BatteryStatsImpl extends BatteryStats { /** * The CPU times we had at the last history details update. */ - long mLastStepUserTime; - long mLastStepSystemTime; - long mCurStepUserTime; - long mCurStepSystemTime; + long mLastStepUserTimeMs; + long mLastStepSystemTimeMs; + long mCurStepUserTimeMs; + long mCurStepSystemTimeMs; LongSamplingCounter mUserCpuTime; LongSamplingCounter mSystemCpuTime; @@ -6915,17 +7391,19 @@ public class BatteryStatsImpl extends BatteryStats { private double mProportionalSystemServiceUsage; public Uid(BatteryStatsImpl bsi, int uid) { + this(bsi, uid, bsi.mClocks.elapsedRealtime(), bsi.mClocks.uptimeMillis()); + } + + public Uid(BatteryStatsImpl bsi, int uid, long elapsedRealtimeMs, long uptimeMs) { mBsi = bsi; mUid = uid; /* Observer list of TimeBase object in Uid is short */ mOnBatteryBackgroundTimeBase = new TimeBase(false); - mOnBatteryBackgroundTimeBase.init(mBsi.mClocks.uptimeMillis() * 1000, - mBsi.mClocks.elapsedRealtime() * 1000); + mOnBatteryBackgroundTimeBase.init(uptimeMs * 1000, elapsedRealtimeMs * 1000); /* Observer list of TimeBase object in Uid is short */ mOnBatteryScreenOffBackgroundTimeBase = new TimeBase(false); - mOnBatteryScreenOffBackgroundTimeBase.init(mBsi.mClocks.uptimeMillis() * 1000, - mBsi.mClocks.elapsedRealtime() * 1000); + mOnBatteryScreenOffBackgroundTimeBase.init(uptimeMs * 1000, elapsedRealtimeMs * 1000); mUserCpuTime = new LongSamplingCounter(mBsi.mOnBatteryTimeBase); mSystemCpuTime = new LongSamplingCounter(mBsi.mOnBatteryTimeBase); @@ -7520,13 +7998,13 @@ public class BatteryStatsImpl extends BatteryStats { return mVibratorOnTimer; } - public void noteVibratorOnLocked(long durationMillis) { - createVibratorOnTimerLocked().addDuration(mBsi, durationMillis); + public void noteVibratorOnLocked(long durationMillis, long elapsedRealtimeMs) { + createVibratorOnTimerLocked().addDuration(mBsi, durationMillis, elapsedRealtimeMs); } - public void noteVibratorOffLocked() { + public void noteVibratorOffLocked(long elapsedRealtimeMs) { if (mVibratorOnTimer != null) { - mVibratorOnTimer.abortLastDuration(mBsi); + mVibratorOnTimer.abortLastDuration(mBsi, elapsedRealtimeMs); } } @@ -7962,58 +8440,58 @@ public class BatteryStatsImpl extends BatteryStats { * inactive so can be dropped. */ @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE) - public boolean reset(long uptime, long realtime) { + public boolean reset(long uptimeUs, long realtimeUs) { boolean active = false; - mOnBatteryBackgroundTimeBase.init(uptime, realtime); - mOnBatteryScreenOffBackgroundTimeBase.init(uptime, realtime); + mOnBatteryBackgroundTimeBase.init(uptimeUs, realtimeUs); + mOnBatteryScreenOffBackgroundTimeBase.init(uptimeUs, realtimeUs); if (mWifiRunningTimer != null) { - active |= !mWifiRunningTimer.reset(false); + active |= !mWifiRunningTimer.reset(false, realtimeUs); active |= mWifiRunning; } if (mFullWifiLockTimer != null) { - active |= !mFullWifiLockTimer.reset(false); + active |= !mFullWifiLockTimer.reset(false, realtimeUs); active |= mFullWifiLockOut; } if (mWifiScanTimer != null) { - active |= !mWifiScanTimer.reset(false); + active |= !mWifiScanTimer.reset(false, realtimeUs); active |= mWifiScanStarted; } if (mWifiBatchedScanTimer != null) { for (int i = 0; i < NUM_WIFI_BATCHED_SCAN_BINS; i++) { if (mWifiBatchedScanTimer[i] != null) { - active |= !mWifiBatchedScanTimer[i].reset(false); + active |= !mWifiBatchedScanTimer[i].reset(false, realtimeUs); } } active |= (mWifiBatchedScanBinStarted != NO_BATCHED_SCAN_STARTED); } if (mWifiMulticastTimer != null) { - active |= !mWifiMulticastTimer.reset(false); + active |= !mWifiMulticastTimer.reset(false, realtimeUs); active |= (mWifiMulticastWakelockCount > 0); } - active |= !resetIfNotNull(mAudioTurnedOnTimer, false); - active |= !resetIfNotNull(mVideoTurnedOnTimer, false); - active |= !resetIfNotNull(mFlashlightTurnedOnTimer, false); - active |= !resetIfNotNull(mCameraTurnedOnTimer, false); - active |= !resetIfNotNull(mForegroundActivityTimer, false); - active |= !resetIfNotNull(mForegroundServiceTimer, false); - active |= !resetIfNotNull(mAggregatedPartialWakelockTimer, false); - active |= !resetIfNotNull(mBluetoothScanTimer, false); - active |= !resetIfNotNull(mBluetoothUnoptimizedScanTimer, false); + active |= !resetIfNotNull(mAudioTurnedOnTimer, false, realtimeUs); + active |= !resetIfNotNull(mVideoTurnedOnTimer, false, realtimeUs); + active |= !resetIfNotNull(mFlashlightTurnedOnTimer, false, realtimeUs); + active |= !resetIfNotNull(mCameraTurnedOnTimer, false, realtimeUs); + active |= !resetIfNotNull(mForegroundActivityTimer, false, realtimeUs); + active |= !resetIfNotNull(mForegroundServiceTimer, false, realtimeUs); + active |= !resetIfNotNull(mAggregatedPartialWakelockTimer, false, realtimeUs); + active |= !resetIfNotNull(mBluetoothScanTimer, false, realtimeUs); + active |= !resetIfNotNull(mBluetoothUnoptimizedScanTimer, false, realtimeUs); - resetIfNotNull(mBluetoothScanResultCounter, false); - resetIfNotNull(mBluetoothScanResultBgCounter, false); + resetIfNotNull(mBluetoothScanResultCounter, false, realtimeUs); + resetIfNotNull(mBluetoothScanResultBgCounter, false, realtimeUs); if (mProcessStateTimer != null) { for (int i = 0; i < NUM_PROCESS_STATE; i++) { - active |= !resetIfNotNull(mProcessStateTimer[i], false); + active |= !resetIfNotNull(mProcessStateTimer[i], false, realtimeUs); } active |= (mProcessState != ActivityManager.PROCESS_STATE_NONEXISTENT); } if (mVibratorOnTimer != null) { - if (mVibratorOnTimer.reset(false)) { + if (mVibratorOnTimer.reset(false, realtimeUs)) { mVibratorOnTimer.detach(); mVibratorOnTimer = null; } else { @@ -8021,80 +8499,81 @@ public class BatteryStatsImpl extends BatteryStats { } } - resetIfNotNull(mUserActivityCounters, false); + resetIfNotNull(mUserActivityCounters, false, realtimeUs); - resetIfNotNull(mNetworkByteActivityCounters, false); - resetIfNotNull(mNetworkPacketActivityCounters, false); - resetIfNotNull(mMobileRadioActiveTime, false); - resetIfNotNull(mMobileRadioActiveCount, false); + resetIfNotNull(mNetworkByteActivityCounters, false, realtimeUs); + resetIfNotNull(mNetworkPacketActivityCounters, false, realtimeUs); + resetIfNotNull(mMobileRadioActiveTime, false, realtimeUs); + resetIfNotNull(mMobileRadioActiveCount, false, realtimeUs); - resetIfNotNull(mWifiControllerActivity, false); - resetIfNotNull(mBluetoothControllerActivity, false); - resetIfNotNull(mModemControllerActivity, false); + resetIfNotNull(mWifiControllerActivity, false, realtimeUs); + resetIfNotNull(mBluetoothControllerActivity, false, realtimeUs); + resetIfNotNull(mModemControllerActivity, false, realtimeUs); - resetIfNotNull(mUserCpuTime, false); - resetIfNotNull(mSystemCpuTime, false); + resetIfNotNull(mUserCpuTime, false, realtimeUs); + resetIfNotNull(mSystemCpuTime, false, realtimeUs); - resetIfNotNull(mCpuClusterSpeedTimesUs, false); + resetIfNotNull(mCpuClusterSpeedTimesUs, false, realtimeUs); - resetIfNotNull(mCpuFreqTimeMs, false); - resetIfNotNull(mScreenOffCpuFreqTimeMs, false); + resetIfNotNull(mCpuFreqTimeMs, false, realtimeUs /* unused */); + resetIfNotNull(mScreenOffCpuFreqTimeMs, false, realtimeUs /* unused */); - resetIfNotNull(mCpuActiveTimeMs, false); - resetIfNotNull(mCpuClusterTimesMs, false); + resetIfNotNull(mCpuActiveTimeMs, false, realtimeUs /* unused */); + resetIfNotNull(mCpuClusterTimesMs, false, realtimeUs /* unused */); - resetIfNotNull(mProcStateTimeMs, false); + resetIfNotNull(mProcStateTimeMs, false, realtimeUs /* unused */); - resetIfNotNull(mProcStateScreenOffTimeMs, false); + resetIfNotNull(mProcStateScreenOffTimeMs, false, realtimeUs /* unused */); - resetIfNotNull(mMobileRadioApWakeupCount, false); + resetIfNotNull(mMobileRadioApWakeupCount, false, realtimeUs); - resetIfNotNull(mWifiRadioApWakeupCount, false); + resetIfNotNull(mWifiRadioApWakeupCount, false, realtimeUs); final ArrayMap<String, Wakelock> wakeStats = mWakelockStats.getMap(); for (int iw=wakeStats.size()-1; iw>=0; iw--) { Wakelock wl = wakeStats.valueAt(iw); - if (wl.reset()) { + if (wl.reset(realtimeUs)) { wakeStats.removeAt(iw); } else { active = true; } } - mWakelockStats.cleanup(); + final long realtimeMs = realtimeUs / 1000; + mWakelockStats.cleanup(realtimeMs); final ArrayMap<String, DualTimer> syncStats = mSyncStats.getMap(); for (int is=syncStats.size()-1; is>=0; is--) { DualTimer timer = syncStats.valueAt(is); - if (timer.reset(false)) { + if (timer.reset(false, realtimeUs)) { syncStats.removeAt(is); timer.detach(); } else { active = true; } } - mSyncStats.cleanup(); + mSyncStats.cleanup(realtimeMs); final ArrayMap<String, DualTimer> jobStats = mJobStats.getMap(); for (int ij=jobStats.size()-1; ij>=0; ij--) { DualTimer timer = jobStats.valueAt(ij); - if (timer.reset(false)) { + if (timer.reset(false, realtimeUs)) { jobStats.removeAt(ij); timer.detach(); } else { active = true; } } - mJobStats.cleanup(); + mJobStats.cleanup(realtimeMs); mJobCompletions.clear(); - resetIfNotNull(mJobsDeferredEventCount, false); - resetIfNotNull(mJobsDeferredCount, false); - resetIfNotNull(mJobsFreshnessTimeMs, false); - resetIfNotNull(mJobsFreshnessBuckets, false); + resetIfNotNull(mJobsDeferredEventCount, false, realtimeUs); + resetIfNotNull(mJobsDeferredCount, false, realtimeUs); + resetIfNotNull(mJobsFreshnessTimeMs, false, realtimeUs /* unused */); + resetIfNotNull(mJobsFreshnessBuckets, false, realtimeUs); for (int ise = mSensorStats.size() - 1; ise >= 0; ise--) { Sensor s = mSensorStats.valueAt(ise); - if (s.reset()) { + if (s.reset(realtimeUs)) { mSensorStats.removeAt(ise); } else { active = true; @@ -8128,8 +8607,8 @@ public class BatteryStatsImpl extends BatteryStats { mProportionalSystemServiceUsage = 0; - mLastStepUserTime = mLastStepSystemTime = 0; - mCurStepUserTime = mCurStepSystemTime = 0; + mLastStepUserTimeMs = mLastStepSystemTimeMs = 0; + mCurStepUserTimeMs = mCurStepSystemTimeMs = 0; return !active; @@ -8943,13 +9422,13 @@ public class BatteryStatsImpl extends BatteryStats { return new DualTimer(mBsi.mClocks, mUid, type, pool, timeBase, bgTimeBase, in); } - boolean reset() { + boolean reset(long elapsedRealtimeUs) { boolean wlactive = false; - wlactive |= !resetIfNotNull(mTimerFull,false); - wlactive |= !resetIfNotNull(mTimerPartial,false); - wlactive |= !resetIfNotNull(mTimerWindow,false); - wlactive |= !resetIfNotNull(mTimerDraw,false); + wlactive |= !resetIfNotNull(mTimerFull, false, elapsedRealtimeUs); + wlactive |= !resetIfNotNull(mTimerPartial, false, elapsedRealtimeUs); + wlactive |= !resetIfNotNull(mTimerWindow, false, elapsedRealtimeUs); + wlactive |= !resetIfNotNull(mTimerDraw, false, elapsedRealtimeUs); if (!wlactive) { detachIfNotNull(mTimerFull); @@ -9040,8 +9519,8 @@ public class BatteryStatsImpl extends BatteryStats { return new DualTimer(mBsi.mClocks, mUid, 0, pool, timeBase, bgTimeBase, in); } - boolean reset() { - if (mTimer.reset(true)) { + boolean reset(long elapsedRealtimeUs) { + if (mTimer.reset(true, elapsedRealtimeUs)) { mTimer = null; return true; } @@ -9103,17 +9582,17 @@ public class BatteryStatsImpl extends BatteryStats { /** * Total time (in ms) spent executing in user code. */ - long mUserTime; + long mUserTimeMs; /** * Total time (in ms) spent executing in kernel code. */ - long mSystemTime; + long mSystemTimeMs; /** * Amount of time (in ms) the process was running in the foreground. */ - long mForegroundTime; + long mForegroundTimeMs; /** * Number of times the process has been started. @@ -9138,14 +9617,16 @@ public class BatteryStatsImpl extends BatteryStats { mBsi.mOnBatteryTimeBase.add(this); } - public void onTimeStarted(long elapsedRealtime, long baseUptime, long baseRealtime) { + public void onTimeStarted(long elapsedRealtimeUs, long baseUptimeUs, + long baseRealtimeUs) { } - public void onTimeStopped(long elapsedRealtime, long baseUptime, long baseRealtime) { + public void onTimeStopped(long elapsedRealtimeUs, long baseUptimeUs, + long baseRealtimeUs) { } @Override - public boolean reset(boolean detachIfReset) { + public boolean reset(boolean detachIfReset, long elapsedRealtimeUs) { if (detachIfReset) { this.detach(); } @@ -9169,14 +9650,14 @@ public class BatteryStatsImpl extends BatteryStats { return null; } - public void addExcessiveCpu(long overTime, long usedTime) { + public void addExcessiveCpu(long overTimeMs, long usedTimeMs) { if (mExcessivePower == null) { mExcessivePower = new ArrayList<ExcessivePower>(); } ExcessivePower ew = new ExcessivePower(); ew.type = ExcessivePower.TYPE_CPU; - ew.overTime = overTime; - ew.usedTime = usedTime; + ew.overTime = overTimeMs; + ew.usedTime = usedTimeMs; mExcessivePower.add(ew); } @@ -9219,9 +9700,9 @@ public class BatteryStatsImpl extends BatteryStats { } void writeToParcelLocked(Parcel out) { - out.writeLong(mUserTime); - out.writeLong(mSystemTime); - out.writeLong(mForegroundTime); + out.writeLong(mUserTimeMs); + out.writeLong(mSystemTimeMs); + out.writeLong(mForegroundTimeMs); out.writeInt(mStarts); out.writeInt(mNumCrashes); out.writeInt(mNumAnrs); @@ -9229,9 +9710,9 @@ public class BatteryStatsImpl extends BatteryStats { } void readFromParcelLocked(Parcel in) { - mUserTime = in.readLong(); - mSystemTime = in.readLong(); - mForegroundTime = in.readLong(); + mUserTimeMs = in.readLong(); + mSystemTimeMs = in.readLong(); + mForegroundTimeMs = in.readLong(); mStarts = in.readInt(); mNumCrashes = in.readInt(); mNumAnrs = in.readInt(); @@ -9239,20 +9720,20 @@ public class BatteryStatsImpl extends BatteryStats { } @UnsupportedAppUsage - public void addCpuTimeLocked(int utime, int stime) { - addCpuTimeLocked(utime, stime, mBsi.mOnBatteryTimeBase.isRunning()); + public void addCpuTimeLocked(int utimeMs, int stimeMs) { + addCpuTimeLocked(utimeMs, stimeMs, mBsi.mOnBatteryTimeBase.isRunning()); } - public void addCpuTimeLocked(int utime, int stime, boolean isRunning) { + public void addCpuTimeLocked(int utimeMs, int stimeMs, boolean isRunning) { if (isRunning) { - mUserTime += utime; - mSystemTime += stime; + mUserTimeMs += utimeMs; + mSystemTimeMs += stimeMs; } } @UnsupportedAppUsage - public void addForegroundTimeLocked(long ttime) { - mForegroundTime += ttime; + public void addForegroundTimeLocked(long ttimeMs) { + mForegroundTimeMs += ttimeMs; } @UnsupportedAppUsage @@ -9276,19 +9757,19 @@ public class BatteryStatsImpl extends BatteryStats { @Override @UnsupportedAppUsage public long getUserTime(int which) { - return mUserTime; + return mUserTimeMs; } @Override @UnsupportedAppUsage public long getSystemTime(int which) { - return mSystemTime; + return mSystemTimeMs; } @Override @UnsupportedAppUsage public long getForegroundTime(int which) { - return mForegroundTime; + return mForegroundTimeMs; } @Override @@ -9333,14 +9814,16 @@ public class BatteryStatsImpl extends BatteryStats { mBsi.mOnBatteryScreenOffTimeBase.add(this); } - public void onTimeStarted(long elapsedRealtime, long baseUptime, long baseRealtime) { + public void onTimeStarted(long elapsedRealtimeUs, long baseUptimeUs, + long baseRealtimeUs) { } - public void onTimeStopped(long elapsedRealtime, long baseUptime, long baseRealtime) { + public void onTimeStopped(long elapsedRealtimeUs, long baseUptimeUs, + long baseRealtimeUs) { } @Override - public boolean reset(boolean detachIfReset) { + public boolean reset(boolean detachIfReset, long elapsedRealtimeUs) { if (detachIfReset) { this.detach(); } @@ -9430,13 +9913,13 @@ public class BatteryStatsImpl extends BatteryStats { /** * Total time (ms in battery uptime) the service has been left started. */ - protected long mStartTime; + protected long mStartTimeMs; /** * If service has been started and not yet stopped, this is * when it was started. */ - protected long mRunningSince; + protected long mRunningSinceMs; /** * True if we are currently running. @@ -9451,13 +9934,13 @@ public class BatteryStatsImpl extends BatteryStats { /** * Total time (ms in battery uptime) the service has been left launched. */ - protected long mLaunchedTime; + protected long mLaunchedTimeMs; /** * If service has been launched and not yet exited, this is * when it was launched (ms in battery uptime). */ - protected long mLaunchedSince; + protected long mLaunchedSinceMs; /** * True if we are currently launched. @@ -9477,16 +9960,16 @@ public class BatteryStatsImpl extends BatteryStats { mBsi.mOnBatteryTimeBase.add(this); } - public void onTimeStarted(long elapsedRealtime, long baseUptime, - long baseRealtime) { + public void onTimeStarted(long elapsedRealtimeUs, long baseUptimeUs, + long baseRealtimeUs) { } - public void onTimeStopped(long elapsedRealtime, long baseUptime, - long baseRealtime) { + public void onTimeStopped(long elapsedRealtimeUs, long baseUptimeUs, + long baseRealtimeUs) { } @Override - public boolean reset(boolean detachIfReset) { + public boolean reset(boolean detachIfReset, long elapsedRealtimeUs) { if (detachIfReset) { this.detach(); } @@ -9495,59 +9978,68 @@ public class BatteryStatsImpl extends BatteryStats { /** * Remove this Serv as a listener from the time base. - */ + Ms*/ @Override public void detach() { mBsi.mOnBatteryTimeBase.remove(this); } public void readFromParcelLocked(Parcel in) { - mStartTime = in.readLong(); - mRunningSince = in.readLong(); + mStartTimeMs = in.readLong(); + mRunningSinceMs = in.readLong(); mRunning = in.readInt() != 0; mStarts = in.readInt(); - mLaunchedTime = in.readLong(); - mLaunchedSince = in.readLong(); + mLaunchedTimeMs = in.readLong(); + mLaunchedSinceMs = in.readLong(); mLaunched = in.readInt() != 0; mLaunches = in.readInt(); } public void writeToParcelLocked(Parcel out) { - out.writeLong(mStartTime); - out.writeLong(mRunningSince); + out.writeLong(mStartTimeMs); + out.writeLong(mRunningSinceMs); out.writeInt(mRunning ? 1 : 0); out.writeInt(mStarts); - out.writeLong(mLaunchedTime); - out.writeLong(mLaunchedSince); + out.writeLong(mLaunchedTimeMs); + out.writeLong(mLaunchedSinceMs); out.writeInt(mLaunched ? 1 : 0); out.writeInt(mLaunches); } - public long getLaunchTimeToNowLocked(long batteryUptime) { - if (!mLaunched) return mLaunchedTime; - return mLaunchedTime + batteryUptime - mLaunchedSince; + public long getLaunchTimeToNowLocked(long batteryUptimeMs) { + if (!mLaunched) return mLaunchedTimeMs; + return mLaunchedTimeMs + batteryUptimeMs - mLaunchedSinceMs; } - public long getStartTimeToNowLocked(long batteryUptime) { - if (!mRunning) return mStartTime; - return mStartTime + batteryUptime - mRunningSince; + public long getStartTimeToNowLocked(long batteryUptimeMs) { + if (!mRunning) return mStartTimeMs; + return mStartTimeMs + batteryUptimeMs - mRunningSinceMs; } @UnsupportedAppUsage public void startLaunchedLocked() { + startLaunchedLocked(mBsi.mClocks.uptimeMillis()); + } + + public void startLaunchedLocked(long uptimeMs) { if (!mLaunched) { mLaunches++; - mLaunchedSince = mBsi.getBatteryUptimeLocked(); + mLaunchedSinceMs = mBsi.getBatteryUptimeLocked(uptimeMs) / 1000; mLaunched = true; } } @UnsupportedAppUsage public void stopLaunchedLocked() { + stopLaunchedLocked(mBsi.mClocks.uptimeMillis()); + } + + public void stopLaunchedLocked(long uptimeMs) { if (mLaunched) { - long time = mBsi.getBatteryUptimeLocked() - mLaunchedSince; - if (time > 0) { - mLaunchedTime += time; + long timeMs = mBsi.getBatteryUptimeLocked(uptimeMs) / 1000 + - mLaunchedSinceMs; + if (timeMs > 0) { + mLaunchedTimeMs += timeMs; } else { mLaunches--; } @@ -9557,19 +10049,28 @@ public class BatteryStatsImpl extends BatteryStats { @UnsupportedAppUsage public void startRunningLocked() { + startRunningLocked(mBsi.mClocks.uptimeMillis()); + } + + public void startRunningLocked(long uptimeMs) { if (!mRunning) { mStarts++; - mRunningSince = mBsi.getBatteryUptimeLocked(); + mRunningSinceMs = mBsi.getBatteryUptimeLocked(uptimeMs) / 1000; mRunning = true; } } @UnsupportedAppUsage public void stopRunningLocked() { + stopRunningLocked(mBsi.mClocks.uptimeMillis()); + } + + public void stopRunningLocked(long uptimeMs) { if (mRunning) { - long time = mBsi.getBatteryUptimeLocked() - mRunningSince; - if (time > 0) { - mStartTime += time; + long timeMs = mBsi.getBatteryUptimeLocked(uptimeMs) / 1000 + - mRunningSinceMs; + if (timeMs > 0) { + mStartTimeMs += timeMs; } else { mStarts--; } @@ -9619,6 +10120,12 @@ public class BatteryStatsImpl extends BatteryStats { @GuardedBy("mBsi") public void updateUidProcessStateLocked(int procState) { + updateUidProcessStateLocked(procState, + mBsi.mClocks.elapsedRealtime(), mBsi.mClocks.uptimeMillis()); + } + + public void updateUidProcessStateLocked(int procState, + long elapsedRealtimeMs, long uptimeMs) { int uidRunningState; // Make special note of Foreground Services final boolean userAwareService = @@ -9629,10 +10136,7 @@ public class BatteryStatsImpl extends BatteryStats { return; } - final long elapsedRealtimeMs = mBsi.mClocks.elapsedRealtime(); if (mProcessState != uidRunningState) { - final long uptimeMs = mBsi.mClocks.uptimeMillis(); - if (mProcessState != ActivityManager.PROCESS_STATE_NONEXISTENT) { mProcessStateTimer[mProcessState].stopRunningLocked(elapsedRealtimeMs); @@ -9789,28 +10293,28 @@ public class BatteryStatsImpl extends BatteryStats { } public void noteStartSyncLocked(String name, long elapsedRealtimeMs) { - DualTimer t = mSyncStats.startObject(name); + DualTimer t = mSyncStats.startObject(name, elapsedRealtimeMs); if (t != null) { t.startRunningLocked(elapsedRealtimeMs); } } public void noteStopSyncLocked(String name, long elapsedRealtimeMs) { - DualTimer t = mSyncStats.stopObject(name); + DualTimer t = mSyncStats.stopObject(name, elapsedRealtimeMs); if (t != null) { t.stopRunningLocked(elapsedRealtimeMs); } } public void noteStartJobLocked(String name, long elapsedRealtimeMs) { - DualTimer t = mJobStats.startObject(name); + DualTimer t = mJobStats.startObject(name, elapsedRealtimeMs); if (t != null) { t.startRunningLocked(elapsedRealtimeMs); } } public void noteStopJobLocked(String name, long elapsedRealtimeMs, int stopReason) { - DualTimer t = mJobStats.stopObject(name); + DualTimer t = mJobStats.stopObject(name, elapsedRealtimeMs); if (t != null) { t.stopRunningLocked(elapsedRealtimeMs); } @@ -9873,7 +10377,7 @@ public class BatteryStatsImpl extends BatteryStats { } public void noteStartWakeLocked(int pid, String name, int type, long elapsedRealtimeMs) { - Wakelock wl = mWakelockStats.startObject(name); + Wakelock wl = mWakelockStats.startObject(name, elapsedRealtimeMs); if (wl != null) { getWakelockTimerLocked(wl, type).startRunningLocked(elapsedRealtimeMs); } @@ -9889,7 +10393,7 @@ public class BatteryStatsImpl extends BatteryStats { } public void noteStopWakeLocked(int pid, String name, int type, long elapsedRealtimeMs) { - Wakelock wl = mWakelockStats.stopObject(name); + Wakelock wl = mWakelockStats.stopObject(name, elapsedRealtimeMs); if (wl != null) { StopwatchTimer wlt = getWakelockTimerLocked(wl, type); wlt.stopRunningLocked(elapsedRealtimeMs); @@ -9910,10 +10414,10 @@ public class BatteryStatsImpl extends BatteryStats { } } - public void reportExcessiveCpuLocked(String proc, long overTime, long usedTime) { + public void reportExcessiveCpuLocked(String proc, long overTimeMs, long usedTimeMs) { Proc p = getProcessStatsLocked(proc); if (p != null) { - p.addExcessiveCpu(overTime, usedTime); + p.addExcessiveCpu(overTimeMs, usedTimeMs); } } @@ -10041,16 +10545,16 @@ public class BatteryStatsImpl extends BatteryStats { mDischargeDeepDozeCounter = new LongSamplingCounter(mOnBatteryTimeBase); mDischargeCounter = new LongSamplingCounter(mOnBatteryTimeBase); mOnBattery = mOnBatteryInternal = false; - long uptime = mClocks.uptimeMillis() * 1000; - long realtime = mClocks.elapsedRealtime() * 1000; - initTimes(uptime, realtime); + long uptimeUs = mClocks.uptimeMillis() * 1000; + long realtimeUs = mClocks.elapsedRealtime() * 1000; + initTimes(uptimeUs, realtimeUs); mStartPlatformVersion = mEndPlatformVersion = Build.ID; mDischargeStartLevel = 0; mDischargeUnplugLevel = 0; mDischargePlugLevel = -1; mDischargeCurrentLevel = 0; mCurrentBatteryLevel = 0; - initDischarge(); + initDischarge(realtimeUs); clearHistoryLocked(); updateDailyDeadlineLocked(); mPlatformIdleStateCallback = cb; @@ -10110,9 +10614,9 @@ public class BatteryStatsImpl extends BatteryStats { mCallback = cb; } - public void setRadioScanningTimeoutLocked(long timeout) { + public void setRadioScanningTimeoutLocked(long timeoutUs) { if (mPhoneSignalScanningTimer != null) { - mPhoneSignalScanningTimer.setTimeout(timeout); + mPhoneSignalScanningTimer.setTimeout(timeoutUs); } } @@ -10122,9 +10626,9 @@ public class BatteryStatsImpl extends BatteryStats { public void updateDailyDeadlineLocked() { // Get the current time. - long currentTime = mDailyStartTime = System.currentTimeMillis(); + long currentTimeMs = mDailyStartTimeMs = System.currentTimeMillis(); Calendar calDeadline = Calendar.getInstance(); - calDeadline.setTimeInMillis(currentTime); + calDeadline.setTimeInMillis(currentTimeMs); // Move time up to the next day, ranging from 1am to 3pm. calDeadline.set(Calendar.DAY_OF_YEAR, calDeadline.get(Calendar.DAY_OF_YEAR) + 1); @@ -10132,25 +10636,24 @@ public class BatteryStatsImpl extends BatteryStats { calDeadline.set(Calendar.SECOND, 0); calDeadline.set(Calendar.MINUTE, 0); calDeadline.set(Calendar.HOUR_OF_DAY, 1); - mNextMinDailyDeadline = calDeadline.getTimeInMillis(); + mNextMinDailyDeadlineMs = calDeadline.getTimeInMillis(); calDeadline.set(Calendar.HOUR_OF_DAY, 3); - mNextMaxDailyDeadline = calDeadline.getTimeInMillis(); + mNextMaxDailyDeadlineMs = calDeadline.getTimeInMillis(); } - public void recordDailyStatsIfNeededLocked(boolean settled) { - long currentTime = System.currentTimeMillis(); - if (currentTime >= mNextMaxDailyDeadline) { + public void recordDailyStatsIfNeededLocked(boolean settled, long currentTimeMs) { + if (currentTimeMs >= mNextMaxDailyDeadlineMs) { recordDailyStatsLocked(); - } else if (settled && currentTime >= mNextMinDailyDeadline) { + } else if (settled && currentTimeMs >= mNextMinDailyDeadlineMs) { recordDailyStatsLocked(); - } else if (currentTime < (mDailyStartTime-(1000*60*60*24))) { + } else if (currentTimeMs < (mDailyStartTimeMs - (1000 * 60 * 60 * 24))) { recordDailyStatsLocked(); } } public void recordDailyStatsLocked() { DailyItem item = new DailyItem(); - item.mStartTime = mDailyStartTime; + item.mStartTime = mDailyStartTimeMs; item.mEndTime = System.currentTimeMillis(); boolean hasData = false; if (mDailyDischargeStepTracker.mNumStepDurations > 0) { @@ -10175,7 +10678,7 @@ public class BatteryStatsImpl extends BatteryStats { updateDailyDeadlineLocked(); if (hasData) { - final long startTime = SystemClock.uptimeMillis(); + final long startTimeMs = SystemClock.uptimeMillis(); mDailyItems.add(item); while (mDailyItems.size() > MAX_DAILY_ITEMS) { mDailyItems.remove(0); @@ -10185,12 +10688,12 @@ public class BatteryStatsImpl extends BatteryStats { XmlSerializer out = new FastXmlSerializer(); out.setOutput(memStream, StandardCharsets.UTF_8.name()); writeDailyItemsLocked(out); - final long initialTime = SystemClock.uptimeMillis() - startTime; + final long initialTimeMs = SystemClock.uptimeMillis() - startTimeMs; BackgroundThread.getHandler().post(new Runnable() { @Override public void run() { synchronized (mCheckinFile) { - final long startTime2 = SystemClock.uptimeMillis(); + final long startTimeMs2 = SystemClock.uptimeMillis(); FileOutputStream stream = null; try { stream = mDailyFile.startWrite(); @@ -10199,7 +10702,7 @@ public class BatteryStatsImpl extends BatteryStats { mDailyFile.finishWrite(stream); com.android.internal.logging.EventLogTags.writeCommitSysConfigFile( "batterystats-daily", - initialTime + SystemClock.uptimeMillis() - startTime2); + initialTimeMs + SystemClock.uptimeMillis() - startTimeMs2); } catch (IOException e) { Slog.w("BatteryStats", "Error writing battery daily items", e); @@ -10431,17 +10934,17 @@ public class BatteryStatsImpl extends BatteryStats { @Override public long getCurrentDailyStartTime() { - return mDailyStartTime; + return mDailyStartTimeMs; } @Override public long getNextMinDailyDeadline() { - return mNextMinDailyDeadline; + return mNextMinDailyDeadlineMs; } @Override public long getNextMaxDailyDeadline() { - return mNextMaxDailyDeadline; + return mNextMaxDailyDeadlineMs; } @Override @@ -10554,12 +11057,12 @@ public class BatteryStatsImpl extends BatteryStats { if (p == null) { return false; } - final long lastRealtime = out.time; - final long lastWalltime = out.currentTime; + final long lastRealtimeMs = out.time; + final long lastWalltimeMs = out.currentTime; readHistoryDelta(p, out); if (out.cmd != HistoryItem.CMD_CURRENT_TIME - && out.cmd != HistoryItem.CMD_RESET && lastWalltime != 0) { - out.currentTime = lastWalltime + (out.time - lastRealtime); + && out.cmd != HistoryItem.CMD_RESET && lastWalltimeMs != 0) { + out.currentTime = lastWalltimeMs + (out.time - lastRealtimeMs); } return true; } @@ -10574,7 +11077,7 @@ public class BatteryStatsImpl extends BatteryStats { @Override public long getHistoryBaseTime() { - return mHistoryBaseTime; + return mHistoryBaseTimeMs; } @Override @@ -10604,17 +11107,17 @@ public class BatteryStatsImpl extends BatteryStats { return state == Display.STATE_DOZE || state == Display.STATE_DOZE_SUSPEND; } - void initTimes(long uptime, long realtime) { - mStartClockTime = System.currentTimeMillis(); - mOnBatteryTimeBase.init(uptime, realtime); - mOnBatteryScreenOffTimeBase.init(uptime, realtime); - mRealtime = 0; - mUptime = 0; - mRealtimeStart = realtime; - mUptimeStart = uptime; + void initTimes(long uptimeUs, long realtimeUs) { + mStartClockTimeMs = System.currentTimeMillis(); + mOnBatteryTimeBase.init(uptimeUs, realtimeUs); + mOnBatteryScreenOffTimeBase.init(uptimeUs, realtimeUs); + mRealtimeUs = 0; + mUptimeUs = 0; + mRealtimeStartUs = realtimeUs; + mUptimeStartUs = uptimeUs; } - void initDischarge() { + void initDischarge(long elapsedRealtimeUs) { mLowDischargeAmountSinceCharge = 0; mHighDischargeAmountSinceCharge = 0; mDischargeAmountScreenOn = 0; @@ -10625,26 +11128,26 @@ public class BatteryStatsImpl extends BatteryStats { mDischargeAmountScreenDozeSinceCharge = 0; mDischargeStepTracker.init(); mChargeStepTracker.init(); - mDischargeScreenOffCounter.reset(false); - mDischargeScreenDozeCounter.reset(false); - mDischargeLightDozeCounter.reset(false); - mDischargeDeepDozeCounter.reset(false); - mDischargeCounter.reset(false); + mDischargeScreenOffCounter.reset(false, elapsedRealtimeUs); + mDischargeScreenDozeCounter.reset(false, elapsedRealtimeUs); + mDischargeLightDozeCounter.reset(false, elapsedRealtimeUs); + mDischargeDeepDozeCounter.reset(false, elapsedRealtimeUs); + mDischargeCounter.reset(false, elapsedRealtimeUs); } public void resetAllStatsCmdLocked() { - resetAllStatsLocked(); final long mSecUptime = mClocks.uptimeMillis(); - long uptime = mSecUptime * 1000; + long uptimeUs = mSecUptime * 1000; long mSecRealtime = mClocks.elapsedRealtime(); - long realtime = mSecRealtime * 1000; + long realtimeUs = mSecRealtime * 1000; + resetAllStatsLocked(mSecUptime, mSecRealtime); mDischargeStartLevel = mHistoryCur.batteryLevel; pullPendingStateUpdatesLocked(); addHistoryRecordLocked(mSecRealtime, mSecUptime); mDischargeCurrentLevel = mDischargeUnplugLevel = mDischargePlugLevel = mCurrentBatteryLevel = mHistoryCur.batteryLevel; - mOnBatteryTimeBase.reset(uptime, realtime); - mOnBatteryScreenOffTimeBase.reset(uptime, realtime); + mOnBatteryTimeBase.reset(uptimeUs, realtimeUs); + mOnBatteryScreenOffTimeBase.reset(uptimeUs, realtimeUs); if ((mHistoryCur.states&HistoryItem.STATE_BATTERY_PLUGGED_FLAG) == 0) { if (isScreenOn(mScreenState)) { mDischargeScreenOnUnplugLevel = mHistoryCur.batteryLevel; @@ -10666,15 +11169,15 @@ public class BatteryStatsImpl extends BatteryStats { initActiveHistoryEventsLocked(mSecRealtime, mSecUptime); } - private void resetAllStatsLocked() { - final long uptimeMillis = mClocks.uptimeMillis(); - final long elapsedRealtimeMillis = mClocks.elapsedRealtime(); + private void resetAllStatsLocked(long uptimeMillis, long elapsedRealtimeMillis) { + final long uptimeUs = uptimeMillis * 1000; + final long elapsedRealtimeUs = elapsedRealtimeMillis * 1000; mStartCount = 0; - initTimes(uptimeMillis * 1000, elapsedRealtimeMillis * 1000); - mScreenOnTimer.reset(false); - mScreenDozeTimer.reset(false); + initTimes(uptimeUs, elapsedRealtimeUs); + mScreenOnTimer.reset(false, uptimeUs); + mScreenDozeTimer.reset(false, elapsedRealtimeUs); for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) { - mScreenBrightnessTimer[i].reset(false); + mScreenBrightnessTimer[i].reset(false, elapsedRealtimeUs); } if (mPowerProfile != null) { @@ -10684,60 +11187,60 @@ public class BatteryStatsImpl extends BatteryStats { } mMinLearnedBatteryCapacity = -1; mMaxLearnedBatteryCapacity = -1; - mInteractiveTimer.reset(false); - mPowerSaveModeEnabledTimer.reset(false); - mLastIdleTimeStart = elapsedRealtimeMillis; - mLongestLightIdleTime = 0; - mLongestFullIdleTime = 0; - mDeviceIdleModeLightTimer.reset(false); - mDeviceIdleModeFullTimer.reset(false); - mDeviceLightIdlingTimer.reset(false); - mDeviceIdlingTimer.reset(false); - mPhoneOnTimer.reset(false); - mAudioOnTimer.reset(false); - mVideoOnTimer.reset(false); - mFlashlightOnTimer.reset(false); - mCameraOnTimer.reset(false); - mBluetoothScanTimer.reset(false); + mInteractiveTimer.reset(false, elapsedRealtimeUs); + mPowerSaveModeEnabledTimer.reset(false, elapsedRealtimeUs); + mLastIdleTimeStartMs = elapsedRealtimeMillis; + mLongestLightIdleTimeMs = 0; + mLongestFullIdleTimeMs = 0; + mDeviceIdleModeLightTimer.reset(false, elapsedRealtimeUs); + mDeviceIdleModeFullTimer.reset(false, elapsedRealtimeUs); + mDeviceLightIdlingTimer.reset(false, elapsedRealtimeUs); + mDeviceIdlingTimer.reset(false, elapsedRealtimeUs); + mPhoneOnTimer.reset(false, elapsedRealtimeUs); + mAudioOnTimer.reset(false, elapsedRealtimeUs); + mVideoOnTimer.reset(false, elapsedRealtimeUs); + mFlashlightOnTimer.reset(false, elapsedRealtimeUs); + mCameraOnTimer.reset(false, elapsedRealtimeUs); + mBluetoothScanTimer.reset(false, elapsedRealtimeUs); for (int i = 0; i < CellSignalStrength.getNumSignalStrengthLevels(); i++) { - mPhoneSignalStrengthsTimer[i].reset(false); + mPhoneSignalStrengthsTimer[i].reset(false, elapsedRealtimeUs); } - mPhoneSignalScanningTimer.reset(false); + mPhoneSignalScanningTimer.reset(false, elapsedRealtimeUs); for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) { - mPhoneDataConnectionsTimer[i].reset(false); + mPhoneDataConnectionsTimer[i].reset(false, elapsedRealtimeUs); } for (int i = 0; i < NUM_NETWORK_ACTIVITY_TYPES; i++) { - mNetworkByteActivityCounters[i].reset(false); - mNetworkPacketActivityCounters[i].reset(false); - } - mMobileRadioActiveTimer.reset(false); - mMobileRadioActivePerAppTimer.reset(false); - mMobileRadioActiveAdjustedTime.reset(false); - mMobileRadioActiveUnknownTime.reset(false); - mMobileRadioActiveUnknownCount.reset(false); - mWifiOnTimer.reset(false); - mGlobalWifiRunningTimer.reset(false); + mNetworkByteActivityCounters[i].reset(false, elapsedRealtimeUs); + mNetworkPacketActivityCounters[i].reset(false, elapsedRealtimeUs); + } + mMobileRadioActiveTimer.reset(false, elapsedRealtimeUs); + mMobileRadioActivePerAppTimer.reset(false, elapsedRealtimeUs); + mMobileRadioActiveAdjustedTime.reset(false, elapsedRealtimeUs); + mMobileRadioActiveUnknownTime.reset(false, elapsedRealtimeUs); + mMobileRadioActiveUnknownCount.reset(false, elapsedRealtimeUs); + mWifiOnTimer.reset(false, elapsedRealtimeUs); + mGlobalWifiRunningTimer.reset(false, elapsedRealtimeUs); for (int i=0; i<NUM_WIFI_STATES; i++) { - mWifiStateTimer[i].reset(false); + mWifiStateTimer[i].reset(false, elapsedRealtimeUs); } for (int i=0; i<NUM_WIFI_SUPPL_STATES; i++) { - mWifiSupplStateTimer[i].reset(false); + mWifiSupplStateTimer[i].reset(false, elapsedRealtimeUs); } for (int i=0; i<NUM_WIFI_SIGNAL_STRENGTH_BINS; i++) { - mWifiSignalStrengthsTimer[i].reset(false); + mWifiSignalStrengthsTimer[i].reset(false, elapsedRealtimeUs); } - mWifiMulticastWakelockTimer.reset(false); - mWifiActiveTimer.reset(false); - mWifiActivity.reset(false); + mWifiMulticastWakelockTimer.reset(false, elapsedRealtimeUs); + mWifiActiveTimer.reset(false, elapsedRealtimeUs); + mWifiActivity.reset(false, elapsedRealtimeUs); for (int i=0; i< GnssMetrics.NUM_GPS_SIGNAL_QUALITY_LEVELS; i++) { - mGpsSignalQualityTimer[i].reset(false); + mGpsSignalQualityTimer[i].reset(false, elapsedRealtimeUs); } - mBluetoothActivity.reset(false); - mModemActivity.reset(false); + mBluetoothActivity.reset(false, elapsedRealtimeUs); + mModemActivity.reset(false, elapsedRealtimeUs); mNumConnectivityChange = 0; for (int i=0; i<mUidStats.size(); i++) { - if (mUidStats.valueAt(i).reset(uptimeMillis * 1000, elapsedRealtimeMillis * 1000)) { + if (mUidStats.valueAt(i).reset(uptimeUs, elapsedRealtimeUs)) { mUidStats.valueAt(i).detachFromTimeBase(); mUidStats.remove(mUidStats.keyAt(i)); i--; @@ -10780,25 +11283,25 @@ public class BatteryStatsImpl extends BatteryStats { mTmpRailStats.reset(); - resetIfNotNull(mSystemServerThreadCpuTimesUs, false); - resetIfNotNull(mBinderThreadCpuTimesUs, false); + resetIfNotNull(mSystemServerThreadCpuTimesUs, false, elapsedRealtimeUs); + resetIfNotNull(mBinderThreadCpuTimesUs, false, elapsedRealtimeUs); mLastHistoryStepDetails = null; - mLastStepCpuUserTime = mLastStepCpuSystemTime = 0; - mCurStepCpuUserTime = mCurStepCpuSystemTime = 0; - mLastStepCpuUserTime = mCurStepCpuUserTime = 0; - mLastStepCpuSystemTime = mCurStepCpuSystemTime = 0; - mLastStepStatUserTime = mCurStepStatUserTime = 0; - mLastStepStatSystemTime = mCurStepStatSystemTime = 0; - mLastStepStatIOWaitTime = mCurStepStatIOWaitTime = 0; - mLastStepStatIrqTime = mCurStepStatIrqTime = 0; - mLastStepStatSoftIrqTime = mCurStepStatSoftIrqTime = 0; - mLastStepStatIdleTime = mCurStepStatIdleTime = 0; + mLastStepCpuUserTimeMs = mLastStepCpuSystemTimeMs = 0; + mCurStepCpuUserTimeMs = mCurStepCpuSystemTimeMs = 0; + mLastStepCpuUserTimeMs = mCurStepCpuUserTimeMs = 0; + mLastStepCpuSystemTimeMs = mCurStepCpuSystemTimeMs = 0; + mLastStepStatUserTimeMs = mCurStepStatUserTimeMs = 0; + mLastStepStatSystemTimeMs = mCurStepStatSystemTimeMs = 0; + mLastStepStatIOWaitTimeMs = mCurStepStatIOWaitTimeMs = 0; + mLastStepStatIrqTimeMs = mCurStepStatIrqTimeMs = 0; + mLastStepStatSoftIrqTimeMs = mCurStepStatSoftIrqTimeMs = 0; + mLastStepStatIdleTimeMs = mCurStepStatIdleTimeMs = 0; mNumAllUidCpuTimeReads = 0; mNumUidsRemoved = 0; - initDischarge(); + initDischarge(elapsedRealtimeUs); clearHistoryLocked(); mBatteryStatsHistory.resetAllFiles(); @@ -10915,6 +11418,14 @@ public class BatteryStatsImpl extends BatteryStats { * @param info The energy information from the WiFi controller. */ public void updateWifiState(@Nullable final WifiActivityEnergyInfo info) { + updateWifiState(info, mClocks.elapsedRealtime(), mClocks.uptimeMillis()); + } + + /** + * @see #updateWifiState(WifiActivityEnergyInfo) + */ + public void updateWifiState(@Nullable final WifiActivityEnergyInfo info, + long elapsedRealtimeMs, long uptimeMs) { if (DEBUG_ENERGY) { Slog.d(TAG, "Updating wifi stats: " + Arrays.toString(mWifiIfaces)); } @@ -10939,7 +11450,6 @@ public class BatteryStatsImpl extends BatteryStats { return; } - final long elapsedRealtimeMs = mClocks.elapsedRealtime(); SparseLongArray rxPackets = new SparseLongArray(); SparseLongArray txPackets = new SparseLongArray(); long totalTxPackets = 0; @@ -10961,7 +11471,7 @@ public class BatteryStatsImpl extends BatteryStats { continue; } - final Uid u = getUidStatsLocked(mapUid(entry.uid)); + final Uid u = getUidStatsLocked(mapUid(entry.uid), elapsedRealtimeMs, uptimeMs); if (entry.rxBytes != 0) { u.noteNetworkActivityLocked(NETWORK_WIFI_RX_DATA, entry.rxBytes, entry.rxPackets); @@ -11127,7 +11637,8 @@ public class BatteryStatsImpl extends BatteryStats { // Distribute the remaining Tx power appropriately between all apps that transmitted // packets. for (int i = 0; i < txPackets.size(); i++) { - final Uid uid = getUidStatsLocked(txPackets.keyAt(i)); + final Uid uid = getUidStatsLocked(txPackets.keyAt(i), + elapsedRealtimeMs, uptimeMs); final long myTxTimeMs = (txPackets.valueAt(i) * leftOverTxTimeMs) / totalTxPackets; if (DEBUG_ENERGY) { @@ -11140,7 +11651,8 @@ public class BatteryStatsImpl extends BatteryStats { // Distribute the remaining Rx power appropriately between all apps that received // packets. for (int i = 0; i < rxPackets.size(); i++) { - final Uid uid = getUidStatsLocked(rxPackets.keyAt(i)); + final Uid uid = getUidStatsLocked(rxPackets.keyAt(i), + elapsedRealtimeMs, uptimeMs); final long myRxTimeMs = (rxPackets.valueAt(i) * leftOverRxTimeMs) / totalRxPackets; if (DEBUG_ENERGY) { @@ -11179,7 +11691,7 @@ public class BatteryStatsImpl extends BatteryStats { monitoredRailChargeConsumedMaMs); mHistoryCur.wifiRailChargeMah += (monitoredRailChargeConsumedMaMs / MILLISECONDS_IN_HOUR); - addHistoryRecordLocked(mClocks.elapsedRealtime(), mClocks.uptimeMillis()); + addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs); mTmpRailStats.resetWifiTotalEnergyUsed(); } } @@ -11210,13 +11722,21 @@ public class BatteryStatsImpl extends BatteryStats { * Distribute Cell radio energy info and network traffic to apps. */ public void updateMobileRadioState(@Nullable final ModemActivityInfo activityInfo) { + updateMobileRadioState(activityInfo, mClocks.elapsedRealtime(), mClocks.uptimeMillis()); + } + + /** + * @see #updateMobileRadioState(ModemActivityInfo) + */ + public void updateMobileRadioState(@Nullable final ModemActivityInfo activityInfo, + long elapsedRealtimeMs, long uptimeMs) { if (DEBUG_ENERGY) { Slog.d(TAG, "Updating mobile radio stats with " + activityInfo); } ModemActivityInfo deltaInfo = getDeltaModemActivityInfo(activityInfo); // Add modem tx power to history. - addModemTxPowerToHistory(deltaInfo); + addModemTxPowerToHistory(deltaInfo, elapsedRealtimeMs, uptimeMs); // Grab a separate lock to acquire the network stats, which may do I/O. NetworkStats delta = null; @@ -11279,12 +11799,11 @@ public class BatteryStatsImpl extends BatteryStats { monitoredRailChargeConsumedMaMs); mHistoryCur.modemRailChargeMah += (monitoredRailChargeConsumedMaMs / MILLISECONDS_IN_HOUR); - addHistoryRecordLocked(mClocks.elapsedRealtime(), mClocks.uptimeMillis()); + addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs); mTmpRailStats.resetCellularTotalEnergyUsed(); } } - final long elapsedRealtimeMs = mClocks.elapsedRealtime(); - long radioTime = mMobileRadioActivePerAppTimer.getTimeSinceMarkLocked( + long radioTimeUs = mMobileRadioActivePerAppTimer.getTimeSinceMarkLocked( elapsedRealtimeMs * 1000); mMobileRadioActivePerAppTimer.setMark(elapsedRealtimeMs); @@ -11308,7 +11827,7 @@ public class BatteryStatsImpl extends BatteryStats { totalRxPackets += entry.rxPackets; totalTxPackets += entry.txPackets; - final Uid u = getUidStatsLocked(mapUid(entry.uid)); + final Uid u = getUidStatsLocked(mapUid(entry.uid), elapsedRealtimeMs, uptimeMs); u.noteNetworkActivityLocked(NETWORK_MOBILE_RX_DATA, entry.rxBytes, entry.rxPackets); u.noteNetworkActivityLocked(NETWORK_MOBILE_TX_DATA, entry.txBytes, @@ -11339,16 +11858,17 @@ public class BatteryStatsImpl extends BatteryStats { continue; } - final Uid u = getUidStatsLocked(mapUid(entry.uid)); + final Uid u = getUidStatsLocked(mapUid(entry.uid), + elapsedRealtimeMs, uptimeMs); // Distribute total radio active time in to this app. final long appPackets = entry.rxPackets + entry.txPackets; - final long appRadioTime = (radioTime * appPackets) / totalPackets; - u.noteMobileRadioActiveTimeLocked(appRadioTime); + final long appRadioTimeUs = (radioTimeUs * appPackets) / totalPackets; + u.noteMobileRadioActiveTimeLocked(appRadioTimeUs); // Remove this app from the totals, so that we don't lose any time // due to rounding. - radioTime -= appRadioTime; + radioTimeUs -= appRadioTimeUs; totalPackets -= appPackets; if (deltaInfo != null) { @@ -11373,9 +11893,9 @@ public class BatteryStatsImpl extends BatteryStats { } } - if (radioTime > 0) { + if (radioTimeUs > 0) { // Whoops, there is some radio time we can't blame on an app! - mMobileRadioActiveUnknownTime.addCountLocked(radioTime); + mMobileRadioActiveUnknownTime.addCountLocked(radioTimeUs); mMobileRadioActiveUnknownCount.addCountLocked(1); } @@ -11391,7 +11911,8 @@ public class BatteryStatsImpl extends BatteryStats { * time at the highest power level. * @param activityInfo */ - private synchronized void addModemTxPowerToHistory(final ModemActivityInfo activityInfo) { + private synchronized void addModemTxPowerToHistory(final ModemActivityInfo activityInfo, + long elapsedRealtimeMs, long uptimeMs) { if (activityInfo == null) { return; } @@ -11399,8 +11920,6 @@ public class BatteryStatsImpl extends BatteryStats { if (txPowerInfo == null || txPowerInfo.size() != ModemActivityInfo.TX_POWER_LEVELS) { return; } - final long elapsedRealtime = mClocks.elapsedRealtime(); - final long uptime = mClocks.uptimeMillis(); int levelMaxTimeSpent = 0; for (int i = 1; i < txPowerInfo.size(); i++) { if (txPowerInfo.get(i).getTimeInMillis() > txPowerInfo.get(levelMaxTimeSpent) @@ -11410,7 +11929,7 @@ public class BatteryStatsImpl extends BatteryStats { } if (levelMaxTimeSpent == ModemActivityInfo.TX_POWER_LEVELS - 1) { mHistoryCur.states2 |= HistoryItem.STATE2_CELLULAR_HIGH_TX_POWER_FLAG; - addHistoryRecordLocked(elapsedRealtime, uptime); + addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs); } } @@ -11446,6 +11965,14 @@ public class BatteryStatsImpl extends BatteryStats { * @param info The energy information from the bluetooth controller. */ public void updateBluetoothStateLocked(@Nullable final BluetoothActivityEnergyInfo info) { + updateBluetoothStateLocked(info, mClocks.elapsedRealtime(), mClocks.uptimeMillis()); + } + + /** + * @see #updateBluetoothStateLocked(BluetoothActivityEnergyInfo) + */ + public void updateBluetoothStateLocked(@Nullable final BluetoothActivityEnergyInfo info, + long elapsedRealtimeMs, long uptimeMs) { if (DEBUG_ENERGY) { Slog.d(TAG, "Updating bluetooth stats: " + info); } @@ -11456,7 +11983,6 @@ public class BatteryStatsImpl extends BatteryStats { mHasBluetoothReporting = true; - final long elapsedRealtimeMs = mClocks.elapsedRealtime(); final long rxTimeMs = info.getControllerRxTimeMillis() - mLastBluetoothActivityInfo.rxTimeMs; final long txTimeMs = @@ -11560,7 +12086,7 @@ public class BatteryStatsImpl extends BatteryStats { mNetworkByteActivityCounters[NETWORK_BT_TX_DATA].addCountLocked(txBytes); // Add to the UID counters. - final Uid u = getUidStatsLocked(mapUid(traffic.getUid())); + final Uid u = getUidStatsLocked(mapUid(traffic.getUid()), elapsedRealtimeMs, uptimeMs); u.noteNetworkActivityLocked(NETWORK_BT_RX_DATA, rxBytes, 0); u.noteNetworkActivityLocked(NETWORK_BT_TX_DATA, txBytes, 0); @@ -11579,7 +12105,7 @@ public class BatteryStatsImpl extends BatteryStats { final long txBytes = traffic.getTxBytes() - mLastBluetoothActivityInfo.uidTxBytes.get(uid); - final Uid u = getUidStatsLocked(mapUid(uid)); + final Uid u = getUidStatsLocked(mapUid(uid), elapsedRealtimeMs, uptimeMs); final ControllerActivityCounterImpl counter = u.getOrCreateBluetoothControllerActivityLocked(); @@ -11623,6 +12149,13 @@ public class BatteryStatsImpl extends BatteryStats { * instead of fetching it anew. */ public void updateRpmStatsLocked() { + updateRpmStatsLocked(mClocks.elapsedRealtime() * 1000); + } + + /** + * @see #updateRpmStatsLocked() + */ + public void updateRpmStatsLocked(long elapsedRealtimeUs) { if (mPlatformIdleStateCallback == null) return; long now = SystemClock.elapsedRealtime(); if (now - mLastRpmStatsUpdateTimeMs >= RPM_STATS_UPDATE_FREQ_MS) { @@ -11637,9 +12170,9 @@ public class BatteryStatsImpl extends BatteryStats { final String pName = pstate.getKey(); final long pTimeUs = pstate.getValue().mTimeMs * 1000; final int pCount = pstate.getValue().mCount; - getRpmTimerLocked(pName).update(pTimeUs, pCount); + getRpmTimerLocked(pName).update(pTimeUs, pCount, elapsedRealtimeUs); if (SCREEN_OFF_RPM_STATS_ENABLED) { - getScreenOffRpmTimerLocked(pName).update(pTimeUs, pCount); + getScreenOffRpmTimerLocked(pName).update(pTimeUs, pCount, elapsedRealtimeUs); } // Update values for each voter of this platform state. @@ -11648,9 +12181,9 @@ public class BatteryStatsImpl extends BatteryStats { final String vName = pName + "." + voter.getKey(); final long vTimeUs = voter.getValue().mTimeMs * 1000; final int vCount = voter.getValue().mCount; - getRpmTimerLocked(vName).update(vTimeUs, vCount); + getRpmTimerLocked(vName).update(vTimeUs, vCount, elapsedRealtimeUs); if (SCREEN_OFF_RPM_STATS_ENABLED) { - getScreenOffRpmTimerLocked(vName).update(vTimeUs, vCount); + getScreenOffRpmTimerLocked(vName).update(vTimeUs, vCount, elapsedRealtimeUs); } } } @@ -11664,9 +12197,9 @@ public class BatteryStatsImpl extends BatteryStats { final String name = subsysName + "." + sstate.getKey(); final long timeUs = sstate.getValue().mTimeMs * 1000; final int count = sstate.getValue().mCount; - getRpmTimerLocked(name).update(timeUs, count); + getRpmTimerLocked(name).update(timeUs, count, elapsedRealtimeUs); if (SCREEN_OFF_RPM_STATS_ENABLED) { - getScreenOffRpmTimerLocked(name).update(timeUs, count); + getScreenOffRpmTimerLocked(name).update(timeUs, count, elapsedRealtimeUs); } } } @@ -11686,6 +12219,13 @@ public class BatteryStatsImpl extends BatteryStats { * Read and distribute kernel wake lock use across apps. */ public void updateKernelWakelocksLocked() { + updateKernelWakelocksLocked(mClocks.elapsedRealtime() * 1000); + } + + /** + * @see #updateKernelWakelocksLocked() + */ + public void updateKernelWakelocksLocked(long elapsedRealtimeUs) { final KernelWakelockStats wakelockStats = mKernelWakelockReader.readKernelWakelockStats( mTmpWakelockStats); if (wakelockStats == null) { @@ -11704,7 +12244,7 @@ public class BatteryStatsImpl extends BatteryStats { mKernelWakelockStats.put(name, kwlt); } - kwlt.update(kws.mTotalTime, kws.mCount); + kwlt.update(kws.mTotalTime, kws.mCount, elapsedRealtimeUs); kwlt.setUpdateVersion(kws.mVersion); } @@ -11714,7 +12254,7 @@ public class BatteryStatsImpl extends BatteryStats { for (Map.Entry<String, SamplingTimer> ent : mKernelWakelockStats.entrySet()) { SamplingTimer st = ent.getValue(); if (st.getUpdateVersion() != wakelockStats.kernelWakelockVersion) { - st.endSample(); + st.endSample(elapsedRealtimeUs); numWakelocksSetStale++; } } @@ -11742,6 +12282,10 @@ public class BatteryStatsImpl extends BatteryStats { * Reads the newest memory stats from the kernel. */ public void updateKernelMemoryBandwidthLocked() { + updateKernelMemoryBandwidthLocked(mClocks.elapsedRealtime() * 1000); + } + + public void updateKernelMemoryBandwidthLocked(long elapsedRealtimeUs) { mKernelMemoryBandwidthStats.updateStats(); LongSparseLongArray bandwidthEntries = mKernelMemoryBandwidthStats.getBandwidthEntries(); final int bandwidthEntryCount = bandwidthEntries.size(); @@ -11754,12 +12298,12 @@ public class BatteryStatsImpl extends BatteryStats { timer = new SamplingTimer(mClocks, mOnBatteryTimeBase); mKernelMemoryStats.put(bandwidthEntries.keyAt(i), timer); } - timer.update(bandwidthEntries.valueAt(i), 1); + timer.update(bandwidthEntries.valueAt(i), 1, elapsedRealtimeUs); if (DEBUG_MEMORY) { Slog.d(TAG, String.format("Added entry %d and updated timer to: " - + "mUnpluggedReportedTotalTime %d size %d", bandwidthEntries.keyAt(i), + + "mUnpluggedReportedTotalTimeUs %d size %d", bandwidthEntries.keyAt(i), mKernelMemoryStats.get( - bandwidthEntries.keyAt(i)).mUnpluggedReportedTotalTime, + bandwidthEntries.keyAt(i)).mUnpluggedReportedTotalTimeUs, mKernelMemoryStats.size())); } } @@ -11898,8 +12442,8 @@ public class BatteryStatsImpl extends BatteryStats { } if (DEBUG_BINDER_STATS) { Slog.d(TAG, "System server threads per CPU cluster (binder threads/total threads/%)"); - long binderThreadTime = 0; - long totalThreadTime = 0; + long binderThreadTimeMs = 0; + long totalThreadTimeMs = 0; int cpuIndex = 0; for (int cluster = 0; cluster < numCpuClusters; cluster++) { StringBuilder sb = new StringBuilder(); @@ -11909,26 +12453,27 @@ public class BatteryStatsImpl extends BatteryStats { if (speed != 0) { sb.append(", "); } - long totalCount = mSystemServerThreadCpuTimesUs[cluster][speed].getCountLocked( - 0) / 1000; - long binderCount = mBinderThreadCpuTimesUs[cluster][speed].getCountLocked(0) + long totalCountMs = + mSystemServerThreadCpuTimesUs[cluster][speed].getCountLocked(0) / 1000; + long binderCountMs = mBinderThreadCpuTimesUs[cluster][speed].getCountLocked(0) / 1000; sb.append(String.format("%d/%d(%.1f%%)", - binderCount, - totalCount, - totalCount != 0 ? (double) binderCount * 100 / totalCount : 0)); + binderCountMs, + totalCountMs, + totalCountMs != 0 ? (double) binderCountMs * 100 / totalCountMs : 0)); - totalThreadTime += totalCount; - binderThreadTime += binderCount; + totalThreadTimeMs += totalCountMs; + binderThreadTimeMs += binderCountMs; index++; } cpuIndex += mPowerProfile.getNumCoresInCpuCluster(cluster); Slog.d(TAG, sb.toString()); } - Slog.d(TAG, "Total system server thread time (ms): " + totalThreadTime); + Slog.d(TAG, "Total system server thread time (ms): " + totalThreadTimeMs); Slog.d(TAG, String.format("Total Binder thread time (ms): %d (%.1f%%)", - binderThreadTime, - binderThreadTime != 0 ? (double) binderThreadTime * 100 / totalThreadTime : 0)); + binderThreadTimeMs, + binderThreadTimeMs != 0 + ? (double) binderThreadTimeMs * 100 / totalThreadTimeMs : 0)); } } @@ -11985,8 +12530,10 @@ public class BatteryStatsImpl extends BatteryStats { // So, we distribute total time spent by an uid to different cpu freqs based on the // amount of time cpu was running at that freq. final int updatedUidsCount = updatedUids.size(); + final long elapsedRealtimeMs = mClocks.elapsedRealtime(); + final long uptimeMs = mClocks.uptimeMillis(); for (int i = 0; i < updatedUidsCount; ++i) { - final Uid u = getUidStatsLocked(updatedUids.keyAt(i)); + final Uid u = getUidStatsLocked(updatedUids.keyAt(i), elapsedRealtimeMs, uptimeMs); final long appCpuTimeUs = updatedUids.valueAt(i); // Add the cpu speeds to this UID. final int numClusters = mPowerProfile.getNumCpuClusters(); @@ -12031,6 +12578,7 @@ public class BatteryStatsImpl extends BatteryStats { mTempTotalCpuUserTimeUs = mTempTotalCpuSystemTimeUs = 0; final int numWakelocks = partialTimers == null ? 0 : partialTimers.size(); final long startTimeMs = mClocks.uptimeMillis(); + final long elapsedRealtimeMs = mClocks.elapsedRealtime(); mCpuUidUserSysTimeReader.readDelta((uid, timesUs) -> { long userTimeUs = timesUs[0], systemTimeUs = timesUs[1]; @@ -12048,7 +12596,7 @@ public class BatteryStatsImpl extends BatteryStats { mCpuUidUserSysTimeReader.removeUid(uid); return; } - final Uid u = getUidStatsLocked(uid); + final Uid u = getUidStatsLocked(uid, elapsedRealtimeMs, startTimeMs); // Accumulate the total system and user time. mTempTotalCpuUserTimeUs += userTimeUs; @@ -12144,6 +12692,7 @@ public class BatteryStatsImpl extends BatteryStats { final int numClusters = mPowerProfile.getNumCpuClusters(); mWakeLockAllocationsUs = null; final long startTimeMs = mClocks.uptimeMillis(); + final long elapsedRealtimeMs = mClocks.elapsedRealtime(); mCpuUidFreqTimeReader.readDelta((uid, cpuFreqTimeMs) -> { uid = mapUid(uid); if (Process.isIsolated(uid)) { @@ -12156,7 +12705,7 @@ public class BatteryStatsImpl extends BatteryStats { mCpuUidFreqTimeReader.removeUid(uid); return; } - final Uid u = getUidStatsLocked(uid); + final Uid u = getUidStatsLocked(uid, elapsedRealtimeMs, startTimeMs); if (u.mCpuFreqTimeMs == null || u.mCpuFreqTimeMs.getSize() != cpuFreqTimeMs.length) { detachIfNotNull(u.mCpuFreqTimeMs); u.mCpuFreqTimeMs = new LongSamplingCounterArray(mOnBatteryTimeBase); @@ -12257,6 +12806,7 @@ public class BatteryStatsImpl extends BatteryStats { @VisibleForTesting public void readKernelUidCpuActiveTimesLocked(boolean onBattery) { final long startTimeMs = mClocks.uptimeMillis(); + final long elapsedRealtimeMs = mClocks.elapsedRealtime(); mCpuUidActiveTimeReader.readDelta((uid, cpuActiveTimesMs) -> { uid = mapUid(uid); if (Process.isIsolated(uid)) { @@ -12269,7 +12819,7 @@ public class BatteryStatsImpl extends BatteryStats { mCpuUidActiveTimeReader.removeUid(uid); return; } - final Uid u = getUidStatsLocked(uid); + final Uid u = getUidStatsLocked(uid, elapsedRealtimeMs, startTimeMs); u.mCpuActiveTimeMs.addCountLocked(cpuActiveTimesMs, onBattery); }); @@ -12286,6 +12836,7 @@ public class BatteryStatsImpl extends BatteryStats { @VisibleForTesting public void readKernelUidCpuClusterTimesLocked(boolean onBattery) { final long startTimeMs = mClocks.uptimeMillis(); + final long elapsedRealtimeMs = mClocks.elapsedRealtime(); mCpuUidClusterTimeReader.readDelta((uid, cpuClusterTimesMs) -> { uid = mapUid(uid); if (Process.isIsolated(uid)) { @@ -12298,7 +12849,7 @@ public class BatteryStatsImpl extends BatteryStats { mCpuUidClusterTimeReader.removeUid(uid); return; } - final Uid u = getUidStatsLocked(uid); + final Uid u = getUidStatsLocked(uid, elapsedRealtimeMs, startTimeMs); u.mCpuClusterTimesMs.addCountLocked(cpuClusterTimesMs, onBattery); }); @@ -12338,8 +12889,8 @@ public class BatteryStatsImpl extends BatteryStats { m.arg1 = onBattery ? 1 : 0; mHandler.sendMessage(m); - final long uptime = mSecUptime * 1000; - final long realtime = mSecRealtime * 1000; + final long uptimeUs = mSecUptime * 1000; + final long realtimeUs = mSecRealtime * 1000; final int screenState = mScreenState; if (onBattery) { // We will reset our status if we are unplugging after the @@ -12358,14 +12909,14 @@ public class BatteryStatsImpl extends BatteryStats { // stats to be reported in the next checkin. Only do this if we have // a sufficient amount of data to make it interesting. if (getLowDischargeAmountSinceCharge() >= 20) { - final long startTime = SystemClock.uptimeMillis(); + final long startTimeMs = SystemClock.uptimeMillis(); final Parcel parcel = Parcel.obtain(); writeSummaryToParcel(parcel, true); - final long initialTime = SystemClock.uptimeMillis() - startTime; + final long initialTimeMs = SystemClock.uptimeMillis() - startTimeMs; BackgroundThread.getHandler().post(new Runnable() { @Override public void run() { synchronized (mCheckinFile) { - final long startTime2 = SystemClock.uptimeMillis(); + final long startTimeMs2 = SystemClock.uptimeMillis(); FileOutputStream stream = null; try { stream = mCheckinFile.startWrite(); @@ -12373,8 +12924,8 @@ public class BatteryStatsImpl extends BatteryStats { stream.flush(); mCheckinFile.finishWrite(stream); com.android.internal.logging.EventLogTags.writeCommitSysConfigFile( - "batterystats-checkin", - initialTime + SystemClock.uptimeMillis() - startTime2); + "batterystats-checkin", initialTimeMs + + SystemClock.uptimeMillis() - startTimeMs2); } catch (IOException e) { Slog.w("BatteryStats", "Error writing checkin battery statistics", e); @@ -12387,7 +12938,7 @@ public class BatteryStatsImpl extends BatteryStats { }); } doWrite = true; - resetAllStatsLocked(); + resetAllStatsLocked(mSecUptime, mSecRealtime); if (chargeUAh > 0 && level > 0) { // Only use the reported coulomb charge value if it is supported and reported. mEstimatedBatteryCapacity = (int) ((chargeUAh / 1000) / (level / 100.0)); @@ -12434,7 +12985,7 @@ public class BatteryStatsImpl extends BatteryStats { mDischargeAmountScreenOn = 0; mDischargeAmountScreenDoze = 0; mDischargeAmountScreenOff = 0; - updateTimeBasesLocked(true, screenState, uptime, realtime); + updateTimeBasesLocked(true, screenState, uptimeUs, realtimeUs); } else { mLastChargingStateLevel = level; mOnBattery = mOnBatteryInternal = false; @@ -12450,14 +13001,14 @@ public class BatteryStatsImpl extends BatteryStats { mHighDischargeAmountSinceCharge += mDischargeUnplugLevel-level; } updateDischargeScreenLevelsLocked(screenState, screenState); - updateTimeBasesLocked(false, screenState, uptime, realtime); + updateTimeBasesLocked(false, screenState, uptimeUs, realtimeUs); mChargeStepTracker.init(); mLastChargeStepLevel = level; mMaxChargeStepLevel = level; mInitStepMode = mCurStepMode; mModStepMode = 0; } - if (doWrite || (mLastWriteTime + (60 * 1000)) < mSecRealtime) { + if (doWrite || (mLastWriteTimeMs + (60 * 1000)) < mSecRealtime) { if (mStatsFile != null && mBatteryStatsHistory.getActiveFile() != null) { writeAsyncLocked(); } @@ -12477,18 +13028,18 @@ public class BatteryStatsImpl extends BatteryStats { } } - private void recordCurrentTimeChangeLocked(final long currentTime, final long elapsedRealtimeMs, - final long uptimeMs) { + private void recordCurrentTimeChangeLocked(final long currentTimeMs, + final long elapsedRealtimeMs, final long uptimeMs) { if (mRecordingHistory) { - mHistoryCur.currentTime = currentTime; + mHistoryCur.currentTime = currentTimeMs; addHistoryBufferLocked(elapsedRealtimeMs, HistoryItem.CMD_CURRENT_TIME, mHistoryCur); mHistoryCur.currentTime = 0; } } - private void recordShutdownLocked(final long elapsedRealtimeMs, final long uptimeMs) { + private void recordShutdownLocked(final long currentTimeMs, final long elapsedRealtimeMs) { if (mRecordingHistory) { - mHistoryCur.currentTime = System.currentTimeMillis(); + mHistoryCur.currentTime = currentTimeMs; addHistoryBufferLocked(elapsedRealtimeMs, HistoryItem.CMD_SHUTDOWN, mHistoryCur); mHistoryCur.currentTime = 0; } @@ -12507,6 +13058,15 @@ public class BatteryStatsImpl extends BatteryStats { public void setBatteryStateLocked(final int status, final int health, final int plugType, final int level, /* not final */ int temp, final int volt, final int chargeUAh, final int chargeFullUAh, final long chargeTimeToFullSeconds) { + setBatteryStateLocked(status, health, plugType, level, temp, volt, chargeUAh, + chargeFullUAh, chargeTimeToFullSeconds, + mClocks.elapsedRealtime(), mClocks.uptimeMillis(), System.currentTimeMillis()); + } + + public void setBatteryStateLocked(final int status, final int health, final int plugType, + final int level, /* not final */ int temp, final int volt, final int chargeUAh, + final int chargeFullUAh, final long chargeTimeToFullSeconds, + final long elapsedRealtimeMs, final long uptimeMs, final long currentTimeMs) { // Temperature is encoded without the signed bit, so clamp any negative temperatures to 0. temp = Math.max(0, temp); @@ -12514,8 +13074,6 @@ public class BatteryStatsImpl extends BatteryStats { status, plugType, level); final boolean onBattery = isOnBattery(plugType, status); - final long uptime = mClocks.uptimeMillis(); - final long elapsedRealtime = mClocks.elapsedRealtime(); if (!mHaveBatteryLevel) { mHaveBatteryLevel = true; // We start out assuming that the device is plugged in (not @@ -12538,20 +13096,20 @@ public class BatteryStatsImpl extends BatteryStats { mLastChargeStepLevel = mLastDischargeStepLevel = level; mLastChargingStateLevel = level; } else if (mCurrentBatteryLevel != level || mOnBattery != onBattery) { - recordDailyStatsIfNeededLocked(level >= 100 && onBattery); + recordDailyStatsIfNeededLocked(level >= 100 && onBattery, currentTimeMs); } int oldStatus = mHistoryCur.batteryStatus; if (onBattery) { mDischargeCurrentLevel = level; if (!mRecordingHistory) { mRecordingHistory = true; - startRecordingHistory(elapsedRealtime, uptime, true); + startRecordingHistory(elapsedRealtimeMs, uptimeMs, true); } } else if (level < 96 && status != BatteryManager.BATTERY_STATUS_UNKNOWN) { if (!mRecordingHistory) { mRecordingHistory = true; - startRecordingHistory(elapsedRealtime, uptime, true); + startRecordingHistory(elapsedRealtimeMs, uptimeMs, true); } } mCurrentBatteryLevel = level; @@ -12581,7 +13139,7 @@ public class BatteryStatsImpl extends BatteryStats { } } mHistoryCur.batteryChargeUAh = chargeUAh; - setOnBatteryLocked(elapsedRealtime, uptime, onBattery, oldStatus, level, chargeUAh); + setOnBatteryLocked(elapsedRealtimeMs, uptimeMs, onBattery, oldStatus, level, chargeUAh); } else { boolean changed = false; if (mHistoryCur.batteryLevel != level) { @@ -12641,9 +13199,9 @@ public class BatteryStatsImpl extends BatteryStats { changed |= setChargingLocked(false); if (mLastDischargeStepLevel != level && mMinDischargeStepLevel > level) { mDischargeStepTracker.addLevelSteps(mLastDischargeStepLevel - level, - modeBits, elapsedRealtime); + modeBits, elapsedRealtimeMs); mDailyDischargeStepTracker.addLevelSteps(mLastDischargeStepLevel - level, - modeBits, elapsedRealtime); + modeBits, elapsedRealtimeMs); mLastDischargeStepLevel = level; mMinDischargeStepLevel = level; mInitStepMode = mCurStepMode; @@ -12681,9 +13239,9 @@ public class BatteryStatsImpl extends BatteryStats { } if (mLastChargeStepLevel != level && mMaxChargeStepLevel < level) { mChargeStepTracker.addLevelSteps(level - mLastChargeStepLevel, - modeBits, elapsedRealtime); + modeBits, elapsedRealtimeMs); mDailyChargeStepTracker.addLevelSteps(level - mLastChargeStepLevel, - modeBits, elapsedRealtime); + modeBits, elapsedRealtimeMs); mMaxChargeStepLevel = level; mInitStepMode = mCurStepMode; mModStepMode = 0; @@ -12691,7 +13249,7 @@ public class BatteryStatsImpl extends BatteryStats { mLastChargeStepLevel = level; } if (changed) { - addHistoryRecordLocked(elapsedRealtime, uptime); + addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs); } } if (!onBattery && @@ -12737,7 +13295,7 @@ public class BatteryStatsImpl extends BatteryStats { public long getAwakeTimeBattery() { // This previously evaluated to mOnBatteryTimeBase.getUptime(getBatteryUptimeLocked()); // for over a decade, but surely that was a mistake. - return getBatteryUptimeLocked(); + return getBatteryUptimeLocked(mClocks.uptimeMillis()); } @UnsupportedAppUsage @@ -12746,35 +13304,35 @@ public class BatteryStatsImpl extends BatteryStats { } @Override - public long computeUptime(long curTime, int which) { - return mUptime + (curTime - mUptimeStart); + public long computeUptime(long curTimeUs, int which) { + return mUptimeUs + (curTimeUs - mUptimeStartUs); } @Override - public long computeRealtime(long curTime, int which) { - return mRealtime + (curTime - mRealtimeStart); + public long computeRealtime(long curTimeUs, int which) { + return mRealtimeUs + (curTimeUs - mRealtimeStartUs); } @Override @UnsupportedAppUsage - public long computeBatteryUptime(long curTime, int which) { - return mOnBatteryTimeBase.computeUptime(curTime, which); + public long computeBatteryUptime(long curTimeUs, int which) { + return mOnBatteryTimeBase.computeUptime(curTimeUs, which); } @Override @UnsupportedAppUsage - public long computeBatteryRealtime(long curTime, int which) { - return mOnBatteryTimeBase.computeRealtime(curTime, which); + public long computeBatteryRealtime(long curTimeUs, int which) { + return mOnBatteryTimeBase.computeRealtime(curTimeUs, which); } @Override - public long computeBatteryScreenOffUptime(long curTime, int which) { - return mOnBatteryScreenOffTimeBase.computeUptime(curTime, which); + public long computeBatteryScreenOffUptime(long curTimeUs, int which) { + return mOnBatteryScreenOffTimeBase.computeUptime(curTimeUs, which); } @Override - public long computeBatteryScreenOffRealtime(long curTime, int which) { - return mOnBatteryScreenOffTimeBase.computeRealtime(curTime, which); + public long computeBatteryScreenOffRealtime(long curTimeUs, int which) { + return mOnBatteryScreenOffTimeBase.computeRealtime(curTimeUs, which); } private long computeTimePerLevel(long[] steps, int numSteps) { @@ -12877,7 +13435,7 @@ public class BatteryStatsImpl extends BatteryStats { /*@hide */ public CellularBatteryStats getCellularBatteryStats() { final int which = STATS_SINCE_CHARGED; - final long rawRealTime = SystemClock.elapsedRealtime() * 1000; + final long rawRealTimeUs = SystemClock.elapsedRealtime() * 1000; final ControllerActivityCounter counter = getModemControllerActivity(); final long sleepTimeMs = counter.getSleepTimeCounter().getCountLocked(which); final long idleTimeMs = counter.getIdleTimeCounter().getCountLocked(which); @@ -12887,13 +13445,13 @@ public class BatteryStatsImpl extends BatteryStats { counter.getMonitoredRailChargeConsumedMaMs().getCountLocked(which); long[] timeInRatMs = new long[BatteryStats.NUM_DATA_CONNECTION_TYPES]; for (int i = 0; i < timeInRatMs.length; i++) { - timeInRatMs[i] = getPhoneDataConnectionTime(i, rawRealTime, which) / 1000; + timeInRatMs[i] = getPhoneDataConnectionTime(i, rawRealTimeUs, which) / 1000; } long[] timeInRxSignalStrengthLevelMs = new long[CellSignalStrength.getNumSignalStrengthLevels()]; for (int i = 0; i < timeInRxSignalStrengthLevelMs.length; i++) { - timeInRxSignalStrengthLevelMs[i] - = getPhoneSignalStrengthTime(i, rawRealTime, which) / 1000; + timeInRxSignalStrengthLevelMs[i] = + getPhoneSignalStrengthTime(i, rawRealTimeUs, which) / 1000; } long[] txTimeMs = new long[Math.min(ModemActivityInfo.TX_POWER_LEVELS, counter.getTxTimeCounters().length)]; @@ -12903,8 +13461,8 @@ public class BatteryStatsImpl extends BatteryStats { totalTxTimeMs += txTimeMs[i]; } - return new CellularBatteryStats(computeBatteryRealtime(rawRealTime, which) / 1000, - getMobileRadioActiveTime(rawRealTime, which) / 1000, + return new CellularBatteryStats(computeBatteryRealtime(rawRealTimeUs, which) / 1000, + getMobileRadioActiveTime(rawRealTimeUs, which) / 1000, getNetworkActivityPackets(NETWORK_MOBILE_TX_DATA, which), getNetworkActivityBytes(NETWORK_MOBILE_TX_DATA, which), getNetworkActivityPackets(NETWORK_MOBILE_RX_DATA, which), @@ -12917,7 +13475,7 @@ public class BatteryStatsImpl extends BatteryStats { /*@hide */ public WifiBatteryStats getWifiBatteryStats() { final int which = STATS_SINCE_CHARGED; - final long rawRealTime = SystemClock.elapsedRealtime() * 1000; + final long rawRealTimeUs = SystemClock.elapsedRealtime() * 1000; final ControllerActivityCounter counter = getWifiControllerActivity(); final long idleTimeMs = counter.getIdleTimeCounter().getCountLocked(which); final long scanTimeMs = counter.getScanTimeCounter().getCountLocked(which); @@ -12936,19 +13494,19 @@ public class BatteryStatsImpl extends BatteryStats { } long[] timeInStateMs = new long[NUM_WIFI_STATES]; for (int i=0; i<NUM_WIFI_STATES; i++) { - timeInStateMs[i] = getWifiStateTime(i, rawRealTime, which) / 1000; + timeInStateMs[i] = getWifiStateTime(i, rawRealTimeUs, which) / 1000; } long[] timeInSupplStateMs = new long[NUM_WIFI_SUPPL_STATES]; for (int i=0; i<NUM_WIFI_SUPPL_STATES; i++) { - timeInSupplStateMs[i] = getWifiSupplStateTime(i, rawRealTime, which) / 1000; + timeInSupplStateMs[i] = getWifiSupplStateTime(i, rawRealTimeUs, which) / 1000; } long[] timeSignalStrengthTimeMs = new long[NUM_WIFI_SIGNAL_STRENGTH_BINS]; for (int i=0; i<NUM_WIFI_SIGNAL_STRENGTH_BINS; i++) { - timeSignalStrengthTimeMs[i] = getWifiSignalStrengthTime(i, rawRealTime, which) / 1000; + timeSignalStrengthTimeMs[i] = getWifiSignalStrengthTime(i, rawRealTimeUs, which) / 1000; } return new WifiBatteryStats( - computeBatteryRealtime(rawRealTime, which) / 1000, - getWifiActiveTime(rawRealTime, which) / 1000, + computeBatteryRealtime(rawRealTimeUs, which) / 1000, + getWifiActiveTime(rawRealTimeUs, which) / 1000, getNetworkActivityPackets(NETWORK_WIFI_TX_DATA, which), getNetworkActivityBytes(NETWORK_WIFI_TX_DATA, which), getNetworkActivityPackets(NETWORK_WIFI_RX_DATA, which), @@ -12962,12 +13520,12 @@ public class BatteryStatsImpl extends BatteryStats { public GpsBatteryStats getGpsBatteryStats() { GpsBatteryStats s = new GpsBatteryStats(); final int which = STATS_SINCE_CHARGED; - final long rawRealTime = SystemClock.elapsedRealtime() * 1000; - s.setLoggingDurationMs(computeBatteryRealtime(rawRealTime, which) / 1000); + final long rawRealTimeUs = SystemClock.elapsedRealtime() * 1000; + s.setLoggingDurationMs(computeBatteryRealtime(rawRealTimeUs, which) / 1000); s.setEnergyConsumedMaMs(getGpsBatteryDrainMaMs()); long[] time = new long[GnssMetrics.NUM_GPS_SIGNAL_QUALITY_LEVELS]; for (int i=0; i<time.length; i++) { - time[i] = getGpsSignalQualityTime(i, rawRealTime, which) / 1000; + time[i] = getGpsSignalQualityTime(i, rawRealTimeUs, which) / 1000; } s.setTimeInGpsSignalQualityLevel(time); return s; @@ -12988,19 +13546,29 @@ public class BatteryStatsImpl extends BatteryStats { return mDailyPackageChanges; } + /** + * @return battery uptime in microseconds + */ protected long getBatteryUptimeLocked() { - return mOnBatteryTimeBase.getUptime(mClocks.uptimeMillis() * 1000); + return getBatteryUptimeLocked(mClocks.uptimeMillis()); + } + + /** + * @return battery uptime in microseconds + */ + protected long getBatteryUptimeLocked(long uptimeMs) { + return mOnBatteryTimeBase.getUptime(uptimeMs * 1000); } @Override - public long getBatteryUptime(long curTime) { - return mOnBatteryTimeBase.getUptime(curTime); + public long getBatteryUptime(long curTimeUs) { + return mOnBatteryTimeBase.getUptime(curTimeUs); } @Override @UnsupportedAppUsage - public long getBatteryRealtime(long curTime) { - return mOnBatteryTimeBase.getRealtime(curTime); + public long getBatteryRealtime(long curTimeUs) { + return mOnBatteryTimeBase.getRealtime(curTimeUs); } @Override @@ -13188,22 +13756,22 @@ public class BatteryStatsImpl extends BatteryStats { return 0; } - final long uidTimeAtCpuSpeed = systemUid.getTimeAtCpuSpeed(cluster, step, + final long uidTimeAtCpuSpeedUs = systemUid.getTimeAtCpuSpeed(cluster, step, BatteryStats.STATS_SINCE_CHARGED); - if (uidTimeAtCpuSpeed == 0) { + if (uidTimeAtCpuSpeedUs == 0) { return 0; } - final long uidThreadTime = + final long uidThreadTimeUs = threadTimesForCluster[step].getCountLocked(BatteryStats.STATS_SINCE_CHARGED); - if (uidThreadTime == 0) { + if (uidThreadTimeUs == 0) { return 0; } - final long binderThreadTime = mBinderThreadCpuTimesUs[cluster][step].getCountLocked( + final long binderThreadTimeUs = mBinderThreadCpuTimesUs[cluster][step].getCountLocked( BatteryStats.STATS_SINCE_CHARGED); - return uidTimeAtCpuSpeed * binderThreadTime / uidThreadTime; + return uidTimeAtCpuSpeedUs * binderThreadTimeUs / uidThreadTimeUs; } /** @@ -13211,9 +13779,13 @@ public class BatteryStatsImpl extends BatteryStats { */ @UnsupportedAppUsage public Uid getUidStatsLocked(int uid) { + return getUidStatsLocked(uid, mClocks.elapsedRealtime(), mClocks.uptimeMillis()); + } + + public Uid getUidStatsLocked(int uid, long elapsedRealtimeMs, long uptimeMs) { Uid u = mUidStats.get(uid); if (u == null) { - u = new Uid(this, uid); + u = new Uid(this, uid, elapsedRealtimeMs, uptimeMs); mUidStats.put(uid, u); } return u; @@ -13229,10 +13801,14 @@ public class BatteryStatsImpl extends BatteryStats { } public void onCleanupUserLocked(int userId) { + onCleanupUserLocked(userId, mClocks.elapsedRealtime()); + } + + public void onCleanupUserLocked(int userId, long elapsedRealtimeMs) { final int firstUidForUser = UserHandle.getUid(userId, 0); final int lastUidForUser = UserHandle.getUid(userId, UserHandle.PER_USER_RANGE - 1); mPendingRemovedUids.add( - new UidToRemove(firstUidForUser, lastUidForUser, mClocks.elapsedRealtime())); + new UidToRemove(firstUidForUser, lastUidForUser, elapsedRealtimeMs)); } public void onUserRemovedLocked(int userId) { @@ -13256,12 +13832,19 @@ public class BatteryStatsImpl extends BatteryStats { */ @UnsupportedAppUsage public void removeUidStatsLocked(int uid) { + removeUidStatsLocked(uid, mClocks.elapsedRealtime()); + } + + /** + * @see #removeUidStatsLocked(int) + */ + public void removeUidStatsLocked(int uid, long elapsedRealtimeMs) { final Uid u = mUidStats.get(uid); if (u != null) { u.detachFromTimeBase(); } mUidStats.remove(uid); - mPendingRemovedUids.add(new UidToRemove(uid, mClocks.elapsedRealtime())); + mPendingRemovedUids.add(new UidToRemove(uid, elapsedRealtimeMs)); } /** @@ -13270,8 +13853,16 @@ public class BatteryStatsImpl extends BatteryStats { */ @UnsupportedAppUsage public Uid.Proc getProcessStatsLocked(int uid, String name) { + return getProcessStatsLocked(uid, name, mClocks.elapsedRealtime(), mClocks.uptimeMillis()); + } + + /** + * @see #getProcessStatsLocked(int, String) + */ + public Uid.Proc getProcessStatsLocked(int uid, String name, + long elapsedRealtimeMs, long uptimeMs) { uid = mapUid(uid); - Uid u = getUidStatsLocked(uid); + Uid u = getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs); return u.getProcessStatsLocked(name); } @@ -13281,8 +13872,16 @@ public class BatteryStatsImpl extends BatteryStats { */ @UnsupportedAppUsage public Uid.Pkg getPackageStatsLocked(int uid, String pkg) { + return getPackageStatsLocked(uid, pkg, mClocks.elapsedRealtime(), mClocks.uptimeMillis()); + } + + /** + * @see getPackageStatsLocked(int, String) + */ + public Uid.Pkg getPackageStatsLocked(int uid, String pkg, + long elapsedRealtimeMs, long uptimeMs) { uid = mapUid(uid); - Uid u = getUidStatsLocked(uid); + Uid u = getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs); return u.getPackageStatsLocked(pkg); } @@ -13292,13 +13891,19 @@ public class BatteryStatsImpl extends BatteryStats { */ @UnsupportedAppUsage public Uid.Pkg.Serv getServiceStatsLocked(int uid, String pkg, String name) { + return getServiceStatsLocked(uid, pkg, name, + mClocks.elapsedRealtime(), mClocks.uptimeMillis()); + } + + public Uid.Pkg.Serv getServiceStatsLocked(int uid, String pkg, String name, + long elapsedRealtimeMs, long uptimeMs) { uid = mapUid(uid); - Uid u = getUidStatsLocked(uid); + Uid u = getUidStatsLocked(uid, elapsedRealtimeMs, uptimeMs); return u.getServiceStatsLocked(pkg, name); } public void shutdownLocked() { - recordShutdownLocked(mClocks.elapsedRealtime(), mClocks.uptimeMillis()); + recordShutdownLocked(System.currentTimeMillis(), mClocks.elapsedRealtime()); writeSyncLocked(); mShuttingDown = true; } @@ -13462,7 +14067,7 @@ public class BatteryStatsImpl extends BatteryStats { mNumSingleUidCpuTimeReads = 0; mNumBatchedSingleUidCpuTimeReads = 0; - mCpuTimeReadsTrackingStartTime = mClocks.uptimeMillis(); + mCpuTimeReadsTrackingStartTimeMs = mClocks.uptimeMillis(); } } @@ -13471,7 +14076,7 @@ public class BatteryStatsImpl extends BatteryStats { if (oldDelayMillis != newDelayMillis) { mNumSingleUidCpuTimeReads = 0; mNumBatchedSingleUidCpuTimeReads = 0; - mCpuTimeReadsTrackingStartTime = mClocks.uptimeMillis(); + mCpuTimeReadsTrackingStartTimeMs = mClocks.uptimeMillis(); } } @@ -13569,11 +14174,11 @@ public class BatteryStatsImpl extends BatteryStats { Uid uid = mUidStats.get(u); double proportionalSystemServiceUsage = uid.getProportionalSystemServiceUsage(); - long time = 0; + long timeUs = 0; for (int cluster = 0; cluster < mSystemServerThreadCpuTimesUs.length; cluster++) { int numSpeeds = mSystemServerThreadCpuTimesUs[cluster].length; for (int speed = 0; speed < numSpeeds; speed++) { - time += getSystemServiceTimeAtCpuSpeed(cluster, speed) + timeUs += getSystemServiceTimeAtCpuSpeed(cluster, speed) * proportionalSystemServiceUsage; } } @@ -13581,7 +14186,7 @@ public class BatteryStatsImpl extends BatteryStats { pw.print(" "); pw.print(u); pw.print(": "); - pw.println(time); + pw.println(timeUs / 1000); } } } @@ -13616,7 +14221,7 @@ public class BatteryStatsImpl extends BatteryStats { Slog.d(TAG, "writeSummaryToParcel duration ms:" + (SystemClock.uptimeMillis() - start) + " bytes:" + p.dataSize()); } - mLastWriteTime = mClocks.elapsedRealtime(); + mLastWriteTimeMs = mClocks.elapsedRealtime(); writeParcelToFileLocked(p, mStatsFile, sync); } @@ -13657,18 +14262,18 @@ public class BatteryStatsImpl extends BatteryStats { mWriteLock.lock(); FileOutputStream fos = null; try { - final long startTime = SystemClock.uptimeMillis(); + final long startTimeMs = SystemClock.uptimeMillis(); fos = file.startWrite(); fos.write(p.marshall()); fos.flush(); file.finishWrite(fos); if (DEBUG) { Slog.d(TAG, "commitPendingDataToDisk file:" + file.getBaseFile().getPath() - + " duration ms:" + (SystemClock.uptimeMillis() - startTime) + + " duration ms:" + (SystemClock.uptimeMillis() - startTimeMs) + " bytes:" + p.dataSize()); } com.android.internal.logging.EventLogTags.writeCommitSysConfigFile( - "batterystats", SystemClock.uptimeMillis() - startTime); + "batterystats", SystemClock.uptimeMillis() - startTimeMs); } catch (IOException e) { Slog.w(TAG, "Error writing battery statistics", e); file.failWrite(fos); @@ -13714,7 +14319,7 @@ public class BatteryStatsImpl extends BatteryStats { } } catch (Exception e) { Slog.e(TAG, "Error reading battery statistics", e); - resetAllStatsLocked(); + resetAllStatsLocked(SystemClock.uptimeMillis(), SystemClock.elapsedRealtime()); } finally { stats.recycle(); } @@ -13749,16 +14354,17 @@ public class BatteryStatsImpl extends BatteryStats { if (mHistoryBuffer.dataPosition() > 0 || mBatteryStatsHistory.getFilesNumbers().size() > 1) { mRecordingHistory = true; - final long elapsedRealtime = mClocks.elapsedRealtime(); - final long uptime = mClocks.uptimeMillis(); + final long elapsedRealtimeMs = mClocks.elapsedRealtime(); + final long uptimeMs = mClocks.uptimeMillis(); if (USE_OLD_HISTORY) { - addHistoryRecordLocked(elapsedRealtime, uptime, HistoryItem.CMD_START, mHistoryCur); + addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs, + HistoryItem.CMD_START, mHistoryCur); } - addHistoryBufferLocked(elapsedRealtime, HistoryItem.CMD_START, mHistoryCur); - startRecordingHistory(elapsedRealtime, uptime, false); + addHistoryBufferLocked(elapsedRealtimeMs, HistoryItem.CMD_START, mHistoryCur); + startRecordingHistory(elapsedRealtimeMs, uptimeMs, false); } - recordDailyStatsIfNeededLocked(false); + recordDailyStatsIfNeededLocked(false, System.currentTimeMillis()); } public int describeContents() { @@ -13799,27 +14405,27 @@ public class BatteryStatsImpl extends BatteryStats { if (DEBUG_HISTORY) { StringBuilder sb = new StringBuilder(128); - sb.append("****************** OLD mHistoryBaseTime: "); - TimeUtils.formatDuration(mHistoryBaseTime, sb); + sb.append("****************** OLD mHistoryBaseTimeMs: "); + TimeUtils.formatDuration(mHistoryBaseTimeMs, sb); Slog.i(TAG, sb.toString()); } - mHistoryBaseTime = historyBaseTime; + mHistoryBaseTimeMs = historyBaseTime; if (DEBUG_HISTORY) { StringBuilder sb = new StringBuilder(128); - sb.append("****************** NEW mHistoryBaseTime: "); - TimeUtils.formatDuration(mHistoryBaseTime, sb); + sb.append("****************** NEW mHistoryBaseTimeMs: "); + TimeUtils.formatDuration(mHistoryBaseTimeMs, sb); Slog.i(TAG, sb.toString()); } // We are just arbitrarily going to insert 1 minute from the sample of // the last run until samples in this run. - if (mHistoryBaseTime > 0) { + if (mHistoryBaseTimeMs > 0) { long oldnow = mClocks.elapsedRealtime(); - mHistoryBaseTime = mHistoryBaseTime - oldnow + 1; + mHistoryBaseTimeMs = mHistoryBaseTimeMs - oldnow + 1; if (DEBUG_HISTORY) { StringBuilder sb = new StringBuilder(128); - sb.append("****************** ADJUSTED mHistoryBaseTime: "); - TimeUtils.formatDuration(mHistoryBaseTime, sb); + sb.append("****************** ADJUSTED mHistoryBaseTimeMs: "); + TimeUtils.formatDuration(mHistoryBaseTimeMs, sb); Slog.i(TAG, sb.toString()); } } @@ -13839,14 +14445,14 @@ public class BatteryStatsImpl extends BatteryStats { void writeHistoryBuffer(Parcel out, boolean inclData, boolean andOldHistory) { if (DEBUG_HISTORY) { StringBuilder sb = new StringBuilder(128); - sb.append("****************** WRITING mHistoryBaseTime: "); - TimeUtils.formatDuration(mHistoryBaseTime, sb); - sb.append(" mLastHistoryElapsedRealtime: "); - TimeUtils.formatDuration(mLastHistoryElapsedRealtime, sb); + sb.append("****************** WRITING mHistoryBaseTimeMs: "); + TimeUtils.formatDuration(mHistoryBaseTimeMs, sb); + sb.append(" mLastHistoryElapsedRealtimeMs: "); + TimeUtils.formatDuration(mLastHistoryElapsedRealtimeMs, sb); Slog.i(TAG, sb.toString()); } out.writeInt(VERSION); - out.writeLong(mHistoryBaseTime + mLastHistoryElapsedRealtime); + out.writeLong(mHistoryBaseTimeMs + mLastHistoryElapsedRealtimeMs); if (!inclData) { out.writeInt(0); out.writeInt(0); @@ -13913,9 +14519,9 @@ public class BatteryStatsImpl extends BatteryStats { } mStartCount = in.readInt(); - mUptime = in.readLong(); - mRealtime = in.readLong(); - mStartClockTime = in.readLong(); + mUptimeUs = in.readLong(); + mRealtimeUs = in.readLong(); + mStartClockTimeMs = in.readLong(); mStartPlatformVersion = in.readString(); mEndPlatformVersion = in.readString(); mOnBatteryTimeBase.readSummaryFromParcel(in); @@ -13955,9 +14561,9 @@ public class BatteryStatsImpl extends BatteryStats { } else { mDailyPackageChanges = null; } - mDailyStartTime = in.readLong(); - mNextMinDailyDeadline = in.readLong(); - mNextMaxDailyDeadline = in.readLong(); + mDailyStartTimeMs = in.readLong(); + mNextMinDailyDeadlineMs = in.readLong(); + mNextMaxDailyDeadlineMs = in.readLong(); mStartCount++; @@ -13971,8 +14577,8 @@ public class BatteryStatsImpl extends BatteryStats { mInteractiveTimer.readSummaryFromParcelLocked(in); mPhoneOn = false; mPowerSaveModeEnabledTimer.readSummaryFromParcelLocked(in); - mLongestLightIdleTime = in.readLong(); - mLongestFullIdleTime = in.readLong(); + mLongestLightIdleTimeMs = in.readLong(); + mLongestFullIdleTimeMs = in.readLong(); mDeviceIdleModeLightTimer.readSummaryFromParcelLocked(in); mDeviceIdleModeFullTimer.readSummaryFromParcelLocked(in); mDeviceLightIdlingTimer.readSummaryFromParcelLocked(in); @@ -14084,9 +14690,11 @@ public class BatteryStatsImpl extends BatteryStats { if (NU > 10000) { throw new ParcelFormatException("File corrupt: too many uids " + NU); } + final long elapsedRealtimeMs = mClocks.elapsedRealtime(); + final long uptimeMs = mClocks.uptimeMillis(); for (int iu = 0; iu < NU; iu++) { int uid = in.readInt(); - Uid u = new Uid(this, uid); + Uid u = new Uid(this, uid, elapsedRealtimeMs, uptimeMs); mUidStats.put(uid, u); u.mOnBatteryBackgroundTimeBase.readSummaryFromParcel(in); @@ -14329,9 +14937,9 @@ public class BatteryStatsImpl extends BatteryStats { for (int ip = 0; ip < NP; ip++) { String procName = in.readString(); Uid.Proc p = u.getProcessStatsLocked(procName); - p.mUserTime = in.readLong(); - p.mSystemTime = in.readLong(); - p.mForegroundTime = in.readLong(); + p.mUserTimeMs = in.readLong(); + p.mSystemTimeMs = in.readLong(); + p.mForegroundTimeMs = in.readLong(); p.mStarts = in.readInt(); p.mNumCrashes = in.readInt(); p.mNumAnrs = in.readInt(); @@ -14364,7 +14972,7 @@ public class BatteryStatsImpl extends BatteryStats { for (int is = 0; is < NS; is++) { String servName = in.readString(); Uid.Pkg.Serv s = u.getServiceStatsLocked(pkgName, servName); - s.mStartTime = in.readLong(); + s.mStartTimeMs = in.readLong(); s.mStarts = in.readInt(); s.mLaunches = in.readInt(); } @@ -14407,7 +15015,7 @@ public class BatteryStatsImpl extends BatteryStats { out.writeInt(mStartCount); out.writeLong(computeUptime(NOW_SYS, STATS_SINCE_CHARGED)); out.writeLong(computeRealtime(NOWREAL_SYS, STATS_SINCE_CHARGED)); - out.writeLong(mStartClockTime); + out.writeLong(mStartClockTimeMs); out.writeString(mStartPlatformVersion); out.writeString(mEndPlatformVersion); mOnBatteryTimeBase.writeSummaryToParcel(out, NOW_SYS, NOWREAL_SYS); @@ -14445,9 +15053,9 @@ public class BatteryStatsImpl extends BatteryStats { } else { out.writeInt(0); } - out.writeLong(mDailyStartTime); - out.writeLong(mNextMinDailyDeadline); - out.writeLong(mNextMaxDailyDeadline); + out.writeLong(mDailyStartTimeMs); + out.writeLong(mNextMinDailyDeadlineMs); + out.writeLong(mNextMaxDailyDeadlineMs); mScreenOnTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS); mScreenDozeTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS); @@ -14456,8 +15064,8 @@ public class BatteryStatsImpl extends BatteryStats { } mInteractiveTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS); mPowerSaveModeEnabledTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS); - out.writeLong(mLongestLightIdleTime); - out.writeLong(mLongestFullIdleTime); + out.writeLong(mLongestLightIdleTimeMs); + out.writeLong(mLongestFullIdleTimeMs); mDeviceIdleModeLightTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS); mDeviceIdleModeFullTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS); mDeviceLightIdlingTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS); @@ -14852,9 +15460,9 @@ public class BatteryStatsImpl extends BatteryStats { for (int ip=0; ip<NP; ip++) { out.writeString(u.mProcessStats.keyAt(ip)); Uid.Proc ps = u.mProcessStats.valueAt(ip); - out.writeLong(ps.mUserTime); - out.writeLong(ps.mSystemTime); - out.writeLong(ps.mForegroundTime); + out.writeLong(ps.mUserTimeMs); + out.writeLong(ps.mSystemTimeMs); + out.writeLong(ps.mForegroundTimeMs); out.writeInt(ps.mStarts); out.writeInt(ps.mNumCrashes); out.writeInt(ps.mNumAnrs); @@ -14880,7 +15488,7 @@ public class BatteryStatsImpl extends BatteryStats { out.writeString(ps.mServiceStats.keyAt(is)); BatteryStatsImpl.Uid.Pkg.Serv ss = ps.mServiceStats.valueAt(is); long time = ss.getStartTimeToNowLocked( - mOnBatteryTimeBase.getUptime(NOW_SYS)); + mOnBatteryTimeBase.getUptime(NOW_SYS) / 1000); out.writeLong(time); out.writeInt(ss.mStarts); out.writeInt(ss.mLaunches); @@ -14904,13 +15512,13 @@ public class BatteryStatsImpl extends BatteryStats { mBatteryStatsHistory.readFromParcel(in); mStartCount = in.readInt(); - mStartClockTime = in.readLong(); + mStartClockTimeMs = in.readLong(); mStartPlatformVersion = in.readString(); mEndPlatformVersion = in.readString(); - mUptime = in.readLong(); - mUptimeStart = in.readLong(); - mRealtime = in.readLong(); - mRealtimeStart = in.readLong(); + mUptimeUs = in.readLong(); + mUptimeStartUs = in.readLong(); + mRealtimeUs = in.readLong(); + mRealtimeStartUs = in.readLong(); mOnBattery = in.readInt() != 0; mEstimatedBatteryCapacity = in.readInt(); mMinLearnedBatteryCapacity = in.readInt(); @@ -14931,8 +15539,8 @@ public class BatteryStatsImpl extends BatteryStats { mPhoneOn = false; mPowerSaveModeEnabledTimer = new StopwatchTimer(mClocks, null, -2, null, mOnBatteryTimeBase, in); - mLongestLightIdleTime = in.readLong(); - mLongestFullIdleTime = in.readLong(); + mLongestLightIdleTimeMs = in.readLong(); + mLongestFullIdleTimeMs = in.readLong(); mDeviceIdleModeLightTimer = new StopwatchTimer(mClocks, null, -14, null, mOnBatteryTimeBase, in); mDeviceIdleModeFullTimer = new StopwatchTimer(mClocks, null, -11, null, @@ -15030,7 +15638,7 @@ public class BatteryStatsImpl extends BatteryStats { mDischargeScreenDozeCounter = new LongSamplingCounter(mOnBatteryTimeBase, in); mDischargeLightDozeCounter = new LongSamplingCounter(mOnBatteryTimeBase, in); mDischargeDeepDozeCounter = new LongSamplingCounter(mOnBatteryTimeBase, in); - mLastWriteTime = in.readLong(); + mLastWriteTimeMs = in.readLong(); mRpmStats.clear(); int NRPMS = in.readInt(); @@ -15096,9 +15704,11 @@ public class BatteryStatsImpl extends BatteryStats { int numUids = in.readInt(); mUidStats.clear(); + final long elapsedRealtimeMs = mClocks.elapsedRealtime(); + final long uptimeMs = mClocks.uptimeMillis(); for (int i = 0; i < numUids; i++) { int uid = in.readInt(); - Uid u = new Uid(this, uid); + Uid u = new Uid(this, uid, elapsedRealtimeMs, uptimeMs); u.readFromParcelLocked(mOnBatteryTimeBase, mOnBatteryScreenOffTimeBase, in); mUidStats.append(uid, u); } @@ -15137,13 +15747,13 @@ public class BatteryStatsImpl extends BatteryStats { mBatteryStatsHistory.writeToParcel(out); out.writeInt(mStartCount); - out.writeLong(mStartClockTime); + out.writeLong(mStartClockTimeMs); out.writeString(mStartPlatformVersion); out.writeString(mEndPlatformVersion); - out.writeLong(mUptime); - out.writeLong(mUptimeStart); - out.writeLong(mRealtime); - out.writeLong(mRealtimeStart); + out.writeLong(mUptimeUs); + out.writeLong(mUptimeStartUs); + out.writeLong(mRealtimeUs); + out.writeLong(mRealtimeStartUs); out.writeInt(mOnBattery ? 1 : 0); out.writeInt(mEstimatedBatteryCapacity); out.writeInt(mMinLearnedBatteryCapacity); @@ -15158,8 +15768,8 @@ public class BatteryStatsImpl extends BatteryStats { } mInteractiveTimer.writeToParcel(out, uSecRealtime); mPowerSaveModeEnabledTimer.writeToParcel(out, uSecRealtime); - out.writeLong(mLongestLightIdleTime); - out.writeLong(mLongestFullIdleTime); + out.writeLong(mLongestLightIdleTimeMs); + out.writeLong(mLongestFullIdleTimeMs); mDeviceIdleModeLightTimer.writeToParcel(out, uSecRealtime); mDeviceIdleModeFullTimer.writeToParcel(out, uSecRealtime); mDeviceLightIdlingTimer.writeToParcel(out, uSecRealtime); @@ -15227,7 +15837,7 @@ public class BatteryStatsImpl extends BatteryStats { mDischargeScreenDozeCounter.writeToParcel(out); mDischargeLightDozeCounter.writeToParcel(out); mDischargeDeepDozeCounter.writeToParcel(out); - out.writeLong(mLastWriteTime); + out.writeLong(mLastWriteTimeMs); out.writeInt(mRpmStats.size()); for (Map.Entry<String, SamplingTimer> ent : mRpmStats.entrySet()) { @@ -15472,7 +16082,7 @@ public class BatteryStatsImpl extends BatteryStats { pw.print("Batched cpu time reads: "); pw.println(mNumBatchedSingleUidCpuTimeReads); pw.print("Batching Duration (min): "); - pw.println((mClocks.uptimeMillis() - mCpuTimeReadsTrackingStartTime) / (60 * 1000)); + pw.println((mClocks.uptimeMillis() - mCpuTimeReadsTrackingStartTimeMs) / (60 * 1000)); pw.print("All UID cpu time reads since the later of device start or stats reset: "); pw.println(mNumAllUidCpuTimeReads); pw.print("UIDs removed since the later of device start or stats reset: "); diff --git a/core/java/com/android/internal/policy/DecorContext.java b/core/java/com/android/internal/policy/DecorContext.java index 51b41198e272..5e34c15c42e2 100644 --- a/core/java/com/android/internal/policy/DecorContext.java +++ b/core/java/com/android/internal/policy/DecorContext.java @@ -20,8 +20,10 @@ import android.content.AutofillOptions; import android.content.ContentCaptureOptions; import android.content.Context; import android.content.res.AssetManager; +import android.content.res.Configuration; import android.content.res.Resources; import android.view.ContextThemeWrapper; +import android.view.Display; import android.view.contentcapture.ContentCaptureManager; import com.android.internal.annotations.VisibleForTesting; @@ -47,9 +49,17 @@ public class DecorContext extends ContextThemeWrapper { public DecorContext(Context baseContext, PhoneWindow phoneWindow) { super(null /* base */, null); setPhoneWindow(phoneWindow); - final Context displayContext = baseContext.createDisplayContext( - // TODO(b/149790106): Non-activity context can be passed. - phoneWindow.getContext().getDisplayNoVerify()); + // TODO(b/149790106): Non-activity context can be passed. + final Display display = phoneWindow.getContext().getDisplayNoVerify(); + final Context displayContext; + if (display.getDisplayId() == Display.DEFAULT_DISPLAY) { + // TODO(b/166174272): Creating a display context for the default display will result + // in additional resource creation. + displayContext = baseContext.createConfigurationContext(Configuration.EMPTY); + displayContext.updateDisplay(Display.DEFAULT_DISPLAY); + } else { + displayContext = baseContext.createDisplayContext(display); + } attachBaseContext(displayContext); } diff --git a/core/java/com/android/internal/policy/DecorView.java b/core/java/com/android/internal/policy/DecorView.java index b12c5e9ba5b0..a6c3dd1071c9 100644 --- a/core/java/com/android/internal/policy/DecorView.java +++ b/core/java/com/android/internal/policy/DecorView.java @@ -24,6 +24,7 @@ import static android.os.Build.VERSION_CODES.M; import static android.os.Build.VERSION_CODES.N; import static android.view.InsetsState.ITYPE_NAVIGATION_BAR; import static android.view.InsetsState.ITYPE_STATUS_BAR; +import static android.view.InsetsState.clearCompatInsets; import static android.view.View.MeasureSpec.AT_MOST; import static android.view.View.MeasureSpec.EXACTLY; import static android.view.View.MeasureSpec.getMode; @@ -1097,10 +1098,12 @@ public class DecorView extends FrameLayout implements RootViewSurfaceTaker, Wind final Insets systemBarInsets = insets.getInsets(WindowInsets.Type.systemBars()); final Insets stableBarInsets = insets.getInsetsIgnoringVisibility( WindowInsets.Type.systemBars()); - mLastTopInset = systemBarInsets.top; - mLastBottomInset = systemBarInsets.bottom; - mLastRightInset = systemBarInsets.right; - mLastLeftInset = systemBarInsets.left; + final boolean clearCompatInsets = clearCompatInsets(attrs.type, attrs.flags, + getResources().getConfiguration().windowConfiguration.getWindowingMode()); + mLastTopInset = clearCompatInsets ? 0 : systemBarInsets.top; + mLastBottomInset = clearCompatInsets ? 0 : systemBarInsets.bottom; + mLastRightInset = clearCompatInsets ? 0 : systemBarInsets.right; + mLastLeftInset = clearCompatInsets ? 0 : systemBarInsets.left; // Don't animate if the presence of stable insets has changed, because that // indicates that the window was either just added and received them for the diff --git a/core/java/com/android/internal/policy/TaskResizingAlgorithm.java b/core/java/com/android/internal/policy/TaskResizingAlgorithm.java index 1ec020696cf3..64e0b91ae40a 100644 --- a/core/java/com/android/internal/policy/TaskResizingAlgorithm.java +++ b/core/java/com/android/internal/policy/TaskResizingAlgorithm.java @@ -51,8 +51,6 @@ public class TaskResizingAlgorithm { public static final int CTRL_BOTTOM = 0x8; // The minimal aspect ratio which needs to be met to count as landscape (or 1/.. for portrait). - // Note: We do not use the 1.33 from the CDD here since the user is allowed to use what ever - // aspect he desires. @VisibleForTesting public static final float MIN_ASPECT = 1.2f; diff --git a/core/java/com/android/internal/telephony/IPhoneStateListener.aidl b/core/java/com/android/internal/telephony/IPhoneStateListener.aidl index d41d30735d7d..25d1ae699aa6 100644 --- a/core/java/com/android/internal/telephony/IPhoneStateListener.aidl +++ b/core/java/com/android/internal/telephony/IPhoneStateListener.aidl @@ -23,6 +23,7 @@ import android.telephony.CellInfo; import android.telephony.DataConnectionRealTimeInfo; import android.telephony.TelephonyDisplayInfo; import android.telephony.PhoneCapability; +import android.telephony.PhysicalChannelConfig; import android.telephony.PreciseCallState; import android.telephony.PreciseDataConnectionState; import android.telephony.ServiceState; @@ -68,4 +69,6 @@ oneway interface IPhoneStateListener { void onRegistrationFailed(in CellIdentity cellIdentity, String chosenPlmn, int domain, int causeCode, int additionalCauseCode); void onBarringInfoChanged(in BarringInfo barringInfo); + void onPhysicalChannelConfigurationChanged(in List<PhysicalChannelConfig> configs); + } diff --git a/core/java/com/android/internal/telephony/ITelephonyRegistry.aidl b/core/java/com/android/internal/telephony/ITelephonyRegistry.aidl index ea09fc8cd34a..313bd42fe8c1 100644 --- a/core/java/com/android/internal/telephony/ITelephonyRegistry.aidl +++ b/core/java/com/android/internal/telephony/ITelephonyRegistry.aidl @@ -47,10 +47,10 @@ interface ITelephonyRegistry { */ @UnsupportedAppUsage void listen(String pkg, IPhoneStateListener callback, int events, boolean notifyNow); - void listenWithFeature(String pkg, String featureId, IPhoneStateListener callback, int events, + void listenWithFeature(String pkg, String featureId, IPhoneStateListener callback, long events, boolean notifyNow); void listenForSubscriber(in int subId, String pkg, String featureId, - IPhoneStateListener callback, int events, boolean notifyNow); + IPhoneStateListener callback, long events, boolean notifyNow); @UnsupportedAppUsage void notifyCallStateForAllSubs(int state, String incomingNumber); void notifyCallState(in int phoneId, in int subId, int state, String incomingNumber); @@ -99,4 +99,6 @@ interface ITelephonyRegistry { void notifyRegistrationFailed(int slotIndex, int subId, in CellIdentity cellIdentity, String chosenPlmn, int domain, int causeCode, int additionalCauseCode); void notifyBarringInfoChanged(int slotIndex, int subId, in BarringInfo barringInfo); + void notifyPhysicalChannelConfigurationForSubscriber(in int subId, + in List<PhysicalChannelConfig> configs); } diff --git a/core/java/com/android/internal/view/BaseIWindow.java b/core/java/com/android/internal/view/BaseIWindow.java index 7f3eb4515654..d5f54a199828 100644 --- a/core/java/com/android/internal/view/BaseIWindow.java +++ b/core/java/com/android/internal/view/BaseIWindow.java @@ -18,13 +18,11 @@ package com.android.internal.view; import android.compat.annotation.UnsupportedAppUsage; import android.graphics.Point; -import android.graphics.Rect; import android.hardware.input.InputManager; import android.os.Bundle; import android.os.ParcelFileDescriptor; import android.os.RemoteException; import android.util.MergedConfiguration; -import android.view.DisplayCutout; import android.view.DragEvent; import android.view.IScrollCaptureController; import android.view.IWindow; @@ -33,6 +31,7 @@ import android.view.InsetsSourceControl; import android.view.InsetsState; import android.view.PointerIcon; import android.view.WindowInsets.Type.InsetsType; +import android.window.ClientWindowFrames; import com.android.internal.os.IResultReceiver; @@ -51,11 +50,9 @@ public class BaseIWindow extends IWindow.Stub { } @Override - public void resized(Rect frame, Rect contentInsets, Rect visibleInsets, - Rect stableInsets, boolean reportDraw, - MergedConfiguration mergedConfiguration, Rect backDropFrame, boolean forceLayout, - boolean alwaysConsumeSystemBars, int displayId, - DisplayCutout.ParcelableWrapper displayCutout) { + public void resized(ClientWindowFrames frames, boolean reportDraw, + MergedConfiguration mergedConfiguration, boolean forceLayout, + boolean alwaysConsumeSystemBars, int displayId) { if (reportDraw) { try { mSession.finishDrawing(this, null /* postDrawTransaction */); diff --git a/core/jni/android_media_AudioSystem.cpp b/core/jni/android_media_AudioSystem.cpp index 3f39478ffd43..5c4c5099bf4c 100644 --- a/core/jni/android_media_AudioSystem.cpp +++ b/core/jni/android_media_AudioSystem.cpp @@ -2407,6 +2407,79 @@ static jint android_media_AudioSystem_getDevicesForRoleAndStrategy(JNIEnv *env, return AUDIO_JAVA_SUCCESS; } +static jint android_media_AudioSystem_setDevicesRoleForCapturePreset( + JNIEnv *env, jobject thiz, jint capturePreset, jint role, jintArray jDeviceTypes, + jobjectArray jDeviceAddresses) { + AudioDeviceTypeAddrVector nDevices; + jint results = getVectorOfAudioDeviceTypeAddr(env, jDeviceTypes, jDeviceAddresses, nDevices); + if (results != NO_ERROR) { + return results; + } + int status = check_AudioSystem_Command( + AudioSystem::setDevicesRoleForCapturePreset((audio_source_t)capturePreset, + (device_role_t)role, nDevices)); + return (jint)status; +} + +static jint android_media_AudioSystem_addDevicesRoleForCapturePreset( + JNIEnv *env, jobject thiz, jint capturePreset, jint role, jintArray jDeviceTypes, + jobjectArray jDeviceAddresses) { + AudioDeviceTypeAddrVector nDevices; + jint results = getVectorOfAudioDeviceTypeAddr(env, jDeviceTypes, jDeviceAddresses, nDevices); + if (results != NO_ERROR) { + return results; + } + int status = check_AudioSystem_Command( + AudioSystem::addDevicesRoleForCapturePreset((audio_source_t)capturePreset, + (device_role_t)role, nDevices)); + return (jint)status; +} + +static jint android_media_AudioSystem_removeDevicesRoleForCapturePreset( + JNIEnv *env, jobject thiz, jint capturePreset, jint role, jintArray jDeviceTypes, + jobjectArray jDeviceAddresses) { + AudioDeviceTypeAddrVector nDevices; + jint results = getVectorOfAudioDeviceTypeAddr(env, jDeviceTypes, jDeviceAddresses, nDevices); + if (results != NO_ERROR) { + return results; + } + int status = check_AudioSystem_Command( + AudioSystem::removeDevicesRoleForCapturePreset((audio_source_t)capturePreset, + (device_role_t)role, nDevices)); + return (jint)status; +} + +static jint android_media_AudioSystem_clearDevicesRoleForCapturePreset(JNIEnv *env, jobject thiz, + jint capturePreset, + jint role) { + return (jint)check_AudioSystem_Command( + AudioSystem::clearDevicesRoleForCapturePreset((audio_source_t)capturePreset, + (device_role_t)role)); +} + +static jint android_media_AudioSystem_getDevicesForRoleAndCapturePreset(JNIEnv *env, jobject thiz, + jint capturePreset, + jint role, + jobject jDevices) { + AudioDeviceTypeAddrVector nDevices; + status_t status = check_AudioSystem_Command( + AudioSystem::getDevicesForRoleAndCapturePreset((audio_source_t)capturePreset, + (device_role_t)role, nDevices)); + if (status != NO_ERROR) { + return (jint)status; + } + for (const auto &device : nDevices) { + jobject jAudioDeviceAttributes = NULL; + jint jStatus = createAudioDeviceAttributesFromNative(env, &jAudioDeviceAttributes, &device); + if (jStatus != AUDIO_JAVA_SUCCESS) { + return jStatus; + } + env->CallBooleanMethod(jDevices, gListMethods.add, jAudioDeviceAttributes); + env->DeleteLocalRef(jAudioDeviceAttributes); + } + return AUDIO_JAVA_SUCCESS; +} + static jint android_media_AudioSystem_getDevicesForAttributes(JNIEnv *env, jobject thiz, jobject jaa, jobjectArray jDeviceArray) @@ -2558,6 +2631,16 @@ static const JNINativeMethod gMethods[] = (void *)android_media_AudioSystem_removeDevicesRoleForStrategy}, {"getDevicesForRoleAndStrategy", "(IILjava/util/List;)I", (void *)android_media_AudioSystem_getDevicesForRoleAndStrategy}, + {"setDevicesRoleForCapturePreset", "(II[I[Ljava/lang/String;)I", + (void *)android_media_AudioSystem_setDevicesRoleForCapturePreset}, + {"addDevicesRoleForCapturePreset", "(II[I[Ljava/lang/String;)I", + (void *)android_media_AudioSystem_addDevicesRoleForCapturePreset}, + {"removeDevicesRoleForCapturePreset", "(II[I[Ljava/lang/String;)I", + (void *)android_media_AudioSystem_removeDevicesRoleForCapturePreset}, + {"clearDevicesRoleForCapturePreset", "(II)I", + (void *)android_media_AudioSystem_clearDevicesRoleForCapturePreset}, + {"getDevicesForRoleAndCapturePreset", "(IILjava/util/List;)I", + (void *)android_media_AudioSystem_getDevicesForRoleAndCapturePreset}, {"getDevicesForAttributes", "(Landroid/media/AudioAttributes;[Landroid/media/AudioDeviceAttributes;)I", (void *)android_media_AudioSystem_getDevicesForAttributes}, diff --git a/core/jni/android_util_Process.cpp b/core/jni/android_util_Process.cpp index c51f334f1f2e..c08363bbb0ba 100644 --- a/core/jni/android_util_Process.cpp +++ b/core/jni/android_util_Process.cpp @@ -19,18 +19,16 @@ // To make sure cpu_set_t is included from sched.h #define _GNU_SOURCE 1 -#include <android-base/properties.h> -#include <android-base/unique_fd.h> -#include <binder/ActivityManager.h> +#include <utils/Log.h> #include <binder/IPCThreadState.h> #include <binder/IServiceManager.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 <utils/Log.h> -#include <utils/String8.h> -#include <utils/Vector.h> +#include <android-base/unique_fd.h> #include <algorithm> #include <array> @@ -86,8 +84,6 @@ Mutex gKeyCreateMutex; static pthread_key_t gBgKey = -1; #endif -static bool boot_completed = false; - // For both of these, err should be in the errno range (positive), not a status_t (negative) static void signalExceptionForError(JNIEnv* env, int err, int tid) { switch (err) { @@ -584,20 +580,7 @@ void android_os_Process_setThreadPriority(JNIEnv* env, jobject clazz, } #endif - SchedPolicy policy; - bool policy_changed = false; - int rc = 0, curr_pri = getpriority(PRIO_PROCESS, pid); - - if (pri == curr_pri) { - return; - } - - if (!boot_completed) { - boot_completed = android::base::GetBoolProperty("sys.boot_completed", false); - } - - // Do not change sched policy cgroup after boot complete. - rc = androidSetThreadPriorityAndPolicy(pid, pri, !boot_completed); + int rc = androidSetThreadPriority(pid, pri); if (rc != 0) { if (rc == INVALID_OPERATION) { signalExceptionForPriorityError(env, errno, pid); @@ -606,31 +589,6 @@ void android_os_Process_setThreadPriority(JNIEnv* env, jobject clazz, } } - // Only use async approach after boot complete. - if (!boot_completed) { - return; - } - - // Change to background sched policy for the thread if setting to low priority. - if (pri >= ANDROID_PRIORITY_BACKGROUND) { - policy = SP_BACKGROUND; - policy_changed = true; - // Change to sched policy of the process if thread priority is raising from low priority. - } else if (curr_pri >= ANDROID_PRIORITY_BACKGROUND) { - // If we cannot get sched policy of the process, use SP_FOREGROUND as default. - policy = SP_FOREGROUND; - get_sched_policy(getpid(), &policy); - policy_changed = true; - } - - // Sched policy will only change in above 2 cases. - if (policy_changed) { - ActivityManager am; - if (!am.setSchedPolicyCgroup(pid, policy)) { - ALOGE("am.setThreadPriority failed: tid=%d priority=%d policy=%d", pid, pri, policy); - } - } - //ALOGI("Setting priority of %" PRId32 ": %" PRId32 ", getpriority returns %d\n", // pid, pri, getpriority(PRIO_PROCESS, pid)); } diff --git a/core/jni/android_view_KeyEvent.cpp b/core/jni/android_view_KeyEvent.cpp index 54567e5010c5..8177ec6df803 100644 --- a/core/jni/android_view_KeyEvent.cpp +++ b/core/jni/android_view_KeyEvent.cpp @@ -20,6 +20,7 @@ #include <android_runtime/AndroidRuntime.h> #include <android_runtime/Log.h> +#include <attestation/HmacKeyManager.h> #include <input/Input.h> #include <nativehelper/ScopedPrimitiveArray.h> #include <nativehelper/ScopedUtfChars.h> diff --git a/core/jni/android_view_MotionEvent.cpp b/core/jni/android_view_MotionEvent.cpp index 2e396f247979..ce8b59941a5a 100644 --- a/core/jni/android_view_MotionEvent.cpp +++ b/core/jni/android_view_MotionEvent.cpp @@ -21,12 +21,13 @@ #include <android/graphics/matrix.h> #include <android_runtime/AndroidRuntime.h> #include <android_runtime/Log.h> -#include <utils/Log.h> +#include <attestation/HmacKeyManager.h> #include <input/Input.h> #include <nativehelper/ScopedUtfChars.h> +#include <utils/Log.h> #include "android_os_Parcel.h" -#include "android_view_MotionEvent.h" #include "android_util_Binder.h" +#include "android_view_MotionEvent.h" #include "core_jni_helpers.h" diff --git a/core/jni/android_view_SurfaceControl.cpp b/core/jni/android_view_SurfaceControl.cpp index 85b4fe197980..f2b4a1b2b032 100644 --- a/core/jni/android_view_SurfaceControl.cpp +++ b/core/jni/android_view_SurfaceControl.cpp @@ -30,6 +30,7 @@ #include <android_runtime/android_hardware_HardwareBuffer.h> #include <android_runtime/android_view_Surface.h> #include <android_runtime/android_view_SurfaceSession.h> +#include <gui/IScreenCaptureListener.h> #include <gui/ISurfaceComposer.h> #include <gui/Surface.h> #include <gui/SurfaceComposerClient.h> @@ -188,6 +189,11 @@ static struct { static struct { jclass clazz; + jmethodID onScreenCaptureComplete; +} gScreenCaptureListenerClassInfo; + +static struct { + jclass clazz; jmethodID ctor; jfieldID defaultConfig; jfieldID primaryRefreshRateMin; @@ -226,6 +232,54 @@ constexpr ui::Dataspace pickDataspaceFromColorMode(const ui::ColorMode colorMode } } +class ScreenCaptureListenerWrapper : public BnScreenCaptureListener { +public: + explicit ScreenCaptureListenerWrapper(JNIEnv* env, jobject jobject) { + env->GetJavaVM(&mVm); + screenCaptureListenerObject = env->NewGlobalRef(jobject); + LOG_ALWAYS_FATAL_IF(!screenCaptureListenerObject, "Failed to make global ref"); + } + + ~ScreenCaptureListenerWrapper() { + if (screenCaptureListenerObject) { + getenv()->DeleteGlobalRef(screenCaptureListenerObject); + screenCaptureListenerObject = nullptr; + } + } + + status_t onScreenCaptureComplete(const ScreenCaptureResults& captureResults) { + JNIEnv* env = getenv(); + if (captureResults.result != NO_ERROR || captureResults.buffer == nullptr) { + env->CallVoidMethod(screenCaptureListenerObject, + gScreenCaptureListenerClassInfo.onScreenCaptureComplete, nullptr); + return NO_ERROR; + } + jobject jhardwareBuffer = android_hardware_HardwareBuffer_createFromAHardwareBuffer( + env, captureResults.buffer->toAHardwareBuffer()); + const jint namedColorSpace = + fromDataspaceToNamedColorSpaceValue(captureResults.capturedDataspace); + jobject screenshotHardwareBuffer = + env->CallStaticObjectMethod(gScreenshotHardwareBufferClassInfo.clazz, + gScreenshotHardwareBufferClassInfo.builder, + jhardwareBuffer, namedColorSpace, + captureResults.capturedSecureLayers); + env->CallVoidMethod(screenCaptureListenerObject, + gScreenCaptureListenerClassInfo.onScreenCaptureComplete, + screenshotHardwareBuffer); + return NO_ERROR; + } + +private: + jobject screenCaptureListenerObject; + JavaVM* mVm; + + JNIEnv* getenv() { + JNIEnv* env; + mVm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6); + return env; + } +}; + // ---------------------------------------------------------------------------- static jlong nativeCreateTransaction(JNIEnv* env, jclass clazz) { @@ -327,36 +381,28 @@ static DisplayCaptureArgs displayCaptureArgsFromObject(JNIEnv* env, return captureArgs; } -static jobject nativeCaptureDisplay(JNIEnv* env, jclass clazz, jobject displayCaptureArgsObject) { +static jint nativeCaptureDisplay(JNIEnv* env, jclass clazz, jobject displayCaptureArgsObject, + jobject screenCaptureListenerObject) { const DisplayCaptureArgs captureArgs = displayCaptureArgsFromObject(env, displayCaptureArgsObject); if (captureArgs.displayToken == NULL) { - return NULL; - } - - ScreenCaptureResults captureResults; - status_t res = ScreenshotClient::captureDisplay(captureArgs, captureResults); - if (res != NO_ERROR) { - return NULL; + return BAD_VALUE; } - jobject jhardwareBuffer = android_hardware_HardwareBuffer_createFromAHardwareBuffer( - env, captureResults.buffer->toAHardwareBuffer()); - const jint namedColorSpace = - fromDataspaceToNamedColorSpaceValue(captureResults.capturedDataspace); - return env->CallStaticObjectMethod(gScreenshotHardwareBufferClassInfo.clazz, - gScreenshotHardwareBufferClassInfo.builder, jhardwareBuffer, - namedColorSpace, captureResults.capturedSecureLayers); + sp<IScreenCaptureListener> captureListener = + new ScreenCaptureListenerWrapper(env, screenCaptureListenerObject); + return ScreenshotClient::captureDisplay(captureArgs, captureListener); } -static jobject nativeCaptureLayers(JNIEnv* env, jclass clazz, jobject layerCaptureArgsObject) { +static jint nativeCaptureLayers(JNIEnv* env, jclass clazz, jobject layerCaptureArgsObject, + jobject screenCaptureListenerObject) { LayerCaptureArgs captureArgs; getCaptureArgs(env, layerCaptureArgsObject, captureArgs); SurfaceControl* layer = reinterpret_cast<SurfaceControl*>( env->GetLongField(layerCaptureArgsObject, gLayerCaptureArgsClassInfo.layer)); if (layer == nullptr) { - return nullptr; + return BAD_VALUE; } captureArgs.layerHandle = layer->getHandle(); @@ -380,19 +426,9 @@ static jobject nativeCaptureLayers(JNIEnv* env, jclass clazz, jobject layerCaptu env->ReleaseLongArrayElements(excludeObjectArray, const_cast<jlong*>(objects), JNI_ABORT); } - ScreenCaptureResults captureResults; - status_t res = ScreenshotClient::captureLayers(captureArgs, captureResults); - if (res != NO_ERROR) { - return NULL; - } - - jobject jhardwareBuffer = android_hardware_HardwareBuffer_createFromAHardwareBuffer( - env, captureResults.buffer->toAHardwareBuffer()); - const jint namedColorSpace = - fromDataspaceToNamedColorSpaceValue(captureResults.capturedDataspace); - return env->CallStaticObjectMethod(gScreenshotHardwareBufferClassInfo.clazz, - gScreenshotHardwareBufferClassInfo.builder, jhardwareBuffer, - namedColorSpace, captureResults.capturedSecureLayers); + sp<IScreenCaptureListener> captureListener = + new ScreenCaptureListenerWrapper(env, screenCaptureListenerObject); + return ScreenshotClient::captureLayers(captureArgs, captureListener); } static void nativeApplyTransaction(JNIEnv* env, jclass clazz, jlong transactionObj, jboolean sync) { @@ -1505,9 +1541,25 @@ static jlong nativeGetHandle(JNIEnv* env, jclass clazz, jlong nativeObject) { return reinterpret_cast<jlong>(surfaceControl->getHandle().get()); } +static void nativeSetFocusedWindow(JNIEnv* env, jclass clazz, jlong transactionObj, + jobject toTokenObj, jobject focusedTokenObj, jint displayId) { + auto transaction = reinterpret_cast<SurfaceComposerClient::Transaction*>(transactionObj); + if (toTokenObj == NULL) return; + + sp<IBinder> toToken(ibinderForJavaObject(env, toTokenObj)); + sp<IBinder> focusedToken; + if (focusedTokenObj != NULL) { + focusedToken = ibinderForJavaObject(env, focusedTokenObj); + } + transaction->setFocusedWindow(toToken, focusedToken, systemTime(SYSTEM_TIME_MONOTONIC), + displayId); +} + // ---------------------------------------------------------------------------- +// clang-format off static const JNINativeMethod sSurfaceControlMethods[] = { + // clang-format off {"nativeCreate", "(Landroid/view/SurfaceSession;Ljava/lang/String;IIIIJLandroid/os/Parcel;)J", (void*)nativeCreate }, {"nativeReadFromParcel", "(Landroid/os/Parcel;)J", @@ -1649,12 +1701,10 @@ static const JNINativeMethod sSurfaceControlMethods[] = { {"nativeSetOverrideScalingMode", "(JJI)V", (void*)nativeSetOverrideScalingMode }, {"nativeCaptureDisplay", - "(Landroid/view/SurfaceControl$DisplayCaptureArgs;)" - "Landroid/view/SurfaceControl$ScreenshotHardwareBuffer;", + "(Landroid/view/SurfaceControl$DisplayCaptureArgs;Landroid/view/SurfaceControl$ScreenCaptureListener;)I", (void*)nativeCaptureDisplay }, {"nativeCaptureLayers", - "(Landroid/view/SurfaceControl$LayerCaptureArgs;)" - "Landroid/view/SurfaceControl$ScreenshotHardwareBuffer;", + "(Landroid/view/SurfaceControl$LayerCaptureArgs;Landroid/view/SurfaceControl$ScreenCaptureListener;)I", (void*)nativeCaptureLayers }, {"nativeSetInputWindowInfo", "(JJLandroid/view/InputWindowHandle;)V", (void*)nativeSetInputWindowInfo }, @@ -1686,8 +1736,13 @@ static const JNINativeMethod sSurfaceControlMethods[] = { (void*)nativeSetGlobalShadowSettings }, {"nativeGetHandle", "(J)J", (void*)nativeGetHandle }, - {"nativeSetFixedTransformHint", "(JJI)V", (void*)nativeSetFixedTransformHint}, + {"nativeSetFixedTransformHint", "(JJI)V", + (void*)nativeSetFixedTransformHint}, + {"nativeSetFocusedWindow", "(JLandroid/os/IBinder;Landroid/os/IBinder;I)V", + (void*)nativeSetFocusedWindow}, + // clang-format on }; +// clang-format on int register_android_view_SurfaceControl(JNIEnv* env) { @@ -1856,6 +1911,12 @@ int register_android_view_SurfaceControl(JNIEnv* env) gLayerCaptureArgsClassInfo.childrenOnly = GetFieldIDOrDie(env, layerCaptureArgsClazz, "mChildrenOnly", "Z"); + jclass screenCaptureListenerClazz = + FindClassOrDie(env, "android/view/SurfaceControl$ScreenCaptureListener"); + gScreenCaptureListenerClassInfo.clazz = MakeGlobalRefOrDie(env, screenCaptureListenerClazz); + gScreenCaptureListenerClassInfo.onScreenCaptureComplete = + GetMethodIDOrDie(env, screenCaptureListenerClazz, "onScreenCaptureComplete", + "(Landroid/view/SurfaceControl$ScreenshotHardwareBuffer;)V"); return err; } diff --git a/core/proto/android/app/settings_enums.proto b/core/proto/android/app/settings_enums.proto index 6212bcbbc05f..7fac615aa88d 100644 --- a/core/proto/android/app/settings_enums.proto +++ b/core/proto/android/app/settings_enums.proto @@ -2748,4 +2748,7 @@ enum PageId { // CATEGORY: SETTINGS // OS: R QPR ADAPTIVE_CONNECTIVITY_CATEGORY = 1850; + + // OS: R QPR2 + BLUETOOTH_PAIRING_RECEIVER = 1851; } diff --git a/core/proto/android/providers/settings/config.proto b/core/proto/android/providers/settings/config.proto index b0a70ef56dbc..d433c0e1859d 100644 --- a/core/proto/android/providers/settings/config.proto +++ b/core/proto/android/providers/settings/config.proto @@ -31,11 +31,14 @@ message ConfigSettingsProto { repeated SettingProto activity_manager_settings = 4; repeated SettingProto app_compat_settings = 5; repeated SettingProto autofill_settings = 6; + repeated SettingProto blobstore_settings = 23; repeated SettingProto connectivity_settings = 7; repeated SettingProto content_capture_settings = 8; - repeated SettingProto dex_boot_settings = 9; + repeated SettingProto device_idle_settings = 24; + reserved 9; // dex_boot_settings repeated SettingProto game_driver_settings = 10; repeated SettingProto input_native_boot_settings = 11; + repeated SettingProto job_scheduler_settings = 25; repeated SettingProto netd_native_settings = 12; repeated SettingProto privacy_settings = 13; repeated SettingProto rollback_boot_settings = 14; @@ -47,7 +50,8 @@ message ConfigSettingsProto { repeated SettingProto systemui_settings = 20; repeated SettingProto telephony_settings = 21; repeated SettingProto textclassifier_settings = 22; - repeated SettingProto blobstore_settings = 23; + + // Next tag: 26 message NamespaceProto { optional string namespace = 1; diff --git a/core/proto/android/providers/settings/global.proto b/core/proto/android/providers/settings/global.proto index 9fccdaf9684f..3ec14c01c363 100644 --- a/core/proto/android/providers/settings/global.proto +++ b/core/proto/android/providers/settings/global.proto @@ -292,7 +292,7 @@ message GlobalSettingsProto { optional SettingProto name = 1; optional SettingProto provisioned = 2 [ (android.privacy).dest = DEST_AUTOMATIC ]; optional SettingProto provisioning_mobile_data_enabled = 3 [ (android.privacy).dest = DEST_AUTOMATIC ]; - optional SettingProto idle_constants = 4; + reserved 4; // idle_constants optional SettingProto policy_constants = 5; optional SettingProto demo_mode = 6 [ (android.privacy).dest = DEST_AUTOMATIC ]; } diff --git a/core/proto/android/providers/settings/secure.proto b/core/proto/android/providers/settings/secure.proto index 3d12d072eb80..7f743ef037a2 100644 --- a/core/proto/android/providers/settings/secure.proto +++ b/core/proto/android/providers/settings/secure.proto @@ -219,6 +219,8 @@ message SecureSettingsProto { optional SettingProto enhanced_voice_privacy_enabled = 23 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto force_bold_text = 85 [ (android.privacy).dest = DEST_AUTOMATIC ]; + message Gesture { optional SettingProto aware_enabled = 1 [ (android.privacy).dest = DEST_AUTOMATIC ]; @@ -615,5 +617,5 @@ message SecureSettingsProto { // Please insert fields in alphabetical order and group them into messages // if possible (to avoid reaching the method limit). - // Next tag = 85; + // Next tag = 86; } diff --git a/core/proto/android/server/windowmanagerservice.proto b/core/proto/android/server/windowmanagerservice.proto index ff0ba8dd5ad4..3a59a16b54ca 100644 --- a/core/proto/android/server/windowmanagerservice.proto +++ b/core/proto/android/server/windowmanagerservice.proto @@ -316,6 +316,7 @@ message ActivityRecordProto { optional bool front_of_task = 28; optional int32 proc_id = 29; optional bool translucent = 30; + optional bool pip_auto_enter_allowed = 31; } /* represents WindowToken */ diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml index cdcb24b6a247..560e3c11d2f4 100644 --- a/core/res/AndroidManifest.xml +++ b/core/res/AndroidManifest.xml @@ -4691,6 +4691,12 @@ <permission android:name="android.permission.HANDLE_CAR_MODE_CHANGES" android:protectionLevel="signature|privileged" /> + <!-- @SystemApi Allows the holder to send category_car notifications. + @hide --> + <permission + android:name="android.permission.SEND_CATEGORY_CAR_NOTIFICATIONS" + android:protectionLevel="signature|privileged" /> + <!-- The system process is explicitly the only one allowed to launch the confirmation UI for full backup/restore --> <uses-permission android:name="android.permission.CONFIRM_FULL_BACKUP"/> @@ -5496,6 +5502,10 @@ android:permission="android.permission.BIND_JOB_SERVICE" > </service> + <service android:name="com.android.server.profcollect.ProfcollectForwardingService$ProfcollectBGJobService" + android:permission="android.permission.BIND_JOB_SERVICE" > + </service> + <service android:name="com.android.server.autofill.AutofillCompatAccessibilityService" android:permission="android.permission.BIND_ACCESSIBILITY_SERVICE" diff --git a/core/res/res/values-bs/strings.xml b/core/res/res/values-bs/strings.xml index 0e176b53f236..feef587dd685 100644 --- a/core/res/res/values-bs/strings.xml +++ b/core/res/res/values-bs/strings.xml @@ -1283,7 +1283,7 @@ <string name="network_switch_type_name_unknown" msgid="3665696841646851068">"nepoznata vrsta mreže"</string> <string name="accept" msgid="5447154347815825107">"Prihvati"</string> <string name="decline" msgid="6490507610282145874">"Odbijte"</string> - <string name="select_character" msgid="3352797107930786979">"Umetni karakter"</string> + <string name="select_character" msgid="3352797107930786979">"Umetni znak"</string> <string name="sms_control_title" msgid="4748684259903148341">"Slanje SMS poruka"</string> <string name="sms_control_message" msgid="6574313876316388239">"<b><xliff:g id="APP_NAME">%1$s</xliff:g></b> šalje veliki broj SMS poruka. Da li želite dozvoliti ovoj aplikaciji da nastavi slanje poruka?"</string> <string name="sms_control_yes" msgid="4858845109269524622">"Dozvoli"</string> diff --git a/core/res/res/values-hu/strings.xml b/core/res/res/values-hu/strings.xml index 0004ff1a3f13..9062435ec9ce 100644 --- a/core/res/res/values-hu/strings.xml +++ b/core/res/res/values-hu/strings.xml @@ -1900,8 +1900,8 @@ <string name="profile_encrypted_message" msgid="1128512616293157802">"A feloldáshoz koppintson rá"</string> <string name="usb_mtp_launch_notification_title" msgid="774319638256707227">"Csatlakoztatva a(z) <xliff:g id="PRODUCT_NAME">%1$s</xliff:g> eszközhöz"</string> <string name="usb_mtp_launch_notification_description" msgid="6942535713629852684">"Koppintson ide a fájlok megtekintéséhez"</string> - <string name="pin_target" msgid="8036028973110156895">"Rögzítés"</string> - <string name="pin_specific_target" msgid="7824671240625957415">"<xliff:g id="LABEL">%1$s</xliff:g> rögzítése"</string> + <string name="pin_target" msgid="8036028973110156895">"Kitűzés"</string> + <string name="pin_specific_target" msgid="7824671240625957415">"<xliff:g id="LABEL">%1$s</xliff:g> kitűzése"</string> <string name="unpin_target" msgid="3963318576590204447">"Feloldás"</string> <string name="unpin_specific_target" msgid="3859828252160908146">"<xliff:g id="LABEL">%1$s</xliff:g> rögzítésének feloldása"</string> <string name="app_info" msgid="6113278084877079851">"Alkalmazásinformáció"</string> diff --git a/core/res/res/values-hy/strings.xml b/core/res/res/values-hy/strings.xml index 264a8fcb343d..4f66b6e8a947 100644 --- a/core/res/res/values-hy/strings.xml +++ b/core/res/res/values-hy/strings.xml @@ -1979,7 +1979,7 @@ <string name="shortcut_restore_signature_mismatch" msgid="579345304221605479">"Չհաջողվեց վերականգնել դյուրանցումը, քանի որ հավելվածների ստորագրությունները տարբեր են"</string> <string name="shortcut_restore_unknown_issue" msgid="2478146134395982154">"Չհաջողվեց վերականգնել դյուրանցումը"</string> <string name="shortcut_disabled_reason_unknown" msgid="753074793553599166">"Դյուրանցումն անջատված է"</string> - <string name="harmful_app_warning_uninstall" msgid="6472912975664191772">"ՀԵՌԱՑՆԵԼ"</string> + <string name="harmful_app_warning_uninstall" msgid="6472912975664191772">"ԱՊԱՏԵՂԱԴՐԵԼ"</string> <string name="harmful_app_warning_open_anyway" msgid="5963657791740211807">"ԲԱՑԵԼ"</string> <string name="harmful_app_warning_title" msgid="8794823880881113856">"Հայտնաբերվել է վնասաբեր հավելված"</string> <string name="slices_permission_request" msgid="3677129866636153406">"<xliff:g id="APP_0">%1$s</xliff:g> հավելվածն ուզում է ցուցադրել հատվածներ <xliff:g id="APP_2">%2$s</xliff:g> հավելվածից"</string> diff --git a/core/res/res/values-mn/strings.xml b/core/res/res/values-mn/strings.xml index a65f80c9332f..2c041dced482 100644 --- a/core/res/res/values-mn/strings.xml +++ b/core/res/res/values-mn/strings.xml @@ -1120,7 +1120,7 @@ <string name="yes" msgid="9069828999585032361">"ОК"</string> <string name="no" msgid="5122037903299899715">"Цуцлах"</string> <string name="dialog_alert_title" msgid="651856561974090712">"Анхаар"</string> - <string name="loading" msgid="3138021523725055037">"Ачааллаж байна..."</string> + <string name="loading" msgid="3138021523725055037">"Ачаалж байна..."</string> <string name="capital_on" msgid="2770685323900821829">"Идэвхтэй"</string> <string name="capital_off" msgid="7443704171014626777">"Идэвхгүй"</string> <string name="checked" msgid="9179896827054513119">"тэмдэглэсэн"</string> diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml index 2b511706d024..20ef017f59f8 100644 --- a/core/res/res/values/attrs.xml +++ b/core/res/res/values/attrs.xml @@ -2784,7 +2784,11 @@ exactly one parameter of type View. For instance, if you specify <code>android:onClick="sayHello"</code>, you must declare a <code>public void sayHello(View v)</code> method of your context - (typically, your Activity). --> + (typically, your Activity). + {@deprecated View actually traverses the Context + hierarchy looking for the relevant method, which is fragile (an intermediate + ContextWrapper adding a same-named method would change behavior) and restricts + bytecode optimizers such as R8. Instead, use View.setOnClickListener.}--> <attr name="onClick" format="string" /> <!-- Defines over-scrolling behavior. This property is used only if the @@ -7505,7 +7509,11 @@ <attr name="enabled" /> <!-- Name of a method on the Context used to inflate the menu that will be - called when the item is clicked. --> + called when the item is clicked. + {@deprecated Menu actually traverses the Context hierarchy looking for the + relevant method, which is fragile (an intermediate ContextWrapper adding a + same-named method would change behavior) and restricts bytecode optimizers + such as R8. Instead, use MenuItem.setOnMenuItemClickListener.} --> <attr name="onClick" /> <!-- How this item should display in the Action Bar, if present. --> diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml index 5f2e4f905b1c..550162a242dc 100644 --- a/core/res/res/values/config.xml +++ b/core/res/res/values/config.xml @@ -2258,7 +2258,7 @@ <!-- Amount of time in ms the user needs to press the relevant keys to trigger the screenshot chord --> - <integer name="config_screenshotChordKeyTimeout">500</integer> + <integer name="config_screenshotChordKeyTimeout">0</integer> <!-- Default width of a vertical scrollbar and height of a horizontal scrollbar. Takes effect only if the scrollbar drawables have no intrinsic size. --> @@ -2783,6 +2783,7 @@ <item>power</item> <item>restart</item> <item>logout</item> + <item>screenshot</item> <item>bugreport</item> </string-array> diff --git a/core/tests/coretests/AndroidManifest.xml b/core/tests/coretests/AndroidManifest.xml index e17c312dbffc..6ae6faa5446e 100644 --- a/core/tests/coretests/AndroidManifest.xml +++ b/core/tests/coretests/AndroidManifest.xml @@ -50,6 +50,7 @@ <uses-permission android:name="android.permission.CLEAR_APP_CACHE" /> <uses-permission android:name="android.permission.CLEAR_APP_USER_DATA" /> <uses-permission android:name="android.permission.DELETE_CACHE_FILES" /> + <uses-permission android:name="android.permission.DEVICE_POWER"/> <uses-permission android:name="android.permission.DOWNLOAD_CACHE_NON_PURGEABLE" /> <uses-permission android:name="android.permission.FOREGROUND_SERVICE"/> <uses-permission android:name="android.permission.GET_PACKAGE_SIZE" /> diff --git a/core/tests/coretests/src/android/content/pm/PackageManagerTests.java b/core/tests/coretests/src/android/content/pm/PackageManagerTests.java index 04906788f4cb..88faa0a49c9c 100644 --- a/core/tests/coretests/src/android/content/pm/PackageManagerTests.java +++ b/core/tests/coretests/src/android/content/pm/PackageManagerTests.java @@ -574,16 +574,16 @@ public class PackageManagerTests extends AndroidTestCase { InstallParams(String outFileName, int rawResId) throws PackageParserException { this.pkg = getParsedPackage(outFileName, rawResId); - this.packageURI = Uri.fromFile(new File(pkg.getCodePath())); + this.packageURI = Uri.fromFile(new File(pkg.getPath())); } InstallParams(ParsingPackage pkg) { - this.packageURI = Uri.fromFile(new File(pkg.getCodePath())); + this.packageURI = Uri.fromFile(new File(pkg.getPath())); this.pkg = pkg; } long getApkSize() { - File file = new File(pkg.getCodePath()); + File file = new File(pkg.getPath()); return file.length(); } } @@ -1003,7 +1003,7 @@ public class PackageManagerTests extends AndroidTestCase { try { cleanUpInstall(ip.pkg.getPackageName()); } finally { - File outFile = new File(ip.pkg.getCodePath()); + File outFile = new File(ip.pkg.getPath()); if (outFile != null && outFile.exists()) { outFile.delete(); } diff --git a/core/tests/coretests/src/android/view/ImeInsetsSourceConsumerTest.java b/core/tests/coretests/src/android/view/ImeInsetsSourceConsumerTest.java index eb695258142a..a5b7c6156109 100644 --- a/core/tests/coretests/src/android/view/ImeInsetsSourceConsumerTest.java +++ b/core/tests/coretests/src/android/view/ImeInsetsSourceConsumerTest.java @@ -16,9 +16,11 @@ package android.view; +import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED; import static android.view.ImeInsetsSourceConsumer.areEditorsSimilar; import static android.view.InsetsState.ITYPE_IME; import static android.view.WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE; +import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION; import static junit.framework.Assert.assertFalse; import static junit.framework.Assert.assertTrue; @@ -86,6 +88,7 @@ public class ImeInsetsSourceConsumerTest { false, new DisplayCutout( Insets.of(10, 10, 10, 10), rect, rect, rect, rect), + TYPE_APPLICATION, WINDOWING_MODE_UNDEFINED, SOFT_INPUT_ADJUST_RESIZE, 0, 0); mImeConsumer = (ImeInsetsSourceConsumer) mController.getSourceConsumer(ITYPE_IME); }); diff --git a/core/tests/coretests/src/android/view/InsetsControllerTest.java b/core/tests/coretests/src/android/view/InsetsControllerTest.java index de128ad6d78e..88e1f5781e0e 100644 --- a/core/tests/coretests/src/android/view/InsetsControllerTest.java +++ b/core/tests/coretests/src/android/view/InsetsControllerTest.java @@ -16,6 +16,7 @@ package android.view; +import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED; import static android.view.InsetsController.ANIMATION_TYPE_HIDE; import static android.view.InsetsController.ANIMATION_TYPE_NONE; import static android.view.InsetsController.ANIMATION_TYPE_SHOW; @@ -30,6 +31,7 @@ import static android.view.WindowInsets.Type.ime; import static android.view.WindowInsets.Type.navigationBars; import static android.view.WindowInsets.Type.statusBars; import static android.view.WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE; +import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; @@ -169,6 +171,7 @@ public class InsetsControllerTest { false, new DisplayCutout( Insets.of(10, 10, 10, 10), rect, rect, rect, rect), + TYPE_APPLICATION, WINDOWING_MODE_UNDEFINED, SOFT_INPUT_ADJUST_RESIZE, 0, 0); mController.onFrameChanged(new Rect(0, 0, 100, 100)); }); diff --git a/core/tests/coretests/src/android/view/InsetsStateTest.java b/core/tests/coretests/src/android/view/InsetsStateTest.java index c7d835ca7c7e..4306e3e0fe7b 100644 --- a/core/tests/coretests/src/android/view/InsetsStateTest.java +++ b/core/tests/coretests/src/android/view/InsetsStateTest.java @@ -16,6 +16,8 @@ package android.view; +import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM; +import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED; import static android.view.InsetsState.ISIDE_BOTTOM; import static android.view.InsetsState.ISIDE_TOP; import static android.view.InsetsState.ITYPE_BOTTOM_GESTURES; @@ -30,9 +32,13 @@ import static android.view.WindowInsets.Type.ime; import static android.view.WindowInsets.Type.navigationBars; import static android.view.WindowInsets.Type.statusBars; import static android.view.WindowManager.LayoutParams.FLAG_FULLSCREEN; +import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS; import static android.view.WindowManager.LayoutParams.SOFT_INPUT_ADJUST_NOTHING; import static android.view.WindowManager.LayoutParams.SOFT_INPUT_ADJUST_PAN; import static android.view.WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE; +import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION; +import static android.view.WindowManager.LayoutParams.TYPE_SYSTEM_ERROR; +import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; @@ -78,7 +84,8 @@ public class InsetsStateTest { mState.getSource(ITYPE_IME).setVisible(true); SparseIntArray typeSideMap = new SparseIntArray(); WindowInsets insets = mState.calculateInsets(new Rect(0, 0, 100, 300), null, false, - false, DisplayCutout.NO_CUTOUT, SOFT_INPUT_ADJUST_RESIZE, 0, 0, typeSideMap); + false, DisplayCutout.NO_CUTOUT, SOFT_INPUT_ADJUST_RESIZE, 0, 0, + TYPE_APPLICATION, WINDOWING_MODE_UNDEFINED, typeSideMap); assertEquals(Insets.of(0, 100, 0, 100), insets.getSystemWindowInsets()); assertEquals(Insets.of(0, 100, 0, 100), insets.getInsets(Type.all())); assertEquals(ISIDE_TOP, typeSideMap.get(ITYPE_STATUS_BAR)); @@ -97,7 +104,8 @@ public class InsetsStateTest { mState.getSource(ITYPE_IME).setFrame(new Rect(0, 100, 100, 300)); mState.getSource(ITYPE_IME).setVisible(true); WindowInsets insets = mState.calculateInsets(new Rect(0, 0, 100, 300), null, false, - false, DisplayCutout.NO_CUTOUT, SOFT_INPUT_ADJUST_RESIZE, 0, 0, null); + false, DisplayCutout.NO_CUTOUT, SOFT_INPUT_ADJUST_RESIZE, 0, 0, + TYPE_APPLICATION, WINDOWING_MODE_UNDEFINED, null); assertEquals(100, insets.getStableInsetBottom()); assertEquals(Insets.of(0, 0, 0, 100), insets.getInsetsIgnoringVisibility(Type.systemBars())); assertEquals(Insets.of(0, 0, 0, 200), insets.getSystemWindowInsets()); @@ -116,7 +124,8 @@ public class InsetsStateTest { mState.getSource(ITYPE_NAVIGATION_BAR).setFrame(new Rect(80, 0, 100, 300)); mState.getSource(ITYPE_NAVIGATION_BAR).setVisible(true); WindowInsets insets = mState.calculateInsets(new Rect(0, 0, 100, 300), null, false, - false, DisplayCutout.NO_CUTOUT, 0, 0, 0, null); + false, DisplayCutout.NO_CUTOUT, 0, 0, 0, TYPE_APPLICATION, + WINDOWING_MODE_UNDEFINED, null); assertEquals(Insets.of(0, 100, 20, 0), insets.getSystemWindowInsets()); assertEquals(Insets.of(0, 100, 0, 0), insets.getInsets(Type.statusBars())); assertEquals(Insets.of(0, 0, 20, 0), insets.getInsets(Type.navigationBars())); @@ -132,7 +141,8 @@ public class InsetsStateTest { mState.getSource(ITYPE_IME).setFrame(new Rect(0, 200, 100, 300)); mState.getSource(ITYPE_IME).setVisible(true); WindowInsets insets = mState.calculateInsets(new Rect(0, 0, 100, 300), null, false, - false, DisplayCutout.NO_CUTOUT, SOFT_INPUT_ADJUST_NOTHING, 0, 0, null); + false, DisplayCutout.NO_CUTOUT, SOFT_INPUT_ADJUST_NOTHING, 0, 0, + TYPE_APPLICATION, WINDOWING_MODE_UNDEFINED, null); assertEquals(0, insets.getSystemWindowInsetBottom()); assertEquals(100, insets.getInsets(ime()).bottom); assertTrue(insets.isVisible(ime())); @@ -149,11 +159,11 @@ public class InsetsStateTest { mState.getSource(ITYPE_IME).setVisible(true); WindowInsets insets = mState.calculateInsets(new Rect(0, 0, 100, 300), null, false, false, DisplayCutout.NO_CUTOUT, SOFT_INPUT_ADJUST_NOTHING, 0, - SYSTEM_UI_FLAG_LAYOUT_STABLE, null); + SYSTEM_UI_FLAG_LAYOUT_STABLE, TYPE_APPLICATION, WINDOWING_MODE_UNDEFINED, null); assertEquals(100, insets.getSystemWindowInsetTop()); insets = mState.calculateInsets(new Rect(0, 0, 100, 300), null, false, false, DisplayCutout.NO_CUTOUT, SOFT_INPUT_ADJUST_NOTHING, 0, - 0 /* legacySystemUiFlags */, null); + 0 /* legacySystemUiFlags */, TYPE_APPLICATION, WINDOWING_MODE_UNDEFINED, null); assertEquals(0, insets.getSystemWindowInsetTop()); } } @@ -166,15 +176,37 @@ public class InsetsStateTest { mState.getSource(ITYPE_STATUS_BAR).setVisible(false); WindowInsets insets = mState.calculateInsets(new Rect(0, 0, 100, 300), null, false, false, DisplayCutout.NO_CUTOUT, SOFT_INPUT_ADJUST_NOTHING, FLAG_FULLSCREEN, - SYSTEM_UI_FLAG_LAYOUT_STABLE, null); + SYSTEM_UI_FLAG_LAYOUT_STABLE, TYPE_APPLICATION, WINDOWING_MODE_UNDEFINED, null); assertEquals(0, insets.getSystemWindowInsetTop()); insets = mState.calculateInsets(new Rect(0, 0, 100, 300), null, false, false, DisplayCutout.NO_CUTOUT, SOFT_INPUT_ADJUST_NOTHING, 0, - 0 /* legacySystemUiFlags */, null); + 0 /* legacySystemUiFlags */, TYPE_APPLICATION, WINDOWING_MODE_UNDEFINED, null); assertEquals(0, insets.getSystemWindowInsetTop()); } } + @Test + public void testCalculateInsets_flagLayoutNoLimits() { + mState.getSource(ITYPE_STATUS_BAR).setFrame(new Rect(0, 0, 100, 100)); + mState.getSource(ITYPE_STATUS_BAR).setVisible(true); + WindowInsets insets = mState.calculateInsets(new Rect(0, 0, 100, 300), null, false, + false, DisplayCutout.NO_CUTOUT, SOFT_INPUT_ADJUST_NOTHING, FLAG_LAYOUT_NO_LIMITS, + 0 /* legacySystemUiFlags */, TYPE_APPLICATION, WINDOWING_MODE_UNDEFINED, null); + assertEquals(0, insets.getSystemWindowInsetTop()); + insets = mState.calculateInsets(new Rect(0, 0, 100, 300), null, false, + false, DisplayCutout.NO_CUTOUT, SOFT_INPUT_ADJUST_NOTHING, FLAG_LAYOUT_NO_LIMITS, + 0 /* legacySystemUiFlags */, TYPE_SYSTEM_ERROR, WINDOWING_MODE_UNDEFINED, null); + assertEquals(100, insets.getSystemWindowInsetTop()); + insets = mState.calculateInsets(new Rect(0, 0, 100, 300), null, false, + false, DisplayCutout.NO_CUTOUT, SOFT_INPUT_ADJUST_NOTHING, FLAG_LAYOUT_NO_LIMITS, + 0 /* legacySystemUiFlags */, TYPE_WALLPAPER, WINDOWING_MODE_UNDEFINED, null); + assertEquals(100, insets.getSystemWindowInsetTop()); + insets = mState.calculateInsets(new Rect(0, 0, 100, 300), null, false, + false, DisplayCutout.NO_CUTOUT, SOFT_INPUT_ADJUST_NOTHING, FLAG_LAYOUT_NO_LIMITS, + 0 /* legacySystemUiFlags */, TYPE_APPLICATION, WINDOWING_MODE_FREEFORM, null); + assertEquals(100, insets.getSystemWindowInsetTop()); + } + @Test public void testCalculateInsets_captionStatusBarOverlap() throws Exception { @@ -213,7 +245,8 @@ public class InsetsStateTest { mState.getSource(ITYPE_EXTRA_NAVIGATION_BAR).setFrame(new Rect(80, 0, 100, 300)); mState.getSource(ITYPE_EXTRA_NAVIGATION_BAR).setVisible(true); WindowInsets insets = mState.calculateInsets(new Rect(0, 0, 100, 300), null, false, - false, DisplayCutout.NO_CUTOUT, 0, 0, 0, null); + false, DisplayCutout.NO_CUTOUT, 0, 0, 0, TYPE_APPLICATION, + WINDOWING_MODE_UNDEFINED, null); assertEquals(Insets.of(0, 100, 20, 0), insets.getSystemWindowInsets()); assertEquals(Insets.of(0, 100, 0, 0), insets.getInsets(Type.statusBars())); assertEquals(Insets.of(0, 0, 20, 0), insets.getInsets(Type.navigationBars())); @@ -229,7 +262,8 @@ public class InsetsStateTest { mState.getSource(ITYPE_NAVIGATION_BAR).setFrame(new Rect(80, 0, 100, 300)); mState.getSource(ITYPE_NAVIGATION_BAR).setVisible(true); WindowInsets insets = mState.calculateInsets(new Rect(0, 0, 100, 300), null, false, - false, DisplayCutout.NO_CUTOUT, 0, 0, 0, null); + false, DisplayCutout.NO_CUTOUT, 0, 0, 0, TYPE_APPLICATION, + WINDOWING_MODE_UNDEFINED, null); assertEquals(Insets.of(0, 100, 20, 0), insets.getSystemWindowInsets()); assertEquals(Insets.of(0, 100, 0, 0), insets.getInsets(Type.statusBars())); assertEquals(Insets.of(0, 0, 20, 0), insets.getInsets(Type.navigationBars())); @@ -244,7 +278,8 @@ public class InsetsStateTest { mState.getSource(ITYPE_IME).setVisible(true); mState.removeSource(ITYPE_IME); WindowInsets insets = mState.calculateInsets(new Rect(0, 0, 100, 300), null, false, false, - DisplayCutout.NO_CUTOUT, SOFT_INPUT_ADJUST_RESIZE, 0, 0, null); + DisplayCutout.NO_CUTOUT, SOFT_INPUT_ADJUST_RESIZE, 0, 0, TYPE_APPLICATION, + WINDOWING_MODE_UNDEFINED, null); assertEquals(0, insets.getSystemWindowInsetBottom()); } diff --git a/core/tests/coretests/src/com/android/internal/content/OverlayConfigIterationRule.java b/core/tests/coretests/src/com/android/internal/content/OverlayConfigIterationRule.java index fbf75dfb4979..a01459f20f6b 100644 --- a/core/tests/coretests/src/com/android/internal/content/OverlayConfigIterationRule.java +++ b/core/tests/coretests/src/com/android/internal/content/OverlayConfigIterationRule.java @@ -146,7 +146,7 @@ public class OverlayConfigIterationRule implements TestRule { when(a.getTargetSdkVersion()).thenReturn(info.targetSdkVersion); when(a.isOverlayIsStatic()).thenReturn(info.isStatic); when(a.getOverlayPriority()).thenReturn(info.priority); - when(a.getBaseCodePath()).thenReturn(info.path.getPath()); + when(a.getBaseApkPath()).thenReturn(info.path.getPath()); f.accept(a, !info.path.getPath().contains("data/overlay")); } return null; diff --git a/core/tests/coretests/src/com/android/internal/os/BatteryInputSuspendTest.java b/core/tests/coretests/src/com/android/internal/os/BatteryInputSuspendTest.java new file mode 100644 index 000000000000..e870d6022058 --- /dev/null +++ b/core/tests/coretests/src/com/android/internal/os/BatteryInputSuspendTest.java @@ -0,0 +1,130 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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.assertTrue; + +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.Intent; +import android.content.IntentFilter; +import android.os.BatteryManager; +import android.os.Build; +import android.os.ConditionVariable; + +import androidx.test.platform.app.InstrumentationRegistry; +import androidx.test.runner.AndroidJUnit4; + +import com.android.compatibility.common.util.SystemUtil; + +import com.google.android.collect.Sets; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; + +import java.util.Set; + +@RunWith(AndroidJUnit4.class) +public class BatteryInputSuspendTest { + + public static final Set<String> SUPPORTED_DEVICES = Sets.newArraySet( + "blueline", + "crosshatch", + "coral" + ); + + private ChargerStateMonitor mChargerStateMonitor; + + @Before + public void verifyCharging() { + if (!SUPPORTED_DEVICES.contains(Build.DEVICE)) { + return; + } + + mChargerStateMonitor = new ChargerStateMonitor(); + + assertTrue("Device must be connected to USB", mChargerStateMonitor.isCharging()); + } + + @Test + public void testSuspendInput() { + if (!SUPPORTED_DEVICES.contains(Build.DEVICE)) { + return; + } + + SystemUtil.runShellCommand("dumpsys battery suspend_input"); + + mChargerStateMonitor.waitForChargerState(/* isPluggedIn */false); + } + + @After + public void reenableCharging() { + if (!SUPPORTED_DEVICES.contains(Build.DEVICE)) { + return; + } + + mChargerStateMonitor.reset(); + + SystemUtil.runShellCommand("dumpsys battery reset"); + + mChargerStateMonitor.waitForChargerState(/* isPluggedIn */true); + } + + private static class ChargerStateMonitor { + private final Intent mBatteryMonitor; + private final ConditionVariable mReady = new ConditionVariable(); + private boolean mExpectedChargingState; + + ChargerStateMonitor() { + Context context = InstrumentationRegistry.getInstrumentation().getContext(); + mBatteryMonitor = context.registerReceiver(new BroadcastReceiver() { + @Override + public void onReceive(Context context, Intent intent) { + if (isCharging(intent) == mExpectedChargingState) { + mReady.open(); + } + } + }, new IntentFilter(Intent.ACTION_BATTERY_CHANGED)); + } + + public boolean isCharging() { + return isCharging(mBatteryMonitor); + } + + private boolean isCharging(Intent batteryMonitor) { + return batteryMonitor.getIntExtra(BatteryManager.EXTRA_PLUGGED, -1) != 0; + } + + void waitForChargerState(boolean isPluggedIn) { + mExpectedChargingState = isPluggedIn; + + boolean charging = isCharging(); + if (charging == mExpectedChargingState) { + return; + } + + boolean success = mReady.block(100000); + assertTrue("Timed out waiting for charging state to change", success); + } + + void reset() { + mReady.close(); + } + } +} diff --git a/core/tests/coretests/src/com/android/internal/os/BatteryStatsSamplingTimerTest.java b/core/tests/coretests/src/com/android/internal/os/BatteryStatsSamplingTimerTest.java index 61d20dfb32d9..3b27f1897bd2 100644 --- a/core/tests/coretests/src/com/android/internal/os/BatteryStatsSamplingTimerTest.java +++ b/core/tests/coretests/src/com/android/internal/os/BatteryStatsSamplingTimerTest.java @@ -18,6 +18,7 @@ package com.android.internal.os; import android.os.BatteryStats; import android.os.Parcel; +import android.os.SystemClock; import androidx.test.filters.SmallTest; @@ -36,9 +37,9 @@ public class BatteryStatsSamplingTimerTest extends TestCase { timer.onTimeStarted(100, 100, 100); // First update is absorbed. - timer.update(10, 1); + timer.update(10, 1, SystemClock.elapsedRealtime() * 1000); - timer.update(20, 2); + timer.update(20, 2, SystemClock.elapsedRealtime() * 1000); assertEquals(1, timer.getCountLocked(BatteryStats.STATS_SINCE_CHARGED)); assertEquals(10, timer.getTotalTimeLocked(200, BatteryStats.STATS_SINCE_CHARGED)); @@ -62,7 +63,7 @@ public class BatteryStatsSamplingTimerTest extends TestCase { timeBase); // First once is absorbed. - timer.update(10, 1); + timer.update(10, 1, SystemClock.elapsedRealtime() * 1000); timer.add(10, 1); @@ -71,7 +72,7 @@ public class BatteryStatsSamplingTimerTest extends TestCase { // This is less than we currently have, so we will end the sample. Time isn't running, so // nothing should happen. - timer.update(0, 0); + timer.update(0, 0, SystemClock.elapsedRealtime() * 1000); assertEquals(0, timer.getCountLocked(BatteryStats.STATS_SINCE_CHARGED)); assertEquals(0, timer.getTotalTimeLocked(200, BatteryStats.STATS_SINCE_CHARGED)); @@ -86,7 +87,7 @@ public class BatteryStatsSamplingTimerTest extends TestCase { // This is less than we currently have, so we should end our sample and continue with the // entire amount updated here. - timer.update(50, 5); + timer.update(50, 5, SystemClock.elapsedRealtime() * 1000); assertEquals(150, timer.getTotalTimeLocked(200, BatteryStats.STATS_SINCE_CHARGED)); assertEquals(15, timer.getCountLocked(BatteryStats.STATS_SINCE_CHARGED)); @@ -106,7 +107,7 @@ public class BatteryStatsSamplingTimerTest extends TestCase { // This should be absorbed because it is our first update and we don't know what // was being counted before. - timer.update(10, 1); + timer.update(10, 1, SystemClock.elapsedRealtime() * 1000); assertEquals(0, timer.getTotalTimeLocked(10, BatteryStats.STATS_SINCE_CHARGED)); assertEquals(0, timer.getCountLocked(BatteryStats.STATS_SINCE_CHARGED)); @@ -115,7 +116,7 @@ public class BatteryStatsSamplingTimerTest extends TestCase { timer.onTimeStarted(100, 100, 100); // This should be absorbed. - timer.update(10, 1); + timer.update(10, 1, SystemClock.elapsedRealtime() * 1000); assertEquals(0, timer.getTotalTimeLocked(100, BatteryStats.STATS_SINCE_CHARGED)); assertEquals(0, timer.getCountLocked(BatteryStats.STATS_SINCE_CHARGED)); @@ -206,13 +207,13 @@ public class BatteryStatsSamplingTimerTest extends TestCase { // Now, just like with a fresh timer, the first update should be absorbed to account for // data being collected when we weren't recording. - unparceledOnBatteryTimer.update(10, 10); + unparceledOnBatteryTimer.update(10, 10, SystemClock.elapsedRealtime() * 1000); assertEquals(10, unparceledOnBatteryTimer.getTotalTimeLocked(0, BatteryStats.STATS_SINCE_CHARGED)); assertEquals(1, unparceledOnBatteryTimer.getCountLocked(BatteryStats.STATS_SINCE_CHARGED)); - unparceledOffBatteryTimer.update(10, 10); + unparceledOffBatteryTimer.update(10, 10, SystemClock.elapsedRealtime() * 1000); assertEquals(10, unparceledOffBatteryTimer.getTotalTimeLocked(0, BatteryStats.STATS_SINCE_CHARGED)); diff --git a/core/tests/coretests/src/com/android/internal/os/BatteryStatsServTest.java b/core/tests/coretests/src/com/android/internal/os/BatteryStatsServTest.java index df549c5b51c8..80e066c1e794 100644 --- a/core/tests/coretests/src/com/android/internal/os/BatteryStatsServTest.java +++ b/core/tests/coretests/src/com/android/internal/os/BatteryStatsServTest.java @@ -36,22 +36,22 @@ public class BatteryStatsServTest extends TestCase { } void populate() { - mStartTime = 1010; - mRunningSince = 2021; + mStartTimeMs = 1010; + mRunningSinceMs = 2021; mRunning = true; mStarts = 4042; - mLaunchedTime = 5053; - mLaunchedSince = 6064; + mLaunchedTimeMs = 5053; + mLaunchedSinceMs = 6064; mLaunched = true; mLaunches = 8085; } long getStartTime() { - return mStartTime; + return mStartTimeMs; } long getRunningSince() { - return mRunningSince; + return mRunningSinceMs; } void setRunning(boolean val) { @@ -67,11 +67,11 @@ public class BatteryStatsServTest extends TestCase { } long getLaunchedTime() { - return mLaunchedTime; + return mLaunchedTimeMs; } long getLaunchedSince() { - return mLaunchedSince; + return mLaunchedSinceMs; } void setLaunched(boolean val) { @@ -173,7 +173,12 @@ public class BatteryStatsServTest extends TestCase { MockBatteryStatsImpl bsi = new MockBatteryStatsImpl() { @Override public long getBatteryUptimeLocked() { - return 777777L; + return 777777L * 1000; // microseconds + } + + @Override + public long getBatteryUptimeLocked(long uptimeMs) { + return 777777L * 1000; // microseconds } }; @@ -202,7 +207,12 @@ public class BatteryStatsServTest extends TestCase { MockBatteryStatsImpl bsi = new MockBatteryStatsImpl() { @Override public long getBatteryUptimeLocked() { - return 777777L; + return 777777L * 1000; // microseconds + } + + @Override + public long getBatteryUptimeLocked(long uptimeMs) { + return 777777L * 1000; // microseconds } }; @@ -229,7 +239,12 @@ public class BatteryStatsServTest extends TestCase { MockBatteryStatsImpl bsi = new MockBatteryStatsImpl() { @Override public long getBatteryUptimeLocked() { - return 777777L; + return 777777L * 1000; // microseconds + } + + @Override + public long getBatteryUptimeLocked(long uptimeMs) { + return 777777L * 1000; // microseconds } }; TestServ serv = new TestServ(bsi); @@ -259,7 +274,12 @@ public class BatteryStatsServTest extends TestCase { MockBatteryStatsImpl bsi = new MockBatteryStatsImpl() { @Override public long getBatteryUptimeLocked() { - return 777777L; + return 777777L * 1000; // microseconds + } + + @Override + public long getBatteryUptimeLocked(long uptimeMs) { + return 777777L * 1000; // microseconds } }; TestServ serv = new TestServ(bsi); @@ -316,7 +336,12 @@ public class BatteryStatsServTest extends TestCase { MockBatteryStatsImpl bsi = new MockBatteryStatsImpl() { @Override public long getBatteryUptimeLocked() { - return 777777L; + return 777777L * 1000; // microseconds + } + + @Override + public long getBatteryUptimeLocked(long uptimeMs) { + return 777777L * 1000; // microseconds } }; TestServ serv = new TestServ(bsi); @@ -345,7 +370,12 @@ public class BatteryStatsServTest extends TestCase { MockBatteryStatsImpl bsi = new MockBatteryStatsImpl() { @Override public long getBatteryUptimeLocked() { - return 777777L; + return 777777L * 1000; // microseconds + } + + @Override + public long getBatteryUptimeLocked(long uptimeMs) { + return 777777L * 1000; // microseconds } }; TestServ serv = new TestServ(bsi); @@ -374,7 +404,12 @@ public class BatteryStatsServTest extends TestCase { MockBatteryStatsImpl bsi = new MockBatteryStatsImpl() { @Override public long getBatteryUptimeLocked() { - return 777777L; + return 777777L * 1000; // microseconds + } + + @Override + public long getBatteryUptimeLocked(long uptimeMs) { + return 777777L * 1000; // microseconds } }; TestServ serv = new TestServ(bsi); diff --git a/core/tests/coretests/src/com/android/internal/os/BatteryStatsTimeBaseTest.java b/core/tests/coretests/src/com/android/internal/os/BatteryStatsTimeBaseTest.java index e5441c018875..f016e75a45b1 100644 --- a/core/tests/coretests/src/com/android/internal/os/BatteryStatsTimeBaseTest.java +++ b/core/tests/coretests/src/com/android/internal/os/BatteryStatsTimeBaseTest.java @@ -41,29 +41,29 @@ public class BatteryStatsTimeBaseTest extends TestCase { public void populate(long uptime, long realtime, boolean running, long pastUptime, long uptimeStart, long pastRealtime, long realtimeStart, long unpluggedUptime, long unpluggedRealtime) { - mUptime = uptime; - mRealtime = realtime; + mUptimeUs = uptime; + mRealtimeUs = realtime; mRunning = running; - mPastUptime = pastUptime; - mUptimeStart = uptimeStart; - mPastRealtime = pastRealtime; - mRealtimeStart = realtimeStart; - mUnpluggedUptime = unpluggedUptime; - mUnpluggedRealtime = unpluggedRealtime; + mPastUptimeUs = pastUptime; + mUptimeStartUs = uptimeStart; + mPastRealtimeUs = pastRealtime; + mRealtimeStartUs = realtimeStart; + mUnpluggedUptimeUs = unpluggedUptime; + mUnpluggedRealtimeUs = unpluggedRealtime; } public void verify(long uptime, long realtime, boolean running, long pastUptime, long uptimeStart, long pastRealtime, long realtimeStart, long unpluggedUptime, long unpluggedRealtime) { - Assert.assertEquals(uptime, mUptime); - Assert.assertEquals(realtime, mRealtime); + Assert.assertEquals(uptime, mUptimeUs); + Assert.assertEquals(realtime, mRealtimeUs); Assert.assertEquals(running, mRunning); - Assert.assertEquals(pastUptime, mPastUptime); - Assert.assertEquals(uptimeStart, mUptimeStart); - Assert.assertEquals(pastRealtime, mPastRealtime); - Assert.assertEquals(realtimeStart, mRealtimeStart); - Assert.assertEquals(unpluggedUptime, mUnpluggedUptime); - Assert.assertEquals(unpluggedRealtime, mUnpluggedRealtime); + Assert.assertEquals(pastUptime, mPastUptimeUs); + Assert.assertEquals(uptimeStart, mUptimeStartUs); + Assert.assertEquals(pastRealtime, mPastRealtimeUs); + Assert.assertEquals(realtimeStart, mRealtimeStartUs); + Assert.assertEquals(unpluggedUptime, mUnpluggedUptimeUs); + Assert.assertEquals(unpluggedRealtime, mUnpluggedRealtimeUs); } } diff --git a/core/tests/coretests/src/com/android/internal/os/BatteryStatsTimerTest.java b/core/tests/coretests/src/com/android/internal/os/BatteryStatsTimerTest.java index 40e3a5f55ca5..11a01b3a42dc 100644 --- a/core/tests/coretests/src/com/android/internal/os/BatteryStatsTimerTest.java +++ b/core/tests/coretests/src/com/android/internal/os/BatteryStatsTimerTest.java @@ -49,7 +49,8 @@ public class BatteryStatsTimerTest extends TestCase { super(clocks, type, timeBase); } - protected long computeRunTimeLocked(long curBatteryRealtime) { + @Override + protected long computeRunTimeLocked(long curBatteryRealtime, long elapsedRealtimeUs) { lastComputeRunTimeRealtime = curBatteryRealtime; return nextComputeRunTime; } @@ -67,19 +68,19 @@ public class BatteryStatsTimerTest extends TestCase { } public long getTotalTime() { - return mTotalTime; + return mTotalTimeUs; } public void setTotalTime(long val) { - mTotalTime = val; + mTotalTimeUs = val; } public long getTimeBeforeMark() { - return mTimeBeforeMark; + return mTimeBeforeMarkUs; } public void setTimeBeforeMark(long val) { - mTimeBeforeMark = val; + mTimeBeforeMarkUs = val; } } diff --git a/core/tests/coretests/src/com/android/internal/policy/DecorContextTest.java b/core/tests/coretests/src/com/android/internal/policy/DecorContextTest.java index 02870a53773e..7f4e9ada7b22 100644 --- a/core/tests/coretests/src/com/android/internal/policy/DecorContextTest.java +++ b/core/tests/coretests/src/com/android/internal/policy/DecorContextTest.java @@ -20,6 +20,9 @@ import static android.view.Display.DEFAULT_DISPLAY; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.verify; import android.app.Activity; import android.app.EmptyActivity; @@ -41,6 +44,7 @@ import org.junit.Before; import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; +import org.mockito.Mockito; /** * Tests {@link DecorContext}. @@ -63,13 +67,18 @@ public final class DecorContextTest { @Test public void testDecorContextWithDefaultDisplay() { + final Context baseContext = Mockito.spy(mContext.getApplicationContext()); Display defaultDisplay = new Display(DisplayManagerGlobal.getInstance(), DEFAULT_DISPLAY, new DisplayInfo(), DisplayAdjustments.DEFAULT_DISPLAY_ADJUSTMENTS); final Context defaultDisplayContext = mContext.createDisplayContext(defaultDisplay); final PhoneWindow window = new PhoneWindow(defaultDisplayContext); - DecorContext context = new DecorContext(mContext.getApplicationContext(), window); + DecorContext context = new DecorContext(baseContext, window); assertDecorContextDisplay(DEFAULT_DISPLAY, context); + + // TODO(b/166174272): Creating a display context for the default display will result + // in additional resource creation. + verify(baseContext, never()).createDisplayContext(any()); } @Test diff --git a/core/tests/coretests/src/com/android/internal/util/HexDumpTest.java b/core/tests/coretests/src/com/android/internal/util/HexDumpTest.java index 359bd5e93dae..f1cd89bf49f4 100644 --- a/core/tests/coretests/src/com/android/internal/util/HexDumpTest.java +++ b/core/tests/coretests/src/com/android/internal/util/HexDumpTest.java @@ -16,8 +16,16 @@ package com.android.internal.util; +import static com.android.internal.util.HexDump.hexStringToByteArray; +import static com.android.internal.util.HexDump.toHexString; + import junit.framework.TestCase; +import java.io.PrintWriter; +import java.io.StringWriter; +import java.util.Arrays; +import java.util.Random; + public final class HexDumpTest extends TestCase { public void testBytesToHexString() { assertEquals("abcdef", HexDump.toHexString( @@ -25,7 +33,143 @@ public final class HexDumpTest extends TestCase { assertEquals("ABCDEF", HexDump.toHexString( new byte[] { (byte) 0xab, (byte) 0xcd, (byte) 0xef }, true)); } - public void testNullArray() { - assertEquals("(null)", HexDump.toHexString(null)); + + public void testNullByteArray() { + assertThrows( + NullPointerException.class, + () -> HexDump.toHexString(null)); + } + + public void testBytesToHexString_allByteValues() { + byte[] bytes = new byte[256]; + for (int i = 0; i < bytes.length; i++) { + bytes[i] = (byte) (i % 256); + } + + StringBuilder sb = new StringBuilder(); + for (char firstChar : "0123456789ABCDEF".toCharArray()) { + for (char secondChar : "0123456789ABCDEF".toCharArray()) { + sb.append(firstChar).append(secondChar); + } + } + String expected = sb.toString(); + + assertEquals(expected, HexDump.toHexString(bytes)); + } + + public void testRoundTrip_fromBytes() { + Random deterministicRandom = new Random(31337); // arbitrary but deterministic + for (int length = 0; length < 100; length++) { + byte[] bytes = new byte[length]; + deterministicRandom.nextBytes(bytes); + byte[] reconstruction = hexStringToByteArray(toHexString(bytes)); + + assertBytesEqual(bytes, reconstruction); + } + } + + public void testRoundTrip_fromString() { + String hexString = "0123456789ABCDEF72f9a3438934c378d34f32a8b932"; + for (int length = 0; length < hexString.length(); length += 2) { + String original = hexString.substring(0, length); + String reconstruction = toHexString(hexStringToByteArray(original)); + assertEquals(original.toUpperCase(), reconstruction); + } + } + + public void testToHexString_offsetLength() { + byte[] bytes = new byte[32]; + for (int i = 0; i < 16; i++) { + bytes[i] = (byte) i; + bytes[16 + i] = (byte) (16 * i); + } + String expected = "000102030405060708090A0B0C0D0E0F00102030405060708090A0B0C0D0E0F0"; + for (int offset = 0; offset < bytes.length; offset++) { + for (int len = 0; len < (bytes.length - offset); len++) { + + byte[] subBytes = new byte[len]; + System.arraycopy(bytes, offset, subBytes, 0, len); + + String actual = toHexString(bytes, offset, len); + assertEquals(expected.substring(2 * offset, 2 * offset + 2 * len), actual); + assertEquals(toHexString(subBytes), actual); + } + } + } + + public void testToHexString_case() { + byte[] bytes = new byte[32]; + for (int i = 0; i < 16; i++) { + bytes[i] = (byte) i; + bytes[16 + i] = (byte) (16 * i); + } + + String expected = "000102030405060708090A0B0C0D0E0F00102030405060708090A0B0C0D0E0F0"; + + assertEquals(expected.toUpperCase(), toHexString(bytes, true)); + assertEquals(expected.toLowerCase(), toHexString(bytes, false)); + + // default is uppercase + assertEquals(expected.toUpperCase(), toHexString(bytes)); + } + + public void testHexStringToByteArray_empty() { + assertBytesEqual(new byte[0], HexDump.hexStringToByteArray("")); + } + + public void testHexStringToByteArray_null() { + assertThrows( + NullPointerException.class, + () -> HexDump.hexStringToByteArray((String) null)); + } + + public void testHexStringToByteArray_invalidCharacters() { + // IllegalArgumentException would probably have been better than RuntimeException, but it + // might be too late to change now. + assertThrows( + RuntimeException.class, + () -> HexDump.hexStringToByteArray("GG")); + assertThrows( + RuntimeException.class, + () -> HexDump.hexStringToByteArray("\0\0")); + assertThrows( + RuntimeException.class, + () -> HexDump.hexStringToByteArray("abcdefgh")); + } + + public void testHexStringToByteArray_oddLength() { + // IllegalArgumentException would probably have been better than + // StringIndexOutOfBoundsException, but it might be too late to change now. + assertThrows( + StringIndexOutOfBoundsException.class, + () -> HexDump.hexStringToByteArray("A")); + assertThrows( + StringIndexOutOfBoundsException.class, + () -> HexDump.hexStringToByteArray("123")); + assertThrows( + StringIndexOutOfBoundsException.class, + () -> HexDump.hexStringToByteArray("ABCDE")); } + + private static void assertBytesEqual(byte[] expected, byte[] actual) { + if (!Arrays.equals(expected, actual)) { + fail("Expected " + Arrays.toString(expected) + ", got " + Arrays.toString(actual)); + } + } + + private static void assertThrows(Class<? extends RuntimeException> clazz, Runnable runnable) { + try { + runnable.run(); + fail(); + } catch (RuntimeException expected) { + assertEquals(toStrackTrace(expected), clazz, expected.getClass()); + } + } + + private static String toStrackTrace(Throwable throwable) { + StringWriter stringWriter = new StringWriter(); + throwable.printStackTrace(new PrintWriter(stringWriter)); + return stringWriter.toString(); + } + } diff --git a/core/tests/mockingcoretests/src/android/app/activity/ActivityThreadClientTest.java b/core/tests/mockingcoretests/src/android/app/activity/ActivityThreadClientTest.java index 1cdc75aa1f40..9d95de7eb60f 100644 --- a/core/tests/mockingcoretests/src/android/app/activity/ActivityThreadClientTest.java +++ b/core/tests/mockingcoretests/src/android/app/activity/ActivityThreadClientTest.java @@ -23,6 +23,8 @@ import static android.app.servertransaction.ActivityLifecycleItem.ON_RESUME; import static android.app.servertransaction.ActivityLifecycleItem.ON_START; import static android.app.servertransaction.ActivityLifecycleItem.ON_STOP; +import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation; + import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn; import static com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSession; import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn; @@ -30,7 +32,11 @@ import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn; import static org.junit.Assert.assertEquals; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyInt; +import static org.mockito.Mockito.after; +import static org.mockito.Mockito.clearInvocations; import static org.mockito.Mockito.doNothing; +import static org.mockito.Mockito.timeout; +import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import android.app.Activity; @@ -50,6 +56,7 @@ import android.os.Binder; import android.os.RemoteException; import android.os.UserHandle; import android.platform.test.annotations.Presubmit; +import android.testing.PollingCheck; import android.view.WindowManagerGlobal; import androidx.test.annotation.UiThreadTest; @@ -63,6 +70,8 @@ import org.mockito.Mockito; import org.mockito.MockitoSession; import org.mockito.quality.Strictness; +import java.util.concurrent.TimeUnit; + /** * Test for verifying {@link android.app.ActivityThread} class. * @@ -76,6 +85,7 @@ import org.mockito.quality.Strictness; @MediumTest @Presubmit public class ActivityThreadClientTest { + private static final long WAIT_TIMEOUT_MS = TimeUnit.SECONDS.toMillis(5); @Test @UiThreadTest @@ -152,6 +162,63 @@ public class ActivityThreadClientTest { } } + @Test + public void testLifecycleOfRelaunch() throws Exception { + try (ClientMockSession clientSession = new ClientMockSession()) { + ActivityThread activityThread = clientSession.mockThread(); + ActivityClientRecord r = clientSession.stubActivityRecord(); + final TestActivity[] activity = new TestActivity[1]; + + // Verify for ON_CREATE state. Activity should not be relaunched. + getInstrumentation().runOnMainSync(() -> { + activity[0] = (TestActivity) clientSession.launchActivity(r); + }); + recreateAndVerifyNoRelaunch(activityThread, activity[0]); + + // Verify for ON_START state. Activity should be relaunched. + getInstrumentation().runOnMainSync(() -> clientSession.startActivity(r)); + recreateAndVerifyRelaunched(activityThread, activity[0], r, ON_START); + + // Verify for ON_RESUME state. Activity should be relaunched. + getInstrumentation().runOnMainSync(() -> clientSession.resumeActivity(r)); + recreateAndVerifyRelaunched(activityThread, activity[0], r, ON_RESUME); + + // Verify for ON_PAUSE state. Activity should be relaunched. + getInstrumentation().runOnMainSync(() -> clientSession.pauseActivity(r)); + recreateAndVerifyRelaunched(activityThread, activity[0], r, ON_PAUSE); + + // Verify for ON_STOP state. Activity should be relaunched. + getInstrumentation().runOnMainSync(() -> clientSession.stopActivity(r)); + recreateAndVerifyRelaunched(activityThread, activity[0], r, ON_STOP); + + // Verify for ON_DESTROY state. Activity should not be relaunched. + getInstrumentation().runOnMainSync(() -> clientSession.destroyActivity(r)); + recreateAndVerifyNoRelaunch(activityThread, activity[0]); + } + } + + private void recreateAndVerifyNoRelaunch(ActivityThread activityThread, TestActivity activity) { + clearInvocations(activityThread); + getInstrumentation().runOnMainSync(() -> activity.recreate()); + + verify(activityThread, after(WAIT_TIMEOUT_MS).never()) + .handleRelaunchActivity(any(), any()); + } + + private void recreateAndVerifyRelaunched(ActivityThread activityThread, TestActivity activity, + ActivityClientRecord r, int expectedState) throws Exception { + clearInvocations(activityThread); + getInstrumentation().runOnMainSync(() -> activity.recreate()); + + verify(activityThread, timeout(WAIT_TIMEOUT_MS)).handleRelaunchActivity(any(), any()); + + // Wait for the relaunch to complete. + PollingCheck.check("Waiting for the expected state " + expectedState + " timeout", + WAIT_TIMEOUT_MS, + () -> expectedState == r.getLifecycleState()); + assertEquals(expectedState, r.getLifecycleState()); + } + private class ClientMockSession implements AutoCloseable { private MockitoSession mMockSession; private ActivityThread mThread; @@ -200,6 +267,11 @@ public class ActivityThreadClientTest { false /* getNonConfigInstance */, "test"); } + private ActivityThread mockThread() { + spyOn(mThread); + return mThread; + } + private ActivityClientRecord stubActivityRecord() { ComponentName component = new ComponentName( InstrumentationRegistry.getInstrumentation().getContext(), TestActivity.class); diff --git a/core/tests/powertests/PowerStatsLoadTests/Android.bp b/core/tests/powertests/PowerStatsLoadTests/Android.bp new file mode 100644 index 000000000000..66c91adc6540 --- /dev/null +++ b/core/tests/powertests/PowerStatsLoadTests/Android.bp @@ -0,0 +1,13 @@ +android_test { + name: "PowerStatsLoadTests", + srcs: ["src/**/*.java"], + static_libs: [ + "androidx.test.rules", + "androidx.test.ext.junit", + "compatibility-device-util-axt", + "junit", + ], + libs: ["android.test.runner"], + platform_apis: true, + certificate: "platform", +} diff --git a/core/tests/powertests/PowerStatsLoadTests/AndroidManifest.xml b/core/tests/powertests/PowerStatsLoadTests/AndroidManifest.xml new file mode 100644 index 000000000000..b1c2a639aff4 --- /dev/null +++ b/core/tests/powertests/PowerStatsLoadTests/AndroidManifest.xml @@ -0,0 +1,36 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (C) 2020 The Android Open Source Project + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT 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.frameworks.core.powerstatsloadtests"> + + <uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/> + <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/> + <uses-permission android:name="android.permission.BATTERY_STATS"/> + <uses-permission android:name="android.permission.CHANGE_WIFI_STATE"/> + <uses-permission android:name="android.permission.INTERNET"/> + + <instrumentation + android:name="androidx.test.runner.AndroidJUnitRunner" + android:targetPackage="com.android.frameworks.core.powerstatsloadtests" + android:label="Power Stats Load Tests" /> + + <queries> + <!-- The load test resolves http://... intents. Let it do so. --> + <package android:name="com.android.chrome"/> + </queries> +</manifest> diff --git a/core/tests/powertests/PowerStatsLoadTests/src/com/android/frameworks/core/powerstatsloadtests/ConnectivitySetupRule.java b/core/tests/powertests/PowerStatsLoadTests/src/com/android/frameworks/core/powerstatsloadtests/ConnectivitySetupRule.java new file mode 100644 index 000000000000..ca2942647f08 --- /dev/null +++ b/core/tests/powertests/PowerStatsLoadTests/src/com/android/frameworks/core/powerstatsloadtests/ConnectivitySetupRule.java @@ -0,0 +1,159 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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.frameworks.core.powerstatsloadtests; + +import static org.junit.Assert.assertEquals; + +import android.app.Instrumentation; +import android.content.Context; +import android.net.ConnectivityManager; +import android.net.LinkProperties; +import android.net.Network; +import android.net.NetworkCapabilities; +import android.net.NetworkRequest; +import android.net.wifi.WifiManager; +import android.os.Handler; +import android.os.Looper; +import android.os.Message; + +import androidx.test.platform.app.InstrumentationRegistry; + +import com.android.compatibility.common.util.SystemUtil; + +import org.junit.rules.TestRule; +import org.junit.runner.Description; +import org.junit.runners.model.Statement; + +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; + +public class ConnectivitySetupRule implements TestRule { + + private final boolean mWifiEnabled; + private final ConnectivityManager mConnectivityManager; + private final WifiManager mWifiManager; + private boolean mInitialWifiState; + + public ConnectivitySetupRule(boolean wifiEnabled) { + mWifiEnabled = wifiEnabled; + + Instrumentation instrumentation = InstrumentationRegistry.getInstrumentation(); + Context context = instrumentation.getContext(); + mConnectivityManager = context.getSystemService(ConnectivityManager.class); + mWifiManager = context.getSystemService(WifiManager.class); + } + + @Override + public Statement apply(Statement base, Description description) { + return new Statement() { + @Override + public void evaluate() throws Throwable { + try { + mInitialWifiState = isWiFiConnected(); + setWiFiState(mWifiEnabled); + base.evaluate(); + } finally { + setWiFiState(mInitialWifiState); + } + } + }; + } + + private void setWiFiState(final boolean enable) throws InterruptedException { + boolean wiFiConnected = isWiFiConnected(); + if (enable == wiFiConnected) { + return; + } + + NetworkTracker tracker = new NetworkTracker(!mWifiEnabled); + mConnectivityManager.registerNetworkCallback( + new NetworkRequest.Builder() + .addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED).build(), + tracker); + + if (enable) { + SystemUtil.runShellCommand("svc wifi enable"); + //noinspection deprecation + SystemUtil.runWithShellPermissionIdentity(mWifiManager::reconnect, + android.Manifest.permission.NETWORK_SETTINGS); + } else { + SystemUtil.runShellCommand("svc wifi disable"); + } + + tracker.waitForExpectedState(); + + assertEquals("Wifi must be " + (enable ? "connected to" : "disconnected from") + + " an access point for this test.", enable, isWiFiConnected()); + + mConnectivityManager.unregisterNetworkCallback(tracker); + } + + private boolean isWiFiConnected() { + return mWifiManager.isWifiEnabled() && mConnectivityManager.getActiveNetwork() != null + && !mConnectivityManager.isActiveNetworkMetered(); + } + + private class NetworkTracker extends ConnectivityManager.NetworkCallback { + private static final int MSG_CHECK_ACTIVE_NETWORK = 1; + + private final CountDownLatch mReceiveLatch = new CountDownLatch(1); + + private final boolean mExpectedMetered; + + private final Handler mHandler = new Handler(Looper.getMainLooper()) { + @Override + public void handleMessage(Message msg) { + if (msg.what == MSG_CHECK_ACTIVE_NETWORK) { + checkActiveNetwork(); + } + } + }; + + private NetworkTracker(boolean expectedMetered) { + mExpectedMetered = expectedMetered; + } + + @Override + public void onAvailable(Network network, NetworkCapabilities networkCapabilities, + LinkProperties linkProperties, boolean blocked) { + checkActiveNetwork(); + } + + @Override + public void onLost(Network network) { + checkActiveNetwork(); + } + + boolean waitForExpectedState() throws InterruptedException { + checkActiveNetwork(); + return mReceiveLatch.await(60, TimeUnit.SECONDS); + } + + private void checkActiveNetwork() { + if (mReceiveLatch.getCount() == 0) { + return; + } + + if (mConnectivityManager.getActiveNetwork() != null + && mConnectivityManager.isActiveNetworkMetered() == mExpectedMetered) { + mReceiveLatch.countDown(); + } else { + mHandler.sendEmptyMessageDelayed(MSG_CHECK_ACTIVE_NETWORK, 5000); + } + } + } +} diff --git a/core/tests/powertests/PowerStatsLoadTests/src/com/android/frameworks/core/powerstatsloadtests/PowerMetrics.java b/core/tests/powertests/PowerStatsLoadTests/src/com/android/frameworks/core/powerstatsloadtests/PowerMetrics.java new file mode 100644 index 000000000000..88cb719add60 --- /dev/null +++ b/core/tests/powertests/PowerStatsLoadTests/src/com/android/frameworks/core/powerstatsloadtests/PowerMetrics.java @@ -0,0 +1,278 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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.frameworks.core.powerstatsloadtests; + +import android.os.Process; + +import com.android.internal.os.BatterySipper; +import com.android.internal.os.BatteryStatsHelper; + +import java.util.ArrayList; +import java.util.List; + +public class PowerMetrics { + private static final String PACKAGE_CALENDAR_PROVIDER = "com.android.providers.calendar"; + private static final String PACKAGE_MEDIA_PROVIDER = "com.android.providers.media"; + private static final String PACKAGE_SYSTEMUI = "com.android.systemui"; + private static final String[] PACKAGES_SYSTEM = {PACKAGE_MEDIA_PROVIDER, + PACKAGE_CALENDAR_PROVIDER, PACKAGE_SYSTEMUI}; + + enum MetricKind { + POWER, + DURATION, + } + + public static final String METRIC_APP_POWER = "appPower"; + public static final String METRIC_APP_POWER_EXCLUDE_SYSTEM_FROM_TOTAL = "appPowerExcludeSystem"; + public static final String METRIC_APP_POWER_EXCLUDE_SMEARED = "appPowerExcludeSmeared"; + public static final String METRIC_SCREEN_POWER = "screenPower"; + public static final String METRIC_WIFI_POWER = "wifiPower"; + public static final String METRIC_SYSTEM_SERVICE_CPU_POWER = "systemService"; + public static final String METRIC_OTHER_POWER = "otherPower"; + public static final String METRIC_CPU_POWER = "cpuPower"; + public static final String METRIC_RAM_POWER = "ramPower"; + public static final String METRIC_WAKELOCK_POWER = "wakelockPower"; + public static final String METRIC_MOBILE_RADIO_POWER = "mobileRadioPower"; + public static final String METRIC_BLUETOOTH_POWER = "bluetoothPower"; + public static final String METRIC_GPS_POWER = "gpsPower"; + public static final String METRIC_CAMERA_POWER = "cameraPower"; + public static final String METRIC_FLASHLIGHT_POWER = "flashlightPower"; + public static final String METRIC_SENSORS_POWER = "sensorsPower"; + public static final String METRIC_AUDIO_POWER = "audioPower"; + public static final String METRIC_VIDEO_POWER = "videoPower"; + public static final String METRIC_CPU_TIME = "cpuTime"; + public static final String METRIC_CPU_FOREGROUND_TIME = "cpuForegroundTime"; + public static final String METRIC_WAKELOCK_TIME = "wakelockTime"; + public static final String METRIC_WIFI_RUNNING_TIME = "wifiRunningTime"; + public static final String METRIC_BLUETOOTH_RUNNING_TIME = "bluetoothRunningTime"; + public static final String METRIC_GPS_TIME = "gpsTime"; + public static final String METRIC_CAMERA_TIME = "cameraTime"; + public static final String METRIC_FLASHLIGHT_TIME = "flashlightTime"; + public static final String METRIC_AUDIO_TIME = "audioTime"; + public static final String METRIC_VIDEO_TIME = "videoTime"; + + public static class Metric { + public String metricType; + public MetricKind metricKind; + public String title; + public double value; + public double total; + } + + private final double mMinDrainedPower; + private final double mMaxDrainedPower; + + private List<Metric> mMetrics = new ArrayList<>(); + + public PowerMetrics(BatteryStatsHelper batteryStatsHelper, int uid) { + mMinDrainedPower = batteryStatsHelper.getMinDrainedPower(); + mMaxDrainedPower = batteryStatsHelper.getMaxDrainedPower(); + + List<BatterySipper> usageList = batteryStatsHelper.getUsageList(); + + double totalPowerMah = 0; + double totalSmearedPowerMah = 0; + double totalPowerExcludeSystemMah = 0; + double totalScreenPower = 0; + double totalProportionalSmearMah = 0; + double totalCpuPowerMah = 0; + double totalSystemServiceCpuPowerMah = 0; + double totalUsagePowerMah = 0; + double totalWakeLockPowerMah = 0; + double totalMobileRadioPowerMah = 0; + double totalWifiPowerMah = 0; + double totalBluetoothPowerMah = 0; + double totalGpsPowerMah = 0; + double totalCameraPowerMah = 0; + double totalFlashlightPowerMah = 0; + double totalSensorPowerMah = 0; + double totalAudioPowerMah = 0; + double totalVideoPowerMah = 0; + + long totalCpuTimeMs = 0; + long totalCpuFgTimeMs = 0; + long totalWakeLockTimeMs = 0; + long totalWifiRunningTimeMs = 0; + long totalBluetoothRunningTimeMs = 0; + long totalGpsTimeMs = 0; + long totalCameraTimeMs = 0; + long totalFlashlightTimeMs = 0; + long totalAudioTimeMs = 0; + long totalVideoTimeMs = 0; + + BatterySipper uidSipper = null; + for (BatterySipper sipper : usageList) { + if (sipper.drainType == BatterySipper.DrainType.SCREEN) { + totalScreenPower = sipper.sumPower(); + } + + if (isHiddenDrainType(sipper.drainType)) { + continue; + } + + if (sipper.drainType == BatterySipper.DrainType.APP && sipper.getUid() == uid) { + uidSipper = sipper; + } + + totalPowerMah += sipper.sumPower(); + totalSmearedPowerMah += sipper.totalSmearedPowerMah; + totalProportionalSmearMah += sipper.proportionalSmearMah; + + if (!isSystemSipper(sipper)) { + totalPowerExcludeSystemMah += sipper.totalSmearedPowerMah; + } + + totalCpuPowerMah += sipper.cpuPowerMah; + totalSystemServiceCpuPowerMah += sipper.systemServiceCpuPowerMah; + totalUsagePowerMah += sipper.usagePowerMah; + totalWakeLockPowerMah += sipper.wakeLockPowerMah; + totalMobileRadioPowerMah += sipper.mobileRadioPowerMah; + totalWifiPowerMah += sipper.wifiPowerMah; + totalBluetoothPowerMah += sipper.bluetoothPowerMah; + totalGpsPowerMah += sipper.gpsPowerMah; + totalCameraPowerMah += sipper.cameraPowerMah; + totalFlashlightPowerMah += sipper.flashlightPowerMah; + totalSensorPowerMah += sipper.sensorPowerMah; + totalAudioPowerMah += sipper.audioPowerMah; + totalVideoPowerMah += sipper.videoPowerMah; + + totalCpuTimeMs += sipper.cpuTimeMs; + totalCpuFgTimeMs += sipper.cpuFgTimeMs; + totalWakeLockTimeMs += sipper.wakeLockTimeMs; + totalWifiRunningTimeMs += sipper.wifiRunningTimeMs; + totalBluetoothRunningTimeMs += sipper.bluetoothRunningTimeMs; + totalGpsTimeMs += sipper.gpsTimeMs; + totalCameraTimeMs += sipper.cameraTimeMs; + totalFlashlightTimeMs += sipper.flashlightTimeMs; + totalAudioTimeMs += sipper.audioTimeMs; + totalVideoTimeMs += sipper.videoTimeMs; + } + + if (uidSipper == null) { + return; + } + + addMetric(METRIC_APP_POWER, MetricKind.POWER, "Total power", + uidSipper.totalSmearedPowerMah, totalSmearedPowerMah); + addMetric(METRIC_APP_POWER_EXCLUDE_SYSTEM_FROM_TOTAL, MetricKind.POWER, + "Total power excluding system", + uidSipper.totalSmearedPowerMah, totalPowerExcludeSystemMah); + addMetric(METRIC_SCREEN_POWER, MetricKind.POWER, "Screen, smeared", + uidSipper.screenPowerMah, totalScreenPower); + addMetric(METRIC_OTHER_POWER, MetricKind.POWER, "Other, smeared", + uidSipper.proportionalSmearMah, totalProportionalSmearMah); + addMetric(METRIC_APP_POWER_EXCLUDE_SMEARED, MetricKind.POWER, "Excluding smeared", + uidSipper.totalPowerMah, totalPowerMah); + addMetric(METRIC_CPU_POWER, MetricKind.POWER, "CPU", + uidSipper.cpuPowerMah, totalCpuPowerMah); + addMetric(METRIC_SYSTEM_SERVICE_CPU_POWER, MetricKind.POWER, "System services", + uidSipper.systemServiceCpuPowerMah, totalSystemServiceCpuPowerMah); + addMetric(METRIC_RAM_POWER, MetricKind.POWER, "RAM", + uidSipper.usagePowerMah, totalUsagePowerMah); + addMetric(METRIC_WAKELOCK_POWER, MetricKind.POWER, "Wake lock", + uidSipper.wakeLockPowerMah, totalWakeLockPowerMah); + addMetric(METRIC_MOBILE_RADIO_POWER, MetricKind.POWER, "Mobile radio", + uidSipper.mobileRadioPowerMah, totalMobileRadioPowerMah); + addMetric(METRIC_WIFI_POWER, MetricKind.POWER, "WiFi", + uidSipper.wifiPowerMah, totalWifiPowerMah); + addMetric(METRIC_BLUETOOTH_POWER, MetricKind.POWER, "Bluetooth", + uidSipper.bluetoothPowerMah, totalBluetoothPowerMah); + addMetric(METRIC_GPS_POWER, MetricKind.POWER, "GPS", + uidSipper.gpsPowerMah, totalGpsPowerMah); + addMetric(METRIC_CAMERA_POWER, MetricKind.POWER, "Camera", + uidSipper.cameraPowerMah, totalCameraPowerMah); + addMetric(METRIC_FLASHLIGHT_POWER, MetricKind.POWER, "Flashlight", + uidSipper.flashlightPowerMah, totalFlashlightPowerMah); + addMetric(METRIC_SENSORS_POWER, MetricKind.POWER, "Sensors", + uidSipper.sensorPowerMah, totalSensorPowerMah); + addMetric(METRIC_AUDIO_POWER, MetricKind.POWER, "Audio", + uidSipper.audioPowerMah, totalAudioPowerMah); + addMetric(METRIC_VIDEO_POWER, MetricKind.POWER, "Video", + uidSipper.videoPowerMah, totalVideoPowerMah); + + addMetric(METRIC_CPU_TIME, MetricKind.DURATION, "CPU time", + uidSipper.cpuTimeMs, totalCpuTimeMs); + addMetric(METRIC_CPU_FOREGROUND_TIME, MetricKind.DURATION, "CPU foreground time", + uidSipper.cpuFgTimeMs, totalCpuFgTimeMs); + addMetric(METRIC_WAKELOCK_TIME, MetricKind.DURATION, "Wake lock time", + uidSipper.wakeLockTimeMs, totalWakeLockTimeMs); + addMetric(METRIC_WIFI_RUNNING_TIME, MetricKind.DURATION, "WiFi running time", + uidSipper.wifiRunningTimeMs, totalWifiRunningTimeMs); + addMetric(METRIC_BLUETOOTH_RUNNING_TIME, MetricKind.DURATION, "Bluetooth time", + uidSipper.bluetoothRunningTimeMs, totalBluetoothRunningTimeMs); + addMetric(METRIC_GPS_TIME, MetricKind.DURATION, "GPS time", + uidSipper.gpsTimeMs, totalGpsTimeMs); + addMetric(METRIC_CAMERA_TIME, MetricKind.DURATION, "Camera time", + uidSipper.cameraTimeMs, totalCameraTimeMs); + addMetric(METRIC_FLASHLIGHT_TIME, MetricKind.DURATION, "Flashlight time", + uidSipper.flashlightTimeMs, totalFlashlightTimeMs); + addMetric(METRIC_AUDIO_TIME, MetricKind.DURATION, "Audio time", + uidSipper.audioTimeMs, totalAudioTimeMs); + addMetric(METRIC_VIDEO_TIME, MetricKind.DURATION, "Video time", + uidSipper.videoTimeMs, totalVideoTimeMs); + } + + public List<Metric> getMetrics() { + return mMetrics; + } + + public double getMinDrainedPower() { + return mMinDrainedPower; + } + + public double getMaxDrainedPower() { + return mMaxDrainedPower; + } + + protected boolean isHiddenDrainType(BatterySipper.DrainType drainType) { + return drainType == BatterySipper.DrainType.IDLE + || drainType == BatterySipper.DrainType.CELL + || drainType == BatterySipper.DrainType.SCREEN + || drainType == BatterySipper.DrainType.UNACCOUNTED + || drainType == BatterySipper.DrainType.OVERCOUNTED + || drainType == BatterySipper.DrainType.BLUETOOTH + || drainType == BatterySipper.DrainType.WIFI; + } + + private boolean isSystemSipper(BatterySipper sipper) { + final int uid = sipper.uidObj == null ? -1 : sipper.getUid(); + if (uid >= Process.ROOT_UID && uid < Process.FIRST_APPLICATION_UID) { + return true; + } else if (sipper.mPackages != null) { + for (final String packageName : sipper.mPackages) { + for (final String systemPackage : PACKAGES_SYSTEM) { + if (systemPackage.equals(packageName)) { + return true; + } + } + } + } + + return false; + } + + private void addMetric(String metricType, MetricKind metricKind, String title, double amount, + double totalAmount) { + Metric metric = new Metric(); + metric.metricType = metricType; + metric.metricKind = metricKind; + metric.title = title; + metric.value = amount; + metric.total = totalAmount; + mMetrics.add(metric); + } +} diff --git a/core/tests/powertests/PowerStatsLoadTests/src/com/android/frameworks/core/powerstatsloadtests/PowerMetricsCollector.java b/core/tests/powertests/PowerStatsLoadTests/src/com/android/frameworks/core/powerstatsloadtests/PowerMetricsCollector.java new file mode 100644 index 000000000000..0cdb404f6aaa --- /dev/null +++ b/core/tests/powertests/PowerStatsLoadTests/src/com/android/frameworks/core/powerstatsloadtests/PowerMetricsCollector.java @@ -0,0 +1,281 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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.frameworks.core.powerstatsloadtests; + +import static org.junit.Assert.fail; + +import android.app.Instrumentation; +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.Intent; +import android.content.IntentFilter; +import android.os.BatteryManager; +import android.os.BatteryStats; +import android.os.Bundle; +import android.os.Process; +import android.os.SystemClock; +import android.os.UserManager; +import android.util.Log; +import android.util.TimeUtils; + +import androidx.test.platform.app.InstrumentationRegistry; + +import com.android.internal.os.BatteryStatsHelper; +import com.android.internal.os.LoggingPrintStream; + +import org.junit.rules.TestRule; +import org.junit.runner.Description; +import org.junit.runners.model.Statement; + +import java.io.PrintStream; +import java.util.ArrayList; +import java.util.List; +import java.util.Locale; + +public class PowerMetricsCollector implements TestRule { + private final String mTag; + private final float mBatteryDrainThresholdPct; + private final int mTimeoutMillis; + + private final Context mContext; + private final UserManager mUserManager; + private final int mUid; + private final BatteryStatsHelper mStatsHelper; + + private long mStartTime; + private volatile float mInitialBatteryLevel; + private volatile float mCurrentBatteryLevel; + private int mIterations; + private PowerMetrics mInitialPowerMetrics; + private PowerMetrics mFinalPowerMetrics; + private List<PowerMetrics.Metric> mPowerMetricsDelta; + + @Override + public Statement apply(Statement base, Description description) { + return new Statement() { + @Override + public void evaluate() throws Throwable { + disableCharger(); + try { + prepareBatteryLevelMonitor(); + mStartTime = SystemClock.uptimeMillis(); + base.evaluate(); + captureFinalPowerStatsData(); + } finally { + enableCharger(); + } + } + }; + } + + public PowerMetricsCollector(String tag, float batteryDrainThresholdPct, int timeoutMillis) { + mTag = tag; + mBatteryDrainThresholdPct = batteryDrainThresholdPct; + mTimeoutMillis = timeoutMillis; + + Instrumentation instrumentation = InstrumentationRegistry.getInstrumentation(); + mContext = instrumentation.getContext(); + mUid = Process.myUid(); + mUserManager = mContext.getSystemService(UserManager.class); + mStatsHelper = new BatteryStatsHelper(mContext, false /* collectBatteryBroadcast */); + mStatsHelper.create((Bundle) null); + } + + private void disableCharger() { + // TODO(b/167636754): implement this method once the charger suspension API is available + } + + private void enableCharger() { + // TODO(b/167636754): implement this method once the charger suspension API is available + } + + private PowerMetrics readBatteryStatsData() { + mStatsHelper.clearStats(); + mStatsHelper.refreshStats(BatteryStats.STATS_SINCE_CHARGED, + mUserManager.getUserProfiles()); + return new PowerMetrics(mStatsHelper, mUid); + } + + protected void prepareBatteryLevelMonitor() { + Intent batteryStatus = mContext.registerReceiver(new BroadcastReceiver() { + @Override + public void onReceive(Context context, Intent intent) { + handleBatteryStatus(intent); + } + }, new IntentFilter(Intent.ACTION_BATTERY_CHANGED)); + + handleBatteryStatus(batteryStatus); + mInitialBatteryLevel = mCurrentBatteryLevel; + } + + protected void handleBatteryStatus(Intent intent) { + if (intent.getIntExtra(BatteryManager.EXTRA_PLUGGED, -1) != 0) { + fail("Device must remain disconnected from the power source " + + "for the duration of the test"); + } + + int level = intent.getIntExtra(BatteryManager.EXTRA_LEVEL, -1); + int scale = intent.getIntExtra(BatteryManager.EXTRA_SCALE, -1); + + mCurrentBatteryLevel = level * 100 / (float) scale; + Log.i(mTag, "Battery level = " + mCurrentBatteryLevel); + + // We delay tracking until the battery level drops. If the resolution of + // battery level is 1%, and the initially reported level is 73, we don't know whether + // it's 73.1 or 73.7. Once it drops to 72, we can be confident that the real battery + // level it is very close to 72.0 and can start tracking. + if (mInitialPowerMetrics == null && mCurrentBatteryLevel < mInitialBatteryLevel) { + mInitialBatteryLevel = mCurrentBatteryLevel; + mInitialPowerMetrics = readBatteryStatsData(); + } + } + + private void captureFinalPowerStatsData() { + if (mFinalPowerMetrics != null) { + return; + } + + mFinalPowerMetrics = readBatteryStatsData(); + + mPowerMetricsDelta = new ArrayList<>(); + List<PowerMetrics.Metric> initialPowerMetrics = mInitialPowerMetrics.getMetrics(); + List<PowerMetrics.Metric> finalPowerMetrics = mFinalPowerMetrics.getMetrics(); + for (PowerMetrics.Metric initialMetric : initialPowerMetrics) { + PowerMetrics.Metric finalMetric = null; + for (PowerMetrics.Metric metric : finalPowerMetrics) { + if (metric.title.equals(initialMetric.title)) { + finalMetric = metric; + break; + } + } + + if (finalMetric != null) { + PowerMetrics.Metric delta = new PowerMetrics.Metric(); + delta.metricType = initialMetric.metricType; + delta.metricKind = initialMetric.metricKind; + delta.title = initialMetric.title; + delta.total = finalMetric.total - initialMetric.total; + delta.value = finalMetric.value - initialMetric.value; + mPowerMetricsDelta.add(delta); + } + } + } + + /** + * Returns false if sufficient data has been accumulated. + */ + public boolean checkpoint() { + long elapsedTime = SystemClock.uptimeMillis() - mStartTime; + if (elapsedTime >= mTimeoutMillis) { + Log.i(mTag, "Timeout reached " + TimeUtils.formatDuration(elapsedTime)); + captureFinalPowerStatsData(); + return false; + } + + if (mInitialPowerMetrics == null) { + return true; + } + + if (mInitialBatteryLevel - mCurrentBatteryLevel >= mBatteryDrainThresholdPct) { + Log.i(mTag, + "Battery drain reached " + (mInitialBatteryLevel - mCurrentBatteryLevel) + "%"); + captureFinalPowerStatsData(); + return false; + } + + mIterations++; + return true; + } + + + public int getIterationCount() { + return mIterations; + } + + public void dumpMetrics() { + dumpMetrics(new LoggingPrintStream() { + @Override + protected void log(String line) { + Log.i(mTag, line); + } + }); + } + + public void dumpMetrics(PrintStream out) { + List<PowerMetrics.Metric> initialPowerMetrics = mInitialPowerMetrics.getMetrics(); + List<PowerMetrics.Metric> finalPowerMetrics = mFinalPowerMetrics.getMetrics(); + + out.println("== Power metrics at test start"); + dumpPowerStatsData(out, initialPowerMetrics); + + out.println("== Power metrics at test end"); + dumpPowerStatsData(out, finalPowerMetrics); + + out.println("== Power metrics delta"); + dumpPowerStatsData(out, mPowerMetricsDelta); + } + + protected void dumpPowerStatsData(PrintStream out, List<PowerMetrics.Metric> metrics) { + Locale locale = Locale.getDefault(); + for (PowerMetrics.Metric metric : metrics) { + double proportion = metric.total != 0 ? metric.value * 100 / metric.total : 0; + switch (metric.metricKind) { + case POWER: + out.println( + String.format(locale, " %-30s %7.1f mAh %4.1f%%", metric.title, + metric.value, proportion)); + break; + case DURATION: + out.println( + String.format(locale, " %-30s %,7d ms %4.1f%%", metric.title, + (long) metric.value, proportion)); + break; + } + } + } + + public void dumpMetricAsPercentageOfDrainedPower(String metricType) { + double minDrainedPower = + mFinalPowerMetrics.getMinDrainedPower() - mInitialPowerMetrics.getMinDrainedPower(); + double maxDrainedPower = + mFinalPowerMetrics.getMaxDrainedPower() - mInitialPowerMetrics.getMaxDrainedPower(); + + PowerMetrics.Metric metric = getMetric(metricType); + double metricDelta = metric.value; + + if (maxDrainedPower - minDrainedPower < 0.1f) { + Log.i(mTag, String.format(Locale.getDefault(), + "%s power consumed by the test: %.1f of %.1f mAh (%.1f%%)", + metric.title, metricDelta, maxDrainedPower, + metricDelta / maxDrainedPower * 100)); + } else { + Log.i(mTag, String.format(Locale.getDefault(), + "%s power consumed by the test: %.1f of %.1f - %.1f mAh (%.1f%% - %.1f%%)", + metric.title, metricDelta, minDrainedPower, maxDrainedPower, + metricDelta / minDrainedPower * 100, metricDelta / maxDrainedPower * 100)); + } + } + + public PowerMetrics.Metric getMetric(String metricType) { + for (PowerMetrics.Metric metric : mPowerMetricsDelta) { + if (metric.metricType.equals(metricType)) { + return metric; + } + } + return null; + } +} diff --git a/core/tests/powertests/PowerStatsLoadTests/src/com/android/frameworks/core/powerstatsloadtests/SystemServiceCallLoadTest.java b/core/tests/powertests/PowerStatsLoadTests/src/com/android/frameworks/core/powerstatsloadtests/SystemServiceCallLoadTest.java new file mode 100644 index 000000000000..911ccba3ac78 --- /dev/null +++ b/core/tests/powertests/PowerStatsLoadTests/src/com/android/frameworks/core/powerstatsloadtests/SystemServiceCallLoadTest.java @@ -0,0 +1,69 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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.frameworks.core.powerstatsloadtests; + +import static org.junit.Assert.assertNotNull; + +import android.app.Instrumentation; +import android.content.Intent; +import android.content.pm.PackageManager; +import android.content.pm.ResolveInfo; +import android.net.Uri; +import android.util.Log; + +import androidx.test.platform.app.InstrumentationRegistry; + +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; + +public class SystemServiceCallLoadTest { + private static final String TAG = "SystemServiceCallLoadTest"; + private static final int TIMEOUT_MILLIS = 60 * 60 * 1000; + private static final float BATTERY_DRAIN_THRESHOLD_PCT = 2.99f; + + @Rule + public PowerMetricsCollector mPowerMetricsCollector = new PowerMetricsCollector(TAG, + BATTERY_DRAIN_THRESHOLD_PCT, TIMEOUT_MILLIS); + + private PackageManager mPackageManager; + + @Before + public void setup() { + Instrumentation instrumentation = InstrumentationRegistry.getInstrumentation(); + mPackageManager = instrumentation.getContext().getPackageManager(); + } + + @Test + public void test() { + while (mPowerMetricsCollector.checkpoint()) { + Intent intent = new Intent(Intent.ACTION_VIEW); + intent.setDataAndType(Uri.parse("http://example.com/"), "text/plain"); + intent.addCategory(Intent.CATEGORY_BROWSABLE); + ResolveInfo resolveInfo = mPackageManager.resolveActivity(intent, 0); + assertNotNull(resolveInfo); + } + + mPowerMetricsCollector.dumpMetrics(); + + Log.i(TAG, "=="); + Log.i(TAG, "Total system server calls made " + mPowerMetricsCollector.getIterationCount()); + + mPowerMetricsCollector.dumpMetricAsPercentageOfDrainedPower( + PowerMetrics.METRIC_SYSTEM_SERVICE_CPU_POWER); + } +} diff --git a/core/tests/powertests/PowerStatsLoadTests/src/com/android/frameworks/core/powerstatsloadtests/WiFiLoadTest.java b/core/tests/powertests/PowerStatsLoadTests/src/com/android/frameworks/core/powerstatsloadtests/WiFiLoadTest.java new file mode 100644 index 000000000000..90627192946d --- /dev/null +++ b/core/tests/powertests/PowerStatsLoadTests/src/com/android/frameworks/core/powerstatsloadtests/WiFiLoadTest.java @@ -0,0 +1,72 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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.frameworks.core.powerstatsloadtests; + +import android.util.Log; + +import org.junit.Rule; +import org.junit.Test; + +import java.io.IOException; +import java.io.InputStream; +import java.net.URL; + +public class WiFiLoadTest { + private static final String TAG = "WiFiLoadTest"; + private static final String DOWNLOAD_TEST_URL = + "https://i.ytimg.com/vi/l5mE3Tpjejs/maxresdefault.jpg"; + + private static final int TIMEOUT_MILLIS = 60 * 60 * 1000; + private static final float BATTERY_DRAIN_THRESHOLD_PCT = 0.99f; + + @Rule + public PowerMetricsCollector mPowerMetricsCollector = new PowerMetricsCollector(TAG, + BATTERY_DRAIN_THRESHOLD_PCT, TIMEOUT_MILLIS); + + @Rule + public ConnectivitySetupRule mConnectivitySetupRule = + new ConnectivitySetupRule(/* WiFi enabled */true); + + @Test + public void test() throws IOException { + long totalBytesRead = 0; + URL url = new URL(DOWNLOAD_TEST_URL); + byte[] buffer = new byte[131072]; // Large buffer to minimize CPU usage + + while (mPowerMetricsCollector.checkpoint()) { + try (InputStream inputStream = url.openStream()) { + while (true) { + int count = inputStream.read(buffer); + if (count < 0) { + break; + } + totalBytesRead += count; + } + } + } + + mPowerMetricsCollector.dumpMetrics(); + + Log.i(TAG, "=="); + Log.i(TAG, "WiFi running time: " + (long) mPowerMetricsCollector.getMetric( + PowerMetrics.METRIC_WIFI_RUNNING_TIME).value); + Log.i(TAG, "Total bytes read over WiFi: " + totalBytesRead); + + mPowerMetricsCollector.dumpMetricAsPercentageOfDrainedPower( + PowerMetrics.METRIC_WIFI_POWER); + } +} diff --git a/data/etc/car/com.google.android.car.kitchensink.xml b/data/etc/car/com.google.android.car.kitchensink.xml index 7292e0796bf5..59aa45e1f6e4 100644 --- a/data/etc/car/com.google.android.car.kitchensink.xml +++ b/data/etc/car/com.google.android.car.kitchensink.xml @@ -40,6 +40,7 @@ <permission name="android.permission.REAL_GET_TASKS"/> <permission name="android.permission.READ_LOGS"/> <permission name="android.permission.REBOOT"/> + <permission name="android.permission.SEND_CATEGORY_CAR_NOTIFICATIONS"/> <!-- use for CarServiceTest --> <permission name="android.permission.SET_ACTIVITY_WATCHER"/> <permission name="android.permission.WRITE_SECURE_SETTINGS"/> diff --git a/data/etc/services.core.protolog.json b/data/etc/services.core.protolog.json index a2a2216028ac..e69319896762 100644 --- a/data/etc/services.core.protolog.json +++ b/data/etc/services.core.protolog.json @@ -1393,6 +1393,12 @@ "group": "WM_SHOW_SURFACE_ALLOC", "at": "com\/android\/server\/wm\/BlackFrame.java" }, + "155482615": { + "message": "Focus requested for window=%s", + "level": "VERBOSE", + "group": "WM_DEBUG_FOCUS_LIGHT", + "at": "com\/android\/server\/wm\/InputMonitor.java" + }, "174572959": { "message": "DisplayArea info changed name=%s", "level": "VERBOSE", @@ -2635,6 +2641,12 @@ "group": "WM_DEBUG_REMOTE_ANIMATIONS", "at": "com\/android\/server\/wm\/WallpaperAnimationAdapter.java" }, + "2081291430": { + "message": "Focus not requested for window=%s because it has no surface", + "level": "DEBUG", + "group": "WM_DEBUG_FOCUS_LIGHT", + "at": "com\/android\/server\/wm\/InputMonitor.java" + }, "2083556954": { "message": "Set mOrientationChanging of %s", "level": "VERBOSE", diff --git a/framework-jarjar-rules.txt b/framework-jarjar-rules.txt index 70dedb8179b0..d8af726ffa72 100644 --- a/framework-jarjar-rules.txt +++ b/framework-jarjar-rules.txt @@ -1,6 +1,2 @@ rule android.hidl.** android.internal.hidl.@1 rule android.net.wifi.WifiAnnotations* android.internal.wifi.WifiAnnotations@1 - -# Hide media mainline module implementation classes to avoid collisions with -# app-bundled ExoPlayer classes. -rule com.google.android.exoplayer2.** android.media.internal.exo.@1 diff --git a/libs/WindowManager/Shell/Android.bp b/libs/WindowManager/Shell/Android.bp index 16b87c43fc58..1591b0616262 100644 --- a/libs/WindowManager/Shell/Android.bp +++ b/libs/WindowManager/Shell/Android.bp @@ -105,6 +105,7 @@ android_library { static_libs: [ "protolog-lib", "WindowManager-Shell-proto", + "androidx.appcompat_appcompat", ], manifest: "AndroidManifest.xml", }
\ No newline at end of file diff --git a/packages/SystemUI/res/drawable-hdpi/one_handed_tutorial.png b/libs/WindowManager/Shell/res/drawable-hdpi/one_handed_tutorial.png Binary files differindex 6c1f1cfdea7c..6c1f1cfdea7c 100644 --- a/packages/SystemUI/res/drawable-hdpi/one_handed_tutorial.png +++ b/libs/WindowManager/Shell/res/drawable-hdpi/one_handed_tutorial.png diff --git a/packages/SystemUI/res/xml/one_handed_tutorial.xml b/libs/WindowManager/Shell/res/layout/one_handed_tutorial.xml index dc54caf0f14a..dc54caf0f14a 100644 --- a/packages/SystemUI/res/xml/one_handed_tutorial.xml +++ b/libs/WindowManager/Shell/res/layout/one_handed_tutorial.xml diff --git a/libs/WindowManager/Shell/res/values/config.xml b/libs/WindowManager/Shell/res/values/config.xml index 39efd0768eaa..63b0f6ffbec3 100644 --- a/libs/WindowManager/Shell/res/values/config.xml +++ b/libs/WindowManager/Shell/res/values/config.xml @@ -29,4 +29,7 @@ <!-- Animation duration when using long press on recents to dock --> <integer name="long_press_dock_anim_duration">250</integer> + + <!-- Allow one handed to enable round corner --> + <bool name="config_one_handed_enable_round_corner">true</bool> </resources> diff --git a/libs/WindowManager/Shell/res/values/dimen.xml b/libs/WindowManager/Shell/res/values/dimen.xml index ce690281b491..7fb641a4b06e 100644 --- a/libs/WindowManager/Shell/res/values/dimen.xml +++ b/libs/WindowManager/Shell/res/values/dimen.xml @@ -62,4 +62,8 @@ <dimen name="docked_divider_handle_width">16dp</dimen> <dimen name="docked_divider_handle_height">2dp</dimen> + + <!-- One-Handed Mode --> + <!-- Threshold for dragging distance to enable one-handed mode --> + <dimen name="gestures_onehanded_drag_threshold">20dp</dimen> </resources> diff --git a/libs/WindowManager/Shell/res/values/strings.xml b/libs/WindowManager/Shell/res/values/strings.xml index cad924771cd3..b6668fbe4872 100644 --- a/libs/WindowManager/Shell/res/values/strings.xml +++ b/libs/WindowManager/Shell/res/values/strings.xml @@ -88,4 +88,9 @@ <string name="accessibility_action_divider_top_30">Top 30%</string> <!-- Accessibility action for moving docked stack divider to make the bottom screen full screen [CHAR LIMIT=NONE] --> <string name="accessibility_action_divider_bottom_full">Bottom full screen</string> + + <!-- One-Handed Tutorial title [CHAR LIMIT=60] --> + <string name="one_handed_tutorial_title">Using one-handed mode</string> + <!-- One-Handed Tutorial description [CHAR LIMIT=NONE] --> + <string name="one_handed_tutorial_description">To exit, swipe up from the bottom of the screen or tap anywhere above the app</string> </resources> diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/ShellTaskOrganizer.java b/libs/WindowManager/Shell/src/com/android/wm/shell/ShellTaskOrganizer.java index ea9576a511e9..f9ba695c8503 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/ShellTaskOrganizer.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/ShellTaskOrganizer.java @@ -17,23 +17,23 @@ package com.android.wm.shell; import android.app.ActivityManager.RunningTaskInfo; -import android.app.WindowConfiguration; -import android.content.Context; import android.util.Log; import android.util.Pair; import android.util.SparseArray; import android.view.SurfaceControl; +import android.window.ITaskOrganizerController; import android.window.TaskOrganizer; +import com.android.internal.annotations.VisibleForTesting; import com.android.internal.protolog.common.ProtoLog; import com.android.wm.shell.protolog.ShellProtoLogGroup; -import com.android.wm.shell.protolog.ShellProtoLogImpl; import java.util.ArrayList; import java.util.Arrays; /** * Unified task organizer for all components in the shell. + * TODO(b/167582004): may consider consolidating this class and TaskOrganizer */ public class ShellTaskOrganizer extends TaskOrganizer { @@ -56,6 +56,15 @@ public class ShellTaskOrganizer extends TaskOrganizer { // require us to report to both old and new listeners) private final SparseArray<Pair<RunningTaskInfo, SurfaceControl>> mTasks = new SparseArray<>(); + public ShellTaskOrganizer() { + super(); + } + + @VisibleForTesting + ShellTaskOrganizer(ITaskOrganizerController taskOrganizerController) { + super(taskOrganizerController); + } + /** * Adds a listener for tasks in a specific windowing mode. */ diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/SystemWindows.java b/libs/WindowManager/Shell/src/com/android/wm/shell/common/SystemWindows.java index 8abe9eeb6a9a..b4620e27e68c 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/common/SystemWindows.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/SystemWindows.java @@ -22,7 +22,6 @@ import android.annotation.NonNull; import android.content.Context; import android.content.res.Configuration; import android.graphics.Point; -import android.graphics.Rect; import android.graphics.Region; import android.os.Bundle; import android.os.IBinder; @@ -32,7 +31,6 @@ import android.util.MergedConfiguration; import android.util.Slog; import android.util.SparseArray; import android.view.Display; -import android.view.DisplayCutout; import android.view.DragEvent; import android.view.IScrollCaptureController; import android.view.IWindow; @@ -47,6 +45,7 @@ import android.view.View; import android.view.ViewGroup; import android.view.WindowManager; import android.view.WindowlessWindowManager; +import android.window.ClientWindowFrames; import com.android.internal.os.IResultReceiver; @@ -274,22 +273,20 @@ public class SystemWindows { @Override public int relayout(IWindow window, int seq, WindowManager.LayoutParams attrs, int requestedWidth, int requestedHeight, int viewVisibility, int flags, - long frameNumber, Rect outFrame, Rect outOverscanInsets, Rect outContentInsets, - Rect outVisibleInsets, Rect outStableInsets, - DisplayCutout.ParcelableWrapper cutout, MergedConfiguration mergedConfiguration, + long frameNumber, ClientWindowFrames outFrames, + MergedConfiguration mergedConfiguration, SurfaceControl outSurfaceControl, InsetsState outInsetsState, InsetsSourceControl[] outActiveControls, Point outSurfaceSize, SurfaceControl outBLASTSurfaceControl) { int res = super.relayout(window, seq, attrs, requestedWidth, requestedHeight, - viewVisibility, flags, frameNumber, outFrame, outOverscanInsets, - outContentInsets, outVisibleInsets, outStableInsets, - cutout, mergedConfiguration, outSurfaceControl, outInsetsState, + viewVisibility, flags, frameNumber, outFrames, + mergedConfiguration, outSurfaceControl, outInsetsState, outActiveControls, outSurfaceSize, outBLASTSurfaceControl); if (res != 0) { return res; } DisplayLayout dl = mDisplayController.getDisplayLayout(mDisplayId); - outStableInsets.set(dl.stableInsets()); + outFrames.stableInsets.set(dl.stableInsets()); return 0; } @@ -314,10 +311,9 @@ public class SystemWindows { ContainerWindow() {} @Override - public void resized(Rect frame, Rect contentInsets, Rect visibleInsets, Rect stableInsets, - boolean reportDraw, MergedConfiguration newMergedConfiguration, Rect backDropFrame, - boolean forceLayout, boolean alwaysConsumeSystemBars, int displayId, - DisplayCutout.ParcelableWrapper displayCutout) {} + public void resized(ClientWindowFrames frames, boolean reportDraw, + MergedConfiguration newMergedConfiguration, boolean forceLayout, + boolean alwaysConsumeSystemBars, int displayId) {} @Override public void locationInParentDisplayChanged(Point offset) {} diff --git a/packages/SystemUI/src/com/android/systemui/onehanded/OneHanded.java b/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHanded.java index b7c6262b07e0..9c78fc5e57b8 100644 --- a/packages/SystemUI/src/com/android/systemui/onehanded/OneHanded.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHanded.java @@ -14,11 +14,11 @@ * limitations under the License. */ -package com.android.systemui.onehanded; +package com.android.wm.shell.onehanded; import androidx.annotation.NonNull; -import com.android.systemui.onehanded.OneHandedGestureHandler.OneHandedGestureEventCallback; +import com.android.wm.shell.onehanded.OneHandedGestureHandler.OneHandedGestureEventCallback; import java.io.PrintWriter; diff --git a/packages/SystemUI/src/com/android/systemui/onehanded/OneHandedAnimationCallback.java b/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedAnimationCallback.java index 264ace749383..6749f7eec968 100644 --- a/packages/SystemUI/src/com/android/systemui/onehanded/OneHandedAnimationCallback.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedAnimationCallback.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.android.systemui.onehanded; +package com.android.wm.shell.onehanded; import android.view.SurfaceControl; diff --git a/packages/SystemUI/src/com/android/systemui/onehanded/OneHandedAnimationController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedAnimationController.java index 9be1b5a35be6..963909621a1b 100644 --- a/packages/SystemUI/src/com/android/systemui/onehanded/OneHandedAnimationController.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedAnimationController.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.android.systemui.onehanded; +package com.android.wm.shell.onehanded; import android.animation.Animator; import android.animation.ValueAnimator; diff --git a/packages/SystemUI/src/com/android/systemui/onehanded/OneHandedController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedController.java index 90adf838440c..c84b4781d19d 100644 --- a/packages/SystemUI/src/com/android/systemui/onehanded/OneHandedController.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedController.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.android.systemui.onehanded; +package com.android.wm.shell.onehanded; import static android.os.UserHandle.USER_CURRENT; import static android.view.Display.DEFAULT_DISPLAY; @@ -35,9 +35,9 @@ import android.util.Log; import androidx.annotation.NonNull; import androidx.annotation.VisibleForTesting; -import com.android.systemui.onehanded.OneHandedGestureHandler.OneHandedGestureEventCallback; import com.android.wm.shell.common.DisplayChangeController; import com.android.wm.shell.common.DisplayController; +import com.android.wm.shell.onehanded.OneHandedGestureHandler.OneHandedGestureEventCallback; import java.io.PrintWriter; @@ -390,7 +390,7 @@ public class OneHandedController implements OneHanded { } } - @androidx.annotation.VisibleForTesting + @VisibleForTesting private void setEnabledGesturalOverlay(boolean enabled) { try { mOverlayManager.setEnabled(ONE_HANDED_MODE_GESTURAL_OVERLAY, enabled, USER_CURRENT); diff --git a/packages/SystemUI/src/com/android/systemui/onehanded/OneHandedDisplayAreaOrganizer.java b/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedDisplayAreaOrganizer.java index ec40bad06b71..9954618134e8 100644 --- a/packages/SystemUI/src/com/android/systemui/onehanded/OneHandedDisplayAreaOrganizer.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedDisplayAreaOrganizer.java @@ -14,12 +14,12 @@ * limitations under the License. */ -package com.android.systemui.onehanded; +package com.android.wm.shell.onehanded; import static android.view.Display.DEFAULT_DISPLAY; -import static com.android.systemui.onehanded.OneHandedAnimationController.TRANSITION_DIRECTION_EXIT; -import static com.android.systemui.onehanded.OneHandedAnimationController.TRANSITION_DIRECTION_TRIGGER; +import static com.android.wm.shell.onehanded.OneHandedAnimationController.TRANSITION_DIRECTION_EXIT; +import static com.android.wm.shell.onehanded.OneHandedAnimationController.TRANSITION_DIRECTION_TRIGGER; import android.content.Context; import android.graphics.Point; diff --git a/packages/SystemUI/src/com/android/systemui/onehanded/OneHandedEvents.java b/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedEvents.java index 327ed67d6fc8..79ddd2b11e72 100644 --- a/packages/SystemUI/src/com/android/systemui/onehanded/OneHandedEvents.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedEvents.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.android.systemui.onehanded; +package com.android.wm.shell.onehanded; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.logging.UiEvent; diff --git a/packages/SystemUI/src/com/android/systemui/onehanded/OneHandedGestureHandler.java b/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedGestureHandler.java index 4a493ba800ba..3b1e6cbe5ccd 100644 --- a/packages/SystemUI/src/com/android/systemui/onehanded/OneHandedGestureHandler.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedGestureHandler.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.android.systemui.onehanded; +package com.android.wm.shell.onehanded; import static android.view.Display.DEFAULT_DISPLAY; @@ -38,7 +38,7 @@ import android.window.WindowContainerTransaction; import androidx.annotation.VisibleForTesting; -import com.android.systemui.R; +import com.android.wm.shell.R; import com.android.wm.shell.common.DisplayChangeController; import com.android.wm.shell.common.DisplayController; @@ -210,7 +210,7 @@ public class OneHandedGestureHandler implements OneHandedTransitionCallback, displaySize.y); mInputMonitor = InputManager.getInstance().monitorGestureInput( "onehanded-gesture-offset", DEFAULT_DISPLAY); - mInputEventReceiver = new SysUiInputEventReceiver( + mInputEventReceiver = new EventReceiver( mInputMonitor.getInputChannel(), Looper.getMainLooper()); } } @@ -227,8 +227,8 @@ public class OneHandedGestureHandler implements OneHandedTransitionCallback, mRotation = toRotation; } - private class SysUiInputEventReceiver extends InputEventReceiver { - SysUiInputEventReceiver(InputChannel channel, Looper looper) { + private class EventReceiver extends InputEventReceiver { + EventReceiver(InputChannel channel, Looper looper) { super(channel, looper); } diff --git a/packages/SystemUI/src/com/android/systemui/onehanded/OneHandedSettingsUtil.java b/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedSettingsUtil.java index 0598f32c16d5..4d66f2961a29 100644 --- a/packages/SystemUI/src/com/android/systemui/onehanded/OneHandedSettingsUtil.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedSettingsUtil.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.android.systemui.onehanded; +package com.android.wm.shell.onehanded; import android.annotation.IntDef; import android.content.ContentResolver; @@ -22,8 +22,6 @@ import android.database.ContentObserver; import android.net.Uri; import android.provider.Settings; -import com.android.systemui.dagger.SysUISingleton; - import java.io.PrintWriter; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; @@ -31,7 +29,6 @@ import java.lang.annotation.RetentionPolicy; /** * APIs for querying or updating one handed settings . */ -@SysUISingleton public final class OneHandedSettingsUtil { private static final String TAG = "OneHandedSettingsUtil"; diff --git a/packages/SystemUI/src/com/android/systemui/onehanded/OneHandedSurfaceTransactionHelper.java b/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedSurfaceTransactionHelper.java index bc4a9b49205c..e7010db97d77 100644 --- a/packages/SystemUI/src/com/android/systemui/onehanded/OneHandedSurfaceTransactionHelper.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedSurfaceTransactionHelper.java @@ -14,14 +14,14 @@ * limitations under the License. */ -package com.android.systemui.onehanded; +package com.android.wm.shell.onehanded; import android.content.Context; import android.content.res.Resources; import android.graphics.Rect; import android.view.SurfaceControl; -import com.android.systemui.R; +import com.android.wm.shell.R; /** * Abstracts the common operations on {@link SurfaceControl.Transaction} for OneHanded transition. diff --git a/packages/SystemUI/src/com/android/systemui/onehanded/OneHandedThread.java b/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedThread.java index b7b814a31a1e..24d33ede5d63 100644 --- a/packages/SystemUI/src/com/android/systemui/onehanded/OneHandedThread.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedThread.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.android.systemui.onehanded; +package com.android.wm.shell.onehanded; import android.os.Handler; import android.os.HandlerThread; diff --git a/packages/SystemUI/src/com/android/systemui/onehanded/OneHandedTimeoutHandler.java b/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedTimeoutHandler.java index 21329ea1b0e6..9c97cd7db71f 100644 --- a/packages/SystemUI/src/com/android/systemui/onehanded/OneHandedTimeoutHandler.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedTimeoutHandler.java @@ -14,9 +14,9 @@ * limitations under the License. */ -package com.android.systemui.onehanded; +package com.android.wm.shell.onehanded; -import static com.android.systemui.onehanded.OneHandedSettingsUtil.ONE_HANDED_TIMEOUT_MEDIUM_IN_SECONDS; +import static com.android.wm.shell.onehanded.OneHandedSettingsUtil.ONE_HANDED_TIMEOUT_MEDIUM_IN_SECONDS; import android.os.Handler; import android.os.Looper; diff --git a/packages/SystemUI/src/com/android/systemui/onehanded/OneHandedTouchHandler.java b/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedTouchHandler.java index 3d28a426f4f8..721382d52717 100644 --- a/packages/SystemUI/src/com/android/systemui/onehanded/OneHandedTouchHandler.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedTouchHandler.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.android.systemui.onehanded; +package com.android.wm.shell.onehanded; import static android.view.Display.DEFAULT_DISPLAY; @@ -127,7 +127,7 @@ public class OneHandedTouchHandler implements OneHandedTransitionCallback { if (mIsEnabled) { mInputMonitor = InputManager.getInstance().monitorGestureInput( "onehanded-touch", DEFAULT_DISPLAY); - mInputEventReceiver = new SysUiInputEventReceiver( + mInputEventReceiver = new EventReceiver( mInputMonitor.getInputChannel(), Looper.getMainLooper()); } } @@ -150,8 +150,8 @@ public class OneHandedTouchHandler implements OneHandedTransitionCallback { pw.println(mLastUpdatedBounds); } - private class SysUiInputEventReceiver extends InputEventReceiver { - SysUiInputEventReceiver(InputChannel channel, Looper looper) { + private class EventReceiver extends InputEventReceiver { + EventReceiver(InputChannel channel, Looper looper) { super(channel, looper); } diff --git a/packages/SystemUI/src/com/android/systemui/onehanded/OneHandedTransitionCallback.java b/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedTransitionCallback.java index 75eb0ebd5c84..3af7c4b71d0a 100644 --- a/packages/SystemUI/src/com/android/systemui/onehanded/OneHandedTransitionCallback.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedTransitionCallback.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.android.systemui.onehanded; +package com.android.wm.shell.onehanded; import android.graphics.Rect; diff --git a/packages/SystemUI/src/com/android/systemui/onehanded/OneHandedTutorialHandler.java b/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedTutorialHandler.java index beccf3dbc8de..b15b5154c2a4 100644 --- a/packages/SystemUI/src/com/android/systemui/onehanded/OneHandedTutorialHandler.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedTutorialHandler.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.android.systemui.onehanded; +package com.android.wm.shell.onehanded; import android.content.ContentResolver; import android.content.Context; @@ -33,7 +33,7 @@ import android.widget.FrameLayout; import androidx.annotation.NonNull; -import com.android.systemui.R; +import com.android.wm.shell.R; import java.io.PrintWriter; @@ -79,7 +79,7 @@ public class OneHandedTutorialHandler implements OneHandedTransitionCallback { mTargetViewContainer.setClipChildren(false); mTutorialAreaHeight = Math.round(mDisplaySize.y * (SystemProperties.getInt(ONE_HANDED_MODE_OFFSET_PERCENTAGE, 50) / 100.0f)); - mTutorialView = LayoutInflater.from(context).inflate(R.xml.one_handed_tutorial, null); + mTutorialView = LayoutInflater.from(context).inflate(R.layout.one_handed_tutorial, null); mTargetViewContainer.addView(mTutorialView); mCanShowTutorial = (Settings.Secure.getInt(mContentResolver, Settings.Secure.ONE_HANDED_TUTORIAL_SHOW_COUNT, 0) >= MAX_TUTORIAL_SHOW_COUNT) diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/DividerImeController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/DividerImeController.java index 92cee8a1a874..ff617ed466d1 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/DividerImeController.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/DividerImeController.java @@ -30,7 +30,6 @@ import android.view.SurfaceControl; import android.window.TaskOrganizer; import android.window.WindowContainerToken; import android.window.WindowContainerTransaction; -import android.window.WindowOrganizer; import com.android.wm.shell.common.DisplayImeController; import com.android.wm.shell.common.TransactionPool; @@ -44,6 +43,7 @@ class DividerImeController implements DisplayImeController.ImePositionProcessor private final SplitScreenTaskOrganizer mSplits; private final TransactionPool mTransactionPool; private final Handler mHandler; + private final TaskOrganizer mTaskOrganizer; /** * These are the y positions of the top of the IME surface when it is hidden and when it is @@ -92,10 +92,12 @@ class DividerImeController implements DisplayImeController.ImePositionProcessor private boolean mPausedTargetAdjusted = false; private boolean mAdjustedWhileHidden = false; - DividerImeController(SplitScreenTaskOrganizer splits, TransactionPool pool, Handler handler) { + DividerImeController(SplitScreenTaskOrganizer splits, TransactionPool pool, Handler handler, + TaskOrganizer taskOrganizer) { mSplits = splits; mTransactionPool = pool; mHandler = handler; + mTaskOrganizer = taskOrganizer; } private DividerView getView() { @@ -111,7 +113,7 @@ class DividerImeController implements DisplayImeController.ImePositionProcessor } private boolean getSecondaryHasFocus(int displayId) { - WindowContainerToken imeSplit = TaskOrganizer.getImeTarget(displayId); + WindowContainerToken imeSplit = mTaskOrganizer.getImeTarget(displayId); return imeSplit != null && (imeSplit.asBinder() == mSplits.mSecondary.token.asBinder()); } @@ -236,7 +238,7 @@ class DividerImeController implements DisplayImeController.ImePositionProcessor } if (!mSplits.mSplitScreenController.getWmProxy().queueSyncTransactionIfWaiting(wct)) { - WindowOrganizer.applyTransaction(wct); + mTaskOrganizer.applyTransaction(wct); } } diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/DividerView.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/DividerView.java index 79bfda92bd92..00146e9447bd 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/DividerView.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/DividerView.java @@ -619,7 +619,7 @@ public class DividerView extends FrameLayout implements OnTouchListener, mEntranceAnimationRunning = false; mExitAnimationRunning = false; if (!dismissed && !wasMinimizeInteraction) { - WindowManagerProxy.applyResizeSplits(snapTarget.position, mSplitLayout); + mWindowManagerProxy.applyResizeSplits(snapTarget.position, mSplitLayout); } if (mCallback != null) { mCallback.onDraggingEnd(); @@ -889,7 +889,7 @@ public class DividerView extends FrameLayout implements OnTouchListener, t.hide(sc).apply(); mTiles.releaseTransaction(t); int midPos = mSplitLayout.getSnapAlgorithm().getMiddleTarget().position; - WindowManagerProxy.applyResizeSplits(midPos, mSplitLayout); + mWindowManagerProxy.applyResizeSplits(midPos, mSplitLayout); } void setMinimizedDockStack(boolean minimized, long animDuration, diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenController.java index d5326d4845a3..eed5092ea96b 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenController.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenController.java @@ -29,9 +29,9 @@ import android.provider.Settings; import android.util.Slog; import android.view.LayoutInflater; import android.view.View; +import android.window.TaskOrganizer; import android.window.WindowContainerToken; import android.window.WindowContainerTransaction; -import android.window.WindowOrganizer; import com.android.internal.policy.DividerSnapAlgorithm; import com.android.wm.shell.R; @@ -71,6 +71,7 @@ public class SplitScreenController implements SplitScreen, private final SystemWindows mSystemWindows; final TransactionPool mTransactionPool; private final WindowManagerProxy mWindowManagerProxy; + private final TaskOrganizer mTaskOrganizer; private final ArrayList<WeakReference<Consumer<Boolean>>> mDockedStackExistsListeners = new ArrayList<>(); @@ -106,9 +107,12 @@ public class SplitScreenController implements SplitScreen, mHandler = handler; mForcedResizableController = new ForcedResizableInfoActivityController(context, this); mTransactionPool = transactionPool; - mWindowManagerProxy = new WindowManagerProxy(mTransactionPool, mHandler); + mWindowManagerProxy = new WindowManagerProxy(mTransactionPool, mHandler, + shellTaskOrganizer); + mTaskOrganizer = shellTaskOrganizer; mSplits = new SplitScreenTaskOrganizer(this, shellTaskOrganizer); - mImePositionProcessor = new DividerImeController(mSplits, mTransactionPool, mHandler); + mImePositionProcessor = new DividerImeController(mSplits, mTransactionPool, mHandler, + shellTaskOrganizer); mRotationController = (display, fromRotation, toRotation, wct) -> { if (!mSplits.isSplitScreenSupported() || mWindowManagerProxy == null) { @@ -132,7 +136,7 @@ public class SplitScreenController implements SplitScreen, sdl.resizeSplits(target.position, t); if (isSplitActive() && mHomeStackResizable) { - WindowManagerProxy + mWindowManagerProxy .applyHomeTasksMinimized(sdl, mSplits.mSecondary.token, t); } if (mWindowManagerProxy.queueSyncTransactionIfWaiting(t)) { @@ -189,7 +193,7 @@ public class SplitScreenController implements SplitScreen, final WindowContainerTransaction tct = new WindowContainerTransaction(); int midPos = mSplitLayout.getSnapAlgorithm().getMiddleTarget().position; mSplitLayout.resizeSplits(midPos, tct); - WindowOrganizer.applyTransaction(tct); + mTaskOrganizer.applyTransaction(tct); } catch (Exception e) { Slog.e(TAG, "Failed to register docked stack listener", e); removeDivider(); @@ -208,7 +212,7 @@ public class SplitScreenController implements SplitScreen, int midPos = mSplitLayout.getSnapAlgorithm().getMiddleTarget().position; final WindowContainerTransaction tct = new WindowContainerTransaction(); mSplitLayout.resizeSplits(midPos, tct); - WindowOrganizer.applyTransaction(tct); + mTaskOrganizer.applyTransaction(tct); } else if (mSplitLayout.mDisplayLayout.rotation() == mRotateSplitLayout.mDisplayLayout.rotation()) { mSplitLayout.mPrimary = new Rect(mRotateSplitLayout.mPrimary); @@ -372,7 +376,7 @@ public class SplitScreenController implements SplitScreen, // If we are only setting focusability, a sync transaction isn't necessary (in fact it // can interrupt other animations), so see if it can be submitted on pending instead. if (!mWindowManagerProxy.queueSyncTransactionIfWaiting(wct)) { - WindowOrganizer.applyTransaction(wct); + mTaskOrganizer.applyTransaction(wct); } } diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenTaskOrganizer.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenTaskOrganizer.java index 6d28c5e17d42..30bc43b0292f 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenTaskOrganizer.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenTaskOrganizer.java @@ -31,7 +31,6 @@ import android.util.Log; import android.view.Display; import android.view.SurfaceControl; import android.view.SurfaceSession; -import android.window.TaskOrganizer; import com.android.wm.shell.ShellTaskOrganizer; @@ -64,9 +63,9 @@ class SplitScreenTaskOrganizer implements ShellTaskOrganizer.TaskListener { void init() throws RemoteException { synchronized (this) { try { - mPrimary = TaskOrganizer.createRootTask(Display.DEFAULT_DISPLAY, + mPrimary = mTaskOrganizer.createRootTask(Display.DEFAULT_DISPLAY, WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY); - mSecondary = TaskOrganizer.createRootTask(Display.DEFAULT_DISPLAY, + mSecondary = mTaskOrganizer.createRootTask(Display.DEFAULT_DISPLAY, WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_SECONDARY); } catch (Exception e) { // teardown to prevent callbacks diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/WindowManagerProxy.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/WindowManagerProxy.java index cd96676ad1fe..25827cdb9e24 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/WindowManagerProxy.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/WindowManagerProxy.java @@ -83,8 +83,12 @@ class WindowManagerProxy { } }; - WindowManagerProxy(TransactionPool transactionPool, Handler handler) { + private final TaskOrganizer mTaskOrganizer; + + WindowManagerProxy(TransactionPool transactionPool, Handler handler, + TaskOrganizer taskOrganizer) { mSyncTransactionQueue = new SyncTransactionQueue(transactionPool, handler); + mTaskOrganizer = taskOrganizer; } void dismissOrMaximizeDocked(final SplitScreenTaskOrganizer tiles, SplitDisplayLayout layout, @@ -113,18 +117,18 @@ class WindowManagerProxy { mExecutor.execute(mSetTouchableRegionRunnable); } - static void applyResizeSplits(int position, SplitDisplayLayout splitLayout) { + void applyResizeSplits(int position, SplitDisplayLayout splitLayout) { WindowContainerTransaction t = new WindowContainerTransaction(); splitLayout.resizeSplits(position, t); - WindowOrganizer.applyTransaction(t); + new WindowOrganizer().applyTransaction(t); } - private static boolean getHomeAndRecentsTasks(List<ActivityManager.RunningTaskInfo> out, + private boolean getHomeAndRecentsTasks(List<ActivityManager.RunningTaskInfo> out, WindowContainerToken parent) { boolean resizable = false; List<ActivityManager.RunningTaskInfo> rootTasks = parent == null - ? TaskOrganizer.getRootTasks(Display.DEFAULT_DISPLAY, HOME_AND_RECENTS) - : TaskOrganizer.getChildTasks(parent, HOME_AND_RECENTS); + ? mTaskOrganizer.getRootTasks(Display.DEFAULT_DISPLAY, HOME_AND_RECENTS) + : mTaskOrganizer.getChildTasks(parent, HOME_AND_RECENTS); for (int i = 0, n = rootTasks.size(); i < n; ++i) { final ActivityManager.RunningTaskInfo ti = rootTasks.get(i); out.add(ti); @@ -140,7 +144,7 @@ class WindowManagerProxy { * split is minimized. This actually "sticks out" of the secondary split area, but when in * minimized mode, the secondary split gets a 'negative' crop to expose it. */ - static boolean applyHomeTasksMinimized(SplitDisplayLayout layout, WindowContainerToken parent, + boolean applyHomeTasksMinimized(SplitDisplayLayout layout, WindowContainerToken parent, @NonNull WindowContainerTransaction wct) { // Resize the home/recents stacks to the larger minimized-state size final Rect homeBounds; @@ -190,11 +194,11 @@ class WindowManagerProxy { */ boolean applyEnterSplit(SplitScreenTaskOrganizer tiles, SplitDisplayLayout layout) { // Set launchtile first so that any stack created after - // getAllStackInfos and before reparent (even if unlikely) are placed + // getAllRootTaskInfos and before reparent (even if unlikely) are placed // correctly. - TaskOrganizer.setLaunchRoot(DEFAULT_DISPLAY, tiles.mSecondary.token); + mTaskOrganizer.setLaunchRoot(DEFAULT_DISPLAY, tiles.mSecondary.token); List<ActivityManager.RunningTaskInfo> rootTasks = - TaskOrganizer.getRootTasks(DEFAULT_DISPLAY, null /* activityTypes */); + mTaskOrganizer.getRootTasks(DEFAULT_DISPLAY, null /* activityTypes */); WindowContainerTransaction wct = new WindowContainerTransaction(); if (rootTasks.isEmpty()) { return false; @@ -230,7 +234,7 @@ class WindowManagerProxy { return isHomeResizable; } - static boolean isHomeOrRecentTask(ActivityManager.RunningTaskInfo ti) { + boolean isHomeOrRecentTask(ActivityManager.RunningTaskInfo ti) { final int atype = ti.configuration.windowConfiguration.getActivityType(); return atype == ACTIVITY_TYPE_HOME || atype == ACTIVITY_TYPE_RECENTS; } @@ -245,18 +249,18 @@ class WindowManagerProxy { boolean dismissOrMaximize) { // Set launch root first so that any task created after getChildContainers and // before reparent (pretty unlikely) are put into fullscreen. - TaskOrganizer.setLaunchRoot(Display.DEFAULT_DISPLAY, null); + mTaskOrganizer.setLaunchRoot(Display.DEFAULT_DISPLAY, null); // TODO(task-org): Once task-org is more complete, consider using Appeared/Vanished // plus specific APIs to clean this up. List<ActivityManager.RunningTaskInfo> primaryChildren = - TaskOrganizer.getChildTasks(tiles.mPrimary.token, null /* activityTypes */); + mTaskOrganizer.getChildTasks(tiles.mPrimary.token, null /* activityTypes */); List<ActivityManager.RunningTaskInfo> secondaryChildren = - TaskOrganizer.getChildTasks(tiles.mSecondary.token, null /* activityTypes */); + mTaskOrganizer.getChildTasks(tiles.mSecondary.token, null /* activityTypes */); // In some cases (eg. non-resizable is launched), system-server will leave split-screen. // as a result, the above will not capture any tasks; yet, we need to clean-up the // home task bounds. List<ActivityManager.RunningTaskInfo> freeHomeAndRecents = - TaskOrganizer.getRootTasks(DEFAULT_DISPLAY, HOME_AND_RECENTS); + mTaskOrganizer.getRootTasks(DEFAULT_DISPLAY, HOME_AND_RECENTS); // Filter out the root split tasks freeHomeAndRecents.removeIf(p -> p.token.equals(tiles.mSecondary.token) || p.token.equals(tiles.mPrimary.token)); diff --git a/libs/WindowManager/Shell/tests/flicker/Android.bp b/libs/WindowManager/Shell/tests/flicker/Android.bp index 587902221826..d7afa0e166b3 100644 --- a/libs/WindowManager/Shell/tests/flicker/Android.bp +++ b/libs/WindowManager/Shell/tests/flicker/Android.bp @@ -18,7 +18,7 @@ android_test { name: "WMShellFlickerTests", srcs: ["src/**/*.java", "src/**/*.kt"], manifest: "AndroidManifest.xml", - test_config: "AndroidTest.xml", + test_config: "AndroidTestPhysicalDevices.xml", platform_apis: true, certificate: "platform", test_suites: ["device-tests"], @@ -32,3 +32,21 @@ android_test { "launcher-aosp-tapl" ], } + +android_test { + name: "WMShellFlickerTestsVirtual", + srcs: ["src/**/*.java", "src/**/*.kt"], + manifest: "AndroidManifest.xml", + test_config: "AndroidTestVirtualDevices.xml", + platform_apis: true, + certificate: "platform", + libs: ["android.test.runner"], + static_libs: [ + "androidx.test.ext.junit", + "flickerlib", + "truth-prebuilt", + "app-helpers-core", + "launcher-helper-lib", + "launcher-aosp-tapl" + ], +} diff --git a/libs/WindowManager/Shell/tests/flicker/AndroidTest.xml b/libs/WindowManager/Shell/tests/flicker/AndroidTestPhysicalDevices.xml index 526fc502c0fb..9dd9f42bdf81 100644 --- a/libs/WindowManager/Shell/tests/flicker/AndroidTest.xml +++ b/libs/WindowManager/Shell/tests/flicker/AndroidTestPhysicalDevices.xml @@ -27,6 +27,7 @@ </target_preparer> <test class="com.android.tradefed.testtype.AndroidJUnitTest"> <option name="package" value="com.android.wm.shell.flicker"/> + <option name="include-annotation" value="androidx.test.filters.RequiresDevice" /> <option name="exclude-annotation" value="androidx.test.filters.FlakyTest" /> <option name="shell-timeout" value="6600s" /> <option name="test-timeout" value="6000s" /> @@ -37,4 +38,4 @@ <option name="collect-on-run-ended-only" value="true" /> <option name="clean-up" value="true" /> </metrics_collector> -</configuration> +</configuration>
\ No newline at end of file diff --git a/libs/WindowManager/Shell/tests/flicker/AndroidTestVirtualDevices.xml b/libs/WindowManager/Shell/tests/flicker/AndroidTestVirtualDevices.xml new file mode 100644 index 000000000000..afb1166415fc --- /dev/null +++ b/libs/WindowManager/Shell/tests/flicker/AndroidTestVirtualDevices.xml @@ -0,0 +1,41 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + * Copyright 2020 Google Inc. All Rights Reserved. + --> +<configuration description="Runs WindowManager Shell Flicker Tests"> + <option name="test-tag" value="FlickerTests" /> + <target_preparer class="com.android.tradefed.targetprep.DeviceSetup"> + <!-- keeps the screen on during tests --> + <option name="screen-always-on" value="on" /> + <!-- prevents the phone from restarting --> + <option name="force-skip-system-props" value="true" /> + <!-- set WM tracing verbose level to all --> + <option name="run-command" value="cmd window tracing level all" /> + <!-- inform WM to log all transactions --> + <option name="run-command" value="cmd window tracing transaction" /> + <!-- restart launcher to activate TAPL --> + <option name="run-command" value="setprop ro.test_harness 1 ; am force-stop com.google.android.apps.nexuslauncher" /> + </target_preparer> + <target_preparer class="com.android.tradefed.targetprep.DeviceCleaner"> + <!-- reboot the device to teardown any crashed tests --> + <option name="cleanup-action" value="REBOOT" /> + </target_preparer> + <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller"> + <option name="cleanup-apks" value="true"/> + <option name="test-file-name" value="WMShellFlickerTests.apk"/> + <option name="test-file-name" value="WMShellFlickerTestApp.apk" /> + </target_preparer> + <test class="com.android.tradefed.testtype.AndroidJUnitTest"> + <option name="package" value="com.android.wm.shell.flicker"/> + <option name="exclude-annotation" value="androidx.test.filters.RequiresDevice" /> + <option name="exclude-annotation" value="androidx.test.filters.FlakyTest" /> + <option name="shell-timeout" value="6600s" /> + <option name="test-timeout" value="6000s" /> + <option name="hidden-api-checks" value="false" /> + </test> + <metrics_collector class="com.android.tradefed.device.metric.FilePullerLogCollector"> + <option name="directory-keys" value="/storage/emulated/0/Android/data/com.android.wm.shell.flicker/files" /> + <option name="collect-on-run-ended-only" value="true" /> + <option name="clean-up" value="true" /> + </metrics_collector> +</configuration>
\ No newline at end of file diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/helpers/FlickerAppHelper.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/helpers/FlickerAppHelper.kt index 308a36efef87..47a62ce92d11 100644 --- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/helpers/FlickerAppHelper.kt +++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/helpers/FlickerAppHelper.kt @@ -18,7 +18,7 @@ package com.android.wm.shell.flicker.helpers import android.app.Instrumentation import android.support.test.launcherhelper.ILauncherStrategy -import com.android.server.wm.flicker.StandardAppHelper +import com.android.server.wm.flicker.helpers.StandardAppHelper abstract class FlickerAppHelper( instr: Instrumentation, diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipTest.kt index 4b04449bdbc2..c3c576d3f28c 100644 --- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipTest.kt +++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipTest.kt @@ -18,7 +18,7 @@ package com.android.wm.shell.flicker.pip import android.view.Surface import androidx.test.filters.FlakyTest -import androidx.test.filters.LargeTest +import androidx.test.filters.RequiresDevice import com.android.server.wm.flicker.dsl.flicker import com.android.server.wm.flicker.helpers.closePipWindow import com.android.server.wm.flicker.helpers.expandPipWindow @@ -41,7 +41,7 @@ import org.junit.runners.Parameterized * Test Pip launch. * To run this test: `atest FlickerTests:PipToAppTest` */ -@LargeTest +@RequiresDevice @RunWith(Parameterized::class) @FixMethodOrder(MethodSorters.NAME_ASCENDING) @FlakyTest(bugId = 152738416) diff --git a/libs/WindowManager/Shell/tests/unittest/Android.bp b/libs/WindowManager/Shell/tests/unittest/Android.bp index 692e2fa88fc3..937b00b3a0fd 100644 --- a/libs/WindowManager/Shell/tests/unittest/Android.bp +++ b/libs/WindowManager/Shell/tests/unittest/Android.bp @@ -25,6 +25,7 @@ android_test { "androidx.test.ext.junit", "mockito-target-extended-minus-junit4", "truth-prebuilt", + "testables", ], libs: [ "android.test.mock", diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/ShellTaskOrganizerTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/ShellTaskOrganizerTests.java index 10672c8d87ad..497b6b714281 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/ShellTaskOrganizerTests.java +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/ShellTaskOrganizerTests.java @@ -20,10 +20,14 @@ import static android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW; import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED; import static org.junit.Assert.assertTrue; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.verify; import android.app.ActivityManager.RunningTaskInfo; -import android.content.res.Configuration; +import android.os.RemoteException; import android.view.SurfaceControl; +import android.window.ITaskOrganizer; +import android.window.ITaskOrganizerController; import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.filters.SmallTest; @@ -31,6 +35,8 @@ import androidx.test.filters.SmallTest; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; import java.util.ArrayList; @@ -41,6 +47,9 @@ import java.util.ArrayList; @RunWith(AndroidJUnit4.class) public class ShellTaskOrganizerTests { + @Mock + private ITaskOrganizerController mTaskOrganizerController; + ShellTaskOrganizer mOrganizer; private class TrackingTaskListener implements ShellTaskOrganizer.TaskListener { @@ -71,7 +80,15 @@ public class ShellTaskOrganizerTests { @Before public void setUp() { - mOrganizer = new ShellTaskOrganizer(); + MockitoAnnotations.initMocks(this); + mOrganizer = new ShellTaskOrganizer(mTaskOrganizerController); + } + + @Test + public void registerOrganizer_sendRegisterTaskOrganizer() throws RemoteException { + mOrganizer.registerOrganizer(); + + verify(mTaskOrganizerController).registerTaskOrganizer(any(ITaskOrganizer.class)); } @Test diff --git a/packages/SystemUI/tests/src/com/android/systemui/onehanded/OneHandedAnimationControllerTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/onehanded/OneHandedAnimationControllerTest.java index 7fabf8258198..a8a3a9fd7da2 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/onehanded/OneHandedAnimationControllerTest.java +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/onehanded/OneHandedAnimationControllerTest.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.android.systemui.onehanded; +package com.android.wm.shell.onehanded; import static org.junit.Assert.assertNotNull; diff --git a/packages/SystemUI/tests/src/com/android/systemui/onehanded/OneHandedControllerTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/onehanded/OneHandedControllerTest.java index e42cf529373e..1ce8b5445b37 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/onehanded/OneHandedControllerTest.java +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/onehanded/OneHandedControllerTest.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.android.systemui.onehanded; +package com.android.wm.shell.onehanded; import static com.google.common.truth.Truth.assertThat; @@ -112,10 +112,21 @@ public class OneHandedControllerTest extends OneHandedTestCase { } @Test + public void testRegisterTransitionCallbackAfterInit() { + verify(mMockDisplayAreaOrganizer).registerTransitionCallback(mMockTouchHandler); + verify(mMockDisplayAreaOrganizer).registerTransitionCallback(mMockGestureHandler); + verify(mMockDisplayAreaOrganizer).registerTransitionCallback(mMockTutorialHandler); + } + + @Test public void testRegisterTransitionCallback() { - verify(mMockDisplayAreaOrganizer, atLeastOnce()).registerTransitionCallback(any()); + OneHandedTransitionCallback callback = new OneHandedTransitionCallback() {}; + mOneHandedController.registerTransitionCallback(callback); + + verify(mMockDisplayAreaOrganizer).registerTransitionCallback(callback); } + @Test public void testStopOneHanded_shouldRemoveTimer() { mOneHandedController.stopOneHanded(); @@ -139,7 +150,7 @@ public class OneHandedControllerTest extends OneHandedTestCase { verify(mMockTouchHandler, atLeastOnce()).onOneHandedEnabled(enabled); } - @Ignore("b/161980408, fix it after migration finished") + @Ignore("b/167943723, refactor it and fix it") @Test public void tesSettingsObserver_updateTapAppToExit() { Settings.Secure.putInt(mContext.getContentResolver(), @@ -148,7 +159,7 @@ public class OneHandedControllerTest extends OneHandedTestCase { verify(mOneHandedController).setTaskChangeToExit(true); } - @Ignore("b/161980408, fix it after migration finished") + @Ignore("b/167943723, refactor it and fix it") @Test public void tesSettingsObserver_updateEnabled() { Settings.Secure.putInt(mContext.getContentResolver(), @@ -157,7 +168,7 @@ public class OneHandedControllerTest extends OneHandedTestCase { verify(mOneHandedController).setOneHandedEnabled(true); } - @Ignore("b/161980408, fix it after migration finished") + @Ignore("b/167943723, refactor it and fix it") @Test public void tesSettingsObserver_updateTimeout() { Settings.Secure.putInt(mContext.getContentResolver(), @@ -168,7 +179,7 @@ public class OneHandedControllerTest extends OneHandedTestCase { OneHandedSettingsUtil.ONE_HANDED_TIMEOUT_MEDIUM_IN_SECONDS); } - @Ignore("b/161980408, fix it after migration finished") + @Ignore("b/167943723, refactor it and fix it") @Test public void tesSettingsObserver_updateSwipeToNotification() { Settings.Secure.putInt(mContext.getContentResolver(), diff --git a/packages/SystemUI/tests/src/com/android/systemui/onehanded/OneHandedDisplayAreaOrganizerTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/onehanded/OneHandedDisplayAreaOrganizerTest.java index a989cd1f9c40..5ff94b6308ef 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/onehanded/OneHandedDisplayAreaOrganizerTest.java +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/onehanded/OneHandedDisplayAreaOrganizerTest.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.android.systemui.onehanded; +package com.android.wm.shell.onehanded; import static android.view.Display.DEFAULT_DISPLAY; import static android.window.DisplayAreaOrganizer.FEATURE_ONE_HANDED; diff --git a/packages/SystemUI/tests/src/com/android/systemui/onehanded/OneHandedEventsTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/onehanded/OneHandedEventsTest.java index 36c1174fcdce..492c34e10ed5 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/onehanded/OneHandedEventsTest.java +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/onehanded/OneHandedEventsTest.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.android.systemui.onehanded; +package com.android.wm.shell.onehanded; import static org.junit.Assert.assertEquals; @@ -22,7 +22,6 @@ import androidx.test.filters.SmallTest; import com.android.internal.logging.UiEventLogger; import com.android.internal.logging.testing.UiEventLoggerFake; -import com.android.systemui.SysuiTestCase; import org.junit.Before; import org.junit.Test; @@ -34,7 +33,7 @@ import java.util.Collection; @RunWith(Parameterized.class) @SmallTest -public class OneHandedEventsTest extends SysuiTestCase { +public class OneHandedEventsTest extends OneHandedTestCase { private UiEventLoggerFake mUiEventLogger; diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/onehanded/OneHandedGestureHandlerTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/onehanded/OneHandedGestureHandlerTest.java new file mode 100644 index 000000000000..fb417c8ca5e8 --- /dev/null +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/onehanded/OneHandedGestureHandlerTest.java @@ -0,0 +1,93 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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.wm.shell.onehanded; + +import static com.google.common.truth.Truth.assertThat; + +import static org.mockito.ArgumentMatchers.any; + +import android.testing.AndroidTestingRunner; +import android.testing.TestableLooper; + +import androidx.test.filters.SmallTest; + +import com.android.wm.shell.common.DisplayController; + +import org.junit.Before; +import org.junit.Ignore; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; + +@SmallTest +@RunWith(AndroidTestingRunner.class) +@TestableLooper.RunWithLooper +public class OneHandedGestureHandlerTest extends OneHandedTestCase { + OneHandedTutorialHandler mTutorialHandler; + OneHandedGestureHandler mGestureHandler; + @Mock + DisplayController mMockDisplayController; + @Before + public void setUp() throws Exception { + MockitoAnnotations.initMocks(this); + mTutorialHandler = new OneHandedTutorialHandler(mContext); + mGestureHandler = new OneHandedGestureHandler(mContext, mMockDisplayController); + } + + @Test + public void testSetGestureEventListener() { + OneHandedGestureHandler.OneHandedGestureEventCallback callback = + new OneHandedGestureHandler.OneHandedGestureEventCallback() { + @Override + public void onStart() {} + + @Override + public void onStop() {} + }; + + mGestureHandler.setGestureEventListener(callback); + assertThat(mGestureHandler.mGestureEventCallback).isEqualTo(callback); + } + + @Ignore("b/167943723, refactor it and fix it") + @Test + public void testReceiveNewConfig_whenThreeButtonModeEnabled() { + mGestureHandler.onOneHandedEnabled(true); + mGestureHandler.onThreeButtonModeEnabled(true); + + assertThat(mGestureHandler.mInputMonitor).isNotNull(); + assertThat(mGestureHandler.mInputEventReceiver).isNotNull(); + } + + @Test + public void testOneHandedDisabled_shouldDisposeInputChannel() { + mGestureHandler.onOneHandedEnabled(false); + + assertThat(mGestureHandler.mInputMonitor).isNull(); + assertThat(mGestureHandler.mInputEventReceiver).isNull(); + } + + @Test + public void testChangeNavBarToNon3Button_shouldDisposeInputChannel() { + mGestureHandler.onOneHandedEnabled(true); + mGestureHandler.onThreeButtonModeEnabled(false); + + assertThat(mGestureHandler.mInputMonitor).isNull(); + assertThat(mGestureHandler.mInputEventReceiver).isNull(); + } +} diff --git a/packages/SystemUI/tests/src/com/android/systemui/onehanded/OneHandedSettingsUtilTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/onehanded/OneHandedSettingsUtilTest.java index 990eb634e46f..7c11138a47aa 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/onehanded/OneHandedSettingsUtilTest.java +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/onehanded/OneHandedSettingsUtilTest.java @@ -14,12 +14,12 @@ * limitations under the License. */ -package com.android.systemui.onehanded; +package com.android.wm.shell.onehanded; -import static com.android.systemui.onehanded.OneHandedSettingsUtil.ONE_HANDED_TIMEOUT_LONG_IN_SECONDS; -import static com.android.systemui.onehanded.OneHandedSettingsUtil.ONE_HANDED_TIMEOUT_MEDIUM_IN_SECONDS; -import static com.android.systemui.onehanded.OneHandedSettingsUtil.ONE_HANDED_TIMEOUT_NEVER; -import static com.android.systemui.onehanded.OneHandedSettingsUtil.ONE_HANDED_TIMEOUT_SHORT_IN_SECONDS; +import static com.android.wm.shell.onehanded.OneHandedSettingsUtil.ONE_HANDED_TIMEOUT_LONG_IN_SECONDS; +import static com.android.wm.shell.onehanded.OneHandedSettingsUtil.ONE_HANDED_TIMEOUT_MEDIUM_IN_SECONDS; +import static com.android.wm.shell.onehanded.OneHandedSettingsUtil.ONE_HANDED_TIMEOUT_NEVER; +import static com.android.wm.shell.onehanded.OneHandedSettingsUtil.ONE_HANDED_TIMEOUT_SHORT_IN_SECONDS; import static com.google.common.truth.Truth.assertThat; @@ -59,24 +59,24 @@ public class OneHandedSettingsUtilTest extends OneHandedTestCase { @Test public void testRegisterSecureKeyObserver() { final Uri result = OneHandedSettingsUtil.registerSettingsKeyObserver( - Settings.Secure.ONE_HANDED_MODE_ENABLED, mContentResolver, mContentObserver); + Settings.Secure.TAPS_APP_TO_EXIT, mContentResolver, mContentObserver); assertThat(result).isNotNull(); OneHandedSettingsUtil.registerSettingsKeyObserver( - Settings.Secure.ONE_HANDED_MODE_ENABLED, mContentResolver, mContentObserver); + Settings.Secure.TAPS_APP_TO_EXIT, mContentResolver, mContentObserver); } @Test public void testUnregisterSecureKeyObserver() { OneHandedSettingsUtil.registerSettingsKeyObserver( - Settings.Secure.ONE_HANDED_MODE_ENABLED, mContentResolver, mContentObserver); + Settings.Secure.TAPS_APP_TO_EXIT, mContentResolver, mContentObserver); OneHandedSettingsUtil.unregisterSettingsKeyObserver(mContentResolver, mContentObserver); assertThat(mOnChanged).isFalse(); Settings.Secure.putInt(mContext.getContentResolver(), - Settings.Secure.ONE_HANDED_MODE_ENABLED, 0); + Settings.Secure.TAPS_APP_TO_EXIT, 0); assertThat(mOnChanged).isFalse(); } diff --git a/packages/SystemUI/tests/src/com/android/systemui/onehanded/OneHandedTestCase.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/onehanded/OneHandedTestCase.java index f111c4896458..c7ae2a09ad67 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/onehanded/OneHandedTestCase.java +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/onehanded/OneHandedTestCase.java @@ -14,17 +14,21 @@ * limitations under the License. */ -package com.android.systemui.onehanded; +package com.android.wm.shell.onehanded; -import static com.android.systemui.onehanded.OneHandedController.SUPPORT_ONE_HANDED_MODE; -import static com.android.systemui.onehanded.OneHandedSettingsUtil.ONE_HANDED_TIMEOUT_MEDIUM_IN_SECONDS; +import static android.view.Display.DEFAULT_DISPLAY; + +import static com.android.wm.shell.onehanded.OneHandedController.SUPPORT_ONE_HANDED_MODE; +import static com.android.wm.shell.onehanded.OneHandedSettingsUtil.ONE_HANDED_TIMEOUT_MEDIUM_IN_SECONDS; import static org.junit.Assume.assumeTrue; +import android.content.Context; +import android.hardware.display.DisplayManager; import android.os.SystemProperties; import android.provider.Settings; -import com.android.systemui.SysuiTestCase; +import androidx.test.platform.app.InstrumentationRegistry; import org.junit.After; import org.junit.Before; @@ -32,14 +36,26 @@ import org.junit.Before; /** * Base class that does One Handed specific setup. */ -public abstract class OneHandedTestCase extends SysuiTestCase { +public abstract class OneHandedTestCase { static boolean sOrigEnabled; static boolean sOrigTapsAppToExitEnabled; static int sOrigTimeout; static boolean sOrigSwipeToNotification; + protected Context mContext; + @Before public void setupSettings() { + final Context testContext = + InstrumentationRegistry.getInstrumentation().getTargetContext(); + final DisplayManager dm = testContext.getSystemService(DisplayManager.class); + mContext = testContext.createDisplayContext(dm.getDisplay(DEFAULT_DISPLAY)); + + InstrumentationRegistry + .getInstrumentation() + .getUiAutomation() + .adoptShellPermissionIdentity(); + sOrigEnabled = OneHandedSettingsUtil.getSettingsOneHandedModeEnabled( getContext().getContentResolver()); sOrigTimeout = OneHandedSettingsUtil.getSettingsOneHandedModeTimeout( @@ -74,6 +90,15 @@ public abstract class OneHandedTestCase extends SysuiTestCase { Settings.Secure.putInt(mContext.getContentResolver(), Settings.Secure.SWIPE_BOTTOM_TO_NOTIFICATION_ENABLED, sOrigSwipeToNotification ? 1 : 0); + + InstrumentationRegistry + .getInstrumentation() + .getUiAutomation() + .dropShellPermissionIdentity(); + } + + protected Context getContext() { + return mContext; } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/onehanded/OneHandedTimeoutHandlerTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/onehanded/OneHandedTimeoutHandlerTest.java index 7d631319ec5e..e2b70c3bcc70 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/onehanded/OneHandedTimeoutHandlerTest.java +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/onehanded/OneHandedTimeoutHandlerTest.java @@ -14,13 +14,13 @@ * limitations under the License. */ -package com.android.systemui.onehanded; +package com.android.wm.shell.onehanded; -import static com.android.systemui.onehanded.OneHandedSettingsUtil.ONE_HANDED_TIMEOUT_LONG_IN_SECONDS; -import static com.android.systemui.onehanded.OneHandedSettingsUtil.ONE_HANDED_TIMEOUT_MEDIUM_IN_SECONDS; -import static com.android.systemui.onehanded.OneHandedSettingsUtil.ONE_HANDED_TIMEOUT_NEVER; -import static com.android.systemui.onehanded.OneHandedSettingsUtil.ONE_HANDED_TIMEOUT_SHORT_IN_SECONDS; -import static com.android.systemui.onehanded.OneHandedTimeoutHandler.ONE_HANDED_TIMEOUT_STOP_MSG; +import static com.android.wm.shell.onehanded.OneHandedSettingsUtil.ONE_HANDED_TIMEOUT_LONG_IN_SECONDS; +import static com.android.wm.shell.onehanded.OneHandedSettingsUtil.ONE_HANDED_TIMEOUT_MEDIUM_IN_SECONDS; +import static com.android.wm.shell.onehanded.OneHandedSettingsUtil.ONE_HANDED_TIMEOUT_NEVER; +import static com.android.wm.shell.onehanded.OneHandedSettingsUtil.ONE_HANDED_TIMEOUT_SHORT_IN_SECONDS; +import static com.android.wm.shell.onehanded.OneHandedTimeoutHandler.ONE_HANDED_TIMEOUT_STOP_MSG; import static com.google.common.truth.Truth.assertThat; diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/onehanded/OneHandedTouchHandlerTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/onehanded/OneHandedTouchHandlerTest.java new file mode 100644 index 000000000000..c69e385b2602 --- /dev/null +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/onehanded/OneHandedTouchHandlerTest.java @@ -0,0 +1,69 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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.wm.shell.onehanded; + +import static com.google.common.truth.Truth.assertThat; + +import android.testing.AndroidTestingRunner; +import android.testing.TestableLooper; + +import androidx.test.filters.SmallTest; + +import org.junit.Before; +import org.junit.Ignore; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.MockitoAnnotations; + +@SmallTest +@RunWith(AndroidTestingRunner.class) +@TestableLooper.RunWithLooper +public class OneHandedTouchHandlerTest extends OneHandedTestCase { + OneHandedTouchHandler mTouchHandler; + + @Before + public void setUp() { + MockitoAnnotations.initMocks(this); + mTouchHandler = new OneHandedTouchHandler(); + } + + @Test + public void testRegisterTouchEventListener() { + OneHandedTouchHandler.OneHandedTouchEventCallback callback = () -> { + }; + mTouchHandler.registerTouchEventListener(callback); + + assertThat(mTouchHandler.mTouchEventCallback).isEqualTo(callback); + } + + @Test + public void testOneHandedDisabled_shouldDisposeInputChannel() { + mTouchHandler.onOneHandedEnabled(false); + + assertThat(mTouchHandler.mInputMonitor).isNull(); + assertThat(mTouchHandler.mInputEventReceiver).isNull(); + } + + @Ignore("b/167943723, refactor it and fix it") + @Test + public void testOneHandedEnabled_monitorInputChannel() { + mTouchHandler.onOneHandedEnabled(true); + + assertThat(mTouchHandler.mInputMonitor).isNotNull(); + assertThat(mTouchHandler.mInputEventReceiver).isNotNull(); + } +}
\ No newline at end of file diff --git a/packages/SystemUI/tests/src/com/android/systemui/onehanded/OneHandedTutorialHandlerTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/onehanded/OneHandedTutorialHandlerTest.java index 8ea5524eb7e6..4a133d39291a 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/onehanded/OneHandedTutorialHandlerTest.java +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/onehanded/OneHandedTutorialHandlerTest.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.android.systemui.onehanded; +package com.android.wm.shell.onehanded; import static org.mockito.Mockito.verify; @@ -29,13 +29,13 @@ import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; -import org.mockito.Mockito; import org.mockito.MockitoAnnotations; @SmallTest @RunWith(AndroidTestingRunner.class) @TestableLooper.RunWithLooper public class OneHandedTutorialHandlerTest extends OneHandedTestCase { + @Mock OneHandedTouchHandler mTouchHandler; OneHandedTutorialHandler mTutorialHandler; OneHandedGestureHandler mGestureHandler; @@ -48,8 +48,7 @@ public class OneHandedTutorialHandlerTest extends OneHandedTestCase { @Before public void setUp() { MockitoAnnotations.initMocks(this); - mTouchHandler = new OneHandedTouchHandler(); - mTutorialHandler = Mockito.spy(new OneHandedTutorialHandler(mContext)); + mTutorialHandler = new OneHandedTutorialHandler(mContext); mGestureHandler = new OneHandedGestureHandler(mContext, mMockDisplayController); mOneHandedController = new OneHandedController( getContext(), diff --git a/libs/hwui/renderthread/VulkanManager.cpp b/libs/hwui/renderthread/VulkanManager.cpp index 76ec078ce3c9..4dbce92ed01c 100644 --- a/libs/hwui/renderthread/VulkanManager.cpp +++ b/libs/hwui/renderthread/VulkanManager.cpp @@ -84,7 +84,6 @@ VulkanManager::~VulkanManager() { mGraphicsQueue = VK_NULL_HANDLE; mAHBUploadQueue = VK_NULL_HANDLE; - mPresentQueue = VK_NULL_HANDLE; mDevice = VK_NULL_HANDLE; mPhysicalDevice = VK_NULL_HANDLE; mInstance = VK_NULL_HANDLE; @@ -192,10 +191,6 @@ void VulkanManager::setupDevice(GrVkExtensions& grExtensions, VkPhysicalDeviceFe } LOG_ALWAYS_FATAL_IF(mGraphicsQueueIndex == queueCount); - // All physical devices and queue families on Android must be capable of - // presentation with any native window. So just use the first one. - mPresentQueueIndex = 0; - { uint32_t extensionCount = 0; err = mEnumerateDeviceExtensionProperties(mPhysicalDevice, nullptr, &extensionCount, @@ -289,31 +284,21 @@ void VulkanManager::setupDevice(GrVkExtensions& grExtensions, VkPhysicalDeviceFe queueNextPtr = &queuePriorityCreateInfo; } - const VkDeviceQueueCreateInfo queueInfo[2] = { - { - VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO, // sType - queueNextPtr, // pNext - 0, // VkDeviceQueueCreateFlags - mGraphicsQueueIndex, // queueFamilyIndex - 2, // queueCount - queuePriorities, // pQueuePriorities - }, - { - VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO, // sType - queueNextPtr, // pNext - 0, // VkDeviceQueueCreateFlags - mPresentQueueIndex, // queueFamilyIndex - 1, // queueCount - queuePriorities, // pQueuePriorities - }}; - uint32_t queueInfoCount = (mPresentQueueIndex != mGraphicsQueueIndex) ? 2 : 1; + const VkDeviceQueueCreateInfo queueInfo = { + VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO, // sType + queueNextPtr, // pNext + 0, // VkDeviceQueueCreateFlags + mGraphicsQueueIndex, // queueFamilyIndex + 2, // queueCount + queuePriorities, // pQueuePriorities + }; const VkDeviceCreateInfo deviceInfo = { VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO, // sType &features, // pNext 0, // VkDeviceCreateFlags - queueInfoCount, // queueCreateInfoCount - queueInfo, // pQueueCreateInfos + 1, // queueCreateInfoCount + &queueInfo, // pQueueCreateInfos 0, // layerCount nullptr, // ppEnabledLayerNames (uint32_t)mDeviceExtensions.size(), // extensionCount @@ -361,8 +346,6 @@ void VulkanManager::initialize() { mGetDeviceQueue(mDevice, mGraphicsQueueIndex, 0, &mGraphicsQueue); mGetDeviceQueue(mDevice, mGraphicsQueueIndex, 1, &mAHBUploadQueue); - mGetDeviceQueue(mDevice, mPresentQueueIndex, 0, &mPresentQueue); - if (Properties::enablePartialUpdates && Properties::useBufferAge) { mSwapBehavior = SwapBehavior::BufferAge; } @@ -555,8 +538,8 @@ void VulkanManager::swapBuffers(VulkanSurface* surface, const SkRect& dirtyRect) void VulkanManager::destroySurface(VulkanSurface* surface) { // Make sure all submit commands have finished before starting to destroy objects. - if (VK_NULL_HANDLE != mPresentQueue) { - mQueueWaitIdle(mPresentQueue); + if (VK_NULL_HANDLE != mGraphicsQueue) { + mQueueWaitIdle(mGraphicsQueue); } mDeviceWaitIdle(mDevice); diff --git a/libs/hwui/renderthread/VulkanManager.h b/libs/hwui/renderthread/VulkanManager.h index 75c05b828e5d..7a77466303cd 100644 --- a/libs/hwui/renderthread/VulkanManager.h +++ b/libs/hwui/renderthread/VulkanManager.h @@ -163,8 +163,6 @@ private: uint32_t mGraphicsQueueIndex; VkQueue mGraphicsQueue = VK_NULL_HANDLE; VkQueue mAHBUploadQueue = VK_NULL_HANDLE; - uint32_t mPresentQueueIndex; - VkQueue mPresentQueue = VK_NULL_HANDLE; // Variables saved to populate VkFunctorInitParams. static const uint32_t mAPIVersion = VK_MAKE_VERSION(1, 1, 0); diff --git a/libs/hwui/shader/BlurShader.cpp b/libs/hwui/shader/BlurShader.cpp index 4d18cdd27e4e..fa10be100bca 100644 --- a/libs/hwui/shader/BlurShader.cpp +++ b/libs/hwui/shader/BlurShader.cpp @@ -26,7 +26,9 @@ BlurShader::BlurShader(float radiusX, float radiusY, Shader* inputShader, const SkImageFilters::Blur( Blur::convertRadiusToSigma(radiusX), Blur::convertRadiusToSigma(radiusY), - inputShader ? inputShader->asSkImageFilter() : nullptr) + SkTileMode::kClamp, + inputShader ? inputShader->asSkImageFilter() : nullptr, + nullptr) ) { } sk_sp<SkImageFilter> BlurShader::makeSkImageFilter() { diff --git a/location/java/android/location/LocationManager.java b/location/java/android/location/LocationManager.java index 6fc702e4a068..04bcbfc5f6b8 100644 --- a/location/java/android/location/LocationManager.java +++ b/location/java/android/location/LocationManager.java @@ -164,7 +164,7 @@ public class LocationManager { /** * The fused location provider. * - * <p>This provider combines may combine inputs from several location sources to provide the + * <p>This provider may combine inputs from several location sources to provide the * best possible location fix. It is implicitly used for all API's that involve the * {@link LocationRequest} object. * diff --git a/location/java/android/location/timezone/LocationTimeZoneEvent.java b/location/java/android/location/timezone/LocationTimeZoneEvent.java index 540bdfffe16a..55bc507964e6 100644 --- a/location/java/android/location/timezone/LocationTimeZoneEvent.java +++ b/location/java/android/location/timezone/LocationTimeZoneEvent.java @@ -35,7 +35,8 @@ import java.util.Objects; */ public final class LocationTimeZoneEvent implements Parcelable { - @IntDef({ EVENT_TYPE_UNKNOWN, EVENT_TYPE_SUCCESS, EVENT_TYPE_SUCCESS }) + @IntDef({ EVENT_TYPE_UNKNOWN, EVENT_TYPE_PERMANENT_FAILURE, EVENT_TYPE_SUCCESS, + EVENT_TYPE_UNCERTAIN }) @interface EventType {} /** Uninitialized value for {@link #mEventType} - must not be used for real events. */ @@ -43,7 +44,7 @@ public final class LocationTimeZoneEvent implements Parcelable { /** * Indicates there was a permanent failure. This is not generally expected, and probably means a - * required backend service is no longer supported / available. + * required backend service has been turned down, or the client is unreasonably old. */ public static final int EVENT_TYPE_PERMANENT_FAILURE = 1; @@ -54,8 +55,9 @@ public final class LocationTimeZoneEvent implements Parcelable { public static final int EVENT_TYPE_SUCCESS = 2; /** - * Indicates the time zone is not known because there was a (temporary) error, e.g. when - * detecting location, or when resolving the location to a time zone. + * Indicates the time zone is not known because of an expected runtime state or error, e.g. when + * the provider is unable to detect location, or there was a problem when resolving the location + * to a time zone. */ public static final int EVENT_TYPE_UNCERTAIN = 3; diff --git a/media/java/android/media/AudioDeviceAttributes.java b/media/java/android/media/AudioDeviceAttributes.java index 0ab62c14ab9f..6c8b50037d3d 100644 --- a/media/java/android/media/AudioDeviceAttributes.java +++ b/media/java/android/media/AudioDeviceAttributes.java @@ -72,6 +72,11 @@ public final class AudioDeviceAttributes implements Parcelable { private final @Role int mRole; /** + * The internal audio device type + */ + private final int mNativeType; + + /** * @hide * Constructor from a valid {@link AudioDeviceInfo} * @param deviceInfo the connected audio device from which to obtain the device-identifying @@ -83,6 +88,7 @@ public final class AudioDeviceAttributes implements Parcelable { mRole = deviceInfo.isSink() ? ROLE_OUTPUT : ROLE_INPUT; mType = deviceInfo.getType(); mAddress = deviceInfo.getAddress(); + mNativeType = deviceInfo.getInternalType(); } /** @@ -101,9 +107,12 @@ public final class AudioDeviceAttributes implements Parcelable { } if (role == ROLE_OUTPUT) { AudioDeviceInfo.enforceValidAudioDeviceTypeOut(type); - } - if (role == ROLE_INPUT) { + mNativeType = AudioDeviceInfo.convertDeviceTypeToInternalDevice(type); + } else if (role == ROLE_INPUT) { AudioDeviceInfo.enforceValidAudioDeviceTypeIn(type); + mNativeType = AudioDeviceInfo.convertDeviceTypeToInternalInputDevice(type); + } else { + mNativeType = AudioSystem.DEVICE_NONE; } mRole = role; @@ -115,6 +124,7 @@ public final class AudioDeviceAttributes implements Parcelable { mRole = (nativeType & AudioSystem.DEVICE_BIT_IN) != 0 ? ROLE_INPUT : ROLE_OUTPUT; mType = AudioDeviceInfo.convertInternalDeviceToDeviceType(nativeType); mAddress = address; + mNativeType = nativeType; } /** @@ -147,6 +157,15 @@ public final class AudioDeviceAttributes implements Parcelable { return mAddress; } + /** + * @hide + * Returns the internal device type of a device + * @return the internal device type + */ + public int getInternalType() { + return mNativeType; + } + @Override public int hashCode() { return Objects.hash(mRole, mType, mAddress); @@ -189,12 +208,14 @@ public final class AudioDeviceAttributes implements Parcelable { dest.writeInt(mRole); dest.writeInt(mType); dest.writeString(mAddress); + dest.writeInt(mNativeType); } private AudioDeviceAttributes(@NonNull Parcel in) { mRole = in.readInt(); mType = in.readInt(); mAddress = in.readString(); + mNativeType = in.readInt(); } public static final @NonNull Parcelable.Creator<AudioDeviceAttributes> CREATOR = diff --git a/media/java/android/media/AudioDeviceInfo.java b/media/java/android/media/AudioDeviceInfo.java index d4fb1be56890..477519c0da32 100644 --- a/media/java/android/media/AudioDeviceInfo.java +++ b/media/java/android/media/AudioDeviceInfo.java @@ -351,6 +351,14 @@ public final class AudioDeviceInfo { } /** + * @hide + * @return the internal device tyoe + */ + public int getInternalType() { + return mPort.type(); + } + + /** * @return The internal device ID. */ public int getId() { @@ -513,10 +521,21 @@ public final class AudioDeviceInfo { return INT_TO_EXT_DEVICE_MAPPING.get(intDevice, TYPE_UNKNOWN); } + /** @hide */ + public static int convertDeviceTypeToInternalInputDevice(int deviceType) { + return EXT_TO_INT_INPUT_DEVICE_MAPPING.get(deviceType, AudioSystem.DEVICE_NONE); + } + private static final SparseIntArray INT_TO_EXT_DEVICE_MAPPING; private static final SparseIntArray EXT_TO_INT_DEVICE_MAPPING; + /** + * EXT_TO_INT_INPUT_DEVICE_MAPPING aims at mapping external device type to internal input device + * type. + */ + private static final SparseIntArray EXT_TO_INT_INPUT_DEVICE_MAPPING; + static { INT_TO_EXT_DEVICE_MAPPING = new SparseIntArray(); INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_OUT_EARPIECE, TYPE_BUILTIN_EARPIECE); @@ -601,6 +620,32 @@ public final class AudioDeviceInfo { EXT_TO_INT_DEVICE_MAPPING.put(TYPE_REMOTE_SUBMIX, AudioSystem.DEVICE_OUT_REMOTE_SUBMIX); EXT_TO_INT_DEVICE_MAPPING.put(TYPE_BLE_HEADSET, AudioSystem.DEVICE_OUT_BLE_HEADSET); EXT_TO_INT_DEVICE_MAPPING.put(TYPE_BLE_SPEAKER, AudioSystem.DEVICE_OUT_BLE_SPEAKER); + + // privileges mapping to input device + EXT_TO_INT_INPUT_DEVICE_MAPPING = new SparseIntArray(); + EXT_TO_INT_INPUT_DEVICE_MAPPING.put(TYPE_BUILTIN_MIC, AudioSystem.DEVICE_IN_BUILTIN_MIC); + EXT_TO_INT_INPUT_DEVICE_MAPPING.put( + TYPE_BLUETOOTH_SCO, AudioSystem.DEVICE_IN_BLUETOOTH_SCO_HEADSET); + EXT_TO_INT_INPUT_DEVICE_MAPPING.put( + TYPE_WIRED_HEADSET, AudioSystem.DEVICE_IN_WIRED_HEADSET); + EXT_TO_INT_INPUT_DEVICE_MAPPING.put(TYPE_HDMI, AudioSystem.DEVICE_IN_HDMI); + EXT_TO_INT_INPUT_DEVICE_MAPPING.put(TYPE_TELEPHONY, AudioSystem.DEVICE_IN_TELEPHONY_RX); + EXT_TO_INT_INPUT_DEVICE_MAPPING.put(TYPE_DOCK, AudioSystem.DEVICE_IN_ANLG_DOCK_HEADSET); + EXT_TO_INT_INPUT_DEVICE_MAPPING.put( + TYPE_USB_ACCESSORY, AudioSystem.DEVICE_IN_USB_ACCESSORY); + EXT_TO_INT_INPUT_DEVICE_MAPPING.put(TYPE_USB_DEVICE, AudioSystem.DEVICE_IN_USB_DEVICE); + EXT_TO_INT_INPUT_DEVICE_MAPPING.put(TYPE_USB_HEADSET, AudioSystem.DEVICE_IN_USB_HEADSET); + EXT_TO_INT_INPUT_DEVICE_MAPPING.put(TYPE_FM_TUNER, AudioSystem.DEVICE_IN_FM_TUNER); + EXT_TO_INT_INPUT_DEVICE_MAPPING.put(TYPE_TV_TUNER, AudioSystem.DEVICE_IN_TV_TUNER); + EXT_TO_INT_INPUT_DEVICE_MAPPING.put(TYPE_LINE_ANALOG, AudioSystem.DEVICE_IN_LINE); + EXT_TO_INT_INPUT_DEVICE_MAPPING.put(TYPE_LINE_DIGITAL, AudioSystem.DEVICE_IN_SPDIF); + EXT_TO_INT_INPUT_DEVICE_MAPPING.put( + TYPE_BLUETOOTH_A2DP, AudioSystem.DEVICE_IN_BLUETOOTH_A2DP); + EXT_TO_INT_INPUT_DEVICE_MAPPING.put(TYPE_IP, AudioSystem.DEVICE_IN_IP); + EXT_TO_INT_INPUT_DEVICE_MAPPING.put(TYPE_BUS, AudioSystem.DEVICE_IN_BUS); + EXT_TO_INT_INPUT_DEVICE_MAPPING.put( + TYPE_REMOTE_SUBMIX, AudioSystem.DEVICE_IN_REMOTE_SUBMIX); + EXT_TO_INT_INPUT_DEVICE_MAPPING.put(TYPE_BLE_HEADSET, AudioSystem.DEVICE_IN_BLE_HEADSET); } } diff --git a/media/java/android/media/AudioManager.java b/media/java/android/media/AudioManager.java index a16e063fe969..e1e55c25b3fa 100755..100644 --- a/media/java/android/media/AudioManager.java +++ b/media/java/android/media/AudioManager.java @@ -1949,6 +1949,349 @@ public class AudioManager { } //==================================================================== + // Audio Capture Preset routing + + /** + * @hide + * Set the preferred device for a given capture preset, i.e. the audio routing to be used by + * this capture preset. Note that the device may not be available at the time the preferred + * device is set, but it will be used once made available. + * <p>Use {@link #clearPreferredDevicesForCapturePreset(int)} to cancel setting this preference + * for this capture preset.</p> + * @param capturePreset the audio capture preset whose routing will be affected + * @param device the audio device to route to when available + * @return true if the operation was successful, false otherwise + */ + @SystemApi + @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) + public boolean setPreferredDeviceForCapturePreset(int capturePreset, + @NonNull AudioDeviceAttributes device) { + return setPreferredDevicesForCapturePreset(capturePreset, Arrays.asList(device)); + } + + /** + * @hide + * Remove all the preferred audio devices previously set + * @param capturePreset the audio capture preset whose routing will be affected + * @return true if the operation was successful, false otherwise (invalid capture preset, or no + * device set for example) + */ + @SystemApi + @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) + public boolean clearPreferredDevicesForCapturePreset(int capturePreset) { + if (!MediaRecorder.isValidAudioSource(capturePreset)) { + return false; + } + try { + final int status = getService().clearPreferredDevicesForCapturePreset(capturePreset); + return status == AudioSystem.SUCCESS; + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + /** + * @hide + * Return the preferred devices for an audio capture preset, previously set with + * {@link #setPreferredDeviceForCapturePreset(int, AudioDeviceAttributes)} + * @param capturePreset the capture preset to query + * @return a list that contains preferred devices for that capture preset. + */ + @NonNull + @SystemApi + @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) + public List<AudioDeviceAttributes> getPreferredDevicesForCapturePreset(int capturePreset) { + if (!MediaRecorder.isValidAudioSource(capturePreset)) { + return new ArrayList<AudioDeviceAttributes>(); + } + try { + return getService().getPreferredDevicesForCapturePreset(capturePreset); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + private boolean setPreferredDevicesForCapturePreset( + int capturePreset, @NonNull List<AudioDeviceAttributes> devices) { + Objects.requireNonNull(devices); + if (!MediaRecorder.isValidAudioSource(capturePreset)) { + return false; + } + if (devices.size() != 1) { + throw new IllegalArgumentException( + "Only support setting one preferred devices for capture preset"); + } + for (AudioDeviceAttributes device : devices) { + Objects.requireNonNull(device); + } + try { + final int status = + getService().setPreferredDevicesForCapturePreset(capturePreset, devices); + return status == AudioSystem.SUCCESS; + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + /** + * @hide + * Interface to be notified of changes in the preferred audio devices set for a given capture + * preset. + * <p>Note that this listener will only be invoked whenever + * {@link #setPreferredDeviceForCapturePreset(int, AudioDeviceAttributes)} or + * {@link #clearPreferredDevicesForCapturePreset(int)} causes a change in + * preferred device. It will not be invoked directly after registration with + * {@link #addOnPreferredDevicesForCapturePresetChangedListener( + * Executor, OnPreferredDevicesForCapturePresetChangedListener)} + * to indicate which strategies had preferred devices at the time of registration.</p> + * @see #setPreferredDeviceForCapturePreset(int, AudioDeviceAttributes) + * @see #clearPreferredDevicesForCapturePreset(int) + * @see #getPreferredDevicesForCapturePreset(int) + */ + @SystemApi + public interface OnPreferredDevicesForCapturePresetChangedListener { + /** + * Called on the listener to indicate that the preferred audio devices for the given + * capture preset has changed. + * @param capturePreset the capture preset whose preferred device changed + * @param devices a list of newly set preferred audio devices + */ + void onPreferredDevicesForCapturePresetChanged( + int capturePreset, @NonNull List<AudioDeviceAttributes> devices); + } + + /** + * @hide + * Adds a listener for being notified of changes to the capture-preset-preferred audio device. + * @param executor + * @param listener + * @throws SecurityException if the caller doesn't hold the required permission + */ + @SystemApi + @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) + public void addOnPreferredDevicesForCapturePresetChangedListener( + @NonNull @CallbackExecutor Executor executor, + @NonNull OnPreferredDevicesForCapturePresetChangedListener listener) + throws SecurityException { + Objects.requireNonNull(executor); + Objects.requireNonNull(listener); + int status = addOnDevRoleForCapturePresetChangedListener( + executor, listener, AudioSystem.DEVICE_ROLE_PREFERRED); + if (status == AudioSystem.ERROR) { + // This must not happen + throw new RuntimeException("Unknown error happened"); + } + if (status == AudioSystem.BAD_VALUE) { + throw new IllegalArgumentException( + "attempt to call addOnPreferredDevicesForCapturePresetChangedListener() " + + "on a previously registered listener"); + } + } + + /** + * @hide + * Removes a previously added listener of changes to the capture-preset-preferred audio device. + * @param listener + */ + @SystemApi + @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) + public void removeOnPreferredDevicesForCapturePresetChangedListener( + @NonNull OnPreferredDevicesForCapturePresetChangedListener listener) { + Objects.requireNonNull(listener); + int status = removeOnDevRoleForCapturePresetChangedListener( + listener, AudioSystem.DEVICE_ROLE_PREFERRED); + if (status == AudioSystem.ERROR) { + // This must not happen + throw new RuntimeException("Unknown error happened"); + } + if (status == AudioSystem.BAD_VALUE) { + throw new IllegalArgumentException( + "attempt to call removeOnPreferredDevicesForCapturePresetChangedListener() " + + "on an unregistered listener"); + } + } + + private <T> int addOnDevRoleForCapturePresetChangedListener( + @NonNull @CallbackExecutor Executor executor, + @NonNull T listener, int deviceRole) { + Objects.requireNonNull(executor); + Objects.requireNonNull(listener); + DevRoleListeners<T> devRoleListeners = + (DevRoleListeners<T>) mDevRoleForCapturePresetListeners.get(deviceRole); + if (devRoleListeners == null) { + return AudioSystem.ERROR; + } + synchronized (devRoleListeners.mDevRoleListenersLock) { + if (devRoleListeners.hasDevRoleListener(listener)) { + return AudioSystem.BAD_VALUE; + } + // lazy initialization of the list of device role listener + if (devRoleListeners.mListenerInfos == null) { + devRoleListeners.mListenerInfos = new ArrayList<>(); + } + final int oldCbCount = devRoleListeners.mListenerInfos.size(); + devRoleListeners.mListenerInfos.add(new DevRoleListenerInfo<T>(executor, listener)); + if (oldCbCount == 0 && devRoleListeners.mListenerInfos.size() > 0) { + // register binder for callbacks + synchronized (mDevRoleForCapturePresetListenersLock) { + int deviceRoleListenerStatus = mDeviceRoleListenersStatus; + mDeviceRoleListenersStatus |= (1 << deviceRole); + if (deviceRoleListenerStatus != 0) { + // There are already device role changed listeners active. + return AudioSystem.SUCCESS; + } + if (mDevicesRoleForCapturePresetDispatcherStub == null) { + mDevicesRoleForCapturePresetDispatcherStub = + new CapturePresetDevicesRoleDispatcherStub(); + } + try { + getService().registerCapturePresetDevicesRoleDispatcher( + mDevicesRoleForCapturePresetDispatcherStub); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + } + } + return AudioSystem.SUCCESS; + } + + private <T> int removeOnDevRoleForCapturePresetChangedListener( + @NonNull T listener, int deviceRole) { + Objects.requireNonNull(listener); + DevRoleListeners<T> devRoleListeners = + (DevRoleListeners<T>) mDevRoleForCapturePresetListeners.get(deviceRole); + if (devRoleListeners == null) { + return AudioSystem.ERROR; + } + synchronized (devRoleListeners.mDevRoleListenersLock) { + if (!devRoleListeners.removeDevRoleListener(listener)) { + return AudioSystem.BAD_VALUE; + } + if (devRoleListeners.mListenerInfos.size() == 0) { + // unregister binder for callbacks + synchronized (mDevRoleForCapturePresetListenersLock) { + mDeviceRoleListenersStatus ^= (1 << deviceRole); + if (mDeviceRoleListenersStatus != 0) { + // There are some other device role changed listeners active. + return AudioSystem.SUCCESS; + } + try { + getService().unregisterCapturePresetDevicesRoleDispatcher( + mDevicesRoleForCapturePresetDispatcherStub); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + } + } + return AudioSystem.SUCCESS; + } + + private final Map<Integer, Object> mDevRoleForCapturePresetListeners = new HashMap<>(){{ + put(AudioSystem.DEVICE_ROLE_PREFERRED, + new DevRoleListeners<OnPreferredDevicesForCapturePresetChangedListener>()); + }}; + + private class DevRoleListenerInfo<T> { + final @NonNull Executor mExecutor; + final @NonNull T mListener; + DevRoleListenerInfo(Executor executor, T listener) { + mExecutor = executor; + mListener = listener; + } + } + + private class DevRoleListeners<T> { + private final Object mDevRoleListenersLock = new Object(); + @GuardedBy("mDevRoleListenersLock") + private @Nullable ArrayList<DevRoleListenerInfo<T>> mListenerInfos; + + @GuardedBy("mDevRoleListenersLock") + private @Nullable DevRoleListenerInfo<T> getDevRoleListenerInfo(T listener) { + if (mListenerInfos == null) { + return null; + } + for (DevRoleListenerInfo<T> listenerInfo : mListenerInfos) { + if (listenerInfo.mListener == listener) { + return listenerInfo; + } + } + return null; + } + + @GuardedBy("mDevRoleListenersLock") + private boolean hasDevRoleListener(T listener) { + return getDevRoleListenerInfo(listener) != null; + } + + @GuardedBy("mDevRoleListenersLock") + private boolean removeDevRoleListener(T listener) { + final DevRoleListenerInfo<T> infoToRemove = getDevRoleListenerInfo(listener); + if (infoToRemove != null) { + mListenerInfos.remove(infoToRemove); + return true; + } + return false; + } + } + + private final Object mDevRoleForCapturePresetListenersLock = new Object(); + /** + * Record if there is a listener added for device role change. If there is a listener added for + * a specified device role change, the bit at position `1 << device_role` is set. + */ + @GuardedBy("mDevRoleForCapturePresetListenersLock") + private int mDeviceRoleListenersStatus = 0; + @GuardedBy("mDevRoleForCapturePresetListenersLock") + private CapturePresetDevicesRoleDispatcherStub mDevicesRoleForCapturePresetDispatcherStub; + + private final class CapturePresetDevicesRoleDispatcherStub + extends ICapturePresetDevicesRoleDispatcher.Stub { + + @Override + public void dispatchDevicesRoleChanged( + int capturePreset, int role, List<AudioDeviceAttributes> devices) { + final Object listenersObj = mDevRoleForCapturePresetListeners.get(role); + if (listenersObj == null) { + return; + } + switch (role) { + case AudioSystem.DEVICE_ROLE_PREFERRED: { + final DevRoleListeners<OnPreferredDevicesForCapturePresetChangedListener> + listeners = + (DevRoleListeners<OnPreferredDevicesForCapturePresetChangedListener>) + listenersObj; + final ArrayList<DevRoleListenerInfo< + OnPreferredDevicesForCapturePresetChangedListener>> prefDevListeners; + synchronized (listeners.mDevRoleListenersLock) { + if (listeners.mListenerInfos.isEmpty()) { + return; + } + prefDevListeners = (ArrayList<DevRoleListenerInfo< + OnPreferredDevicesForCapturePresetChangedListener>>) + listeners.mListenerInfos.clone(); + } + final long ident = Binder.clearCallingIdentity(); + try { + for (DevRoleListenerInfo< + OnPreferredDevicesForCapturePresetChangedListener> info : + prefDevListeners) { + info.mExecutor.execute(() -> + info.mListener.onPreferredDevicesForCapturePresetChanged( + capturePreset, devices)); + } + } finally { + Binder.restoreCallingIdentity(ident); + } + } break; + default: + break; + } + } + } + + //==================================================================== // Offload query /** * Returns whether offloaded playback of an audio format is supported on the device. @@ -6306,6 +6649,132 @@ public class AudioManager { } } + /** + * Adjusts the volume of the most relevant stream, or the given fallback + * stream. + * <p> + * This method should only be used by applications that replace the + * platform-wide management of audio settings or the main telephony + * application. + * <p> + * This method has no effect if the device implements a fixed volume policy + * as indicated by {@link #isVolumeFixed()}. + * <p>This API checks if the caller has the necessary permissions based on the provided + * component name, uid, and pid values. + * See {@link #adjustSuggestedStreamVolume(int, int, int)}. + * + * @param suggestedStreamType The stream type that will be used if there + * isn't a relevant stream. {@link #USE_DEFAULT_STREAM_TYPE} is + * valid here. + * @param direction The direction to adjust the volume. One of + * {@link #ADJUST_LOWER}, {@link #ADJUST_RAISE}, + * {@link #ADJUST_SAME}, {@link #ADJUST_MUTE}, + * {@link #ADJUST_UNMUTE}, or {@link #ADJUST_TOGGLE_MUTE}. + * @param flags One or more flags. + * @param packageName the package name of client application + * @param uid the uid of client application + * @param pid the pid of client application + * @param targetSdkVersion the target sdk version of client application + * @see #adjustVolume(int, int) + * @see #adjustStreamVolume(int, int, int) + * @see #setStreamVolume(int, int, int) + * @see #isVolumeFixed() + * + * @hide + */ + @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) + public void adjustSuggestedStreamVolumeForUid(int suggestedStreamType, int direction, int flags, + @NonNull String packageName, int uid, int pid, int targetSdkVersion) { + try { + getService().adjustSuggestedStreamVolumeForUid(suggestedStreamType, direction, flags, + packageName, uid, pid, UserHandle.getUserHandleForUid(uid), targetSdkVersion); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + /** + * Adjusts the volume of a particular stream by one step in a direction. + * <p> + * This method should only be used by applications that replace the platform-wide + * management of audio settings or the main telephony application. + * <p>This method has no effect if the device implements a fixed volume policy + * as indicated by {@link #isVolumeFixed()}. + * <p>From N onward, ringer mode adjustments that would toggle Do Not Disturb are not allowed + * unless the app has been granted Do Not Disturb Access. + * See {@link NotificationManager#isNotificationPolicyAccessGranted()}. + * <p>This API checks if the caller has the necessary permissions based on the provided + * component name, uid, and pid values. + * See {@link #adjustStreamVolume(int, int, int)}. + * + * @param streamType The stream type to adjust. One of {@link #STREAM_VOICE_CALL}, + * {@link #STREAM_SYSTEM}, {@link #STREAM_RING}, {@link #STREAM_MUSIC}, + * {@link #STREAM_ALARM} or {@link #STREAM_ACCESSIBILITY}. + * @param direction The direction to adjust the volume. One of + * {@link #ADJUST_LOWER}, {@link #ADJUST_RAISE}, or + * {@link #ADJUST_SAME}. + * @param flags One or more flags. + * @param packageName the package name of client application + * @param uid the uid of client application + * @param pid the pid of client application + * @param targetSdkVersion the target sdk version of client application + * @see #adjustVolume(int, int) + * @see #setStreamVolume(int, int, int) + * @throws SecurityException if the adjustment triggers a Do Not Disturb change + * and the caller is not granted notification policy access. + * + * @hide + */ + @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) + public void adjustStreamVolumeForUid(int streamType, int direction, int flags, + @NonNull String packageName, int uid, int pid, int targetSdkVersion) { + try { + getService().adjustStreamVolumeForUid(streamType, direction, flags, packageName, uid, + pid, UserHandle.getUserHandleForUid(uid), targetSdkVersion); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + /** + * Sets the volume index for a particular stream. + * <p>This method has no effect if the device implements a fixed volume policy + * as indicated by {@link #isVolumeFixed()}. + * <p>From N onward, volume adjustments that would toggle Do Not Disturb are not allowed unless + * the app has been granted Do Not Disturb Access. + * See {@link NotificationManager#isNotificationPolicyAccessGranted()}. + * <p>This API checks if the caller has the necessary permissions based on the provided + * component name, uid, and pid values. + * See {@link #setStreamVolume(int, int, int)}. + * + * @param streamType The stream whose volume index should be set. + * @param index The volume index to set. See + * {@link #getStreamMaxVolume(int)} for the largest valid value. + * @param flags One or more flags. + * @param packageName the package name of client application + * @param uid the uid of client application + * @param pid the pid of client application + * @param targetSdkVersion the target sdk version of client application + * @see #getStreamMaxVolume(int) + * @see #getStreamVolume(int) + * @see #isVolumeFixed() + * @throws SecurityException if the volume change triggers a Do Not Disturb change + * and the caller is not granted notification policy access. + * + * @hide + */ + @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) + public void setStreamVolumeForUid(int streamType, int index, int flags, + @NonNull String packageName, int uid, int pid, int targetSdkVersion) { + try { + getService().setStreamVolumeForUid(streamType, index, flags, packageName, uid, pid, + UserHandle.getUserHandleForUid(uid), targetSdkVersion); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + /** @hide * TODO: make this a @SystemApi */ @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) diff --git a/media/java/android/media/AudioManagerInternal.java b/media/java/android/media/AudioManagerInternal.java index b44d7bba834f..c827932194ae 100644 --- a/media/java/android/media/AudioManagerInternal.java +++ b/media/java/android/media/AudioManagerInternal.java @@ -28,15 +28,6 @@ import com.android.server.LocalServices; */ public abstract class AudioManagerInternal { - public abstract void adjustSuggestedStreamVolumeForUid(int streamType, int direction, - int flags, String callingPackage, int uid, int pid); - - public abstract void adjustStreamVolumeForUid(int streamType, int direction, int flags, - String callingPackage, int uid, int pid); - - public abstract void setStreamVolumeForUid(int streamType, int direction, int flags, - String callingPackage, int uid, int pid); - public abstract void setRingerModeDelegate(RingerModeDelegate delegate); public abstract int getRingerModeInternal(); diff --git a/media/java/android/media/AudioSystem.java b/media/java/android/media/AudioSystem.java index 22f625004aaf..279ba0a55be0 100644 --- a/media/java/android/media/AudioSystem.java +++ b/media/java/android/media/AudioSystem.java @@ -27,6 +27,7 @@ import android.media.audiofx.AudioEffect; import android.media.audiopolicy.AudioMix; import android.telephony.TelephonyManager; import android.util.Log; +import android.util.Pair; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; @@ -1755,6 +1756,134 @@ public class AudioSystem public static native int getDevicesForRoleAndStrategy( int strategy, int role, @NonNull List<AudioDeviceAttributes> devices); + // use case routing by capture preset + + private static Pair<int[], String[]> populateInputDevicesTypeAndAddress( + @NonNull List<AudioDeviceAttributes> devices) { + int[] types = new int[devices.size()]; + String[] addresses = new String[devices.size()]; + for (int i = 0; i < devices.size(); ++i) { + types[i] = devices.get(i).getInternalType(); + if (types[i] == AudioSystem.DEVICE_NONE) { + types[i] = AudioDeviceInfo.convertDeviceTypeToInternalInputDevice( + devices.get(i).getType()); + } + addresses[i] = devices.get(i).getAddress(); + } + return new Pair<int[], String[]>(types, addresses); + } + + /** + * @hide + * Set devices as role for capture preset. + * @param capturePreset the capture preset to configure + * @param role the role of the devices + * @param devices the list of devices to be set as role for the given capture preset + * @return {@link #SUCCESS} if successfully set + */ + public static int setDevicesRoleForCapturePreset( + int capturePreset, int role, @NonNull List<AudioDeviceAttributes> devices) { + if (devices.isEmpty()) { + return BAD_VALUE; + } + Pair<int[], String[]> typeAddresses = populateInputDevicesTypeAndAddress(devices); + return setDevicesRoleForCapturePreset( + capturePreset, role, typeAddresses.first, typeAddresses.second); + } + + /** + * @hide + * Set devices as role for capture preset. + * @param capturePreset the capture preset to configure + * @param role the role of the devices + * @param types all device types + * @param addresses all device addresses + * @return {@link #SUCCESS} if successfully set + */ + private static native int setDevicesRoleForCapturePreset( + int capturePreset, int role, @NonNull int[] types, @NonNull String[] addresses); + + /** + * @hide + * Add devices as role for capture preset. + * @param capturePreset the capture preset to configure + * @param role the role of the devices + * @param devices the list of devices to be added as role for the given capture preset + * @return {@link #SUCCESS} if successfully add + */ + public static int addDevicesRoleForCapturePreset( + int capturePreset, int role, @NonNull List<AudioDeviceAttributes> devices) { + if (devices.isEmpty()) { + return BAD_VALUE; + } + Pair<int[], String[]> typeAddresses = populateInputDevicesTypeAndAddress(devices); + return addDevicesRoleForCapturePreset( + capturePreset, role, typeAddresses.first, typeAddresses.second); + } + + /** + * @hide + * Add devices as role for capture preset. + * @param capturePreset the capture preset to configure + * @param role the role of the devices + * @param types all device types + * @param addresses all device addresses + * @return {@link #SUCCESS} if successfully set + */ + private static native int addDevicesRoleForCapturePreset( + int capturePreset, int role, @NonNull int[] types, @NonNull String[] addresses); + + /** + * @hide + * Remove devices as role for the capture preset + * @param capturePreset the capture preset to configure + * @param role the role of the devices + * @param devices the devices to be removed + * @return {@link #SUCCESS} if successfully removed + */ + public static int removeDevicesRoleForCapturePreset( + int capturePreset, int role, @NonNull List<AudioDeviceAttributes> devices) { + if (devices.isEmpty()) { + return BAD_VALUE; + } + Pair<int[], String[]> typeAddresses = populateInputDevicesTypeAndAddress(devices); + return removeDevicesRoleForCapturePreset( + capturePreset, role, typeAddresses.first, typeAddresses.second); + } + + /** + * @hide + * Remove devices as role for capture preset. + * @param capturePreset the capture preset to configure + * @param role the role of the devices + * @param types all device types + * @param addresses all device addresses + * @return {@link #SUCCESS} if successfully set + */ + private static native int removeDevicesRoleForCapturePreset( + int capturePreset, int role, @NonNull int[] types, @NonNull String[] addresses); + + /** + * @hide + * Remove all devices as role for the capture preset + * @param capturePreset the capture preset to configure + * @param role the role of the devices + * @return {@link #SUCCESS} if successfully removed + */ + public static native int clearDevicesRoleForCapturePreset(int capturePreset, int role); + + /** + * @hide + * Query previously set devices as role for a capture preset + * @param capturePreset the capture preset to query for + * @param role the role of the devices + * @param devices a list that will contain the devices of role + * @return {@link #SUCCESS} if there is a preferred device and it was successfully retrieved + * and written to the array + */ + public static native int getDevicesForRoleAndCapturePreset( + int capturePreset, int role, @NonNull List<AudioDeviceAttributes> devices); + // Items shared with audio service /** diff --git a/media/java/android/media/IAudioService.aidl b/media/java/android/media/IAudioService.aidl index ef8b0edb1fe5..47e60000cd04 100755 --- a/media/java/android/media/IAudioService.aidl +++ b/media/java/android/media/IAudioService.aidl @@ -17,6 +17,7 @@ package android.media; import android.bluetooth.BluetoothDevice; +import android.content.ComponentName; import android.media.AudioAttributes; import android.media.AudioDeviceAttributes; import android.media.AudioFocusInfo; @@ -26,6 +27,7 @@ import android.media.AudioRoutesInfo; import android.media.IAudioFocusDispatcher; import android.media.IAudioRoutesObserver; import android.media.IAudioServerStateDispatcher; +import android.media.ICapturePresetDevicesRoleDispatcher; import android.media.IPlaybackConfigDispatcher; import android.media.IRecordingConfigDispatcher; import android.media.IRingtonePlayer; @@ -40,6 +42,7 @@ import android.media.audiopolicy.AudioVolumeGroup; import android.media.audiopolicy.IAudioPolicyCallback; import android.media.projection.IMediaProjection; import android.net.Uri; +import android.os.UserHandle; import android.view.KeyEvent; /** @@ -307,4 +310,28 @@ interface IAudioService { // code via IAudioManager.h need to be added to the top section. oneway void setMultiAudioFocusEnabled(in boolean enabled); + + int setPreferredDevicesForCapturePreset( + in int capturePreset, in List<AudioDeviceAttributes> devices); + + int clearPreferredDevicesForCapturePreset(in int capturePreset); + + List<AudioDeviceAttributes> getPreferredDevicesForCapturePreset(in int capturePreset); + + void registerCapturePresetDevicesRoleDispatcher(ICapturePresetDevicesRoleDispatcher dispatcher); + + oneway void unregisterCapturePresetDevicesRoleDispatcher( + ICapturePresetDevicesRoleDispatcher dispatcher); + + oneway void adjustStreamVolumeForUid(int streamType, int direction, int flags, + in String packageName, int uid, int pid, in UserHandle userHandle, + int targetSdkVersion); + + oneway void adjustSuggestedStreamVolumeForUid(int streamType, int direction, int flags, + in String packageName, int uid, int pid, in UserHandle userHandle, + int targetSdkVersion); + + oneway void setStreamVolumeForUid(int streamType, int direction, int flags, + in String packageName, int uid, int pid, in UserHandle userHandle, + int targetSdkVersion); } diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/FlickerAppHelper.kt b/media/java/android/media/ICapturePresetDevicesRoleDispatcher.aidl index 71475774343a..5e03e632c4ff 100644 --- a/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/FlickerAppHelper.kt +++ b/media/java/android/media/ICapturePresetDevicesRoleDispatcher.aidl @@ -14,18 +14,18 @@ * limitations under the License. */ -package com.android.server.wm.flicker.helpers +package android.media; -import android.app.Instrumentation -import android.support.test.launcherhelper.ILauncherStrategy -import com.android.server.wm.flicker.StandardAppHelper +import android.media.AudioDeviceAttributes; + +/** + * AIDL for AudioService to signal devices role for capture preset updates. + * + * {@hide} + */ +oneway interface ICapturePresetDevicesRoleDispatcher { + + void dispatchDevicesRoleChanged( + int capturePreset, int role, in List<AudioDeviceAttributes> devices); -abstract class FlickerAppHelper( - instr: Instrumentation, - launcherName: String, - launcherStrategy: ILauncherStrategy -) : StandardAppHelper(instr, sFlickerPackage, launcherName, launcherStrategy) { - companion object { - var sFlickerPackage = "com.android.server.wm.flicker.testapp" - } } diff --git a/media/java/android/media/MediaMetadata.java b/media/java/android/media/MediaMetadata.java index a23191f36efc..523a072b957a 100644 --- a/media/java/android/media/MediaMetadata.java +++ b/media/java/android/media/MediaMetadata.java @@ -15,8 +15,10 @@ */ package android.media; +import android.annotation.IntRange; import android.annotation.NonNull; import android.annotation.StringDef; +import android.annotation.SystemApi; import android.compat.annotation.UnsupportedAppUsage; import android.content.ContentResolver; import android.graphics.Bitmap; @@ -738,15 +740,16 @@ public final class MediaMetadata implements Parcelable { /** * Create a Builder using a {@link MediaMetadata} instance to set - * initial values, but replace bitmaps with a scaled down copy if they - * are larger than maxBitmapSize. + * initial values, but replace bitmaps with a scaled down copy if their width (or height) + * is larger than maxBitmapSize. * * @param source The original metadata to copy. * @param maxBitmapSize The maximum height/width for bitmaps contained * in the metadata. * @hide */ - public Builder(MediaMetadata source, int maxBitmapSize) { + @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) + public Builder(@NonNull MediaMetadata source, @IntRange(from = 1) int maxBitmapSize) { this(source); for (String key : mBundle.keySet()) { Object value = mBundle.get(key); diff --git a/media/java/android/media/MediaRecorder.java b/media/java/android/media/MediaRecorder.java index 4198d7917932..1db02beaea1a 100644 --- a/media/java/android/media/MediaRecorder.java +++ b/media/java/android/media/MediaRecorder.java @@ -404,6 +404,32 @@ public class MediaRecorder implements AudioRouting, } } + /** + * @hide + * @param source An audio source to test + * @return true if the source is a valid one + */ + public static boolean isValidAudioSource(int source) { + switch(source) { + case AudioSource.MIC: + case AudioSource.VOICE_UPLINK: + case AudioSource.VOICE_DOWNLINK: + case AudioSource.VOICE_CALL: + case AudioSource.CAMCORDER: + case AudioSource.VOICE_RECOGNITION: + case AudioSource.VOICE_COMMUNICATION: + case AudioSource.REMOTE_SUBMIX: + case AudioSource.UNPROCESSED: + case AudioSource.VOICE_PERFORMANCE: + case AudioSource.ECHO_REFERENCE: + case AudioSource.RADIO_TUNER: + case AudioSource.HOTWORD: + return true; + default: + return false; + } + } + /** @hide */ public static final String toLogFriendlyAudioSource(int source) { switch(source) { diff --git a/media/java/android/media/MediaTranscodeManager.java b/media/java/android/media/MediaTranscodeManager.java index cf61152c4775..451677f6a8bc 100644 --- a/media/java/android/media/MediaTranscodeManager.java +++ b/media/java/android/media/MediaTranscodeManager.java @@ -27,6 +27,7 @@ import android.content.ContentResolver; import android.content.Context; import android.content.res.AssetFileDescriptor; import android.net.Uri; +import android.os.Bundle; import android.os.ParcelFileDescriptor; import android.os.RemoteException; import android.os.ServiceManager; @@ -102,7 +103,7 @@ import java.util.concurrent.Executors; */ @TestApi @SystemApi -public final class MediaTranscodeManager implements AutoCloseable { +public final class MediaTranscodeManager { private static final String TAG = "MediaTranscodeManager"; private static final String MEDIA_TRANSCODING_SERVICE = "media.transcoding"; @@ -131,28 +132,6 @@ public final class MediaTranscodeManager implements AutoCloseable { */ public static final int TRANSCODING_TYPE_IMAGE = 2; - @Override - public void close() { - release(); - } - - /** - * Releases the MediaTranscodeManager. - */ - private void release() { - synchronized (mLock) { - try { - if (mTranscodingClient != null) { - mTranscodingClient.unregister(); - } - } catch (Exception ex) { - Log.e(TAG, "Failed to unregister the client"); - } finally { - mTranscodingClient = null; - } - } - } - /** @hide */ @IntDef(prefix = {"TRANSCODING_TYPE_"}, value = { TRANSCODING_TYPE_UNKNOWN, @@ -182,6 +161,7 @@ public final class MediaTranscodeManager implements AutoCloseable { * <p>Jobs with PRIORITY_OFFLINE will be scheduled behind PRIORITY_REALTIME. Always set to * PRIORITY_OFFLINE if client does not need the result as soon as possible and could accept * delay of the transcoding result. + * @hide * TODO(hkuang): Add more description of this when priority is finalized. */ public static final int PRIORITY_OFFLINE = 2; @@ -287,7 +267,7 @@ public final class MediaTranscodeManager implements AutoCloseable { // Notifies client the progress update. if (job.mProgressUpdateExecutor != null && job.mProgressUpdateListener != null) { job.mProgressUpdateExecutor.execute( - () -> job.mProgressUpdateListener.onProgressUpdate(newProgress)); + () -> job.mProgressUpdateListener.onProgressUpdate(job, newProgress)); } } } @@ -503,11 +483,6 @@ public final class MediaTranscodeManager implements AutoCloseable { mTranscodingClient = registerClient(service); } - @Override - protected void finalize() { - release(); - } - public static final class TranscodingRequest { /** Uri of the source media file. */ private @NonNull Uri mSourceUri; @@ -840,6 +815,141 @@ public final class MediaTranscodeManager implements AutoCloseable { return new TranscodingRequest(this); } } + + /** + * Helper class for deciding if transcoding is needed, and if so, the track + * formats to use. + */ + public static class MediaFormatResolver { + private static final int BIT_RATE = 20000000; // 20Mbps + + private MediaFormat mSrcVideoFormatHint; + private MediaFormat mSrcAudioFormatHint; + private Bundle mClientCaps; + + /** + * A key describing whether the client supports HEVC-encoded video. + * + * The value associated with this key is a boolean. If unspecified, it's up to + * the MediaFormatResolver to determine the default. + * + * @see #setClientCapabilities(Bundle) + */ + public static final String CAPS_SUPPORTS_HEVC = "support-hevc"; + + /** + * Sets the abilities of the client consuming the media. Must be called + * before {@link #shouldTranscode()} or {@link #resolveVideoFormat()}. + * + * @param clientCaps A Bundle object containing the client's capabilities, such as + * {@link #CAPS_SUPPORTS_HEVC}. + * @return the same VideoFormatResolver instance. + * @hide + */ + @NonNull + public MediaFormatResolver setClientCapabilities(@NonNull Bundle clientCaps) { + mClientCaps = clientCaps; + return this; + } + + /** + * Sets the video format hint about the source. Must be called before + * {@link #shouldTranscode()} or {@link #resolveVideoFormat()}. + * + * @param format A MediaFormat object containing information about the source's + * video track format that could affect the transcoding decision. + * Such information could include video codec types, color spaces, + * whether special format info (eg. slow-motion markers) are present, + * etc.. If a particular information is not present, it will not be + * used to make the decision. + * @return the same MediaFormatResolver instance. + */ + @NonNull + public MediaFormatResolver setSourceVideoFormatHint(@NonNull MediaFormat format) { + mSrcVideoFormatHint = format; + return this; + } + + /** + * Sets the audio format hint about the source. + * + * @param format A MediaFormat object containing information about the source's + * audio track format that could affect the transcoding decision. + * @return the same MediaFormatResolver instance. + * @hide + */ + @NonNull + public MediaFormatResolver setSourceAudioFormatHint(@NonNull MediaFormat format) { + mSrcAudioFormatHint = format; + return this; + } + + /** + * Returns whether the source content should be transcoded. + * + * @return true if the source should be transcoded. + * @throws UnsupportedOperationException if {@link #setClientCapabilities(Bundle)} + * or {@link #setSourceVideoFormatHint(MediaFormat)} was not called. + */ + public boolean shouldTranscode() { + if (mClientCaps == null) { + throw new UnsupportedOperationException( + "Client caps must be set!"); + } + // Video src hint must be provided, audio src hint is not used right now. + if (mSrcVideoFormatHint == null) { + throw new UnsupportedOperationException( + "Source video format hint must be set!"); + } + boolean supportHevc = mClientCaps.getBoolean(CAPS_SUPPORTS_HEVC, false); + if (!supportHevc && MediaFormat.MIMETYPE_VIDEO_HEVC.equals( + mSrcVideoFormatHint.getString(MediaFormat.KEY_MIME))) { + return true; + } + // TODO: add more checks as needed below. + return false; + } + + /** + * Retrieves the video track format to be used on + * {@link Builder#setVideoTrackFormat(MediaFormat)} for this configuration. + * + * @return the video track format to be used if transcoding should be performed, + * and null otherwise. + * @throws UnsupportedOperationException if {@link #setClientCapabilities(Bundle)} + * or {@link #setSourceVideoFormatHint(MediaFormat)} was not called. + */ + @Nullable + public MediaFormat resolveVideoFormat() { + if (!shouldTranscode()) { + return null; + } + // TODO(hkuang): Only modified the video codec type, and use fixed bitrate for now. + // May switch to transcoding profile when it's available. + MediaFormat videoTrackFormat = new MediaFormat(mSrcVideoFormatHint); + videoTrackFormat.setString(MediaFormat.KEY_MIME, MediaFormat.MIMETYPE_VIDEO_AVC); + videoTrackFormat.setInteger(MediaFormat.KEY_BIT_RATE, BIT_RATE); + return videoTrackFormat; + } + + /** + * Retrieves the audio track format to be used for transcoding. + * + * @return the audio track format to be used if transcoding should be performed, and + * null otherwise. + * @throws UnsupportedOperationException if {@link #setClientCapabilities(Bundle)} + * or {@link #setSourceVideoFormatHint(MediaFormat)} was not called. + * @hide + */ + @Nullable + public MediaFormat resolveAudioFormat() { + if (!shouldTranscode()) { + return null; + } + // Audio transcoding is not supported yet, always return null. + return null; + } + } } /** @@ -892,9 +1002,12 @@ public final class MediaTranscodeManager implements AutoCloseable { /** * Called when the progress changes. The progress is in percentage between 0 and 1, * where 0 means that the job has not yet started and 100 means that it has finished. + * + * @param job The job associated with the progress. * @param progress The new progress ranging from 0 ~ 100 inclusive. */ - void onProgressUpdate(@IntRange(from = 0, to = 100) int progress); + void onProgressUpdate(@NonNull TranscodingJob job, + @IntRange(from = 0, to = 100) int progress); } private final ITranscodingClient mJobOwner; diff --git a/media/java/android/media/session/MediaController.java b/media/java/android/media/session/MediaController.java index aa57233bc824..24dacc48f28e 100644 --- a/media/java/android/media/session/MediaController.java +++ b/media/java/android/media/session/MediaController.java @@ -16,8 +16,11 @@ package android.media.session; +import android.annotation.IntDef; +import android.annotation.IntRange; import android.annotation.NonNull; import android.annotation.Nullable; +import android.annotation.SystemApi; import android.app.PendingIntent; import android.compat.annotation.UnsupportedAppUsage; import android.content.Context; @@ -27,6 +30,7 @@ import android.media.AudioManager; import android.media.MediaMetadata; import android.media.Rating; import android.media.VolumeProvider; +import android.media.VolumeProvider.ControlType; import android.media.session.MediaSession.QueueItem; import android.net.Uri; import android.os.Bundle; @@ -41,6 +45,8 @@ import android.text.TextUtils; import android.util.Log; import android.view.KeyEvent; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; import java.lang.ref.WeakReference; import java.util.ArrayList; import java.util.List; @@ -950,6 +956,14 @@ public final class MediaController { * this session. */ public static final class PlaybackInfo implements Parcelable { + + /** + * @hide + */ + @IntDef({PLAYBACK_TYPE_LOCAL, PLAYBACK_TYPE_REMOTE}) + @Retention(RetentionPolicy.SOURCE) + public @interface PlaybackType {} + /** * The session uses local playback. */ @@ -959,7 +973,7 @@ public final class MediaController { */ public static final int PLAYBACK_TYPE_REMOTE = 2; - private final int mVolumeType; + private final int mPlaybackType; private final int mVolumeControl; private final int mMaxVolume; private final int mCurrentVolume; @@ -967,27 +981,35 @@ public final class MediaController { private final String mVolumeControlId; /** + * Creates a new playback info. + * + * @param playbackType The playback type. Should be {@link #PLAYBACK_TYPE_LOCAL} or + * {@link #PLAYBACK_TYPE_REMOTE} + * @param volumeControl The volume control. Should be one of: + * {@link VolumeProvider#VOLUME_CONTROL_ABSOLUTE}, + * {@link VolumeProvider#VOLUME_CONTROL_RELATIVE}, and + * {@link VolumeProvider#VOLUME_CONTROL_FIXED}. + * @param maxVolume The max volume. Should be equal or greater than zero. + * @param currentVolume The current volume. Should be in the interval [0, maxVolume]. + * @param audioAttrs The audio attributes for this playback. Should not be null. + * @param volumeControlId The volume control ID. This is used for matching + * {@link RoutingSessionInfo} and {@link MediaSession}. * @hide */ - public PlaybackInfo(int type, int control, int max, int current, AudioAttributes attrs) { - this(type, control, max, current, attrs, null); - } - - /** - * @hide - */ - public PlaybackInfo(int type, int control, int max, int current, AudioAttributes attrs, - String volumeControlId) { - mVolumeType = type; - mVolumeControl = control; - mMaxVolume = max; - mCurrentVolume = current; - mAudioAttrs = attrs; + @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) + public PlaybackInfo(@PlaybackType int playbackType, @ControlType int volumeControl, + @IntRange(from = 0) int maxVolume, @IntRange(from = 0) int currentVolume, + @NonNull AudioAttributes audioAttrs, @Nullable String volumeControlId) { + mPlaybackType = playbackType; + mVolumeControl = volumeControl; + mMaxVolume = maxVolume; + mCurrentVolume = currentVolume; + mAudioAttrs = audioAttrs; mVolumeControlId = volumeControlId; } PlaybackInfo(Parcel in) { - mVolumeType = in.readInt(); + mPlaybackType = in.readInt(); mVolumeControl = in.readInt(); mMaxVolume = in.readInt(); mCurrentVolume = in.readInt(); @@ -1005,7 +1027,7 @@ public final class MediaController { * @return The type of playback this session is using. */ public int getPlaybackType() { - return mVolumeType; + return mPlaybackType; } /** @@ -1016,8 +1038,7 @@ public final class MediaController { * <li>{@link VolumeProvider#VOLUME_CONTROL_FIXED}</li> * </ul> * - * @return The type of volume control that may be used with this - * session. + * @return The type of volume control that may be used with this session. */ public int getVolumeControl() { return mVolumeControl; @@ -1075,7 +1096,7 @@ public final class MediaController { @Override public String toString() { - return "volumeType=" + mVolumeType + ", volumeControl=" + mVolumeControl + return "playbackType=" + mPlaybackType + ", volumeControlType=" + mVolumeControl + ", maxVolume=" + mMaxVolume + ", currentVolume=" + mCurrentVolume + ", audioAttrs=" + mAudioAttrs + ", volumeControlId=" + mVolumeControlId; } @@ -1087,7 +1108,7 @@ public final class MediaController { @Override public void writeToParcel(Parcel dest, int flags) { - dest.writeInt(mVolumeType); + dest.writeInt(mPlaybackType); dest.writeInt(mVolumeControl); dest.writeInt(mMaxVolume); dest.writeInt(mCurrentVolume); diff --git a/media/java/android/media/session/MediaSession.java b/media/java/android/media/session/MediaSession.java index 549e79353133..624607b61b8f 100644 --- a/media/java/android/media/session/MediaSession.java +++ b/media/java/android/media/session/MediaSession.java @@ -828,9 +828,10 @@ public final class MediaSession { } /** - * Gets the UID of this token. + * Gets the UID of the application that created the media session. * @hide */ + @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) public int getUid() { return mUid; } diff --git a/media/tests/MediaTranscodingTest/src/com/android/mediatranscodingtest/MediaTranscodeManagerDiedTest.java b/media/tests/MediaTranscodingTest/src/com/android/mediatranscodingtest/MediaTranscodeManagerDiedTest.java index 6ea573ea7d3c..f00c14d79bec 100644 --- a/media/tests/MediaTranscodingTest/src/com/android/mediatranscodingtest/MediaTranscodeManagerDiedTest.java +++ b/media/tests/MediaTranscodingTest/src/com/android/mediatranscodingtest/MediaTranscodeManagerDiedTest.java @@ -231,7 +231,7 @@ public class MediaTranscodeManagerDiedTest job.setOnProgressUpdateListener(listenerExecutor, new TranscodingJob.OnProgressUpdateListener() { @Override - public void onProgressUpdate(int newProgress) { + public void onProgressUpdate(TranscodingJob job, int newProgress) { if (newProgress > 0) { jobStartedSemaphore.release(); } diff --git a/media/tests/MediaTranscodingTest/src/com/android/mediatranscodingtest/MediaTranscodeManagerTest.java b/media/tests/MediaTranscodingTest/src/com/android/mediatranscodingtest/MediaTranscodeManagerTest.java index a54655d16dd3..33d6d64c7f37 100644 --- a/media/tests/MediaTranscodingTest/src/com/android/mediatranscodingtest/MediaTranscodeManagerTest.java +++ b/media/tests/MediaTranscodingTest/src/com/android/mediatranscodingtest/MediaTranscodeManagerTest.java @@ -24,6 +24,7 @@ import android.media.MediaFormat; import android.media.MediaTranscodeManager; import android.media.MediaTranscodeManager.TranscodingJob; import android.media.MediaTranscodeManager.TranscodingRequest; +import android.media.MediaTranscodeManager.TranscodingRequest.MediaFormatResolver; import android.media.TranscodingTestConfig; import android.net.Uri; import android.os.Bundle; @@ -414,17 +415,27 @@ public class MediaTranscodeManagerTest Uri destinationUri = Uri.parse(ContentResolver.SCHEME_FILE + "://" + mContext.getCacheDir().getAbsolutePath() + "/HevcTranscode.mp4"); + Bundle clientCaps = new Bundle(); + clientCaps.putBoolean(MediaFormatResolver.CAPS_SUPPORTS_HEVC, false); + MediaFormatResolver resolver = new MediaFormatResolver() + .setSourceVideoFormatHint(MediaFormat.createVideoFormat( + MediaFormat.MIMETYPE_VIDEO_HEVC, WIDTH, HEIGHT)) + .setClientCapabilities(clientCaps); + assertTrue(resolver.shouldTranscode()); + MediaFormat videoTrackFormat = resolver.resolveVideoFormat(); + assertNotNull(videoTrackFormat); + TranscodingRequest request = new TranscodingRequest.Builder() .setSourceUri(mSourceHEVCVideoUri) .setDestinationUri(destinationUri) .setType(MediaTranscodeManager.TRANSCODING_TYPE_VIDEO) .setPriority(MediaTranscodeManager.PRIORITY_REALTIME) - .setVideoTrackFormat(createMediaFormat()) + .setVideoTrackFormat(videoTrackFormat) .build(); Executor listenerExecutor = Executors.newSingleThreadExecutor(); - Log.i(TAG, "transcoding to " + createMediaFormat()); + Log.i(TAG, "transcoding to " + videoTrackFormat); TranscodingJob job = mMediaTranscodeManager.enqueueRequest(request, listenerExecutor, transcodingJob -> { @@ -532,7 +543,7 @@ public class MediaTranscodeManagerTest int mPreviousProgress = 0; @Override - public void onProgressUpdate(int newProgress) { + public void onProgressUpdate(TranscodingJob job, int newProgress) { assertTrue("Invalid proress update", newProgress > mPreviousProgress); assertTrue("Invalid proress update", newProgress <= 100); if (newProgress > 0) { diff --git a/non-updatable-api/current.txt b/non-updatable-api/current.txt index e1b3151acd5b..bb40e24a68ac 100644 --- a/non-updatable-api/current.txt +++ b/non-updatable-api/current.txt @@ -1005,7 +1005,7 @@ package android { field public static final int numericModifiers = 16844111; // 0x101054f field public static final int numericShortcut = 16843236; // 0x10101e4 field public static final int offset = 16844052; // 0x1010514 - field public static final int onClick = 16843375; // 0x101026f + field @Deprecated public static final int onClick = 16843375; // 0x101026f field public static final int oneshot = 16843159; // 0x1010197 field public static final int opacity = 16843550; // 0x101031e field public static final int opticalInsetBottom = 16844171; // 0x101058b @@ -6188,6 +6188,7 @@ package android.app { method public android.app.PictureInPictureParams build(); method public android.app.PictureInPictureParams.Builder setActions(java.util.List<android.app.RemoteAction>); method public android.app.PictureInPictureParams.Builder setAspectRatio(android.util.Rational); + method @NonNull public android.app.PictureInPictureParams.Builder setAutoEnterAllowed(boolean); method public android.app.PictureInPictureParams.Builder setSourceRectHint(android.graphics.Rect); } @@ -46546,7 +46547,8 @@ package android.telephony { method public boolean isVoiceCapable(); method public boolean isVoicemailVibrationEnabled(android.telecom.PhoneAccountHandle); method public boolean isWorldPhone(); - method public void listen(android.telephony.PhoneStateListener, int); + method @Deprecated public void listen(android.telephony.PhoneStateListener, int); + method public void listen(long, @NonNull android.telephony.PhoneStateListener); method @RequiresPermission(android.Manifest.permission.ACCESS_FINE_LOCATION) public void requestCellInfoUpdate(@NonNull java.util.concurrent.Executor, @NonNull android.telephony.TelephonyManager.CellInfoCallback); method @RequiresPermission(allOf={android.Manifest.permission.MODIFY_PHONE_STATE, android.Manifest.permission.ACCESS_FINE_LOCATION}) public android.telephony.NetworkScan requestNetworkScan(android.telephony.NetworkScanRequest, java.util.concurrent.Executor, android.telephony.TelephonyScanManager.NetworkScanCallback); method public void sendDialerSpecialCode(String); diff --git a/non-updatable-api/module-lib-current.txt b/non-updatable-api/module-lib-current.txt index 8892a2954afb..f7f42d0a5956 100644 --- a/non-updatable-api/module-lib-current.txt +++ b/non-updatable-api/module-lib-current.txt @@ -35,17 +35,32 @@ package android.graphics { package android.media { public class AudioManager { + method public void adjustStreamVolumeForUid(int, int, int, @NonNull String, int, int, int); + method public void adjustSuggestedStreamVolumeForUid(int, int, int, @NonNull String, int, int, int); + method public void setStreamVolumeForUid(int, int, int, @NonNull String, int, int, int); field public static final int FLAG_FROM_KEY = 4096; // 0x1000 } + public static final class MediaMetadata.Builder { + ctor public MediaMetadata.Builder(@NonNull android.media.MediaMetadata, @IntRange(from=1) int); + } + } package android.media.session { + public static final class MediaController.PlaybackInfo implements android.os.Parcelable { + ctor public MediaController.PlaybackInfo(int, int, @IntRange(from=0) int, @IntRange(from=0) int, @NonNull android.media.AudioAttributes, @Nullable String); + } + public final class MediaSession { field public static final int FLAG_EXCLUSIVE_GLOBAL_PRIORITY = 65536; // 0x10000 } + public static final class MediaSession.Token implements android.os.Parcelable { + method public int getUid(); + } + public final class MediaSessionManager { method public void dispatchMediaKeyEventAsSystemService(@NonNull android.view.KeyEvent); method public boolean dispatchMediaKeyEventAsSystemService(@NonNull android.media.session.MediaSession.Token, @NonNull android.view.KeyEvent); @@ -84,6 +99,14 @@ package android.os { } +package android.provider { + + public final class DeviceConfig { + field public static final String NAMESPACE_DEVICE_IDLE = "device_idle"; + } + +} + package android.util { public class AtomicFile { diff --git a/non-updatable-api/system-current.txt b/non-updatable-api/system-current.txt index f64be2b1ff03..b807d1be6bf0 100644 --- a/non-updatable-api/system-current.txt +++ b/non-updatable-api/system-current.txt @@ -205,6 +205,7 @@ package android { field public static final String REVOKE_RUNTIME_PERMISSIONS = "android.permission.REVOKE_RUNTIME_PERMISSIONS"; field public static final String SCORE_NETWORKS = "android.permission.SCORE_NETWORKS"; field public static final String SECURE_ELEMENT_PRIVILEGED_OPERATION = "android.permission.SECURE_ELEMENT_PRIVILEGED_OPERATION"; + field public static final String SEND_CATEGORY_CAR_NOTIFICATIONS = "android.permission.SEND_CATEGORY_CAR_NOTIFICATIONS"; field public static final String SEND_DEVICE_CUSTOMIZATION_READY = "android.permission.SEND_DEVICE_CUSTOMIZATION_READY"; field public static final String SEND_SHOW_SUSPENDED_APP_DETAILS = "android.permission.SEND_SHOW_SUSPENDED_APP_DETAILS"; field public static final String SEND_SMS_NO_CONFIRMATION = "android.permission.SEND_SMS_NO_CONFIRMATION"; @@ -4139,8 +4140,10 @@ package android.media { public class AudioManager { method @Deprecated public int abandonAudioFocus(android.media.AudioManager.OnAudioFocusChangeListener, android.media.AudioAttributes); method @Deprecated @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public void addOnPreferredDeviceForStrategyChangedListener(@NonNull java.util.concurrent.Executor, @NonNull android.media.AudioManager.OnPreferredDeviceForStrategyChangedListener) throws java.lang.SecurityException; + method @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public void addOnPreferredDevicesForCapturePresetChangedListener(@NonNull java.util.concurrent.Executor, @NonNull android.media.AudioManager.OnPreferredDevicesForCapturePresetChangedListener) throws java.lang.SecurityException; method @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public void addOnPreferredDevicesForStrategyChangedListener(@NonNull java.util.concurrent.Executor, @NonNull android.media.AudioManager.OnPreferredDevicesForStrategyChangedListener) throws java.lang.SecurityException; method public void clearAudioServerStateCallback(); + method @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public boolean clearPreferredDevicesForCapturePreset(int); method @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public int dispatchAudioFocusChange(@NonNull android.media.AudioFocusInfo, int, @NonNull android.media.audiopolicy.AudioPolicy); method @IntRange(from=0) public long getAdditionalOutputDeviceDelay(@NonNull android.media.AudioDeviceInfo); method @NonNull @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public static java.util.List<android.media.audiopolicy.AudioProductStrategy> getAudioProductStrategies(); @@ -4151,6 +4154,7 @@ package android.media { method @IntRange(from=0) @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public int getMaxVolumeIndexForAttributes(@NonNull android.media.AudioAttributes); method @IntRange(from=0) @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public int getMinVolumeIndexForAttributes(@NonNull android.media.AudioAttributes); method @Nullable @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public android.media.AudioDeviceAttributes getPreferredDeviceForStrategy(@NonNull android.media.audiopolicy.AudioProductStrategy); + method @NonNull @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public java.util.List<android.media.AudioDeviceAttributes> getPreferredDevicesForCapturePreset(int); method @NonNull @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public java.util.List<android.media.AudioDeviceAttributes> getPreferredDevicesForStrategy(@NonNull android.media.audiopolicy.AudioProductStrategy); method @NonNull @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public int[] getSupportedSystemUsages(); method @IntRange(from=0) @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public int getVolumeIndexForAttributes(@NonNull android.media.AudioAttributes); @@ -4159,6 +4163,7 @@ package android.media { method @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public int registerAudioPolicy(@NonNull android.media.audiopolicy.AudioPolicy); method public void registerVolumeGroupCallback(@NonNull java.util.concurrent.Executor, @NonNull android.media.AudioManager.VolumeGroupCallback); method @Deprecated @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public void removeOnPreferredDeviceForStrategyChangedListener(@NonNull android.media.AudioManager.OnPreferredDeviceForStrategyChangedListener); + method @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public void removeOnPreferredDevicesForCapturePresetChangedListener(@NonNull android.media.AudioManager.OnPreferredDevicesForCapturePresetChangedListener); method @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public void removeOnPreferredDevicesForStrategyChangedListener(@NonNull android.media.AudioManager.OnPreferredDevicesForStrategyChangedListener); method @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public boolean removePreferredDeviceForStrategy(@NonNull android.media.audiopolicy.AudioProductStrategy); method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public int requestAudioFocus(android.media.AudioManager.OnAudioFocusChangeListener, @NonNull android.media.AudioAttributes, int, int) throws java.lang.IllegalArgumentException; @@ -4168,6 +4173,7 @@ package android.media { method public void setAudioServerStateCallback(@NonNull java.util.concurrent.Executor, @NonNull android.media.AudioManager.AudioServerStateCallback); method @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public void setDeviceVolumeBehavior(@NonNull android.media.AudioDeviceAttributes, int); method @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public void setFocusRequestResult(@NonNull android.media.AudioFocusInfo, int, @NonNull android.media.audiopolicy.AudioPolicy); + method @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public boolean setPreferredDeviceForCapturePreset(int, @NonNull android.media.AudioDeviceAttributes); method @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public boolean setPreferredDeviceForStrategy(@NonNull android.media.audiopolicy.AudioProductStrategy, @NonNull android.media.AudioDeviceAttributes); method @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public boolean setPreferredDevicesForStrategy(@NonNull android.media.audiopolicy.AudioProductStrategy, @NonNull java.util.List<android.media.AudioDeviceAttributes>); method @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public void setSupportedSystemUsages(@NonNull int[]); @@ -4197,6 +4203,10 @@ package android.media { method @Deprecated public void onPreferredDeviceForStrategyChanged(@NonNull android.media.audiopolicy.AudioProductStrategy, @Nullable android.media.AudioDeviceAttributes); } + public static interface AudioManager.OnPreferredDevicesForCapturePresetChangedListener { + method public void onPreferredDevicesForCapturePresetChanged(int, @NonNull java.util.List<android.media.AudioDeviceAttributes>); + } + public static interface AudioManager.OnPreferredDevicesForStrategyChangedListener { method public void onPreferredDevicesForStrategyChanged(@NonNull android.media.audiopolicy.AudioProductStrategy, @NonNull java.util.List<android.media.AudioDeviceAttributes>); } @@ -4274,11 +4284,8 @@ package android.media { field @RequiresPermission(android.Manifest.permission.CAPTURE_AUDIO_OUTPUT) public static final int RADIO_TUNER = 1998; // 0x7ce } - public final class MediaTranscodeManager implements java.lang.AutoCloseable { - method public void close(); + public final class MediaTranscodeManager { method @NonNull public android.media.MediaTranscodeManager.TranscodingJob enqueueRequest(@NonNull android.media.MediaTranscodeManager.TranscodingRequest, @NonNull java.util.concurrent.Executor, @NonNull android.media.MediaTranscodeManager.OnTranscodingFinishedListener) throws java.io.FileNotFoundException; - method protected void finalize(); - field public static final int PRIORITY_OFFLINE = 2; // 0x2 field public static final int PRIORITY_REALTIME = 1; // 0x1 field public static final int TRANSCODING_TYPE_VIDEO = 1; // 0x1 } @@ -4307,7 +4314,7 @@ package android.media { } @java.lang.FunctionalInterface public static interface MediaTranscodeManager.TranscodingJob.OnProgressUpdateListener { - method public void onProgressUpdate(@IntRange(from=0, to=100) int); + method public void onProgressUpdate(@NonNull android.media.MediaTranscodeManager.TranscodingJob, @IntRange(from=0, to=100) int); } public static final class MediaTranscodeManager.TranscodingRequest { @@ -4328,6 +4335,14 @@ package android.media { method @NonNull public android.media.MediaTranscodeManager.TranscodingRequest.Builder setVideoTrackFormat(@NonNull android.media.MediaFormat); } + public static class MediaTranscodeManager.TranscodingRequest.MediaFormatResolver { + ctor public MediaTranscodeManager.TranscodingRequest.MediaFormatResolver(); + method @Nullable public android.media.MediaFormat resolveVideoFormat(); + method @NonNull public android.media.MediaTranscodeManager.TranscodingRequest.MediaFormatResolver setSourceVideoFormatHint(@NonNull android.media.MediaFormat); + method public boolean shouldTranscode(); + field public static final String CAPS_SUPPORTS_HEVC = "support-hevc"; + } + public class PlayerProxy { method public void pause(); method public void setPan(float); @@ -6798,6 +6813,8 @@ package android.net.wifi.nl80211 { field public static final int BSS_CAPABILITY_CF_POLL_REQUEST = 8; // 0x8 field public static final int BSS_CAPABILITY_CHANNEL_AGILITY = 128; // 0x80 field public static final int BSS_CAPABILITY_DELAYED_BLOCK_ACK = 16384; // 0x4000 + field public static final int BSS_CAPABILITY_DMG_ESS = 3; // 0x3 + field public static final int BSS_CAPABILITY_DMG_IBSS = 1; // 0x1 field public static final int BSS_CAPABILITY_DSSS_OFDM = 8192; // 0x2000 field public static final int BSS_CAPABILITY_ESS = 1; // 0x1 field public static final int BSS_CAPABILITY_IBSS = 2; // 0x2 @@ -6867,7 +6884,7 @@ package android.net.wifi.nl80211 { method @NonNull public java.util.List<android.net.wifi.nl80211.NativeScanResult> getScanResults(@NonNull String, int); method @Nullable public android.net.wifi.nl80211.WifiNl80211Manager.TxPacketCounters getTxPacketCounters(@NonNull String); method @Nullable public static android.net.wifi.nl80211.WifiNl80211Manager.OemSecurityType parseOemSecurityTypeElement(int, int, @NonNull byte[]); - method public boolean registerApCallback(@NonNull String, @NonNull java.util.concurrent.Executor, @NonNull android.net.wifi.nl80211.WifiNl80211Manager.SoftApCallback); + method @Deprecated public boolean registerApCallback(@NonNull String, @NonNull java.util.concurrent.Executor, @NonNull android.net.wifi.nl80211.WifiNl80211Manager.SoftApCallback); method public void sendMgmtFrame(@NonNull String, @NonNull byte[], int, @NonNull java.util.concurrent.Executor, @NonNull android.net.wifi.nl80211.WifiNl80211Manager.SendMgmtFrameCallback); method public void setOnServiceDeadCallback(@NonNull Runnable); method public boolean setupInterfaceForClientMode(@NonNull String, @NonNull java.util.concurrent.Executor, @NonNull android.net.wifi.nl80211.WifiNl80211Manager.ScanEventCallback, @NonNull android.net.wifi.nl80211.WifiNl80211Manager.ScanEventCallback); @@ -6918,10 +6935,10 @@ package android.net.wifi.nl80211 { field public final int txBitrateMbps; } - public static interface WifiNl80211Manager.SoftApCallback { - method public void onConnectedClientsChanged(@NonNull android.net.wifi.nl80211.NativeWifiClient, boolean); - method public void onFailure(); - method public void onSoftApChannelSwitched(int, int); + @Deprecated public static interface WifiNl80211Manager.SoftApCallback { + method @Deprecated public void onConnectedClientsChanged(@NonNull android.net.wifi.nl80211.NativeWifiClient, boolean); + method @Deprecated public void onFailure(); + method @Deprecated public void onSoftApChannelSwitched(int, int); } public static class WifiNl80211Manager.TxPacketCounters { @@ -9742,6 +9759,7 @@ package android.telephony { method @Deprecated public void onOutgoingEmergencyCall(@NonNull android.telephony.emergency.EmergencyNumber); method public void onOutgoingEmergencyCall(@NonNull android.telephony.emergency.EmergencyNumber, int); method public void onOutgoingEmergencySms(@NonNull android.telephony.emergency.EmergencyNumber); + method public void onPhysicalChannelConfigurationChanged(@NonNull java.util.List<android.telephony.PhysicalChannelConfig>); method @RequiresPermission("android.permission.READ_PRECISE_PHONE_STATE") public void onPreciseCallStateChanged(@NonNull android.telephony.PreciseCallState); method public void onRadioPowerStateChanged(int); method public void onSrvccStateChanged(int); @@ -9749,12 +9767,29 @@ package android.telephony { field @RequiresPermission("android.permission.READ_PRECISE_PHONE_STATE") public static final int LISTEN_CALL_ATTRIBUTES_CHANGED = 67108864; // 0x4000000 field @RequiresPermission(android.Manifest.permission.READ_ACTIVE_EMERGENCY_SESSION) public static final int LISTEN_OUTGOING_EMERGENCY_CALL = 268435456; // 0x10000000 field @RequiresPermission(android.Manifest.permission.READ_ACTIVE_EMERGENCY_SESSION) public static final int LISTEN_OUTGOING_EMERGENCY_SMS = 536870912; // 0x20000000 + field @RequiresPermission(android.Manifest.permission.READ_PRECISE_PHONE_STATE) public static final long LISTEN_PHYSICAL_CHANNEL_CONFIGURATION = 4294967296L; // 0x100000000L field @RequiresPermission("android.permission.READ_PRECISE_PHONE_STATE") public static final int LISTEN_PRECISE_CALL_STATE = 2048; // 0x800 field @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public static final int LISTEN_RADIO_POWER_STATE_CHANGED = 8388608; // 0x800000 field @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public static final int LISTEN_SRVCC_STATE_CHANGED = 16384; // 0x4000 field @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public static final int LISTEN_VOICE_ACTIVATION_STATE = 131072; // 0x20000 } + public final class PhysicalChannelConfig implements android.os.Parcelable { + method public int describeContents(); + method public int getCellBandwidthDownlink(); + method public int getChannelNumber(); + method public int getConnectionStatus(); + method public int getNetworkType(); + method @IntRange(from=0, to=1007) public int getPhysicalCellId(); + method public void writeToParcel(@NonNull android.os.Parcel, int); + field public static final int CHANNEL_NUMBER_UNKNOWN = -1; // 0xffffffff + field public static final int CONNECTION_PRIMARY_SERVING = 1; // 0x1 + field public static final int CONNECTION_SECONDARY_SERVING = 2; // 0x2 + field public static final int CONNECTION_UNKNOWN = -1; // 0xffffffff + field @NonNull public static final android.os.Parcelable.Creator<android.telephony.PhysicalChannelConfig> CREATOR; + field public static final int PHYSICAL_CELL_ID_UNKNOWN = -1; // 0xffffffff + } + public final class PreciseCallState implements android.os.Parcelable { ctor public PreciseCallState(int, int, int, int, int); method public int describeContents(); diff --git a/packages/CarSystemUI/res/drawable/hvac_decrease_button.xml b/packages/CarSystemUI/res/drawable/hvac_decrease_button.xml index 469ac91073f9..656e94ae348b 100644 --- a/packages/CarSystemUI/res/drawable/hvac_decrease_button.xml +++ b/packages/CarSystemUI/res/drawable/hvac_decrease_button.xml @@ -27,20 +27,20 @@ android:width="@dimen/system_bar_icon_drawing_size" android:height="@dimen/system_bar_icon_drawing_size"/> <solid - android:color="#3C4043"/> + android:color="@color/hvac_temperature_adjust_button_color"/> </shape> </aapt:attr> </item> <item android:gravity="center" - android:width="48dp" - android:height="48dp"> + android:width="@dimen/system_bar_icon_drawing_size" + android:height="@dimen/system_bar_icon_drawing_size"> <aapt:attr name="android:drawable"> - <vector android:width="48dp" - android:height="48dp" + <vector android:width="@dimen/system_bar_icon_drawing_size" + android:height="@dimen/system_bar_icon_drawing_size" android:viewportWidth="24.0" android:viewportHeight="24.0"> <path - android:fillColor="#8AB4F8" + android:fillColor="@color/hvac_temperature_decrease_arrow_color" android:pathData="M14,7l-5,5 5,5V7z"/> </vector> </aapt:attr> diff --git a/packages/CarSystemUI/res/drawable/hvac_increase_button.xml b/packages/CarSystemUI/res/drawable/hvac_increase_button.xml index a3fca2233ddd..57c07c873d76 100644 --- a/packages/CarSystemUI/res/drawable/hvac_increase_button.xml +++ b/packages/CarSystemUI/res/drawable/hvac_increase_button.xml @@ -27,20 +27,20 @@ android:width="@dimen/system_bar_icon_drawing_size" android:height="@dimen/system_bar_icon_drawing_size"/> <solid - android:color="#3C4043"/> + android:color="@color/hvac_temperature_adjust_button_color"/> </shape> </aapt:attr> </item> <item android:gravity="center" - android:width="48dp" - android:height="48dp"> + android:width="@dimen/system_bar_icon_drawing_size" + android:height="@dimen/system_bar_icon_drawing_size"> <aapt:attr name="android:drawable"> - <vector android:width="48dp" - android:height="48dp" + <vector android:width="@dimen/system_bar_icon_drawing_size" + android:height="@dimen/system_bar_icon_drawing_size" android:viewportWidth="24.0" android:viewportHeight="24.0"> <path - android:fillColor="#F28B82" + android:fillColor="@color/hvac_temperature_increase_arrow_color" android:pathData="M10,17l5,-5 -5,-5v10z"/> </vector> </aapt:attr> diff --git a/packages/CarSystemUI/res/layout/car_top_navigation_bar_unprovisioned.xml b/packages/CarSystemUI/res/layout/car_top_navigation_bar_unprovisioned.xml index d9c149106451..b8ac2b43b047 100644 --- a/packages/CarSystemUI/res/layout/car_top_navigation_bar_unprovisioned.xml +++ b/packages/CarSystemUI/res/layout/car_top_navigation_bar_unprovisioned.xml @@ -56,8 +56,6 @@ android:textAppearance="@style/TextAppearance.CarStatus" systemui:hvacAreaId="49" systemui:hvacPivotOffset="60dp" - systemui:hvacPropertyId="358614275" - systemui:hvacTempFormat="%.0f\u00B0" /> </FrameLayout> @@ -130,8 +128,6 @@ android:textAppearance="@style/TextAppearance.CarStatus" systemui:hvacAreaId="68" systemui:hvacPivotOffset="60dp" - systemui:hvacPropertyId="358614275" - systemui:hvacTempFormat="%.0f\u00B0" /> </FrameLayout> </RelativeLayout> diff --git a/packages/CarSystemUI/res/values/colors.xml b/packages/CarSystemUI/res/values/colors.xml index 1e15affcbf48..c390cc8d70a4 100644 --- a/packages/CarSystemUI/res/values/colors.xml +++ b/packages/CarSystemUI/res/values/colors.xml @@ -37,6 +37,11 @@ <color name="status_bar_background_color">#33000000</color> <drawable name="system_bar_background">@color/status_bar_background_color</drawable> + <!-- colors for hvac temperature view --> + <color name="hvac_temperature_adjust_button_color">#3C4043</color> + <color name="hvac_temperature_decrease_arrow_color">#8AB4F8</color> + <color name="hvac_temperature_increase_arrow_color">#F28B82</color> + <!-- The background color of the notification shade --> <color name="notification_shade_background_color">#D6000000</color> diff --git a/packages/CarSystemUI/res/values/dimens.xml b/packages/CarSystemUI/res/values/dimens.xml index f02a8e7648c0..28b8eadf9750 100644 --- a/packages/CarSystemUI/res/values/dimens.xml +++ b/packages/CarSystemUI/res/values/dimens.xml @@ -48,8 +48,14 @@ <dimen name="system_bar_user_icon_padding">16dp</dimen> <dimen name="system_bar_user_icon_drawing_size">36dp</dimen> + <!-- Padding on either side of the group of all system bar buttons --> <dimen name="system_bar_button_group_padding">64dp</dimen> <dimen name="system_bar_icon_drawing_size">44dp</dimen> + <dimen name="system_bar_button_size">76dp</dimen> + <!-- Margin between the system bar buttons --> + <dimen name="system_bar_button_margin">32dp</dimen> + <!-- Padding between the system bar button and the icon within it --> + <dimen name="system_bar_button_padding">16dp</dimen> <!-- The amount by which to scale up the status bar icons. --> <item name="status_bar_icon_scale_factor" format="float" type="dimen">1.75</item> @@ -61,8 +67,8 @@ <dimen name="hvac_temperature_text_padding">8dp</dimen> <dimen name="hvac_temperature_button_size">76dp</dimen> <!--These values represent MIN and MAX for hvac--> - <item name="hvac_min_value_celsius" format="float" type="dimen">0</item> - <item name="hvac_max_value_celsius" format="float" type="dimen">126</item> + <item name="hvac_min_value_celsius" format="float" type="dimen">10</item> + <item name="hvac_max_value_celsius" format="float" type="dimen">35</item> <!-- Largest size an avatar might need to be drawn in the user picker, status bar, or quick settings header --> diff --git a/packages/CarSystemUI/res/values/styles.xml b/packages/CarSystemUI/res/values/styles.xml index 0db17ac42a77..f242db0aec09 100644 --- a/packages/CarSystemUI/res/values/styles.xml +++ b/packages/CarSystemUI/res/values/styles.xml @@ -43,10 +43,10 @@ </style> <style name="NavigationBarButton"> - <item name="android:layout_height">76dp</item> - <item name="android:layout_width">76dp</item> - <item name="android:layout_marginEnd">32dp</item> - <item name="android:padding">16dp</item> + <item name="android:layout_height">@dimen/system_bar_button_size</item> + <item name="android:layout_width">@dimen/system_bar_button_size</item> + <item name="android:layout_marginEnd">@dimen/system_bar_button_margin</item> + <item name="android:padding">@dimen/system_bar_button_padding</item> <item name="android:gravity">center</item> <item name="android:background">?android:attr/selectableItemBackground</item> </style> diff --git a/packages/CarSystemUI/src/com/android/systemui/car/hvac/AdjustableTemperatureView.java b/packages/CarSystemUI/src/com/android/systemui/car/hvac/AdjustableTemperatureView.java index 4cac4456789d..85d4ceb81eeb 100644 --- a/packages/CarSystemUI/src/com/android/systemui/car/hvac/AdjustableTemperatureView.java +++ b/packages/CarSystemUI/src/com/android/systemui/car/hvac/AdjustableTemperatureView.java @@ -35,22 +35,27 @@ import com.android.systemui.R; */ public class AdjustableTemperatureView extends LinearLayout implements TemperatureView { - private HvacController mHvacController; - private float mCurrentTempC; + private final int mAreaId; private TextView mTempTextView; + private float mMinTempC; + private float mMaxTempC; + private String mTempFormat; private boolean mDisplayInFahrenheit = false; - private final float mMinTempC; - private final float mMaxTempC; - private final int mAreaId; - private final String mTempFormat; + private HvacController mHvacController; + private float mCurrentTempC; public AdjustableTemperatureView(Context context, AttributeSet attrs) { super(context, attrs); TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.TemperatureView); mAreaId = typedArray.getInt(R.styleable.TemperatureView_hvacAreaId, -1); + } - LayoutInflater.from(context).inflate(R.layout.adjustable_temperature_view, /* root= */this); + @Override + public void onFinishInflate() { + super.onFinishInflate(); + LayoutInflater.from(getContext()).inflate(R.layout.adjustable_temperature_view, + /* root= */ this); mTempFormat = getResources().getString(R.string.hvac_temperature_format); mMinTempC = getResources().getFloat(R.dimen.hvac_min_value_celsius); mMaxTempC = getResources().getFloat(R.dimen.hvac_max_value_celsius); @@ -63,7 +68,7 @@ public class AdjustableTemperatureView extends LinearLayout implements Temperatu } @Override - public void setTemperatureView(float tempC) { + public void setTemp(float tempC) { if (tempC > mMaxTempC || tempC < mMinTempC) { return; } @@ -78,7 +83,7 @@ public class AdjustableTemperatureView extends LinearLayout implements Temperatu @Override public void setDisplayInFahrenheit(boolean displayFahrenheit) { mDisplayInFahrenheit = displayFahrenheit; - setTemperatureView(mCurrentTempC); + setTemp(mCurrentTempC); } @Override diff --git a/packages/CarSystemUI/src/com/android/systemui/car/hvac/AnimatedTemperatureView.java b/packages/CarSystemUI/src/com/android/systemui/car/hvac/AnimatedTemperatureView.java index 567baa91cb59..b98b68038e6f 100644 --- a/packages/CarSystemUI/src/com/android/systemui/car/hvac/AnimatedTemperatureView.java +++ b/packages/CarSystemUI/src/com/android/systemui/car/hvac/AnimatedTemperatureView.java @@ -189,7 +189,7 @@ public class AnimatedTemperatureView extends FrameLayout implements TemperatureV * @param temp - The current temp or NaN */ @Override - public void setTemperatureView(float temp) { + public void setTemp(float temp) { if (mDisplayInFahrenheit) { temp = convertToFahrenheit(temp); } diff --git a/packages/CarSystemUI/src/com/android/systemui/car/hvac/HvacController.java b/packages/CarSystemUI/src/com/android/systemui/car/hvac/HvacController.java index f7451dc6fdee..10a361c3084e 100644 --- a/packages/CarSystemUI/src/com/android/systemui/car/hvac/HvacController.java +++ b/packages/CarSystemUI/src/com/android/systemui/car/hvac/HvacController.java @@ -30,6 +30,7 @@ import android.view.ViewGroup; import com.android.systemui.car.CarServiceProvider; import com.android.systemui.dagger.SysUISingleton; +import com.android.systemui.dagger.qualifiers.UiBackground; import java.util.ArrayList; import java.util.HashMap; @@ -37,6 +38,7 @@ import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; +import java.util.concurrent.Executor; import javax.inject.Inject; @@ -49,6 +51,7 @@ public class HvacController { public static final String TAG = "HvacController"; private static final boolean DEBUG = true; + private final Executor mBackgroundExecutor; private final CarServiceProvider mCarServiceProvider; private final Set<TemperatureView> mRegisteredViews = new HashSet<>(); @@ -68,7 +71,7 @@ public class HvacController { Log.d(TAG, "onChangeEvent: " + areaId + ":" + value); } for (TemperatureView view : temperatureViews) { - view.setTemperatureView(newTemp); + view.setTemp(newTemp); } } } catch (Exception e) { @@ -117,8 +120,10 @@ public class HvacController { }; @Inject - public HvacController(CarServiceProvider carServiceProvider) { + public HvacController(CarServiceProvider carServiceProvider, + @UiBackground Executor backgroundExecutor) { mCarServiceProvider = carServiceProvider; + mBackgroundExecutor = backgroundExecutor; } /** @@ -171,14 +176,14 @@ public class HvacController { } if (mCarPropertyManager == null || !mCarPropertyManager.isPropertyAvailable( HVAC_TEMPERATURE_SET, zone)) { - view.setTemperatureView(Float.NaN); + view.setTemp(Float.NaN); return; } - view.setTemperatureView( + view.setTemp( mCarPropertyManager.getFloatProperty(HVAC_TEMPERATURE_SET, zone)); view.setHvacController(this); } catch (Exception e) { - view.setTemperatureView(Float.NaN); + view.setTemp(Float.NaN); Log.e(TAG, "Failed to get value from hvac service", e); } } @@ -213,7 +218,8 @@ public class HvacController { public void setTemperature(float tempC, int zone) { if (mCarPropertyManager != null) { // Internally, all temperatures are represented in floating point Celsius - mCarPropertyManager.setFloatProperty(HVAC_TEMPERATURE_SET, zone, tempC); + mBackgroundExecutor.execute( + () -> mCarPropertyManager.setFloatProperty(HVAC_TEMPERATURE_SET, zone, tempC)); } } @@ -234,6 +240,6 @@ public class HvacController { * @return Temperature in Celsius. */ public static float convertToCelsius(float tempF) { - return (float) ((tempF - 32) * 0.55555555556); + return (tempF - 32) * 5f / 9f; } } diff --git a/packages/CarSystemUI/src/com/android/systemui/car/hvac/TemperatureTextView.java b/packages/CarSystemUI/src/com/android/systemui/car/hvac/TemperatureTextView.java index 252f7830b72c..90df15c907dd 100644 --- a/packages/CarSystemUI/src/com/android/systemui/car/hvac/TemperatureTextView.java +++ b/packages/CarSystemUI/src/com/android/systemui/car/hvac/TemperatureTextView.java @@ -56,7 +56,7 @@ public class TemperatureTextView extends TextView implements TemperatureView { * @param temp - The current temp or NaN */ @Override - public void setTemperatureView(float temp) { + public void setTemp(float temp) { if (Float.isNaN(temp)) { setText("--"); return; diff --git a/packages/CarSystemUI/src/com/android/systemui/car/hvac/TemperatureView.java b/packages/CarSystemUI/src/com/android/systemui/car/hvac/TemperatureView.java index 3c0e0acc446c..6edf25431ffd 100644 --- a/packages/CarSystemUI/src/com/android/systemui/car/hvac/TemperatureView.java +++ b/packages/CarSystemUI/src/com/android/systemui/car/hvac/TemperatureView.java @@ -33,7 +33,7 @@ public interface TemperatureView { * * @param temp - The current temp in Celsius or NaN */ - void setTemperatureView(float temp); + void setTemp(float temp); /** * Render the displayed temperature in Fahrenheit diff --git a/packages/CarSystemUI/src/com/android/systemui/car/keyguard/CarKeyguardViewController.java b/packages/CarSystemUI/src/com/android/systemui/car/keyguard/CarKeyguardViewController.java index dadbc22760b9..3af7507ae2b4 100644 --- a/packages/CarSystemUI/src/com/android/systemui/car/keyguard/CarKeyguardViewController.java +++ b/packages/CarSystemUI/src/com/android/systemui/car/keyguard/CarKeyguardViewController.java @@ -30,7 +30,6 @@ import androidx.annotation.VisibleForTesting; import com.android.keyguard.KeyguardUpdateMonitor; import com.android.keyguard.KeyguardViewController; import com.android.keyguard.ViewMediatorCallback; -import com.android.keyguard.dagger.KeyguardBouncerComponent; import com.android.systemui.R; import com.android.systemui.car.CarServiceProvider; import com.android.systemui.car.navigationbar.CarNavigationBarController; @@ -40,6 +39,7 @@ import com.android.systemui.dagger.SysUISingleton; import com.android.systemui.dagger.qualifiers.Main; import com.android.systemui.statusbar.phone.BiometricUnlockController; import com.android.systemui.statusbar.phone.KeyguardBouncer; +import com.android.systemui.statusbar.phone.KeyguardBouncer.Factory; import com.android.systemui.statusbar.phone.KeyguardBypassController; import com.android.systemui.statusbar.phone.NotificationPanelViewController; import com.android.systemui.statusbar.phone.StatusBar; @@ -66,7 +66,7 @@ public class CarKeyguardViewController extends OverlayViewController implements private final Lazy<BiometricUnlockController> mBiometricUnlockControllerLazy; private final ViewMediatorCallback mViewMediatorCallback; private final CarNavigationBarController mCarNavigationBarController; - private final KeyguardBouncerComponent.Factory mKeyguardBouncerComponentFactory; + private final Factory mKeyguardBouncerFactory; // Needed to instantiate mBouncer. private final KeyguardBouncer.BouncerExpansionCallback mExpansionCallback = new KeyguardBouncer.BouncerExpansionCallback() { @@ -107,7 +107,7 @@ public class CarKeyguardViewController extends OverlayViewController implements Lazy<BiometricUnlockController> biometricUnlockControllerLazy, ViewMediatorCallback viewMediatorCallback, CarNavigationBarController carNavigationBarController, - KeyguardBouncerComponent.Factory keyguardBouncerComponentFactory) { + KeyguardBouncer.Factory keyguardBouncerFactory) { super(R.id.keyguard_stub, overlayViewGlobalStateController); @@ -118,7 +118,7 @@ public class CarKeyguardViewController extends OverlayViewController implements mBiometricUnlockControllerLazy = biometricUnlockControllerLazy; mViewMediatorCallback = viewMediatorCallback; mCarNavigationBarController = carNavigationBarController; - mKeyguardBouncerComponentFactory = keyguardBouncerComponentFactory; + mKeyguardBouncerFactory = keyguardBouncerFactory; registerUserSwitchedListener(); } @@ -130,9 +130,8 @@ public class CarKeyguardViewController extends OverlayViewController implements @Override public void onFinishInflate() { - mBouncer = mKeyguardBouncerComponentFactory - .build(getLayout().findViewById(R.id.keyguard_container), mExpansionCallback) - .createKeyguardBouncer(); + mBouncer = mKeyguardBouncerFactory + .create(getLayout().findViewById(R.id.keyguard_container), mExpansionCallback); mBiometricUnlockControllerLazy.get().setKeyguardViewController(this); } diff --git a/packages/CarSystemUI/src/com/android/systemui/car/navigationbar/ButtonSelectionStateController.java b/packages/CarSystemUI/src/com/android/systemui/car/navigationbar/ButtonSelectionStateController.java index aa6da89e2864..2dc475682fac 100644 --- a/packages/CarSystemUI/src/com/android/systemui/car/navigationbar/ButtonSelectionStateController.java +++ b/packages/CarSystemUI/src/com/android/systemui/car/navigationbar/ButtonSelectionStateController.java @@ -16,7 +16,7 @@ package com.android.systemui.car.navigationbar; -import android.app.ActivityManager; +import android.app.ActivityTaskManager.RootTaskInfo; import android.content.ComponentName; import android.content.Context; import android.content.Intent; @@ -97,27 +97,27 @@ public class ButtonSelectionStateController { * The StackInfo is expected to be supplied in order of recency and StackInfo will only be used * for consideration if it has the same displayId as the CarNavigationButton. * - * @param stackInfoList of the currently running application + * @param taskInfoList of the currently running application * @param validDisplay index of the valid display */ - protected void taskChanged(List<ActivityManager.StackInfo> stackInfoList, int validDisplay) { - ActivityManager.StackInfo validStackInfo = null; - for (ActivityManager.StackInfo stackInfo : stackInfoList) { + protected void taskChanged(List<RootTaskInfo> taskInfoList, int validDisplay) { + RootTaskInfo validTaskInfo = null; + for (RootTaskInfo taskInfo : taskInfoList) { // Find the first stack info with a topActivity in the primary display. // TODO: We assume that CarFacetButton will launch an app only in the primary display. // We need to extend the functionality to handle the multiple display properly. - if (stackInfo.topActivity != null && stackInfo.displayId == validDisplay) { - validStackInfo = stackInfo; + if (taskInfo.topActivity != null && taskInfo.displayId == validDisplay) { + validTaskInfo = taskInfo; break; } } - if (validStackInfo == null) { + if (validTaskInfo == null) { // No stack was found that was on the same display as the buttons thus return return; } - int displayId = validStackInfo.displayId; + int displayId = validTaskInfo.displayId; mSelectedButtons.forEach(carNavigationButton -> { if (carNavigationButton.getDisplayId() == displayId) { @@ -126,7 +126,7 @@ public class ButtonSelectionStateController { }); mSelectedButtons.clear(); - HashSet<CarNavigationButton> selectedButtons = findSelectedButtons(validStackInfo); + HashSet<CarNavigationButton> selectedButtons = findSelectedButtons(validTaskInfo); if (selectedButtons != null) { selectedButtons.forEach(carNavigationButton -> { @@ -141,10 +141,10 @@ public class ButtonSelectionStateController { /** * Defaults to Display.DEFAULT_DISPLAY when no parameter is provided for the validDisplay. * - * @param stackInfoList + * @param taskInfoList */ - protected void taskChanged(List<ActivityManager.StackInfo> stackInfoList) { - taskChanged(stackInfoList, Display.DEFAULT_DISPLAY); + protected void taskChanged(List<RootTaskInfo> taskInfoList) { + taskChanged(taskInfoList, Display.DEFAULT_DISPLAY); } /** @@ -171,12 +171,11 @@ public class ButtonSelectionStateController { mRegisteredViews.add(carNavigationButton); } - private HashSet<CarNavigationButton> findSelectedButtons( - ActivityManager.StackInfo validStackInfo) { - String packageName = validStackInfo.topActivity.getPackageName(); + private HashSet<CarNavigationButton> findSelectedButtons(RootTaskInfo validTaskInfo) { + String packageName = validTaskInfo.topActivity.getPackageName(); HashSet<CarNavigationButton> selectedButtons = - findButtonsByComponentName(validStackInfo.topActivity); + findButtonsByComponentName(validTaskInfo.topActivity); if (selectedButtons == null) { selectedButtons = mButtonsByPackage.get(packageName); } diff --git a/packages/CarSystemUI/src/com/android/systemui/car/navigationbar/ButtonSelectionStateListener.java b/packages/CarSystemUI/src/com/android/systemui/car/navigationbar/ButtonSelectionStateListener.java index d6216ba87d95..f74bd4fce312 100644 --- a/packages/CarSystemUI/src/com/android/systemui/car/navigationbar/ButtonSelectionStateListener.java +++ b/packages/CarSystemUI/src/com/android/systemui/car/navigationbar/ButtonSelectionStateListener.java @@ -43,9 +43,9 @@ class ButtonSelectionStateListener extends TaskStackChangeListener { public void onTaskStackChanged() { try { mButtonSelectionStateController.taskChanged( - ActivityTaskManager.getService().getAllStackInfos()); + ActivityTaskManager.getService().getAllRootTaskInfos()); } catch (Exception e) { - Log.e(TAG, "Getting StackInfo from activity manager failed", e); + Log.e(TAG, "Getting RootTaskInfo from activity task manager failed", e); } } @@ -53,9 +53,9 @@ class ButtonSelectionStateListener extends TaskStackChangeListener { public void onTaskDisplayChanged(int taskId, int newDisplayId) { try { mButtonSelectionStateController.taskChanged( - ActivityTaskManager.getService().getAllStackInfos()); + ActivityTaskManager.getService().getAllRootTaskInfos()); } catch (Exception e) { - Log.e(TAG, "Getting StackInfo from activity manager failed", e); + Log.e(TAG, "Getting RootTaskInfo from activity task manager failed", e); } } diff --git a/packages/CarSystemUI/src/com/android/systemui/car/sideloaded/SideLoadedAppDetector.java b/packages/CarSystemUI/src/com/android/systemui/car/sideloaded/SideLoadedAppDetector.java index eb32edb27196..f96ee0f73dc0 100644 --- a/packages/CarSystemUI/src/com/android/systemui/car/sideloaded/SideLoadedAppDetector.java +++ b/packages/CarSystemUI/src/com/android/systemui/car/sideloaded/SideLoadedAppDetector.java @@ -17,7 +17,7 @@ package com.android.systemui.car.sideloaded; import android.annotation.NonNull; -import android.app.ActivityManager; +import android.app.ActivityTaskManager.RootTaskInfo; import android.content.ComponentName; import android.content.pm.ApplicationInfo; import android.content.pm.InstallSourceInfo; @@ -78,10 +78,10 @@ public class SideLoadedAppDetector { return false; } - boolean isSafe(@NonNull ActivityManager.StackInfo stackInfo) { - ComponentName componentName = stackInfo.topActivity; + boolean isSafe(@NonNull RootTaskInfo taskInfo) { + ComponentName componentName = taskInfo.topActivity; if (componentName == null) { - Log.w(TAG, "Stack info does not have top activity: " + stackInfo.stackId); + Log.w(TAG, "Task info does not have top activity: " + taskInfo.taskId); return false; } return isSafe(componentName.getPackageName()); diff --git a/packages/CarSystemUI/src/com/android/systemui/car/sideloaded/SideLoadedAppListener.java b/packages/CarSystemUI/src/com/android/systemui/car/sideloaded/SideLoadedAppListener.java index c8c1a40b8032..db7718bc166b 100644 --- a/packages/CarSystemUI/src/com/android/systemui/car/sideloaded/SideLoadedAppListener.java +++ b/packages/CarSystemUI/src/com/android/systemui/car/sideloaded/SideLoadedAppListener.java @@ -16,8 +16,7 @@ package com.android.systemui.car.sideloaded; -import android.app.ActivityManager; -import android.app.ActivityManager.StackInfo; +import android.app.ActivityTaskManager.RootTaskInfo; import android.app.IActivityTaskManager; import android.app.TaskStackListener; import android.content.ComponentName; @@ -56,15 +55,15 @@ public class SideLoadedAppListener extends TaskStackListener { public void onTaskCreated(int taskId, ComponentName componentName) throws RemoteException { super.onTaskCreated(taskId, componentName); - List<StackInfo> stackInfoList = mActivityTaskManager.getAllStackInfos(); - ActivityManager.StackInfo stackInfo = getStackInfo(stackInfoList, taskId); - if (stackInfo == null) { + List<RootTaskInfo> taskInfoList = mActivityTaskManager.getAllRootTaskInfos(); + RootTaskInfo taskInfo = getStackInfo(taskInfoList, taskId); + if (taskInfo == null) { Log.e(TAG, "Stack info was not available for taskId: " + taskId); return; } - if (!mSideLoadedAppDetector.isSafe(stackInfo)) { - Display display = mDisplayManager.getDisplay(stackInfo.displayId); + if (!mSideLoadedAppDetector.isSafe(taskInfo)) { + Display display = mDisplayManager.getDisplay(taskInfo.displayId); mSideLoadedAppStateController.onUnsafeTaskCreatedOnDisplay(display); } } @@ -75,18 +74,18 @@ public class SideLoadedAppListener extends TaskStackListener { Display[] displays = mDisplayManager.getDisplays(); for (Display display : displays) { - // Note that the stackInfoList is ordered by recency. - List<StackInfo> stackInfoList = - mActivityTaskManager.getAllStackInfosOnDisplay(display.getDisplayId()); + // Note that the taskInfoList is ordered by recency. + List<RootTaskInfo> taskInfoList = + mActivityTaskManager.getAllRootTaskInfosOnDisplay(display.getDisplayId()); - if (stackInfoList == null) { + if (taskInfoList == null) { continue; } - StackInfo stackInfo = getTopVisibleStackInfo(stackInfoList); - if (stackInfo == null) { + RootTaskInfo taskInfo = getTopVisibleStackInfo(taskInfoList); + if (taskInfo == null) { continue; } - if (mSideLoadedAppDetector.isSafe(stackInfo)) { + if (mSideLoadedAppDetector.isSafe(taskInfo)) { mSideLoadedAppStateController.onSafeTaskDisplayedOnDisplay(display); } else { mSideLoadedAppStateController.onUnsafeTaskDisplayedOnDisplay(display); @@ -97,18 +96,17 @@ public class SideLoadedAppListener extends TaskStackListener { /** * Returns stack info for a given taskId. */ - private ActivityManager.StackInfo getStackInfo( - List<ActivityManager.StackInfo> stackInfoList, int taskId) { - if (stackInfoList == null) { + private RootTaskInfo getStackInfo(List<RootTaskInfo> taskInfoList, int taskId) { + if (taskInfoList == null) { return null; } - for (ActivityManager.StackInfo stackInfo : stackInfoList) { - if (stackInfo.taskIds == null) { + for (RootTaskInfo taskInfo : taskInfoList) { + if (taskInfo.childTaskIds == null) { continue; } - for (int stackTaskId : stackInfo.taskIds) { - if (taskId == stackTaskId) { - return stackInfo; + for (int taskTaskId : taskInfo.childTaskIds) { + if (taskId == taskTaskId) { + return taskInfo; } } } @@ -118,11 +116,10 @@ public class SideLoadedAppListener extends TaskStackListener { /** * Returns the first visible stackInfo. */ - private ActivityManager.StackInfo getTopVisibleStackInfo( - List<ActivityManager.StackInfo> stackInfoList) { - for (ActivityManager.StackInfo stackInfo : stackInfoList) { - if (stackInfo.visible) { - return stackInfo; + private RootTaskInfo getTopVisibleStackInfo(List<RootTaskInfo> taskInfoList) { + for (RootTaskInfo taskInfo : taskInfoList) { + if (taskInfo.visible) { + return taskInfo; } } return null; diff --git a/packages/CarSystemUI/tests/src/com/android/systemui/car/hvac/AdjustableTemperatureViewTest.java b/packages/CarSystemUI/tests/src/com/android/systemui/car/hvac/AdjustableTemperatureViewTest.java index e8850def6bcd..a3a55aae5f18 100644 --- a/packages/CarSystemUI/tests/src/com/android/systemui/car/hvac/AdjustableTemperatureViewTest.java +++ b/packages/CarSystemUI/tests/src/com/android/systemui/car/hvac/AdjustableTemperatureViewTest.java @@ -46,9 +46,12 @@ import com.android.systemui.car.CarSystemUiTest; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; +import org.mockito.ArgumentCaptor; import org.mockito.Mock; import org.mockito.MockitoAnnotations; +import java.util.concurrent.Executor; + @CarSystemUiTest @RunWith(AndroidTestingRunner.class) @TestableLooper.RunWithLooper @@ -64,6 +67,8 @@ public class AdjustableTemperatureViewTest extends SysuiTestCase { private Car mCar; @Mock private CarPropertyManager mCarPropertyManager; + @Mock + private Executor mExecutor; @Before public void setUp() { @@ -72,9 +77,10 @@ public class AdjustableTemperatureViewTest extends SysuiTestCase { when(mCar.getCarManager(Car.PROPERTY_SERVICE)).thenReturn(mCarPropertyManager); CarServiceProvider carServiceProvider = new CarServiceProvider(mContext, mCar); - mHvacController = new HvacController(carServiceProvider); + mHvacController = new HvacController(carServiceProvider, mExecutor); mHvacController.connectToCarService(); mAdjustableTemperatureView = new AdjustableTemperatureView(getContext(), /* attrs= */ null); + mAdjustableTemperatureView.onFinishInflate(); mAdjustableTemperatureView.setHvacController(mHvacController); } @@ -118,6 +124,9 @@ public class AdjustableTemperatureViewTest extends SysuiTestCase { mAdjustableTemperatureView.findViewById(R.id.hvac_increase_button).callOnClick(); + ArgumentCaptor<Runnable> setTempRunnableCaptor = ArgumentCaptor.forClass(Runnable.class); + verify(mExecutor).execute(setTempRunnableCaptor.capture()); + setTempRunnableCaptor.getValue().run(); verify(mCarPropertyManager).setFloatProperty(eq(HVAC_TEMPERATURE_SET), anyInt(), eq(TEMP_CELSIUS + 1)); } @@ -132,6 +141,9 @@ public class AdjustableTemperatureViewTest extends SysuiTestCase { mAdjustableTemperatureView.findViewById(R.id.hvac_decrease_button).callOnClick(); + ArgumentCaptor<Runnable> setTempRunnableCaptor = ArgumentCaptor.forClass(Runnable.class); + verify(mExecutor).execute(setTempRunnableCaptor.capture()); + setTempRunnableCaptor.getValue().run(); verify(mCarPropertyManager).setFloatProperty(eq(HVAC_TEMPERATURE_SET), anyInt(), eq(TEMP_CELSIUS - 1)); } @@ -150,6 +162,9 @@ public class AdjustableTemperatureViewTest extends SysuiTestCase { mAdjustableTemperatureView.findViewById(R.id.hvac_increase_button).callOnClick(); + ArgumentCaptor<Runnable> setTempRunnableCaptor = ArgumentCaptor.forClass(Runnable.class); + verify(mExecutor).execute(setTempRunnableCaptor.capture()); + setTempRunnableCaptor.getValue().run(); verify(mCarPropertyManager).setFloatProperty(eq(HVAC_TEMPERATURE_SET), anyInt(), eq(convertToCelsius(convertToFahrenheit(TEMP_CELSIUS) + 1))); } @@ -168,6 +183,9 @@ public class AdjustableTemperatureViewTest extends SysuiTestCase { mAdjustableTemperatureView.findViewById(R.id.hvac_decrease_button).callOnClick(); + ArgumentCaptor<Runnable> setTempRunnableCaptor = ArgumentCaptor.forClass(Runnable.class); + verify(mExecutor).execute(setTempRunnableCaptor.capture()); + setTempRunnableCaptor.getValue().run(); verify(mCarPropertyManager).setFloatProperty(eq(HVAC_TEMPERATURE_SET), anyInt(), eq(convertToCelsius(convertToFahrenheit(TEMP_CELSIUS) - 1))); } diff --git a/packages/CarSystemUI/tests/src/com/android/systemui/car/hvac/HvacControllerTest.java b/packages/CarSystemUI/tests/src/com/android/systemui/car/hvac/HvacControllerTest.java index 9912657d78e1..52f07dfd6b81 100644 --- a/packages/CarSystemUI/tests/src/com/android/systemui/car/hvac/HvacControllerTest.java +++ b/packages/CarSystemUI/tests/src/com/android/systemui/car/hvac/HvacControllerTest.java @@ -40,6 +40,8 @@ import androidx.test.filters.SmallTest; import com.android.systemui.SysuiTestCase; import com.android.systemui.car.CarServiceProvider; import com.android.systemui.car.CarSystemUiTest; +import com.android.systemui.util.concurrency.FakeExecutor; +import com.android.systemui.util.time.FakeSystemClock; import org.junit.Before; import org.junit.Test; @@ -70,7 +72,8 @@ public class HvacControllerTest extends SysuiTestCase { when(mCar.getCarManager(Car.PROPERTY_SERVICE)).thenReturn(mCarPropertyManager); CarServiceProvider carServiceProvider = new CarServiceProvider(mContext, mCar); - mHvacController = new HvacController(carServiceProvider); + mHvacController = new HvacController(carServiceProvider, + new FakeExecutor(new FakeSystemClock())); mHvacController.connectToCarService(); } @@ -86,31 +89,31 @@ public class HvacControllerTest extends SysuiTestCase { TemperatureTextView v = setupMockTemperatureTextView(AREA_ID, TEMP); mHvacController.addTemperatureViewToController(v); - verify(v).setTemperatureView(TEMP); + verify(v).setTemp(TEMP); } @Test public void addTemperatureViewToController_usingSameTemperatureView_registersFirstView() { TemperatureTextView v = setupMockTemperatureTextView(AREA_ID, TEMP); mHvacController.addTemperatureViewToController(v); - verify(v).setTemperatureView(TEMP); + verify(v).setTemp(TEMP); resetTemperatureView(v, AREA_ID); mHvacController.addTemperatureViewToController(v); - verify(v, never()).setTemperatureView(TEMP); + verify(v, never()).setTemp(TEMP); } @Test public void addTemperatureViewToController_usingDifferentTemperatureView_registersBothViews() { TemperatureTextView v1 = setupMockTemperatureTextView(AREA_ID, TEMP); mHvacController.addTemperatureViewToController(v1); - verify(v1).setTemperatureView(TEMP); + verify(v1).setTemp(TEMP); TemperatureTextView v2 = setupMockTemperatureTextView( AREA_ID + 1, TEMP + 1); mHvacController.addTemperatureViewToController(v2); - verify(v2).setTemperatureView(TEMP + 1); + verify(v2).setTemp(TEMP + 1); } @Test @@ -124,7 +127,7 @@ public class HvacControllerTest extends SysuiTestCase { mHvacController.addTemperatureViewToController(v); verify(v).setDisplayInFahrenheit(true); - verify(v).setTemperatureView(TEMP); + verify(v).setTemp(TEMP); } private TemperatureTextView setupMockTemperatureTextView(int areaId, float value) { diff --git a/packages/CarSystemUI/tests/src/com/android/systemui/car/hvac/TemperatureTextViewTest.java b/packages/CarSystemUI/tests/src/com/android/systemui/car/hvac/TemperatureTextViewTest.java index e97d9d9b3f6a..3ed811105a54 100644 --- a/packages/CarSystemUI/tests/src/com/android/systemui/car/hvac/TemperatureTextViewTest.java +++ b/packages/CarSystemUI/tests/src/com/android/systemui/car/hvac/TemperatureTextViewTest.java @@ -40,6 +40,8 @@ import com.android.systemui.R; import com.android.systemui.SysuiTestCase; import com.android.systemui.car.CarServiceProvider; import com.android.systemui.car.CarSystemUiTest; +import com.android.systemui.util.concurrency.FakeExecutor; +import com.android.systemui.util.time.FakeSystemClock; import org.junit.Before; import org.junit.Test; @@ -72,7 +74,8 @@ public class TemperatureTextViewTest extends SysuiTestCase { when(mCar.getCarManager(Car.PROPERTY_SERVICE)).thenReturn(mCarPropertyManager); CarServiceProvider carServiceProvider = new CarServiceProvider(mContext, mCar); - mHvacController = new HvacController(carServiceProvider); + mHvacController = new HvacController(carServiceProvider, + new FakeExecutor(new FakeSystemClock())); mHvacController.connectToCarService(); mTextView = new TemperatureTextView(getContext(), /* attrs= */ null); } diff --git a/packages/CarSystemUI/tests/src/com/android/systemui/car/keyguard/CarKeyguardViewControllerTest.java b/packages/CarSystemUI/tests/src/com/android/systemui/car/keyguard/CarKeyguardViewControllerTest.java index 63d4004fb640..062ab4115263 100644 --- a/packages/CarSystemUI/tests/src/com/android/systemui/car/keyguard/CarKeyguardViewControllerTest.java +++ b/packages/CarSystemUI/tests/src/com/android/systemui/car/keyguard/CarKeyguardViewControllerTest.java @@ -36,7 +36,6 @@ import androidx.test.filters.SmallTest; import com.android.keyguard.KeyguardUpdateMonitor; import com.android.keyguard.ViewMediatorCallback; -import com.android.keyguard.dagger.KeyguardBouncerComponent; import com.android.systemui.R; import com.android.systemui.SysuiTestCase; import com.android.systemui.car.CarServiceProvider; @@ -67,9 +66,7 @@ public class CarKeyguardViewControllerTest extends SysuiTestCase { @Mock private CarKeyguardViewController.OnKeyguardCancelClickedListener mCancelClickedListener; @Mock - private KeyguardBouncerComponent.Factory mKeyguardBouncerComponentFactory; - @Mock - private KeyguardBouncerComponent mKeyguardBouncerComponent; + private KeyguardBouncer.Factory mKeyguardBouncerFactory; @Mock private KeyguardBouncer mBouncer; @@ -77,11 +74,10 @@ public class CarKeyguardViewControllerTest extends SysuiTestCase { public void setUp() { MockitoAnnotations.initMocks(this); - when(mKeyguardBouncerComponentFactory.build( + when(mKeyguardBouncerFactory.create( any(ViewGroup.class), any(KeyguardBouncer.BouncerExpansionCallback.class))) - .thenReturn(mKeyguardBouncerComponent); - when(mKeyguardBouncerComponent.createKeyguardBouncer()).thenReturn(mBouncer); + .thenReturn(mBouncer); mCarKeyguardViewController = new CarKeyguardViewController( Handler.getMain(), @@ -92,7 +88,7 @@ public class CarKeyguardViewControllerTest extends SysuiTestCase { () -> mock(BiometricUnlockController.class), mock(ViewMediatorCallback.class), mock(CarNavigationBarController.class), - mKeyguardBouncerComponentFactory + mKeyguardBouncerFactory ); mCarKeyguardViewController.inflate((ViewGroup) LayoutInflater.from(mContext).inflate( R.layout.sysui_overlay_window, /* root= */ null)); diff --git a/packages/CarSystemUI/tests/src/com/android/systemui/car/navigationbar/ButtonSelectionStateControllerTest.java b/packages/CarSystemUI/tests/src/com/android/systemui/car/navigationbar/ButtonSelectionStateControllerTest.java index f623c26d12b6..bd017cd2835b 100644 --- a/packages/CarSystemUI/tests/src/com/android/systemui/car/navigationbar/ButtonSelectionStateControllerTest.java +++ b/packages/CarSystemUI/tests/src/com/android/systemui/car/navigationbar/ButtonSelectionStateControllerTest.java @@ -18,7 +18,7 @@ package com.android.systemui.car.navigationbar; import static com.google.common.truth.Truth.assertThat; -import android.app.ActivityManager; +import android.app.ActivityTaskManager.RootTaskInfo; import android.content.ComponentName; import android.testing.AndroidTestingRunner; import android.testing.TestableLooper; @@ -71,7 +71,7 @@ public class ButtonSelectionStateControllerTest extends SysuiTestCase { public void onTaskChanged_buttonDetectableByComponentName_selectsAssociatedButton() { CarNavigationButton testButton = mTestView.findViewById(R.id.detectable_by_component_name); mComponentName = new ComponentName(TEST_COMPONENT_NAME_PACKAGE, TEST_COMPONENT_NAME_CLASS); - List<ActivityManager.StackInfo> testStack = createTestStack(mComponentName); + List<RootTaskInfo> testStack = createTestStack(mComponentName); testButton.setSelected(false); mButtonSelectionStateController.taskChanged(testStack, /* validDisplay= */ -1); @@ -82,7 +82,7 @@ public class ButtonSelectionStateControllerTest extends SysuiTestCase { public void onTaskChanged_buttonDetectableByCategory_selectsAssociatedButton() { CarNavigationButton testButton = mTestView.findViewById(R.id.detectable_by_category); mComponentName = new ComponentName(TEST_CATEGORY, TEST_CATEGORY_CLASS); - List<ActivityManager.StackInfo> testStack = createTestStack(mComponentName); + List<RootTaskInfo> testStack = createTestStack(mComponentName); testButton.setSelected(false); mButtonSelectionStateController.taskChanged(testStack, /* validDisplay= */ -1); @@ -93,7 +93,7 @@ public class ButtonSelectionStateControllerTest extends SysuiTestCase { public void onTaskChanged_buttonDetectableByPackage_selectsAssociatedButton() { CarNavigationButton testButton = mTestView.findViewById(R.id.detectable_by_package); mComponentName = new ComponentName(TEST_PACKAGE, TEST_PACKAGE_CLASS); - List<ActivityManager.StackInfo> testStack = createTestStack(mComponentName); + List<RootTaskInfo> testStack = createTestStack(mComponentName); testButton.setSelected(false); mButtonSelectionStateController.taskChanged(testStack, /* validDisplay= */ -1); @@ -104,12 +104,12 @@ public class ButtonSelectionStateControllerTest extends SysuiTestCase { public void onTaskChanged_deselectsPreviouslySelectedButton() { CarNavigationButton oldButton = mTestView.findViewById(R.id.detectable_by_component_name); mComponentName = new ComponentName(TEST_COMPONENT_NAME_PACKAGE, TEST_COMPONENT_NAME_CLASS); - List<ActivityManager.StackInfo> oldStack = createTestStack(mComponentName); + List<RootTaskInfo> oldStack = createTestStack(mComponentName); oldButton.setSelected(false); mButtonSelectionStateController.taskChanged(oldStack, /* validDisplay= */ -1); mComponentName = new ComponentName(TEST_PACKAGE, TEST_PACKAGE_CLASS); - List<ActivityManager.StackInfo> newStack = createTestStack(mComponentName); + List<RootTaskInfo> newStack = createTestStack(mComponentName); mButtonSelectionStateController.taskChanged(newStack, /* validDisplay= */ -1); assertButtonUnselected(oldButton); @@ -125,12 +125,12 @@ public class ButtonSelectionStateControllerTest extends SysuiTestCase { assertThat(button.getAlpha()).isEqualTo(CarNavigationButton.DEFAULT_UNSELECTED_ALPHA); } - private List<ActivityManager.StackInfo> createTestStack(ComponentName componentName) { - ActivityManager.StackInfo validStackInfo = new ActivityManager.StackInfo(); + private List<RootTaskInfo> createTestStack(ComponentName componentName) { + RootTaskInfo validStackInfo = new RootTaskInfo(); validStackInfo.displayId = -1; // No display is assigned to this test view validStackInfo.topActivity = componentName; - List<ActivityManager.StackInfo> testStack = new ArrayList<>(); + List<RootTaskInfo> testStack = new ArrayList<>(); testStack.add(validStackInfo); return testStack; diff --git a/packages/CarSystemUI/tests/src/com/android/systemui/car/sideloaded/SideLoadedAppDetectorTest.java b/packages/CarSystemUI/tests/src/com/android/systemui/car/sideloaded/SideLoadedAppDetectorTest.java index 421e2109356d..bf9ac3017436 100644 --- a/packages/CarSystemUI/tests/src/com/android/systemui/car/sideloaded/SideLoadedAppDetectorTest.java +++ b/packages/CarSystemUI/tests/src/com/android/systemui/car/sideloaded/SideLoadedAppDetectorTest.java @@ -23,7 +23,7 @@ import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.when; -import android.app.ActivityManager; +import android.app.ActivityTaskManager.RootTaskInfo; import android.content.ComponentName; import android.content.pm.ApplicationInfo; import android.content.pm.InstallSourceInfo; @@ -79,8 +79,8 @@ public class SideLoadedAppDetectorTest extends SysuiTestCase { @Test public void isSafe_systemApp_returnsTrue() throws Exception { - ActivityManager.StackInfo stackInfo = new ActivityManager.StackInfo(); - stackInfo.topActivity = new ComponentName(APP_PACKAGE_NAME, APP_CLASS_NAME); + RootTaskInfo taskInfo = new RootTaskInfo(); + taskInfo.topActivity = new ComponentName(APP_PACKAGE_NAME, APP_CLASS_NAME); ApplicationInfo applicationInfo = new ApplicationInfo(); applicationInfo.packageName = APP_PACKAGE_NAME; @@ -89,13 +89,13 @@ public class SideLoadedAppDetectorTest extends SysuiTestCase { when(mPackageManager.getApplicationInfoAsUser(eq(APP_PACKAGE_NAME), anyInt(), any())) .thenReturn(applicationInfo); - assertThat(mSideLoadedAppDetector.isSafe(stackInfo)).isTrue(); + assertThat(mSideLoadedAppDetector.isSafe(taskInfo)).isTrue(); } @Test public void isSafe_updatedSystemApp_returnsTrue() throws Exception { - ActivityManager.StackInfo stackInfo = new ActivityManager.StackInfo(); - stackInfo.topActivity = new ComponentName(APP_PACKAGE_NAME, APP_CLASS_NAME); + RootTaskInfo taskInfo = new RootTaskInfo(); + taskInfo.topActivity = new ComponentName(APP_PACKAGE_NAME, APP_CLASS_NAME); ApplicationInfo applicationInfo = new ApplicationInfo(); applicationInfo.packageName = APP_PACKAGE_NAME; @@ -104,7 +104,7 @@ public class SideLoadedAppDetectorTest extends SysuiTestCase { when(mPackageManager.getApplicationInfoAsUser(eq(APP_PACKAGE_NAME), anyInt(), any())) .thenReturn(applicationInfo); - assertThat(mSideLoadedAppDetector.isSafe(stackInfo)).isTrue(); + assertThat(mSideLoadedAppDetector.isSafe(taskInfo)).isTrue(); } @Test @@ -113,8 +113,8 @@ public class SideLoadedAppDetectorTest extends SysuiTestCase { /* initiatingPackageSigningInfo= */null, /* originatingPackageName= */ null, /* installingPackageName= */ null); - ActivityManager.StackInfo stackInfo = new ActivityManager.StackInfo(); - stackInfo.topActivity = new ComponentName(APP_PACKAGE_NAME, APP_CLASS_NAME); + RootTaskInfo taskInfo = new RootTaskInfo(); + taskInfo.topActivity = new ComponentName(APP_PACKAGE_NAME, APP_CLASS_NAME); ApplicationInfo applicationInfo = new ApplicationInfo(); applicationInfo.packageName = APP_PACKAGE_NAME; @@ -123,7 +123,7 @@ public class SideLoadedAppDetectorTest extends SysuiTestCase { .thenReturn(applicationInfo); when(mPackageManager.getInstallSourceInfo(APP_PACKAGE_NAME)).thenReturn(sourceInfo); - assertThat(mSideLoadedAppDetector.isSafe(stackInfo)).isTrue(); + assertThat(mSideLoadedAppDetector.isSafe(taskInfo)).isTrue(); } @Test @@ -132,8 +132,8 @@ public class SideLoadedAppDetectorTest extends SysuiTestCase { /* initiatingPackageSigningInfo= */null, /* originatingPackageName= */ null, /* installingPackageName= */ null); - ActivityManager.StackInfo stackInfo = new ActivityManager.StackInfo(); - stackInfo.topActivity = new ComponentName(APP_PACKAGE_NAME, APP_CLASS_NAME); + RootTaskInfo taskInfo = new RootTaskInfo(); + taskInfo.topActivity = new ComponentName(APP_PACKAGE_NAME, APP_CLASS_NAME); ApplicationInfo applicationInfo = new ApplicationInfo(); applicationInfo.packageName = APP_PACKAGE_NAME; @@ -142,7 +142,7 @@ public class SideLoadedAppDetectorTest extends SysuiTestCase { .thenReturn(applicationInfo); when(mPackageManager.getInstallSourceInfo(APP_PACKAGE_NAME)).thenReturn(sourceInfo); - assertThat(mSideLoadedAppDetector.isSafe(stackInfo)).isFalse(); + assertThat(mSideLoadedAppDetector.isSafe(taskInfo)).isFalse(); } @Test @@ -151,8 +151,8 @@ public class SideLoadedAppDetectorTest extends SysuiTestCase { /* initiatingPackageSigningInfo= */null, /* originatingPackageName= */ null, /* installingPackageName= */ null); - ActivityManager.StackInfo stackInfo = new ActivityManager.StackInfo(); - stackInfo.topActivity = new ComponentName(APP_PACKAGE_NAME, APP_CLASS_NAME); + RootTaskInfo taskInfo = new RootTaskInfo(); + taskInfo.topActivity = new ComponentName(APP_PACKAGE_NAME, APP_CLASS_NAME); ApplicationInfo applicationInfo = new ApplicationInfo(); applicationInfo.packageName = APP_PACKAGE_NAME; @@ -161,6 +161,6 @@ public class SideLoadedAppDetectorTest extends SysuiTestCase { .thenReturn(applicationInfo); when(mPackageManager.getInstallSourceInfo(APP_PACKAGE_NAME)).thenReturn(sourceInfo); - assertThat(mSideLoadedAppDetector.isSafe(stackInfo)).isFalse(); + assertThat(mSideLoadedAppDetector.isSafe(taskInfo)).isFalse(); } } diff --git a/packages/CarSystemUI/tests/src/com/android/systemui/car/sideloaded/SideLoadedAppListenerTest.java b/packages/CarSystemUI/tests/src/com/android/systemui/car/sideloaded/SideLoadedAppListenerTest.java index 67f222b9e29a..0b5f68f76ebc 100644 --- a/packages/CarSystemUI/tests/src/com/android/systemui/car/sideloaded/SideLoadedAppListenerTest.java +++ b/packages/CarSystemUI/tests/src/com/android/systemui/car/sideloaded/SideLoadedAppListenerTest.java @@ -21,7 +21,7 @@ import static org.mockito.Mockito.never; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; -import android.app.ActivityManager.StackInfo; +import android.app.ActivityTaskManager.RootTaskInfo; import android.app.IActivityTaskManager; import android.content.ComponentName; import android.hardware.display.DisplayManager; @@ -81,22 +81,22 @@ public class SideLoadedAppListenerTest extends SysuiTestCase { int displayId = 123; ComponentName componentName = new ComponentName(APP_PACKAGE_NAME, APP_CLASS_NAME); - StackInfo stackInfo1 = createTask(1, /* isVisible= */ true); - stackInfo1.taskIds = new int[] { 11, 22, 33 }; + RootTaskInfo taskInfo1 = createTask(1, /* isVisible= */ true); + taskInfo1.childTaskIds = new int[] { 11, 22, 33 }; - StackInfo stackInfo2 = createTask(2, /* isVisible= */ true); - stackInfo2.taskIds = new int[] { 111, 222, 333, taskId }; - stackInfo2.displayId = displayId; + RootTaskInfo taskInfo2 = createTask(2, /* isVisible= */ true); + taskInfo2.childTaskIds = new int[] { 111, 222, 333, taskId }; + taskInfo2.displayId = displayId; - List<StackInfo> stackInfoList = Arrays.asList(stackInfo1, stackInfo2); + List<RootTaskInfo> taskInfoList = Arrays.asList(taskInfo1, taskInfo2); - when(mActivityTaskManager.getAllStackInfos()).thenReturn(stackInfoList); - when(mSideLoadedAppDetector.isSafe(stackInfo2)).thenReturn(true); + when(mActivityTaskManager.getAllRootTaskInfos()).thenReturn(taskInfoList); + when(mSideLoadedAppDetector.isSafe(taskInfo2)).thenReturn(true); mSideLoadedAppListener.onTaskCreated(taskId, componentName); - verify(mSideLoadedAppDetector, never()).isSafe(stackInfo1); - verify(mSideLoadedAppDetector).isSafe(stackInfo2); + verify(mSideLoadedAppDetector, never()).isSafe(taskInfo1); + verify(mSideLoadedAppDetector).isSafe(taskInfo2); verify(mSideLoadedAppStateController, never()).onUnsafeTaskCreatedOnDisplay(any()); verify(mSideLoadedAppStateController, never()).onSafeTaskDisplayedOnDisplay(any()); @@ -109,23 +109,23 @@ public class SideLoadedAppListenerTest extends SysuiTestCase { int displayId = 123; ComponentName componentName = new ComponentName(APP_PACKAGE_NAME, APP_CLASS_NAME); - StackInfo stackInfo1 = createTask(1, /* isVisible= */ true); - stackInfo1.taskIds = new int[] { 11, 22, 33 }; - StackInfo stackInfo2 = createTask(2, /* isVisible= */ true); - stackInfo2.taskIds = new int[] { 111, 222, 333, taskId }; - stackInfo2.displayId = displayId; - List<StackInfo> stackInfoList = Arrays.asList(stackInfo1, stackInfo2); + RootTaskInfo taskInfo1 = createTask(1, /* isVisible= */ true); + taskInfo1.childTaskIds = new int[] { 11, 22, 33 }; + RootTaskInfo taskInfo2 = createTask(2, /* isVisible= */ true); + taskInfo2.childTaskIds = new int[] { 111, 222, 333, taskId }; + taskInfo2.displayId = displayId; + List<RootTaskInfo> taskInfoList = Arrays.asList(taskInfo1, taskInfo2); Display display = createDisplay(displayId); - when(mActivityTaskManager.getAllStackInfos()).thenReturn(stackInfoList); - when(mSideLoadedAppDetector.isSafe(stackInfo2)).thenReturn(false); + when(mActivityTaskManager.getAllRootTaskInfos()).thenReturn(taskInfoList); + when(mSideLoadedAppDetector.isSafe(taskInfo2)).thenReturn(false); when(mDisplayManager.getDisplay(displayId)).thenReturn(display); mSideLoadedAppListener.onTaskCreated(taskId, componentName); - verify(mSideLoadedAppDetector, never()).isSafe(stackInfo1); - verify(mSideLoadedAppDetector).isSafe(stackInfo2); + verify(mSideLoadedAppDetector, never()).isSafe(taskInfo1); + verify(mSideLoadedAppDetector).isSafe(taskInfo2); verify(mSideLoadedAppStateController).onUnsafeTaskCreatedOnDisplay(display); verify(mSideLoadedAppStateController, never()).onSafeTaskDisplayedOnDisplay(any()); @@ -135,21 +135,21 @@ public class SideLoadedAppListenerTest extends SysuiTestCase { @Test public void onTaskStackChanged_safeTask_callsSafeTaskDisplayed() throws Exception { Display display = createDisplay(123); - StackInfo stackInfo1 = createTask(1, /* isVisible= */ false); - StackInfo stackInfo2 = createTask(2, /* isVisible= */ true); - StackInfo stackInfo3 = createTask(3, /* isVisible= */ true); - List<StackInfo> stackInfoList = Arrays.asList(stackInfo1, stackInfo2, stackInfo3); - - when(mActivityTaskManager.getAllStackInfosOnDisplay(display.getDisplayId())) - .thenReturn(stackInfoList); - when(mSideLoadedAppDetector.isSafe(stackInfo2)).thenReturn(true); + RootTaskInfo taskInfo1 = createTask(1, /* isVisible= */ false); + RootTaskInfo taskInfo2 = createTask(2, /* isVisible= */ true); + RootTaskInfo taskInfo3 = createTask(3, /* isVisible= */ true); + List<RootTaskInfo> taskInfoList = Arrays.asList(taskInfo1, taskInfo2, taskInfo3); + + when(mActivityTaskManager.getAllRootTaskInfosOnDisplay(display.getDisplayId())) + .thenReturn(taskInfoList); + when(mSideLoadedAppDetector.isSafe(taskInfo2)).thenReturn(true); when(mDisplayManager.getDisplays()).thenReturn(new Display[] { display }); mSideLoadedAppListener.onTaskStackChanged(); - verify(mSideLoadedAppDetector, never()).isSafe(stackInfo1); - verify(mSideLoadedAppDetector).isSafe(stackInfo2); - verify(mSideLoadedAppDetector, never()).isSafe(stackInfo3); + verify(mSideLoadedAppDetector, never()).isSafe(taskInfo1); + verify(mSideLoadedAppDetector).isSafe(taskInfo2); + verify(mSideLoadedAppDetector, never()).isSafe(taskInfo3); verify(mSideLoadedAppStateController, never()).onUnsafeTaskCreatedOnDisplay(any()); verify(mSideLoadedAppStateController).onSafeTaskDisplayedOnDisplay(display); @@ -159,21 +159,21 @@ public class SideLoadedAppListenerTest extends SysuiTestCase { @Test public void onTaskStackChanged_unsafeTask_callsUnsafeTaskDisplayed() throws Exception { Display display = createDisplay(123); - StackInfo stackInfo1 = createTask(1, /* isVisible= */ false); - StackInfo stackInfo2 = createTask(2, /* isVisible= */ true); - StackInfo stackInfo3 = createTask(3, /* isVisible= */ true); - List<StackInfo> stackInfoList = Arrays.asList(stackInfo1, stackInfo2, stackInfo3); - - when(mActivityTaskManager.getAllStackInfosOnDisplay(display.getDisplayId())) - .thenReturn(stackInfoList); - when(mSideLoadedAppDetector.isSafe(stackInfo2)).thenReturn(false); + RootTaskInfo taskInfo1 = createTask(1, /* isVisible= */ false); + RootTaskInfo taskInfo2 = createTask(2, /* isVisible= */ true); + RootTaskInfo taskInfo3 = createTask(3, /* isVisible= */ true); + List<RootTaskInfo> taskInfoList = Arrays.asList(taskInfo1, taskInfo2, taskInfo3); + + when(mActivityTaskManager.getAllRootTaskInfosOnDisplay(display.getDisplayId())) + .thenReturn(taskInfoList); + when(mSideLoadedAppDetector.isSafe(taskInfo2)).thenReturn(false); when(mDisplayManager.getDisplays()).thenReturn(new Display[] { display }); mSideLoadedAppListener.onTaskStackChanged(); - verify(mSideLoadedAppDetector, never()).isSafe(stackInfo1); - verify(mSideLoadedAppDetector).isSafe(stackInfo2); - verify(mSideLoadedAppDetector, never()).isSafe(stackInfo3); + verify(mSideLoadedAppDetector, never()).isSafe(taskInfo1); + verify(mSideLoadedAppDetector).isSafe(taskInfo2); + verify(mSideLoadedAppDetector, never()).isSafe(taskInfo3); verify(mSideLoadedAppStateController, never()).onUnsafeTaskCreatedOnDisplay(any()); verify(mSideLoadedAppStateController, never()).onSafeTaskDisplayedOnDisplay(any()); @@ -183,40 +183,40 @@ public class SideLoadedAppListenerTest extends SysuiTestCase { @Test public void onTaskStackChanged_multiDisplay_callsTasksDisplayed() throws Exception { Display display1 = createDisplay(1); - StackInfo stackInfo1 = createTask(1, /* isVisible= */ false); - StackInfo stackInfo2 = createTask(2, /* isVisible= */ true); - StackInfo stackInfo3 = createTask(3, /* isVisible= */ true); - List<StackInfo> display1Stack = Arrays.asList(stackInfo1, stackInfo2, stackInfo3); + RootTaskInfo taskInfo1 = createTask(1, /* isVisible= */ false); + RootTaskInfo taskInfo2 = createTask(2, /* isVisible= */ true); + RootTaskInfo taskInfo3 = createTask(3, /* isVisible= */ true); + List<RootTaskInfo> display1Tasks = Arrays.asList(taskInfo1, taskInfo2, taskInfo3); Display display2 = createDisplay(2); - StackInfo stackInfo4 = createTask(4, /* isVisible= */ true); - List<StackInfo> display2Stack = Collections.singletonList(stackInfo4); + RootTaskInfo taskInfo4 = createTask(4, /* isVisible= */ true); + List<RootTaskInfo> display2Tasks = Collections.singletonList(taskInfo4); Display display3 = createDisplay(3); - StackInfo stackInfo5 = createTask(5, /* isVisible= */ true); - List<StackInfo> display3Stack = Collections.singletonList(stackInfo5); + RootTaskInfo taskInfo5 = createTask(5, /* isVisible= */ true); + List<RootTaskInfo> display3Tasks = Collections.singletonList(taskInfo5); - when(mActivityTaskManager.getAllStackInfosOnDisplay(display1.getDisplayId())) - .thenReturn(display1Stack); - when(mActivityTaskManager.getAllStackInfosOnDisplay(display2.getDisplayId())) - .thenReturn(display2Stack); - when(mActivityTaskManager.getAllStackInfosOnDisplay(display3.getDisplayId())) - .thenReturn(display3Stack); + when(mActivityTaskManager.getAllRootTaskInfosOnDisplay(display1.getDisplayId())) + .thenReturn(display1Tasks); + when(mActivityTaskManager.getAllRootTaskInfosOnDisplay(display2.getDisplayId())) + .thenReturn(display2Tasks); + when(mActivityTaskManager.getAllRootTaskInfosOnDisplay(display3.getDisplayId())) + .thenReturn(display3Tasks); - when(mSideLoadedAppDetector.isSafe(stackInfo2)).thenReturn(true); - when(mSideLoadedAppDetector.isSafe(stackInfo4)).thenReturn(false); - when(mSideLoadedAppDetector.isSafe(stackInfo5)).thenReturn(true); + when(mSideLoadedAppDetector.isSafe(taskInfo2)).thenReturn(true); + when(mSideLoadedAppDetector.isSafe(taskInfo4)).thenReturn(false); + when(mSideLoadedAppDetector.isSafe(taskInfo5)).thenReturn(true); when(mDisplayManager.getDisplays()) .thenReturn(new Display[] { display1, display2, display3}); mSideLoadedAppListener.onTaskStackChanged(); - verify(mSideLoadedAppDetector, never()).isSafe(stackInfo1); - verify(mSideLoadedAppDetector).isSafe(stackInfo2); - verify(mSideLoadedAppDetector, never()).isSafe(stackInfo3); - verify(mSideLoadedAppDetector).isSafe(stackInfo4); - verify(mSideLoadedAppDetector).isSafe(stackInfo5); + verify(mSideLoadedAppDetector, never()).isSafe(taskInfo1); + verify(mSideLoadedAppDetector).isSafe(taskInfo2); + verify(mSideLoadedAppDetector, never()).isSafe(taskInfo3); + verify(mSideLoadedAppDetector).isSafe(taskInfo4); + verify(mSideLoadedAppDetector).isSafe(taskInfo5); verify(mSideLoadedAppStateController, never()).onUnsafeTaskCreatedOnDisplay(any()); verify(mSideLoadedAppStateController).onSafeTaskDisplayedOnDisplay(display1); @@ -234,10 +234,10 @@ public class SideLoadedAppListenerTest extends SysuiTestCase { DisplayAdjustments.DEFAULT_DISPLAY_ADJUSTMENTS); } - private StackInfo createTask(int id, boolean isVisible) { - StackInfo stackInfo = new StackInfo(); - stackInfo.stackId = id; - stackInfo.visible = isVisible; - return stackInfo; + private RootTaskInfo createTask(int id, boolean isVisible) { + RootTaskInfo taskInfo = new RootTaskInfo(); + taskInfo.taskId = id; + taskInfo.visible = isVisible; + return taskInfo; } } diff --git a/packages/PackageInstaller/res/values-ar/strings.xml b/packages/PackageInstaller/res/values-ar/strings.xml index 87f89ce192c4..c840374d3f6b 100644 --- a/packages/PackageInstaller/res/values-ar/strings.xml +++ b/packages/PackageInstaller/res/values-ar/strings.xml @@ -57,7 +57,7 @@ <string name="uninstall_application_text_all_users" msgid="575491774380227119">"هل تريد إزالة هذا التطبيق "<b>"لكل"</b>" المستخدمين؟ ستتم إزالة التطبيق وبياناته من "<b>"كل"</b>" المستخدمين على هذا الجهاز."</string> <string name="uninstall_application_text_user" msgid="498072714173920526">"هل تريد إزالة هذا التطبيق للمستخدم <xliff:g id="USERNAME">%1$s</xliff:g>؟"</string> <string name="uninstall_update_text" msgid="863648314632448705">"هل تريد استبدال هذا التطبيق بإصدار المصنع؟ ستتم إزالة جميع البيانات."</string> - <string name="uninstall_update_text_multiuser" msgid="8992883151333057227">"هل تريد استبدال هذا التطبيق بإصدار المصنع؟ ستتم إزالة جميع البيانات. وسيؤثر هذا في جميع مستخدمي هذا الجهاز، بما في ذلك من لديهم ملفات شخصية للعمل."</string> + <string name="uninstall_update_text_multiuser" msgid="8992883151333057227">"هل تريد إعادة ضبط هذا التطبيق على الإعدادات الأصلية؟ سؤدي ذلك إلى إزالة جميع البيانات، كما سيؤثر على جميع مستخدمي هذا الجهاز، بما في ذلك من لديهم ملفات شخصية للعمل."</string> <string name="uninstall_keep_data" msgid="7002379587465487550">"الاحتفاظ بالحجم <xliff:g id="SIZE">%1$s</xliff:g> من بيانات التطبيق."</string> <string name="uninstalling_notification_channel" msgid="840153394325714653">"عمليات إلغاء التثبيت الجارية"</string> <string name="uninstall_failure_notification_channel" msgid="1136405866767576588">"عمليات إلغاء التثبيت غير الناجحة"</string> diff --git a/packages/SettingsLib/res/values-be/strings.xml b/packages/SettingsLib/res/values-be/strings.xml index 8f71509772fc..7f6237da9ee0 100644 --- a/packages/SettingsLib/res/values-be/strings.xml +++ b/packages/SettingsLib/res/values-be/strings.xml @@ -212,7 +212,7 @@ <string name="adb_wireless_settings" msgid="2295017847215680229">"Адладка па Wi-Fi"</string> <string name="adb_wireless_list_empty_off" msgid="1713707973837255490">"Каб праглядаць і выкарыстоўваць даступныя прылады, уключыце адладку па Wi-Fi"</string> <string name="adb_pair_method_qrcode_title" msgid="6982904096137468634">"Спалучыць прыладу з дапамогай QR-кода"</string> - <string name="adb_pair_method_qrcode_summary" msgid="7130694277228970888">"Спалучаць новыя прылады з дапамогай сканера QR-кода"</string> + <string name="adb_pair_method_qrcode_summary" msgid="7130694277228970888">"Спалучаць новыя прылады з дапамогай сканера QR-кодаў"</string> <string name="adb_pair_method_code_title" msgid="1122590300445142904">"Спалучыць прыладу з дапамогай кода спалучэння"</string> <string name="adb_pair_method_code_summary" msgid="6370414511333685185">"Спалучаць новыя прылады з дапамогай шасцізначнага кода"</string> <string name="adb_paired_devices_title" msgid="5268997341526217362">"Спалучаныя прылады"</string> diff --git a/packages/SettingsLib/res/values-eu/strings.xml b/packages/SettingsLib/res/values-eu/strings.xml index dcdadbdf3454..4a11aa77c7fc 100644 --- a/packages/SettingsLib/res/values-eu/strings.xml +++ b/packages/SettingsLib/res/values-eu/strings.xml @@ -400,7 +400,7 @@ <string name="inactive_app_active_summary" msgid="8047630990208722344">"Aktibo. Aldatzeko, sakatu hau."</string> <string name="standby_bucket_summary" msgid="5128193447550429600">"Egonean moduko aplikazioaren egoera: <xliff:g id="BUCKET"> %s</xliff:g>"</string> <string name="runningservices_settings_title" msgid="6460099290493086515">"Abian diren zerbitzuak"</string> - <string name="runningservices_settings_summary" msgid="1046080643262665743">"Ikusi eta kontrolatu unean abian diren zerbitzuak"</string> + <string name="runningservices_settings_summary" msgid="1046080643262665743">"Ikusi eta kontrolatu une honetan abian diren zerbitzuak"</string> <string name="select_webview_provider_title" msgid="3917815648099445503">"WebView inplementazioa"</string> <string name="select_webview_provider_dialog_title" msgid="2444261109877277714">"Ezarri WebView inplementazioa"</string> <string name="select_webview_provider_toast_text" msgid="8512254949169359848">"Jada ez dago erabilgarri aukera hori. Saiatu berriro."</string> diff --git a/packages/SettingsLib/res/values-ja/arrays.xml b/packages/SettingsLib/res/values-ja/arrays.xml index 743017c82e3a..7a4e71b18ec0 100644 --- a/packages/SettingsLib/res/values-ja/arrays.xml +++ b/packages/SettingsLib/res/values-ja/arrays.xml @@ -243,7 +243,7 @@ </string-array> <string-array name="track_frame_time_entries"> <item msgid="634406443901014984">"OFF"</item> - <item msgid="1288760936356000927">"バーとして画面に表示"</item> + <item msgid="1288760936356000927">"棒グラフとして画面に表示"</item> <item msgid="5023908510820531131">"<xliff:g id="AS_TYPED_COMMAND">adb shell dumpsys gfxinfo</xliff:g> 内"</item> </string-array> <string-array name="debug_hw_overdraw_entries"> diff --git a/packages/SettingsLib/res/values-ky/strings.xml b/packages/SettingsLib/res/values-ky/strings.xml index c4b5f7e7477f..419c18f3b8c6 100644 --- a/packages/SettingsLib/res/values-ky/strings.xml +++ b/packages/SettingsLib/res/values-ky/strings.xml @@ -396,8 +396,8 @@ <item msgid="1282170165150762976">"Санарип мазмун үчүн оптималдаштырылган түстөр"</item> </string-array> <string name="inactive_apps_title" msgid="5372523625297212320">"Көшүү режиминдеги колдонмолор"</string> - <string name="inactive_app_inactive_summary" msgid="3161222402614236260">"Иштеген жок. Которуштуруу үчүн таптап коюңуз."</string> - <string name="inactive_app_active_summary" msgid="8047630990208722344">"Иштеп турат. Которуштуруу үчүн таптап коюңуз."</string> + <string name="inactive_app_inactive_summary" msgid="3161222402614236260">"Иштеген жок. Күйгүзүү үчүн басып коюңуз."</string> + <string name="inactive_app_active_summary" msgid="8047630990208722344">"Иштеп турат. Өчүрүү үчүн басып коюңуз."</string> <string name="standby_bucket_summary" msgid="5128193447550429600">"Көшүү режиминдеги колдонмонун абалы:<xliff:g id="BUCKET"> %s</xliff:g>"</string> <string name="runningservices_settings_title" msgid="6460099290493086515">"Иштеп жаткан кызматтар"</string> <string name="runningservices_settings_summary" msgid="1046080643262665743">"Учурда иштеп жаткан кызматтарды көрүп, көзөмөлдөп турасыз"</string> diff --git a/packages/SettingsLib/res/values-mk/strings.xml b/packages/SettingsLib/res/values-mk/strings.xml index fb7b63410a5f..58d4af1c2c64 100644 --- a/packages/SettingsLib/res/values-mk/strings.xml +++ b/packages/SettingsLib/res/values-mk/strings.xml @@ -204,10 +204,10 @@ <string name="tethering_settings_not_available" msgid="266821736434699780">"Поставките за спојување не се достапни за овој корисник"</string> <string name="apn_settings_not_available" msgid="1147111671403342300">"Поставките за името на пристапната точка не се достапни за овој корисник"</string> <string name="enable_adb" msgid="8072776357237289039">"Отстранување грешки на USB"</string> - <string name="enable_adb_summary" msgid="3711526030096574316">"Режим на отстранување грешки кога е поврзано USB"</string> + <string name="enable_adb_summary" msgid="3711526030096574316">"Режим за отстранување грешки кога е поврзано USB"</string> <string name="clear_adb_keys" msgid="3010148733140369917">"Отповикај овластувања за отстранување грешки од USB"</string> <string name="enable_adb_wireless" msgid="6973226350963971018">"Безжично отстранување грешки"</string> - <string name="enable_adb_wireless_summary" msgid="7344391423657093011">"Режим на отстранување грешки кога е поврзано Wi‑Fi"</string> + <string name="enable_adb_wireless_summary" msgid="7344391423657093011">"Режим за отстранување грешки кога е поврзано Wi‑Fi"</string> <string name="adb_wireless_error" msgid="721958772149779856">"Грешка"</string> <string name="adb_wireless_settings" msgid="2295017847215680229">"Безжично отстранување грешки"</string> <string name="adb_wireless_list_empty_off" msgid="1713707973837255490">"За да ги гледате и користите достапните уреди, вклучете го безжичното отстранување грешки"</string> diff --git a/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java b/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java index c5e66bef9653..a81a05f1147a 100644 --- a/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java +++ b/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java @@ -116,6 +116,16 @@ public class AccessPoint implements Comparable<AccessPoint> { */ public static final int HIGHER_FREQ_5GHZ = 5900; + /** + * Lower bound on the 60 GHz (802.11ad) WIGIG channels + */ + public static final int LOWER_FREQ_60GHZ = 58320; + + /** + * Upper bound on the 60 GHz (802.11ad) WIGIG channels + */ + public static final int HIGHER_FREQ_60GHZ = 70200; + /** The key which identifies this AccessPoint grouping. */ private String mKey; diff --git a/packages/SettingsLib/src/com/android/settingslib/wifi/WifiUtils.java b/packages/SettingsLib/src/com/android/settingslib/wifi/WifiUtils.java index 1ace0b4250b9..15b146deb1cb 100644 --- a/packages/SettingsLib/src/com/android/settingslib/wifi/WifiUtils.java +++ b/packages/SettingsLib/src/com/android/settingslib/wifi/WifiUtils.java @@ -93,6 +93,7 @@ public class WifiUtils { StringBuilder visibility = new StringBuilder(); StringBuilder scans24GHz = new StringBuilder(); StringBuilder scans5GHz = new StringBuilder(); + StringBuilder scans60GHz = new StringBuilder(); String bssid = null; if (accessPoint.isActive() && info != null) { @@ -115,9 +116,11 @@ public class WifiUtils { int maxRssi5 = INVALID_RSSI; int maxRssi24 = INVALID_RSSI; + int maxRssi60 = INVALID_RSSI; final int maxDisplayedScans = 4; int num5 = 0; // number of scanned BSSID on 5GHz band int num24 = 0; // number of scanned BSSID on 2.4Ghz band + int num60 = 0; // number of scanned BSSID on 60Ghz band int numBlockListed = 0; // TODO: sort list by RSSI or age @@ -152,6 +155,19 @@ public class WifiUtils { verboseScanResultSummary(accessPoint, result, bssid, nowMs)); } + } else if (result.frequency >= AccessPoint.LOWER_FREQ_60GHZ + && result.frequency <= AccessPoint.HIGHER_FREQ_60GHZ) { + // Strictly speaking: [60000, 61000] + num60++; + + if (result.level > maxRssi60) { + maxRssi60 = result.level; + } + if (num60 <= maxDisplayedScans) { + scans60GHz.append( + verboseScanResultSummary(accessPoint, result, bssid, + nowMs)); + } } } visibility.append(" ["); @@ -170,6 +186,14 @@ public class WifiUtils { } visibility.append(scans5GHz.toString()); } + visibility.append(";"); + if (num60 > 0) { + visibility.append("(").append(num60).append(")"); + if (num60 > maxDisplayedScans) { + visibility.append("max=").append(maxRssi60).append(","); + } + visibility.append(scans60GHz.toString()); + } if (numBlockListed > 0) { visibility.append("!").append(numBlockListed); } diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java index a29314817a8f..dd2aa3bbbdf5 100644 --- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java +++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java @@ -58,10 +58,14 @@ class SettingsProtoDumpUtil { ConfigSettingsProto.CONNECTIVITY_SETTINGS); namespaceToFieldMap.put(DeviceConfig.NAMESPACE_CONTENT_CAPTURE, ConfigSettingsProto.CONTENT_CAPTURE_SETTINGS); + namespaceToFieldMap.put(DeviceConfig.NAMESPACE_DEVICE_IDLE, + ConfigSettingsProto.DEVICE_IDLE_SETTINGS); namespaceToFieldMap.put(DeviceConfig.NAMESPACE_GAME_DRIVER, ConfigSettingsProto.GAME_DRIVER_SETTINGS); namespaceToFieldMap.put(DeviceConfig.NAMESPACE_INPUT_NATIVE_BOOT, ConfigSettingsProto.INPUT_NATIVE_BOOT_SETTINGS); + namespaceToFieldMap.put(DeviceConfig.NAMESPACE_JOB_SCHEDULER, + ConfigSettingsProto.JOB_SCHEDULER_SETTINGS); namespaceToFieldMap.put(DeviceConfig.NAMESPACE_NETD_NATIVE, ConfigSettingsProto.NETD_NATIVE_SETTINGS); namespaceToFieldMap.put(DeviceConfig.NAMESPACE_PRIVACY, @@ -564,9 +568,6 @@ class SettingsProtoDumpUtil { Settings.Global.DEVICE_PROVISIONING_MOBILE_DATA_ENABLED, GlobalSettingsProto.Device.PROVISIONING_MOBILE_DATA_ENABLED); dumpSetting(s, p, - Settings.Global.DEVICE_IDLE_CONSTANTS, - GlobalSettingsProto.Device.IDLE_CONSTANTS); - dumpSetting(s, p, Settings.Global.DEVICE_POLICY_CONSTANTS, GlobalSettingsProto.Device.POLICY_CONSTANTS); dumpSetting(s, p, @@ -1776,6 +1777,9 @@ class SettingsProtoDumpUtil { Settings.Secure.ACCESSIBILITY_HIGH_TEXT_CONTRAST_ENABLED, SecureSettingsProto.Accessibility.HIGH_TEXT_CONTRAST_ENABLED); dumpSetting(s, p, + Settings.Secure.FORCE_BOLD_TEXT, + SecureSettingsProto.FORCE_BOLD_TEXT); + dumpSetting(s, p, Settings.Secure.ACCESSIBILITY_LARGE_POINTER_ICON, SecureSettingsProto.Accessibility.LARGE_POINTER_ICON); dumpSetting(s, p, diff --git a/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java b/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java index f219aecfc9d9..d8f772d7f440 100644 --- a/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java +++ b/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java @@ -230,7 +230,6 @@ public class SettingsBackupTest { Settings.Global.DEVELOPMENT_ENABLE_SIZECOMPAT_FREEFORM, Settings.Global.DEVELOPMENT_RENDER_SHADOWS_IN_COMPOSITOR, Settings.Global.DEVICE_DEMO_MODE, - Settings.Global.DEVICE_IDLE_CONSTANTS, Settings.Global.BATTERY_SAVER_ADAPTIVE_CONSTANTS, Settings.Global.BATTERY_SAVER_CONSTANTS, Settings.Global.BATTERY_TIP_CONSTANTS, diff --git a/packages/Shell/AndroidManifest.xml b/packages/Shell/AndroidManifest.xml index 319b44ce216f..190015cebe30 100644 --- a/packages/Shell/AndroidManifest.xml +++ b/packages/Shell/AndroidManifest.xml @@ -217,6 +217,9 @@ <!-- Permission needed for CTS test - UnsupportedErrorDialogTests --> <uses-permission android:name="android.permission.RESET_APP_ERRORS" /> + <!-- Permission needed for CTS test - CtsSystemUiTestCases:PipNotificationTests --> + <uses-permission android:name="android.permission.GET_INTENT_SENDER_INTENT" /> + <!-- Permission needed to run keyguard manager tests in CTS --> <uses-permission android:name="android.permission.CONTROL_KEYGUARD_SECURE_NOTIFICATIONS" /> diff --git a/packages/SimAppDialog/Android.bp b/packages/SimAppDialog/Android.bp index 1c680bb9d25e..176035f73b65 100644 --- a/packages/SimAppDialog/Android.bp +++ b/packages/SimAppDialog/Android.bp @@ -7,8 +7,7 @@ android_app { static_libs: [ "androidx.legacy_legacy-support-v4", - "setupcompat", - "setupdesign", + "setup-wizard-lib", ], resource_dirs: ["res"], diff --git a/packages/SimAppDialog/AndroidManifest.xml b/packages/SimAppDialog/AndroidManifest.xml index e7368f35ed5a..873f6c5bac54 100644 --- a/packages/SimAppDialog/AndroidManifest.xml +++ b/packages/SimAppDialog/AndroidManifest.xml @@ -23,7 +23,7 @@ android:name=".InstallCarrierAppActivity" android:exported="true" android:permission="android.permission.NETWORK_SETTINGS" - android:theme="@style/SudThemeGlif.Light"> + android:theme="@style/SuwThemeGlif.Light"> </activity> </application> </manifest> diff --git a/packages/SimAppDialog/res/layout/install_carrier_app_activity.xml b/packages/SimAppDialog/res/layout/install_carrier_app_activity.xml index 68113dbf5df0..12f9bb6b13ea 100644 --- a/packages/SimAppDialog/res/layout/install_carrier_app_activity.xml +++ b/packages/SimAppDialog/res/layout/install_carrier_app_activity.xml @@ -14,17 +14,18 @@ See the License for the specific language governing permissions and limitations under the License. --> -<com.google.android.setupdesign.GlifLayout +<com.android.setupwizardlib.GlifLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:id="@+id/setup_wizard_layout" android:layout_width="match_parent" android:layout_height="match_parent" android:icon="@drawable/ic_signal_cellular_alt_rounded" - app:sucHeaderText="@string/install_carrier_app_title"> + app:suwHeaderText="@string/install_carrier_app_title" + app:suwFooter="@layout/install_carrier_app_footer"> <LinearLayout - style="@style/SudContentFrame" + style="@style/SuwContentFrame" android:id="@+id/content_frame" android:layout_width="match_parent" android:layout_height="wrap_content" @@ -32,12 +33,12 @@ <TextView android:id="@+id/install_carrier_app_description" - style="@style/SudDescription.Glif" + style="@style/SuwDescription.Glif" android:text="@string/install_carrier_app_description_default" android:layout_width="match_parent" android:layout_height="wrap_content"/> - <com.google.android.setupdesign.view.FillContentLayout + <com.android.setupwizardlib.view.FillContentLayout android:id="@+id/illo_container" android:layout_width="match_parent" android:layout_height="wrap_content" @@ -46,12 +47,12 @@ <ImageView android:src="@drawable/illo_sim_app_dialog" - style="@style/SudContentIllustration" + style="@style/SuwContentIllustration" android:contentDescription="@string/install_carrier_app_image_content_description" android:layout_width="match_parent" android:layout_height="match_parent"/> - </com.google.android.setupdesign.view.FillContentLayout> - </LinearLayout> + </com.android.setupwizardlib.view.FillContentLayout> +</LinearLayout> -</com.google.android.setupdesign.GlifLayout> +</com.android.setupwizardlib.GlifLayout> diff --git a/packages/SimAppDialog/res/layout/install_carrier_app_footer.xml b/packages/SimAppDialog/res/layout/install_carrier_app_footer.xml new file mode 100644 index 000000000000..10dcb77a6584 --- /dev/null +++ b/packages/SimAppDialog/res/layout/install_carrier_app_footer.xml @@ -0,0 +1,43 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + Copyright (C) 2018 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> + +<com.android.setupwizardlib.view.ButtonBarLayout + xmlns:android="http://schemas.android.com/apk/res/android" + android:id="@+id/footer" + style="@style/SuwGlifButtonBar.Stackable" + android:layout_width="match_parent" + android:layout_height="wrap_content"> + + <Button + android:id="@+id/skip_button" + style="@style/SuwGlifButton.Secondary" + android:text="@string/install_carrier_app_defer_action" + android:layout_width="wrap_content" + android:layout_height="wrap_content"/> + + <Space + android:layout_width="0dp" + android:layout_height="0dp" + android:layout_weight="1"/> + + <Button + android:id="@+id/download_button" + style="@style/SuwGlifButton.Primary" + android:text="@string/install_carrier_app_download_action" + android:layout_width="wrap_content" + android:layout_height="wrap_content"/> +</com.android.setupwizardlib.view.ButtonBarLayout> diff --git a/packages/SimAppDialog/res/values/styles.xml b/packages/SimAppDialog/res/values/styles.xml deleted file mode 100644 index 824e3802aca1..000000000000 --- a/packages/SimAppDialog/res/values/styles.xml +++ /dev/null @@ -1,26 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- - Copyright (C) 2020 The Android Open Source Project - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT 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> - - <style name="SetupWizardPartnerResource"> - <!-- Disable to use partner overlay theme for outside setupwizard flow. --> - <item name="sucUsePartnerResource">false</item> - <!-- Enable heavy theme style inside setupwizard flow. --> - <item name="sudUsePartnerHeavyTheme">true</item> - </style> - -</resources> diff --git a/packages/SimAppDialog/src/com/android/simappdialog/InstallCarrierAppActivity.java b/packages/SimAppDialog/src/com/android/simappdialog/InstallCarrierAppActivity.java index 0b6f9bb4f9e0..abe82a885a94 100644 --- a/packages/SimAppDialog/src/com/android/simappdialog/InstallCarrierAppActivity.java +++ b/packages/SimAppDialog/src/com/android/simappdialog/InstallCarrierAppActivity.java @@ -17,17 +17,14 @@ package com.android.simappdialog; import android.app.Activity; import android.content.Intent; -import android.content.res.Resources; import android.os.Bundle; import android.sysprop.SetupWizardProperties; import android.text.TextUtils; import android.view.View; +import android.widget.Button; import android.widget.TextView; -import com.google.android.setupcompat.template.FooterBarMixin; -import com.google.android.setupcompat.template.FooterButton; -import com.google.android.setupdesign.GlifLayout; -import com.google.android.setupdesign.util.ThemeResolver; +import com.android.setupwizardlib.util.WizardManagerHelper; /** * Activity that gives a user the choice to download the SIM app or defer until a later time @@ -38,7 +35,7 @@ import com.google.android.setupdesign.util.ThemeResolver; * Can display the carrier app name if its passed into the intent with key * {@link #BUNDLE_KEY_CARRIER_NAME} */ -public class InstallCarrierAppActivity extends Activity { +public class InstallCarrierAppActivity extends Activity implements View.OnClickListener { /** * Key for the carrier app name that will be displayed as the app to download. If unset, a * default description will be used @@ -53,33 +50,20 @@ public class InstallCarrierAppActivity extends Activity { protected void onCreate(Bundle icicle) { // Setup theme for aosp/pixel setTheme( - new ThemeResolver.Builder() - .setDefaultTheme(R.style.SudThemeGlifV3_Light) - .build() - .resolve(SetupWizardProperties.theme().orElse(""), - /* suppressDayNight= */ false)); + WizardManagerHelper.getThemeRes( + SetupWizardProperties.theme().orElse(""), + R.style.SuwThemeGlif_Light + ) + ); super.onCreate(icicle); setContentView(R.layout.install_carrier_app_activity); - GlifLayout layout = findViewById(R.id.setup_wizard_layout); - FooterBarMixin mixin = layout.getMixin(FooterBarMixin.class); - mixin.setSecondaryButton( - new FooterButton.Builder(this) - .setText(R.string.install_carrier_app_defer_action) - .setListener(this::onSkipButtonClick) - .setButtonType(FooterButton.ButtonType.SKIP) - .setTheme(R.style.SudGlifButton_Secondary) - .build()); - - mixin.setPrimaryButton( - new FooterButton.Builder(this) - .setText(R.string.install_carrier_app_download_action) - .setListener(this::onDownloadButtonClick) - .setButtonType(FooterButton.ButtonType.OTHER) - .setTheme(R.style.SudGlifButton_Primary) - .build()); + Button notNowButton = findViewById(R.id.skip_button); + notNowButton.setOnClickListener(this); + Button downloadButton = findViewById(R.id.download_button); + downloadButton.setOnClickListener(this); // Show/hide illo depending on whether one was provided in a resource overlay boolean showIllo = getResources().getBoolean(R.bool.show_sim_app_dialog_illo); @@ -98,17 +82,15 @@ public class InstallCarrierAppActivity extends Activity { } @Override - protected void onApplyThemeResource(Resources.Theme theme, int resid, boolean first) { - theme.applyStyle(R.style.SetupWizardPartnerResource, true); - super.onApplyThemeResource(theme, resid, first); - } - - protected void onSkipButtonClick(View view) { - finish(DEFER_RESULT); - } - - protected void onDownloadButtonClick(View view) { - finish(DOWNLOAD_RESULT); + public void onClick(View v) { + switch (v.getId()) { + case R.id.skip_button: + finish(DEFER_RESULT); + break; + case R.id.download_button: + finish(DOWNLOAD_RESULT); + break; + } } private void finish(int resultCode) { diff --git a/packages/SystemUI/AndroidManifest.xml b/packages/SystemUI/AndroidManifest.xml index e3f75e3e0b34..06a97b17a73c 100644 --- a/packages/SystemUI/AndroidManifest.xml +++ b/packages/SystemUI/AndroidManifest.xml @@ -711,10 +711,9 @@ <service android:name=".controls.controller.AuxiliaryPersistenceWrapper$DeletionJobService" android:permission="android.permission.BIND_JOB_SERVICE"/> - <!-- started from ControlsFavoritingActivity --> + <!-- started from ControlsRequestReceiver --> <activity android:name=".controls.management.ControlsRequestDialog" - android:exported="true" android:theme="@style/Theme.ControlsRequestDialog" android:finishOnCloseSystemDialogs="true" android:showForAllUsers="true" diff --git a/packages/SystemUI/docs/camera.md b/packages/SystemUI/docs/camera.md new file mode 100644 index 000000000000..7a7a5aa3eb7f --- /dev/null +++ b/packages/SystemUI/docs/camera.md @@ -0,0 +1,33 @@ +# How double-click power launches the camera + +_as of august 2020_ + + +## Sequence of events + + + +1. [PhoneWindowManager.java](/services/core/java/com/android/server/policy/PhoneWindowManager.java) is responsible for all power button presses (see `interceptPowerKeyDown`). +2. Even though PWMgr has a lot of logic to detect all manner of power button multipresses and gestures, it also checks with GestureLauncherService, which is also [offered the chance](/services/core/java/com/android/server/policy/PhoneWindowManager.java#943) to [intercept](/services/core/java/com/android/server/GestureLauncherService.java#358) the power key. +3. GLS is responsible for the camera timeout, and if it detects one, it [forwards it to the StatusBarManagerService](/services/core/java/com/android/server/GestureLauncherService.java#475) (which hands it off to SystemUI). +4. Inside SystemUI, [onCameraLaunchDetected](/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java#3927) looks at the keyguard state and determines + 1. whether the camera is even allowed + 2. whether the screen is on; if not, we need to delay until that happens + 3. whether the device is locked (defined as "keyuguard is showing"). +5. If the device is unlocked (no keyguard), the camera is launched immediately. [Callsite](/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java#3949). +6. If the keyguard is up, however, [KeyguardBottomAreaView.launchCamera](/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java#477) takes over to handle the "secure camera" (a different intent, usually directing to the same app, but giving that app the cue to not allow access to the photo roll, etc). +7. If the intent [would have to launch a resolver](/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java#480) (the user has multiple cameras installed and hasn’t chosen one to always launch for the `SECURE_CAMERA_INTENT`), + 1. In order to show the resolver, the lockscreen "bouncer" (authentication method) [is first presented](/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java#523). +8. Otherwise (just one secure camera), [it is launched](/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java#501) (with some window animation gymnastics). + + +## Which intent launches? + + + +* If the keyguard is not showing (device is unlocked) + * `KeyguardBottomAreaView.INSECURE_CAMERA_INTENT`, defined to be `MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA`. + * [Callsite](/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java#3950) in StatusBar.java. +* If the keyguard is showing (device locked) + * [KeyguardBottomAreaView.getCameraIntent()](/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java#366) is consulted, which allows the "keyguard right button" (which we don’t actually show) to control the camera intent. The [default implementation](/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java#831) returns one of `KeyguardBottomAreaView.INSECURE_CAMERA_INTENT` or `KeyguardBottomAreaView.SECURE_CAMERA_INTENT`, which are `MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA` and `MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA_SECURE`, respectively. + * [Callsite](/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java#523) in KeyguardBottomAreaView.java. diff --git a/packages/SystemUI/res-keyguard/values-ar/strings.xml b/packages/SystemUI/res-keyguard/values-ar/strings.xml index 6d86a78360d8..65e3f0dbd176 100644 --- a/packages/SystemUI/res-keyguard/values-ar/strings.xml +++ b/packages/SystemUI/res-keyguard/values-ar/strings.xml @@ -112,7 +112,7 @@ <string name="kg_pin_accepted" msgid="1625501841604389716">"تم قبول الرمز"</string> <string name="keyguard_carrier_default" msgid="6359808469637388586">"لا تتوفر خدمة."</string> <string name="accessibility_ime_switch_button" msgid="9082358310194861329">"تبديل أسلوب الإدخال"</string> - <string name="airplane_mode" msgid="2528005343938497866">"وضع الطائرة"</string> + <string name="airplane_mode" msgid="2528005343938497866">"وضع الطيران"</string> <string name="kg_prompt_reason_restart_pattern" msgid="4720554342633852066">"يجب رسم النقش بعد إعادة تشغيل الجهاز"</string> <string name="kg_prompt_reason_restart_pin" msgid="1587671566498057656">"يجب إدخال رقم التعريف الشخصي بعد إعادة تشغيل الجهاز"</string> <string name="kg_prompt_reason_restart_password" msgid="8061279087240952002">"يجب إدخال كلمة المرور بعد إعادة تشغيل الجهاز"</string> diff --git a/packages/SystemUI/res/values-af/strings.xml b/packages/SystemUI/res/values-af/strings.xml index 316fa8aac5e6..eae2cbb332df 100644 --- a/packages/SystemUI/res/values-af/strings.xml +++ b/packages/SystemUI/res/values-af/strings.xml @@ -879,17 +879,6 @@ </string-array> <string name="tuner_low_priority" msgid="8412666814123009820">"Wys laeprioriteit-kennisgewingikone"</string> <string name="other" msgid="429768510980739978">"Ander"</string> - <string name="accessibility_divider" msgid="2830785970889237307">"Skermverdeler"</string> - <string name="accessibility_action_divider_left_full" msgid="7598733539422375847">"Volskerm links"</string> - <string name="accessibility_action_divider_left_70" msgid="4919312892541727761">"Links 70%"</string> - <string name="accessibility_action_divider_left_50" msgid="3664701169564893826">"Links 50%"</string> - <string name="accessibility_action_divider_left_30" msgid="4358145268046362088">"Links 30%"</string> - <string name="accessibility_action_divider_right_full" msgid="8576057422864896305">"Volskerm regs"</string> - <string name="accessibility_action_divider_top_full" msgid="4243901660795169777">"Volskerm bo"</string> - <string name="accessibility_action_divider_top_70" msgid="6941226213260515072">"Bo 70%"</string> - <string name="accessibility_action_divider_top_50" msgid="6275211443706497621">"Bo 50%"</string> - <string name="accessibility_action_divider_top_30" msgid="5780597635887574916">"Bo 30%"</string> - <string name="accessibility_action_divider_bottom_full" msgid="7352434720610115395">"Volskerm onder"</string> <string name="accessibility_qs_edit_tile_label" msgid="9079791448815232967">"Posisie <xliff:g id="POSITION">%1$d</xliff:g>, <xliff:g id="TILE_NAME">%2$s</xliff:g>. Dubbeltik om te wysig."</string> <string name="accessibility_qs_edit_add_tile_label" msgid="8292218072049068613">"<xliff:g id="TILE_NAME">%1$s</xliff:g>. Dubbeltik om by te voeg."</string> <string name="accessibility_qs_edit_move_tile" msgid="6027997446473163426">"Skuif <xliff:g id="TILE_NAME">%1$s</xliff:g>"</string> @@ -898,10 +887,6 @@ <string name="accessibility_qs_edit_tile_move" msgid="4841770637244326837">"Skuif <xliff:g id="TILE_NAME">%1$s</xliff:g> na posisie <xliff:g id="POSITION">%2$d</xliff:g>"</string> <string name="accessibility_desc_quick_settings_edit" msgid="741658939453595297">"Kitsinstellingswysiger."</string> <string name="accessibility_desc_notification_icon" msgid="7331265967584178674">"<xliff:g id="ID_1">%1$s</xliff:g>-kennisgewing: <xliff:g id="ID_2">%2$s</xliff:g>"</string> - <string name="dock_forced_resizable" msgid="4689301323912928801">"Program sal dalk nie met verdeelde skerm werk nie."</string> - <string name="dock_non_resizeble_failed_to_dock_text" msgid="7284915968096153808">"Program steun nie verdeelde skerm nie."</string> - <string name="forced_resizable_secondary_display" msgid="522558907654394940">"Program sal dalk nie op \'n sekondêre skerm werk nie."</string> - <string name="activity_launch_on_secondary_display_failed_text" msgid="8446727617187998208">"Program steun nie begin op sekondêre skerms nie."</string> <string name="accessibility_quick_settings_settings" msgid="7098489591715844713">"Maak instellings oop."</string> <string name="accessibility_quick_settings_expand" msgid="2609275052412521467">"Maak kitsinstellings oop."</string> <string name="accessibility_quick_settings_collapse" msgid="4674876336725041982">"Maak kitsinstellings toe."</string> diff --git a/packages/SystemUI/res/values-am/strings.xml b/packages/SystemUI/res/values-am/strings.xml index e2a4dc6404d8..e8326a7b3293 100644 --- a/packages/SystemUI/res/values-am/strings.xml +++ b/packages/SystemUI/res/values-am/strings.xml @@ -879,17 +879,6 @@ </string-array> <string name="tuner_low_priority" msgid="8412666814123009820">"አነስተኛ ቅድሚያ ያላቸው የማሳወቂያ አዶዎችን አሳይ"</string> <string name="other" msgid="429768510980739978">"ሌላ"</string> - <string name="accessibility_divider" msgid="2830785970889237307">"የተከፈለ የማያ ገጽ ከፋይ"</string> - <string name="accessibility_action_divider_left_full" msgid="7598733539422375847">"የግራ ሙሉ ማያ ገጽ"</string> - <string name="accessibility_action_divider_left_70" msgid="4919312892541727761">"ግራ 70%"</string> - <string name="accessibility_action_divider_left_50" msgid="3664701169564893826">"ግራ 50%"</string> - <string name="accessibility_action_divider_left_30" msgid="4358145268046362088">"ግራ 30%"</string> - <string name="accessibility_action_divider_right_full" msgid="8576057422864896305">"የቀኝ ሙሉ ማያ ገጽ"</string> - <string name="accessibility_action_divider_top_full" msgid="4243901660795169777">"የላይ ሙሉ ማያ ገጽ"</string> - <string name="accessibility_action_divider_top_70" msgid="6941226213260515072">"ከላይ 70%"</string> - <string name="accessibility_action_divider_top_50" msgid="6275211443706497621">"ከላይ 50%"</string> - <string name="accessibility_action_divider_top_30" msgid="5780597635887574916">"ከላይ 30%"</string> - <string name="accessibility_action_divider_bottom_full" msgid="7352434720610115395">"የታች ሙሉ ማያ ገጽ"</string> <string name="accessibility_qs_edit_tile_label" msgid="9079791448815232967">"ቦታ <xliff:g id="POSITION">%1$d</xliff:g>፣ <xliff:g id="TILE_NAME">%2$s</xliff:g>። ለማርትዕ ሁለቴ መታ ያድርጉ።"</string> <string name="accessibility_qs_edit_add_tile_label" msgid="8292218072049068613">"<xliff:g id="TILE_NAME">%1$s</xliff:g>። ለማከል ሁለቴ መታ ያድርጉ።"</string> <string name="accessibility_qs_edit_move_tile" msgid="6027997446473163426">"<xliff:g id="TILE_NAME">%1$s</xliff:g>ን ይውሰዱ"</string> @@ -898,10 +887,6 @@ <string name="accessibility_qs_edit_tile_move" msgid="4841770637244326837">"<xliff:g id="TILE_NAME">%1$s</xliff:g>ን ወደ አቀማመጥ <xliff:g id="POSITION">%2$d</xliff:g> አንቀሳቅስ"</string> <string name="accessibility_desc_quick_settings_edit" msgid="741658939453595297">"የፈጣን ቅንብሮች አርታዒ።"</string> <string name="accessibility_desc_notification_icon" msgid="7331265967584178674">"የ<xliff:g id="ID_1">%1$s</xliff:g> ማሳወቂያ፦ <xliff:g id="ID_2">%2$s</xliff:g>"</string> - <string name="dock_forced_resizable" msgid="4689301323912928801">"መተግበሪያ ከተከፈለ ማያ ገጽ ጋር ላይሠራ ይችላል"</string> - <string name="dock_non_resizeble_failed_to_dock_text" msgid="7284915968096153808">"መተግበሪያው የተከፈለ ማያ ገጽን አይደግፍም።"</string> - <string name="forced_resizable_secondary_display" msgid="522558907654394940">"መተግበሪያ በሁለተኛ ማሳያ ላይ ላይሠራ ይችላል።"</string> - <string name="activity_launch_on_secondary_display_failed_text" msgid="8446727617187998208">"መተግበሪያ በሁለተኛ ማሳያዎች ላይ ማስጀመርን አይደግፍም።"</string> <string name="accessibility_quick_settings_settings" msgid="7098489591715844713">"ቅንብሮችን ክፈት።"</string> <string name="accessibility_quick_settings_expand" msgid="2609275052412521467">"ፈጣን ቅንብሮችን ክፈት።"</string> <string name="accessibility_quick_settings_collapse" msgid="4674876336725041982">"ፈጣን ቅንብሮችን ዝጋ።"</string> diff --git a/packages/SystemUI/res/values-ar/strings.xml b/packages/SystemUI/res/values-ar/strings.xml index b33c6c57f905..b020f17dc612 100644 --- a/packages/SystemUI/res/values-ar/strings.xml +++ b/packages/SystemUI/res/values-ar/strings.xml @@ -232,7 +232,7 @@ <string name="not_default_data_content_description" msgid="6757881730711522517">"لم يتم الضبط على استخدام البيانات"</string> <string name="cell_data_off" msgid="4886198950247099526">"غير مفعّلة"</string> <string name="accessibility_bluetooth_tether" msgid="6327291292208790599">"التوصيل عبر البلوتوث"</string> - <string name="accessibility_airplane_mode" msgid="1899529214045998505">"وضع الطائرة."</string> + <string name="accessibility_airplane_mode" msgid="1899529214045998505">"وضع الطيران."</string> <string name="accessibility_vpn_on" msgid="8037549696057288731">"الشبكة الافتراضية الخاصة (VPN) قيد التفعيل."</string> <string name="accessibility_no_sims" msgid="5711270400476534667">"ليس هناك شريحة SIM."</string> <string name="carrier_network_change_mode" msgid="5174141476991149918">"جارٍ تغيير شبكة مشغِّل شبكة الجوّال."</string> @@ -267,10 +267,10 @@ <string name="accessibility_quick_settings_wifi_changed_on" msgid="1490362586009027611">"تم تفعيل Wifi."</string> <string name="accessibility_quick_settings_mobile" msgid="1817825313718492906">"الجوّال <xliff:g id="SIGNAL">%1$s</xliff:g>. <xliff:g id="TYPE">%2$s</xliff:g>. <xliff:g id="NETWORK">%3$s</xliff:g>."</string> <string name="accessibility_quick_settings_battery" msgid="533594896310663853">"البطارية <xliff:g id="STATE">%s</xliff:g>."</string> - <string name="accessibility_quick_settings_airplane_off" msgid="1275658769368793228">"إيقاف وضع الطائرة."</string> - <string name="accessibility_quick_settings_airplane_on" msgid="8106176561295294255">"تفعيل وضع الطائرة."</string> - <string name="accessibility_quick_settings_airplane_changed_off" msgid="8880183481476943754">"تم إيقاف وضع الطائرة."</string> - <string name="accessibility_quick_settings_airplane_changed_on" msgid="6327378061894076288">"تم تفعيل وضع الطائرة."</string> + <string name="accessibility_quick_settings_airplane_off" msgid="1275658769368793228">"إيقاف وضع الطيران."</string> + <string name="accessibility_quick_settings_airplane_on" msgid="8106176561295294255">"تفعيل وضع الطيران."</string> + <string name="accessibility_quick_settings_airplane_changed_off" msgid="8880183481476943754">"تم إيقاف وضع الطيران."</string> + <string name="accessibility_quick_settings_airplane_changed_on" msgid="6327378061894076288">"تم تفعيل وضع الطيران."</string> <string name="accessibility_quick_settings_dnd_none_on" msgid="3235552940146035383">"كتم الصوت تمامًا"</string> <string name="accessibility_quick_settings_dnd_alarms_on" msgid="3375848309132140014">"المنبِّهات فقط"</string> <string name="accessibility_quick_settings_dnd" msgid="2415967452264206047">"عدم الإزعاج"</string> @@ -664,7 +664,7 @@ <string name="status_bar_ethernet" msgid="5690979758988647484">"إيثرنت"</string> <string name="status_bar_alarm" msgid="87160847643623352">"المنبّه"</string> <string name="status_bar_work" msgid="5238641949837091056">"الملف الشخصي للعمل"</string> - <string name="status_bar_airplane" msgid="4848702508684541009">"وضع الطائرة"</string> + <string name="status_bar_airplane" msgid="4848702508684541009">"وضع الطيران"</string> <string name="add_tile" msgid="6239678623873086686">"إضافة فئة"</string> <string name="broadcast_tile" msgid="5224010633596487481">"إرسال فئة"</string> <string name="zen_alarm_warning_indef" msgid="5252866591716504287">"لن تسمع المنبّه القادم في <xliff:g id="WHEN">%1$s</xliff:g> إلا إذا أوقفت هذا قبل الموعد"</string> @@ -899,17 +899,6 @@ </string-array> <string name="tuner_low_priority" msgid="8412666814123009820">"إظهار رموز الإشعارات ذات الأولوية المنخفضة"</string> <string name="other" msgid="429768510980739978">"غير ذلك"</string> - <string name="accessibility_divider" msgid="2830785970889237307">"أداة تقسيم الشاشة"</string> - <string name="accessibility_action_divider_left_full" msgid="7598733539422375847">"عرض النافذة اليسرى بملء الشاشة"</string> - <string name="accessibility_action_divider_left_70" msgid="4919312892541727761">"ضبط حجم النافذة اليسرى ليكون ٧٠%"</string> - <string name="accessibility_action_divider_left_50" msgid="3664701169564893826">"ضبط حجم النافذة اليسرى ليكون ٥٠%"</string> - <string name="accessibility_action_divider_left_30" msgid="4358145268046362088">"ضبط حجم النافذة اليسرى ليكون ٣٠%"</string> - <string name="accessibility_action_divider_right_full" msgid="8576057422864896305">"عرض النافذة اليمنى بملء الشاشة"</string> - <string name="accessibility_action_divider_top_full" msgid="4243901660795169777">"عرض النافذة العلوية بملء الشاشة"</string> - <string name="accessibility_action_divider_top_70" msgid="6941226213260515072">"ضبط حجم النافذة العلوية ليكون ٧٠%"</string> - <string name="accessibility_action_divider_top_50" msgid="6275211443706497621">"ضبط حجم النافذة العلوية ليكون ٥٠%"</string> - <string name="accessibility_action_divider_top_30" msgid="5780597635887574916">"ضبط حجم النافذة العلوية ليكون ٣٠%"</string> - <string name="accessibility_action_divider_bottom_full" msgid="7352434720610115395">"عرض النافذة السفلية بملء الشاشة"</string> <string name="accessibility_qs_edit_tile_label" msgid="9079791448815232967">"الموضع <xliff:g id="POSITION">%1$d</xliff:g>، <xliff:g id="TILE_NAME">%2$s</xliff:g>. انقر مرّتين للتعديل."</string> <string name="accessibility_qs_edit_add_tile_label" msgid="8292218072049068613">"<xliff:g id="TILE_NAME">%1$s</xliff:g>. انقر مرّتين للإضافة."</string> <string name="accessibility_qs_edit_move_tile" msgid="6027997446473163426">"نقل <xliff:g id="TILE_NAME">%1$s</xliff:g>"</string> @@ -918,10 +907,6 @@ <string name="accessibility_qs_edit_tile_move" msgid="4841770637244326837">"نقل <xliff:g id="TILE_NAME">%1$s</xliff:g> إلى الموضع <xliff:g id="POSITION">%2$d</xliff:g>"</string> <string name="accessibility_desc_quick_settings_edit" msgid="741658939453595297">"برنامج تعديل الإعدادات السريعة."</string> <string name="accessibility_desc_notification_icon" msgid="7331265967584178674">"إشعار <xliff:g id="ID_1">%1$s</xliff:g>: <xliff:g id="ID_2">%2$s</xliff:g>"</string> - <string name="dock_forced_resizable" msgid="4689301323912928801">"يمكن ألا يعمل التطبيق مع وضع تقسيم الشاشة."</string> - <string name="dock_non_resizeble_failed_to_dock_text" msgid="7284915968096153808">"التطبيق لا يتيح تقسيم الشاشة."</string> - <string name="forced_resizable_secondary_display" msgid="522558907654394940">"قد لا يعمل التطبيق على شاشة عرض ثانوية."</string> - <string name="activity_launch_on_secondary_display_failed_text" msgid="8446727617187998208">"لا يمكن تشغيل التطبيق على شاشات عرض ثانوية."</string> <string name="accessibility_quick_settings_settings" msgid="7098489591715844713">"فتح الإعدادات."</string> <string name="accessibility_quick_settings_expand" msgid="2609275052412521467">"فتح الإعدادات السريعة."</string> <string name="accessibility_quick_settings_collapse" msgid="4674876336725041982">"إغلاق الإعدادات السريعة."</string> diff --git a/packages/SystemUI/res/values-as/strings.xml b/packages/SystemUI/res/values-as/strings.xml index 5a3c659727d3..31077dac8c41 100644 --- a/packages/SystemUI/res/values-as/strings.xml +++ b/packages/SystemUI/res/values-as/strings.xml @@ -879,17 +879,6 @@ </string-array> <string name="tuner_low_priority" msgid="8412666814123009820">"কম গুৰুত্বপূৰ্ণ জাননীৰ আইকনসমূহ দেখুৱাওক"</string> <string name="other" msgid="429768510980739978">"অন্যান্য"</string> - <string name="accessibility_divider" msgid="2830785970889237307">"স্প্লিট স্ক্ৰীণৰ বিভাজক"</string> - <string name="accessibility_action_divider_left_full" msgid="7598733539422375847">"বাওঁফালৰ স্ক্ৰীণখন সম্পূৰ্ণ স্ক্ৰীণ কৰক"</string> - <string name="accessibility_action_divider_left_70" msgid="4919312892541727761">"বাওঁফালৰ স্ক্ৰীণখন ৭০% কৰক"</string> - <string name="accessibility_action_divider_left_50" msgid="3664701169564893826">"বাওঁফালৰ স্ক্ৰীণখন ৫০% কৰক"</string> - <string name="accessibility_action_divider_left_30" msgid="4358145268046362088">"বাওঁফালৰ স্ক্ৰীণখন ৩০% কৰক"</string> - <string name="accessibility_action_divider_right_full" msgid="8576057422864896305">"সোঁফালৰ স্ক্ৰীণখন সম্পূৰ্ণ স্ক্ৰীণ কৰক"</string> - <string name="accessibility_action_divider_top_full" msgid="4243901660795169777">"শীৰ্ষ স্ক্ৰীণখন সম্পূৰ্ণ স্ক্ৰীণ কৰক"</string> - <string name="accessibility_action_divider_top_70" msgid="6941226213260515072">"শীর্ষ স্ক্ৰীণখন ৭০% কৰক"</string> - <string name="accessibility_action_divider_top_50" msgid="6275211443706497621">"শীর্ষ স্ক্ৰীণখন ৫০% কৰক"</string> - <string name="accessibility_action_divider_top_30" msgid="5780597635887574916">"শীর্ষ স্ক্ৰীণখন ৩০% কৰক"</string> - <string name="accessibility_action_divider_bottom_full" msgid="7352434720610115395">"তলৰ স্ক্ৰীণখন সম্পূৰ্ণ স্ক্ৰীণ কৰক"</string> <string name="accessibility_qs_edit_tile_label" msgid="9079791448815232967">"অৱস্থান <xliff:g id="POSITION">%1$d</xliff:g>, <xliff:g id="TILE_NAME">%2$s</xliff:g>। সম্পাদনা কৰিবৰ বাবে দুবাৰ টিপক।"</string> <string name="accessibility_qs_edit_add_tile_label" msgid="8292218072049068613">"<xliff:g id="TILE_NAME">%1$s</xliff:g>। যোগ কৰিবলৈ দুবাৰ টিপক।"</string> <string name="accessibility_qs_edit_move_tile" msgid="6027997446473163426">"<xliff:g id="TILE_NAME">%1$s</xliff:g> স্থানান্তৰ কৰক"</string> @@ -898,10 +887,6 @@ <string name="accessibility_qs_edit_tile_move" msgid="4841770637244326837">"<xliff:g id="TILE_NAME">%1$s</xliff:g>ক এই স্থান <xliff:g id="POSITION">%2$d</xliff:g>লৈ যাওক"</string> <string name="accessibility_desc_quick_settings_edit" msgid="741658939453595297">"ক্ষিপ্ৰ ছেটিংসমূহৰ সম্পাদক।"</string> <string name="accessibility_desc_notification_icon" msgid="7331265967584178674">"<xliff:g id="ID_1">%1$s</xliff:g> জাননী: <xliff:g id="ID_2">%2$s</xliff:g>"</string> - <string name="dock_forced_resizable" msgid="4689301323912928801">"বিভাজিত স্ক্ৰীণৰ সৈতে এপে হয়তো কাম নকৰিব।"</string> - <string name="dock_non_resizeble_failed_to_dock_text" msgid="7284915968096153808">"এপটোৱে বিভাজিত স্ক্ৰীণ সমৰ্থন নকৰে।"</string> - <string name="forced_resizable_secondary_display" msgid="522558907654394940">"গৌণ ডিছপ্লেত এপে সঠিকভাৱে কাম নকৰিব পাৰে।"</string> - <string name="activity_launch_on_secondary_display_failed_text" msgid="8446727617187998208">"গৌণ ডিছপ্লেত এপ্ লঞ্চ কৰিব নোৱাৰি।"</string> <string name="accessibility_quick_settings_settings" msgid="7098489591715844713">"ছেটিংসমূহ খোলক।"</string> <string name="accessibility_quick_settings_expand" msgid="2609275052412521467">"ক্ষিপ্ৰ ছেটিংসমূহ খোলক।"</string> <string name="accessibility_quick_settings_collapse" msgid="4674876336725041982">"ক্ষিপ্ৰ ছেটিংসমূহ বন্ধ কৰক।"</string> diff --git a/packages/SystemUI/res/values-az/strings.xml b/packages/SystemUI/res/values-az/strings.xml index 40df8cd68bac..b5960668e8fe 100644 --- a/packages/SystemUI/res/values-az/strings.xml +++ b/packages/SystemUI/res/values-az/strings.xml @@ -879,17 +879,6 @@ </string-array> <string name="tuner_low_priority" msgid="8412666814123009820">"Aşağı prioritet bildiriş işarələrini göstərin"</string> <string name="other" msgid="429768510980739978">"Digər"</string> - <string name="accessibility_divider" msgid="2830785970889237307">"Bölünmüş ekran ayırıcısı"</string> - <string name="accessibility_action_divider_left_full" msgid="7598733539422375847">"Sol tam ekran"</string> - <string name="accessibility_action_divider_left_70" msgid="4919312892541727761">"Sol 70%"</string> - <string name="accessibility_action_divider_left_50" msgid="3664701169564893826">"Sol 50%"</string> - <string name="accessibility_action_divider_left_30" msgid="4358145268046362088">"Sol 30%"</string> - <string name="accessibility_action_divider_right_full" msgid="8576057422864896305">"Sağ tam ekran"</string> - <string name="accessibility_action_divider_top_full" msgid="4243901660795169777">"Yuxarı tam ekran"</string> - <string name="accessibility_action_divider_top_70" msgid="6941226213260515072">"Yuxarı 70%"</string> - <string name="accessibility_action_divider_top_50" msgid="6275211443706497621">"Yuxarı 50%"</string> - <string name="accessibility_action_divider_top_30" msgid="5780597635887574916">"Yuxarı 30%"</string> - <string name="accessibility_action_divider_bottom_full" msgid="7352434720610115395">"Aşağı tam ekran"</string> <string name="accessibility_qs_edit_tile_label" msgid="9079791448815232967">"<xliff:g id="POSITION">%1$d</xliff:g> mövqeyi, <xliff:g id="TILE_NAME">%2$s</xliff:g>. Redaktə etmək üçün iki dəfə tıklayın."</string> <string name="accessibility_qs_edit_add_tile_label" msgid="8292218072049068613">"<xliff:g id="TILE_NAME">%1$s</xliff:g>. Əlavə etmək üçün iki dəfə tıklayın."</string> <string name="accessibility_qs_edit_move_tile" msgid="6027997446473163426">"<xliff:g id="TILE_NAME">%1$s</xliff:g> köçürün"</string> @@ -898,10 +887,6 @@ <string name="accessibility_qs_edit_tile_move" msgid="4841770637244326837">"<xliff:g id="POSITION">%2$d</xliff:g> pozisiyasına <xliff:g id="TILE_NAME">%1$s</xliff:g> köçürün"</string> <string name="accessibility_desc_quick_settings_edit" msgid="741658939453595297">"Sürətli ayarlar redaktoru."</string> <string name="accessibility_desc_notification_icon" msgid="7331265967584178674">"<xliff:g id="ID_1">%1$s</xliff:g> bildiriş: <xliff:g id="ID_2">%2$s</xliff:g>"</string> - <string name="dock_forced_resizable" msgid="4689301323912928801">"Tətbiq bölünmüş ekran ilə işləməyə bilər."</string> - <string name="dock_non_resizeble_failed_to_dock_text" msgid="7284915968096153808">"Tətbiq ekran bölünməsini dəstəkləmir."</string> - <string name="forced_resizable_secondary_display" msgid="522558907654394940">"Tətbiq ikinci ekranda işləməyə bilər."</string> - <string name="activity_launch_on_secondary_display_failed_text" msgid="8446727617187998208">"Tətbiq ikinci ekranda başlamağı dəstəkləmir."</string> <string name="accessibility_quick_settings_settings" msgid="7098489591715844713">"Ayarları açın."</string> <string name="accessibility_quick_settings_expand" msgid="2609275052412521467">"Cəld ayarları açın."</string> <string name="accessibility_quick_settings_collapse" msgid="4674876336725041982">"Cəld ayarları bağlayın."</string> diff --git a/packages/SystemUI/res/values-b+sr+Latn/strings.xml b/packages/SystemUI/res/values-b+sr+Latn/strings.xml index a9725f331856..aa141e637932 100644 --- a/packages/SystemUI/res/values-b+sr+Latn/strings.xml +++ b/packages/SystemUI/res/values-b+sr+Latn/strings.xml @@ -884,17 +884,6 @@ </string-array> <string name="tuner_low_priority" msgid="8412666814123009820">"Prikaži ikone obaveštenja niskog prioriteta"</string> <string name="other" msgid="429768510980739978">"Drugo"</string> - <string name="accessibility_divider" msgid="2830785970889237307">"Razdelnik podeljenog ekrana"</string> - <string name="accessibility_action_divider_left_full" msgid="7598733539422375847">"Režim celog ekrana za levi ekran"</string> - <string name="accessibility_action_divider_left_70" msgid="4919312892541727761">"Levi ekran 70%"</string> - <string name="accessibility_action_divider_left_50" msgid="3664701169564893826">"Levi ekran 50%"</string> - <string name="accessibility_action_divider_left_30" msgid="4358145268046362088">"Levi ekran 30%"</string> - <string name="accessibility_action_divider_right_full" msgid="8576057422864896305">"Režim celog ekrana za donji ekran"</string> - <string name="accessibility_action_divider_top_full" msgid="4243901660795169777">"Režim celog ekrana za gornji ekran"</string> - <string name="accessibility_action_divider_top_70" msgid="6941226213260515072">"Gornji ekran 70%"</string> - <string name="accessibility_action_divider_top_50" msgid="6275211443706497621">"Gornji ekran 50%"</string> - <string name="accessibility_action_divider_top_30" msgid="5780597635887574916">"Gornji ekran 30%"</string> - <string name="accessibility_action_divider_bottom_full" msgid="7352434720610115395">"Režim celog ekrana za donji ekran"</string> <string name="accessibility_qs_edit_tile_label" msgid="9079791448815232967">"<xliff:g id="POSITION">%1$d</xliff:g>. pozicija, <xliff:g id="TILE_NAME">%2$s</xliff:g>. Dvaput dodirnite da biste izmenili."</string> <string name="accessibility_qs_edit_add_tile_label" msgid="8292218072049068613">"<xliff:g id="TILE_NAME">%1$s</xliff:g>. Dvaput dodirnite da biste dodali."</string> <string name="accessibility_qs_edit_move_tile" msgid="6027997446473163426">"Premesti pločicu <xliff:g id="TILE_NAME">%1$s</xliff:g>"</string> @@ -903,10 +892,6 @@ <string name="accessibility_qs_edit_tile_move" msgid="4841770637244326837">"Premestite „<xliff:g id="TILE_NAME">%1$s</xliff:g>“ na poziciju <xliff:g id="POSITION">%2$d</xliff:g>"</string> <string name="accessibility_desc_quick_settings_edit" msgid="741658939453595297">"Uređivač za Brza podešavanja."</string> <string name="accessibility_desc_notification_icon" msgid="7331265967584178674">"Obaveštenja za <xliff:g id="ID_1">%1$s</xliff:g>: <xliff:g id="ID_2">%2$s</xliff:g>"</string> - <string name="dock_forced_resizable" msgid="4689301323912928801">"Aplikacija možda neće funkcionisati sa podeljenim ekranom."</string> - <string name="dock_non_resizeble_failed_to_dock_text" msgid="7284915968096153808">"Aplikacija ne podržava podeljeni ekran."</string> - <string name="forced_resizable_secondary_display" msgid="522558907654394940">"Aplikacija možda neće funkcionisati na sekundarnom ekranu."</string> - <string name="activity_launch_on_secondary_display_failed_text" msgid="8446727617187998208">"Aplikacija ne podržava pokretanje na sekundarnim ekranima."</string> <string name="accessibility_quick_settings_settings" msgid="7098489591715844713">"Otvori Podešavanja."</string> <string name="accessibility_quick_settings_expand" msgid="2609275052412521467">"Otvori Brza podešavanja."</string> <string name="accessibility_quick_settings_collapse" msgid="4674876336725041982">"Zatvori Brza podešavanja."</string> diff --git a/packages/SystemUI/res/values-be/strings.xml b/packages/SystemUI/res/values-be/strings.xml index b4c5eba9f77b..194f92b633e4 100644 --- a/packages/SystemUI/res/values-be/strings.xml +++ b/packages/SystemUI/res/values-be/strings.xml @@ -889,17 +889,6 @@ </string-array> <string name="tuner_low_priority" msgid="8412666814123009820">"Паказваць значкі апавяшчэнняў з нізкім прыярытэтам"</string> <string name="other" msgid="429768510980739978">"Іншае"</string> - <string name="accessibility_divider" msgid="2830785970889237307">"Раздзяляльнік падзеленага экрана"</string> - <string name="accessibility_action_divider_left_full" msgid="7598733539422375847">"Левы экран – поўнаэкранны рэжым"</string> - <string name="accessibility_action_divider_left_70" msgid="4919312892541727761">"Левы экран – 70%"</string> - <string name="accessibility_action_divider_left_50" msgid="3664701169564893826">"Левы экран – 50%"</string> - <string name="accessibility_action_divider_left_30" msgid="4358145268046362088">"Левы экран – 30%"</string> - <string name="accessibility_action_divider_right_full" msgid="8576057422864896305">"Правы экран – поўнаэкранны рэжым"</string> - <string name="accessibility_action_divider_top_full" msgid="4243901660795169777">"Верхні экран – поўнаэкранны рэжым"</string> - <string name="accessibility_action_divider_top_70" msgid="6941226213260515072">"Верхні экран – 70%"</string> - <string name="accessibility_action_divider_top_50" msgid="6275211443706497621">"Верхні экран – 50%"</string> - <string name="accessibility_action_divider_top_30" msgid="5780597635887574916">"Верхні экран – 30%"</string> - <string name="accessibility_action_divider_bottom_full" msgid="7352434720610115395">"Ніжні экран – поўнаэкранны рэжым"</string> <string name="accessibility_qs_edit_tile_label" msgid="9079791448815232967">"Месца: <xliff:g id="POSITION">%1$d</xliff:g>, <xliff:g id="TILE_NAME">%2$s</xliff:g>. Краніце двойчы, каб рэдагаваць."</string> <string name="accessibility_qs_edit_add_tile_label" msgid="8292218072049068613">"<xliff:g id="TILE_NAME">%1$s</xliff:g>. Краніце двойчы, каб дадаць."</string> <string name="accessibility_qs_edit_move_tile" msgid="6027997446473163426">"Перамясціць <xliff:g id="TILE_NAME">%1$s</xliff:g>"</string> @@ -908,10 +897,6 @@ <string name="accessibility_qs_edit_tile_move" msgid="4841770637244326837">"Перамясціць \"<xliff:g id="TILE_NAME">%1$s</xliff:g>\" у наступнае месца: <xliff:g id="POSITION">%2$d</xliff:g>"</string> <string name="accessibility_desc_quick_settings_edit" msgid="741658939453595297">"Рэдактар хуткіх налад."</string> <string name="accessibility_desc_notification_icon" msgid="7331265967584178674">"Апавяшчэнне <xliff:g id="ID_1">%1$s</xliff:g>: <xliff:g id="ID_2">%2$s</xliff:g>"</string> - <string name="dock_forced_resizable" msgid="4689301323912928801">"Праграма можа не працаваць у рэжыме дзялення экрана."</string> - <string name="dock_non_resizeble_failed_to_dock_text" msgid="7284915968096153808">"Праграма не падтрымлівае функцыю дзялення экрана."</string> - <string name="forced_resizable_secondary_display" msgid="522558907654394940">"Праграма можа не працаваць на дадатковых экранах."</string> - <string name="activity_launch_on_secondary_display_failed_text" msgid="8446727617187998208">"Праграма не падтрымлівае запуск на дадатковых экранах."</string> <string name="accessibility_quick_settings_settings" msgid="7098489591715844713">"Адкрыць налады."</string> <string name="accessibility_quick_settings_expand" msgid="2609275052412521467">"Адкрыць хуткія налады."</string> <string name="accessibility_quick_settings_collapse" msgid="4674876336725041982">"Закрыць хуткія налады."</string> diff --git a/packages/SystemUI/res/values-bg/strings.xml b/packages/SystemUI/res/values-bg/strings.xml index 52e82869d575..02eea8abe4dd 100644 --- a/packages/SystemUI/res/values-bg/strings.xml +++ b/packages/SystemUI/res/values-bg/strings.xml @@ -879,17 +879,6 @@ </string-array> <string name="tuner_low_priority" msgid="8412666814123009820">"Показване на иконите за известията с нисък приоритет"</string> <string name="other" msgid="429768510980739978">"Друго"</string> - <string name="accessibility_divider" msgid="2830785970889237307">"Разделител в режима за разделен екран"</string> - <string name="accessibility_action_divider_left_full" msgid="7598733539422375847">"Ляв екран: Показване на цял екран"</string> - <string name="accessibility_action_divider_left_70" msgid="4919312892541727761">"Ляв екран: 70%"</string> - <string name="accessibility_action_divider_left_50" msgid="3664701169564893826">"Ляв екран: 50%"</string> - <string name="accessibility_action_divider_left_30" msgid="4358145268046362088">"Ляв екран: 30%"</string> - <string name="accessibility_action_divider_right_full" msgid="8576057422864896305">"Десен екран: Показване на цял екран"</string> - <string name="accessibility_action_divider_top_full" msgid="4243901660795169777">"Горен екран: Показване на цял екран"</string> - <string name="accessibility_action_divider_top_70" msgid="6941226213260515072">"Горен екран: 70%"</string> - <string name="accessibility_action_divider_top_50" msgid="6275211443706497621">"Горен екран: 50%"</string> - <string name="accessibility_action_divider_top_30" msgid="5780597635887574916">"Горен екран: 30%"</string> - <string name="accessibility_action_divider_bottom_full" msgid="7352434720610115395">"Долен екран: Показване на цял екран"</string> <string name="accessibility_qs_edit_tile_label" msgid="9079791448815232967">"Позиция <xliff:g id="POSITION">%1$d</xliff:g>, „<xliff:g id="TILE_NAME">%2$s</xliff:g>“. Докоснете двукратно, за да редактирате."</string> <string name="accessibility_qs_edit_add_tile_label" msgid="8292218072049068613">"„<xliff:g id="TILE_NAME">%1$s</xliff:g>“. Докоснете двукратно, за да добавите."</string> <string name="accessibility_qs_edit_move_tile" msgid="6027997446473163426">"Преместване на „<xliff:g id="TILE_NAME">%1$s</xliff:g>“"</string> @@ -898,10 +887,6 @@ <string name="accessibility_qs_edit_tile_move" msgid="4841770637244326837">"Преместете „<xliff:g id="TILE_NAME">%1$s</xliff:g>“ на позиция <xliff:g id="POSITION">%2$d</xliff:g>"</string> <string name="accessibility_desc_quick_settings_edit" msgid="741658939453595297">"Редактор за бързи настройки."</string> <string name="accessibility_desc_notification_icon" msgid="7331265967584178674">"Известие от <xliff:g id="ID_1">%1$s</xliff:g>: <xliff:g id="ID_2">%2$s</xliff:g>"</string> - <string name="dock_forced_resizable" msgid="4689301323912928801">"Приложението може да не работи в режим на разделен екран."</string> - <string name="dock_non_resizeble_failed_to_dock_text" msgid="7284915968096153808">"Приложението не поддържа разделен екран."</string> - <string name="forced_resizable_secondary_display" msgid="522558907654394940">"Възможно е приложението да не работи на алтернативни дисплеи."</string> - <string name="activity_launch_on_secondary_display_failed_text" msgid="8446727617187998208">"Приложението не поддържа използването на алтернативни дисплеи."</string> <string name="accessibility_quick_settings_settings" msgid="7098489591715844713">"Отваряне на настройките."</string> <string name="accessibility_quick_settings_expand" msgid="2609275052412521467">"Отваряне на бързите настройки."</string> <string name="accessibility_quick_settings_collapse" msgid="4674876336725041982">"Затваряне на бързите настройки."</string> diff --git a/packages/SystemUI/res/values-bn/strings.xml b/packages/SystemUI/res/values-bn/strings.xml index d0de9cf03b38..96a7368b1dfd 100644 --- a/packages/SystemUI/res/values-bn/strings.xml +++ b/packages/SystemUI/res/values-bn/strings.xml @@ -879,17 +879,6 @@ </string-array> <string name="tuner_low_priority" msgid="8412666814123009820">"কম-গুরুত্বপূর্ণ বিজ্ঞপ্তির আইকন দেখুন"</string> <string name="other" msgid="429768510980739978">"অন্যান্য"</string> - <string name="accessibility_divider" msgid="2830785970889237307">"বিভক্ত-স্ক্রিন বিভাজক"</string> - <string name="accessibility_action_divider_left_full" msgid="7598733539422375847">"বাঁ দিকের অংশ নিয়ে পূর্ণ স্ক্রিন"</string> - <string name="accessibility_action_divider_left_70" msgid="4919312892541727761">"৭০% বাকি আছে"</string> - <string name="accessibility_action_divider_left_50" msgid="3664701169564893826">"৫০% বাকি আছে"</string> - <string name="accessibility_action_divider_left_30" msgid="4358145268046362088">"৩০% বাকি আছে"</string> - <string name="accessibility_action_divider_right_full" msgid="8576057422864896305">"ডান দিকের অংশ নিয়ে পূর্ণ স্ক্রিন"</string> - <string name="accessibility_action_divider_top_full" msgid="4243901660795169777">"উপর দিকের অংশ নিয়ে পূর্ণ স্ক্রিন"</string> - <string name="accessibility_action_divider_top_70" msgid="6941226213260515072">"শীর্ষ ৭০%"</string> - <string name="accessibility_action_divider_top_50" msgid="6275211443706497621">"শীর্ষ ৫০%"</string> - <string name="accessibility_action_divider_top_30" msgid="5780597635887574916">"শীর্ষ ৩০%"</string> - <string name="accessibility_action_divider_bottom_full" msgid="7352434720610115395">"নীচের অংশ নিয়ে পূর্ণ স্ক্রিন"</string> <string name="accessibility_qs_edit_tile_label" msgid="9079791448815232967">"<xliff:g id="POSITION">%1$d</xliff:g> লোকেশন, <xliff:g id="TILE_NAME">%2$s</xliff:g>৷ সম্পাদনা করতে দুবার আলতো চাপুন৷"</string> <string name="accessibility_qs_edit_add_tile_label" msgid="8292218072049068613">"<xliff:g id="TILE_NAME">%1$s</xliff:g>৷ যোগ করতে দুবার আলতো চাপুন৷"</string> <string name="accessibility_qs_edit_move_tile" msgid="6027997446473163426">"<xliff:g id="TILE_NAME">%1$s</xliff:g> সরান"</string> @@ -898,10 +887,6 @@ <string name="accessibility_qs_edit_tile_move" msgid="4841770637244326837">"<xliff:g id="TILE_NAME">%1$s</xliff:g> <xliff:g id="POSITION">%2$d</xliff:g>-এ সরান"</string> <string name="accessibility_desc_quick_settings_edit" msgid="741658939453595297">"দ্রুত সেটিংস সম্পাদক৷"</string> <string name="accessibility_desc_notification_icon" msgid="7331265967584178674">"<xliff:g id="ID_1">%1$s</xliff:g> বিজ্ঞপ্তি: <xliff:g id="ID_2">%2$s</xliff:g>"</string> - <string name="dock_forced_resizable" msgid="4689301323912928801">"অ্যাপ্লিকেশানটি বিভক্ত স্ক্রীনে কাজ নাও করতে পারে৷"</string> - <string name="dock_non_resizeble_failed_to_dock_text" msgid="7284915968096153808">"অ্যাপ্লিকেশান বিভক্ত-স্ক্রিন সমর্থন করে না৷"</string> - <string name="forced_resizable_secondary_display" msgid="522558907654394940">"সেকেন্ডারি ডিসপ্লেতে অ্যাপটি কাজ নাও করতে পারে।"</string> - <string name="activity_launch_on_secondary_display_failed_text" msgid="8446727617187998208">"সেকেন্ডারি ডিসপ্লেতে অ্যাপ লঞ্চ করা যাবে না।"</string> <string name="accessibility_quick_settings_settings" msgid="7098489591715844713">"সেটিংস খুলুন।"</string> <string name="accessibility_quick_settings_expand" msgid="2609275052412521467">"দ্রুত সেটিংস খুলুন৷"</string> <string name="accessibility_quick_settings_collapse" msgid="4674876336725041982">"দ্রুত সেটিংস বন্ধ করুন৷"</string> diff --git a/packages/SystemUI/res/values-bs/strings.xml b/packages/SystemUI/res/values-bs/strings.xml index 57b7945c7a8c..0a091aae70b9 100644 --- a/packages/SystemUI/res/values-bs/strings.xml +++ b/packages/SystemUI/res/values-bs/strings.xml @@ -884,17 +884,6 @@ </string-array> <string name="tuner_low_priority" msgid="8412666814123009820">"Prikaži ikone obavještenja niskog prioriteta"</string> <string name="other" msgid="429768510980739978">"Ostalo"</string> - <string name="accessibility_divider" msgid="2830785970889237307">"Razdjelnik ekrana"</string> - <string name="accessibility_action_divider_left_full" msgid="7598733539422375847">"Lijevo cijeli ekran"</string> - <string name="accessibility_action_divider_left_70" msgid="4919312892541727761">"Lijevo 70%"</string> - <string name="accessibility_action_divider_left_50" msgid="3664701169564893826">"Lijevo 50%"</string> - <string name="accessibility_action_divider_left_30" msgid="4358145268046362088">"Lijevo 30%"</string> - <string name="accessibility_action_divider_right_full" msgid="8576057422864896305">"Desno cijeli ekran"</string> - <string name="accessibility_action_divider_top_full" msgid="4243901660795169777">"Gore cijeli ekran"</string> - <string name="accessibility_action_divider_top_70" msgid="6941226213260515072">"Gore 70%"</string> - <string name="accessibility_action_divider_top_50" msgid="6275211443706497621">"Gore 50%"</string> - <string name="accessibility_action_divider_top_30" msgid="5780597635887574916">"Gore 30%"</string> - <string name="accessibility_action_divider_bottom_full" msgid="7352434720610115395">"Donji ekran kao cijeli ekran"</string> <string name="accessibility_qs_edit_tile_label" msgid="9079791448815232967">"Pozicija <xliff:g id="POSITION">%1$d</xliff:g>, <xliff:g id="TILE_NAME">%2$s</xliff:g>. Dodirnite dvaput za uređivanje."</string> <string name="accessibility_qs_edit_add_tile_label" msgid="8292218072049068613">"<xliff:g id="TILE_NAME">%1$s</xliff:g> Dodirnite dvaput za dodavanje."</string> <string name="accessibility_qs_edit_move_tile" msgid="6027997446473163426">"Pomjeri <xliff:g id="TILE_NAME">%1$s</xliff:g>"</string> @@ -903,10 +892,6 @@ <string name="accessibility_qs_edit_tile_move" msgid="4841770637244326837">"Premjesti <xliff:g id="TILE_NAME">%1$s</xliff:g> na poziciju <xliff:g id="POSITION">%2$d</xliff:g>"</string> <string name="accessibility_desc_quick_settings_edit" msgid="741658939453595297">"Uređivanje brzih postavki"</string> <string name="accessibility_desc_notification_icon" msgid="7331265967584178674">"<xliff:g id="ID_1">%1$s</xliff:g> obavještenje: <xliff:g id="ID_2">%2$s</xliff:g>"</string> - <string name="dock_forced_resizable" msgid="4689301323912928801">"Aplikacija možda neće raditi na podijeljenom ekranu"</string> - <string name="dock_non_resizeble_failed_to_dock_text" msgid="7284915968096153808">"Aplikacija ne podržava dijeljenje ekrana."</string> - <string name="forced_resizable_secondary_display" msgid="522558907654394940">"Aplikacija možda neće raditi na sekundarnom ekranu."</string> - <string name="activity_launch_on_secondary_display_failed_text" msgid="8446727617187998208">"Aplikacija ne podržava pokretanje na sekundarnim ekranima."</string> <string name="accessibility_quick_settings_settings" msgid="7098489591715844713">"Otvori postavke."</string> <string name="accessibility_quick_settings_expand" msgid="2609275052412521467">"Otvoriti brze postavke."</string> <string name="accessibility_quick_settings_collapse" msgid="4674876336725041982">"Zatvoriti brze postavke."</string> diff --git a/packages/SystemUI/res/values-ca/strings.xml b/packages/SystemUI/res/values-ca/strings.xml index 0489d18ff36b..d4e8befe3f4d 100644 --- a/packages/SystemUI/res/values-ca/strings.xml +++ b/packages/SystemUI/res/values-ca/strings.xml @@ -707,7 +707,7 @@ <string name="inline_turn_off_notifications" msgid="8543989584403106071">"Desactiva les notificacions"</string> <string name="inline_keep_showing_app" msgid="4393429060390649757">"Vols continuar rebent notificacions d\'aquesta aplicació?"</string> <string name="notification_silence_title" msgid="8608090968400832335">"Silenci"</string> - <string name="notification_alert_title" msgid="3656229781017543655">"Predeterminada"</string> + <string name="notification_alert_title" msgid="3656229781017543655">"Predeterminat"</string> <string name="notification_bubble_title" msgid="8330481035191903164">"Bombolla"</string> <string name="notification_automatic_title" msgid="3745465364578762652">"Automàtic"</string> <string name="notification_channel_summary_low" msgid="4860617986908931158">"Sense so ni vibració"</string> @@ -879,17 +879,6 @@ </string-array> <string name="tuner_low_priority" msgid="8412666814123009820">"Mostra les icones de notificació amb prioritat baixa"</string> <string name="other" msgid="429768510980739978">"Altres"</string> - <string name="accessibility_divider" msgid="2830785970889237307">"Divisor de pantalles"</string> - <string name="accessibility_action_divider_left_full" msgid="7598733539422375847">"Pantalla esquerra completa"</string> - <string name="accessibility_action_divider_left_70" msgid="4919312892541727761">"Pantalla esquerra al 70%"</string> - <string name="accessibility_action_divider_left_50" msgid="3664701169564893826">"Pantalla esquerra al 50%"</string> - <string name="accessibility_action_divider_left_30" msgid="4358145268046362088">"Pantalla esquerra al 30%"</string> - <string name="accessibility_action_divider_right_full" msgid="8576057422864896305">"Pantalla dreta completa"</string> - <string name="accessibility_action_divider_top_full" msgid="4243901660795169777">"Pantalla superior completa"</string> - <string name="accessibility_action_divider_top_70" msgid="6941226213260515072">"Pantalla superior al 70%"</string> - <string name="accessibility_action_divider_top_50" msgid="6275211443706497621">"Pantalla superior al 50%"</string> - <string name="accessibility_action_divider_top_30" msgid="5780597635887574916">"Pantalla superior al 30%"</string> - <string name="accessibility_action_divider_bottom_full" msgid="7352434720610115395">"Pantalla inferior completa"</string> <string name="accessibility_qs_edit_tile_label" msgid="9079791448815232967">"Posició <xliff:g id="POSITION">%1$d</xliff:g>, <xliff:g id="TILE_NAME">%2$s</xliff:g>. Fes doble toc per editar-la."</string> <string name="accessibility_qs_edit_add_tile_label" msgid="8292218072049068613">"<xliff:g id="TILE_NAME">%1$s</xliff:g>. Fes doble toc per afegir-ho."</string> <string name="accessibility_qs_edit_move_tile" msgid="6027997446473163426">"Mou <xliff:g id="TILE_NAME">%1$s</xliff:g>"</string> @@ -898,10 +887,6 @@ <string name="accessibility_qs_edit_tile_move" msgid="4841770637244326837">"Mou <xliff:g id="TILE_NAME">%1$s</xliff:g> a la posició <xliff:g id="POSITION">%2$d</xliff:g>"</string> <string name="accessibility_desc_quick_settings_edit" msgid="741658939453595297">"Editor de configuració ràpida."</string> <string name="accessibility_desc_notification_icon" msgid="7331265967584178674">"Notificació de <xliff:g id="ID_1">%1$s</xliff:g>: <xliff:g id="ID_2">%2$s</xliff:g>"</string> - <string name="dock_forced_resizable" msgid="4689301323912928801">"És possible que l\'aplicació no funcioni amb la pantalla dividida."</string> - <string name="dock_non_resizeble_failed_to_dock_text" msgid="7284915968096153808">"L\'aplicació no admet la pantalla dividida."</string> - <string name="forced_resizable_secondary_display" msgid="522558907654394940">"És possible que l\'aplicació no funcioni en una pantalla secundària."</string> - <string name="activity_launch_on_secondary_display_failed_text" msgid="8446727617187998208">"L\'aplicació no es pot obrir en pantalles secundàries."</string> <string name="accessibility_quick_settings_settings" msgid="7098489591715844713">"Obre la configuració."</string> <string name="accessibility_quick_settings_expand" msgid="2609275052412521467">"Obre la configuració ràpida."</string> <string name="accessibility_quick_settings_collapse" msgid="4674876336725041982">"Tanca la configuració ràpida."</string> diff --git a/packages/SystemUI/res/values-cs/strings.xml b/packages/SystemUI/res/values-cs/strings.xml index acb6637b68dc..239a0f6b3d53 100644 --- a/packages/SystemUI/res/values-cs/strings.xml +++ b/packages/SystemUI/res/values-cs/strings.xml @@ -889,17 +889,6 @@ </string-array> <string name="tuner_low_priority" msgid="8412666814123009820">"Zobrazit ikony oznámení s nízkou prioritou"</string> <string name="other" msgid="429768510980739978">"Jiné"</string> - <string name="accessibility_divider" msgid="2830785970889237307">"Čára rozdělující obrazovku"</string> - <string name="accessibility_action_divider_left_full" msgid="7598733539422375847">"Levá část na celou obrazovku"</string> - <string name="accessibility_action_divider_left_70" msgid="4919312892541727761">"70 % vlevo"</string> - <string name="accessibility_action_divider_left_50" msgid="3664701169564893826">"50 % vlevo"</string> - <string name="accessibility_action_divider_left_30" msgid="4358145268046362088">"30 % vlevo"</string> - <string name="accessibility_action_divider_right_full" msgid="8576057422864896305">"Pravá část na celou obrazovku"</string> - <string name="accessibility_action_divider_top_full" msgid="4243901660795169777">"Horní část na celou obrazovku"</string> - <string name="accessibility_action_divider_top_70" msgid="6941226213260515072">"70 % nahoře"</string> - <string name="accessibility_action_divider_top_50" msgid="6275211443706497621">"50 % nahoře"</string> - <string name="accessibility_action_divider_top_30" msgid="5780597635887574916">"30 % nahoře"</string> - <string name="accessibility_action_divider_bottom_full" msgid="7352434720610115395">"Dolní část na celou obrazovku"</string> <string name="accessibility_qs_edit_tile_label" msgid="9079791448815232967">"Pozice <xliff:g id="POSITION">%1$d</xliff:g>, <xliff:g id="TILE_NAME">%2$s</xliff:g>. Dvojitým klepnutím ji upravíte."</string> <string name="accessibility_qs_edit_add_tile_label" msgid="8292218072049068613">"<xliff:g id="TILE_NAME">%1$s</xliff:g>. Dlaždici přidáte dvojitým klepnutím."</string> <string name="accessibility_qs_edit_move_tile" msgid="6027997446473163426">"Přesunout dlaždici <xliff:g id="TILE_NAME">%1$s</xliff:g>"</string> @@ -908,10 +897,6 @@ <string name="accessibility_qs_edit_tile_move" msgid="4841770637244326837">"Přesunout dlaždici <xliff:g id="TILE_NAME">%1$s</xliff:g> na pozici <xliff:g id="POSITION">%2$d</xliff:g>"</string> <string name="accessibility_desc_quick_settings_edit" msgid="741658939453595297">"Editor rychlého nastavení"</string> <string name="accessibility_desc_notification_icon" msgid="7331265967584178674">"Oznámení aplikace <xliff:g id="ID_1">%1$s</xliff:g>: <xliff:g id="ID_2">%2$s</xliff:g>"</string> - <string name="dock_forced_resizable" msgid="4689301323912928801">"Aplikace v režimu rozdělené obrazovky nemusí fungovat."</string> - <string name="dock_non_resizeble_failed_to_dock_text" msgid="7284915968096153808">"Aplikace nepodporuje režim rozdělené obrazovky."</string> - <string name="forced_resizable_secondary_display" msgid="522558907654394940">"Aplikace na sekundárním displeji nemusí fungovat."</string> - <string name="activity_launch_on_secondary_display_failed_text" msgid="8446727617187998208">"Aplikace nepodporuje spuštění na sekundárních displejích."</string> <string name="accessibility_quick_settings_settings" msgid="7098489591715844713">"Otevřít nastavení."</string> <string name="accessibility_quick_settings_expand" msgid="2609275052412521467">"Otevřít rychlé nastavení."</string> <string name="accessibility_quick_settings_collapse" msgid="4674876336725041982">"Zavřít rychlé nastavení."</string> diff --git a/packages/SystemUI/res/values-da/strings.xml b/packages/SystemUI/res/values-da/strings.xml index 886369598f1c..7ce60ea1536a 100644 --- a/packages/SystemUI/res/values-da/strings.xml +++ b/packages/SystemUI/res/values-da/strings.xml @@ -879,17 +879,6 @@ </string-array> <string name="tuner_low_priority" msgid="8412666814123009820">"Vis ikoner for notifikationer med lav prioritet"</string> <string name="other" msgid="429768510980739978">"Andet"</string> - <string name="accessibility_divider" msgid="2830785970889237307">"Adskiller til opdelt skærm"</string> - <string name="accessibility_action_divider_left_full" msgid="7598733539422375847">"Vis venstre del i fuld skærm"</string> - <string name="accessibility_action_divider_left_70" msgid="4919312892541727761">"Venstre 70 %"</string> - <string name="accessibility_action_divider_left_50" msgid="3664701169564893826">"Venstre 50 %"</string> - <string name="accessibility_action_divider_left_30" msgid="4358145268046362088">"Venstre 30 %"</string> - <string name="accessibility_action_divider_right_full" msgid="8576057422864896305">"Vis højre del i fuld skærm"</string> - <string name="accessibility_action_divider_top_full" msgid="4243901660795169777">"Vis øverste del i fuld skærm"</string> - <string name="accessibility_action_divider_top_70" msgid="6941226213260515072">"Øverste 70 %"</string> - <string name="accessibility_action_divider_top_50" msgid="6275211443706497621">"Øverste 50 %"</string> - <string name="accessibility_action_divider_top_30" msgid="5780597635887574916">"Øverste 30 %"</string> - <string name="accessibility_action_divider_bottom_full" msgid="7352434720610115395">"Vis nederste del i fuld skærm"</string> <string name="accessibility_qs_edit_tile_label" msgid="9079791448815232967">"Position <xliff:g id="POSITION">%1$d</xliff:g>, <xliff:g id="TILE_NAME">%2$s</xliff:g>. Tryk to gange for at redigere."</string> <string name="accessibility_qs_edit_add_tile_label" msgid="8292218072049068613">"<xliff:g id="TILE_NAME">%1$s</xliff:g>. Tryk to gange for at tilføje."</string> <string name="accessibility_qs_edit_move_tile" msgid="6027997446473163426">"Flyt <xliff:g id="TILE_NAME">%1$s</xliff:g>"</string> @@ -898,10 +887,6 @@ <string name="accessibility_qs_edit_tile_move" msgid="4841770637244326837">"Flyt <xliff:g id="TILE_NAME">%1$s</xliff:g> til position <xliff:g id="POSITION">%2$d</xliff:g>"</string> <string name="accessibility_desc_quick_settings_edit" msgid="741658939453595297">"Redigeringsværktøj til Kvikmenu."</string> <string name="accessibility_desc_notification_icon" msgid="7331265967584178674">"<xliff:g id="ID_1">%1$s</xliff:g>-notifikation: <xliff:g id="ID_2">%2$s</xliff:g>"</string> - <string name="dock_forced_resizable" msgid="4689301323912928801">"Appen fungerer muligvis ikke i opdelt skærm."</string> - <string name="dock_non_resizeble_failed_to_dock_text" msgid="7284915968096153808">"Appen understøtter ikke opdelt skærm."</string> - <string name="forced_resizable_secondary_display" msgid="522558907654394940">"Appen fungerer muligvis ikke på sekundære skærme."</string> - <string name="activity_launch_on_secondary_display_failed_text" msgid="8446727617187998208">"Appen kan ikke åbnes på sekundære skærme."</string> <string name="accessibility_quick_settings_settings" msgid="7098489591715844713">"Åbn Indstillinger."</string> <string name="accessibility_quick_settings_expand" msgid="2609275052412521467">"Åbn Kvikmenu."</string> <string name="accessibility_quick_settings_collapse" msgid="4674876336725041982">"Luk Kvikmenu."</string> diff --git a/packages/SystemUI/res/values-de/strings.xml b/packages/SystemUI/res/values-de/strings.xml index 8d990c66ecdf..093e1a20ca97 100644 --- a/packages/SystemUI/res/values-de/strings.xml +++ b/packages/SystemUI/res/values-de/strings.xml @@ -879,17 +879,6 @@ </string-array> <string name="tuner_low_priority" msgid="8412666814123009820">"Symbole für Benachrichtigungen mit einer niedrigen Priorität anzeigen"</string> <string name="other" msgid="429768510980739978">"Sonstiges"</string> - <string name="accessibility_divider" msgid="2830785970889237307">"Bildschirmteiler"</string> - <string name="accessibility_action_divider_left_full" msgid="7598733539422375847">"Vollbild links"</string> - <string name="accessibility_action_divider_left_70" msgid="4919312892541727761">"70 % links"</string> - <string name="accessibility_action_divider_left_50" msgid="3664701169564893826">"50 % links"</string> - <string name="accessibility_action_divider_left_30" msgid="4358145268046362088">"30 % links"</string> - <string name="accessibility_action_divider_right_full" msgid="8576057422864896305">"Vollbild rechts"</string> - <string name="accessibility_action_divider_top_full" msgid="4243901660795169777">"Vollbild oben"</string> - <string name="accessibility_action_divider_top_70" msgid="6941226213260515072">"70 % oben"</string> - <string name="accessibility_action_divider_top_50" msgid="6275211443706497621">"50 % oben"</string> - <string name="accessibility_action_divider_top_30" msgid="5780597635887574916">"30 % oben"</string> - <string name="accessibility_action_divider_bottom_full" msgid="7352434720610115395">"Vollbild unten"</string> <string name="accessibility_qs_edit_tile_label" msgid="9079791448815232967">"Position <xliff:g id="POSITION">%1$d</xliff:g>, <xliff:g id="TILE_NAME">%2$s</xliff:g>. Zum Bearbeiten doppeltippen."</string> <string name="accessibility_qs_edit_add_tile_label" msgid="8292218072049068613">"<xliff:g id="TILE_NAME">%1$s</xliff:g>. Zum Hinzufügen doppeltippen."</string> <string name="accessibility_qs_edit_move_tile" msgid="6027997446473163426">"<xliff:g id="TILE_NAME">%1$s</xliff:g> verschieben"</string> @@ -898,10 +887,6 @@ <string name="accessibility_qs_edit_tile_move" msgid="4841770637244326837">"<xliff:g id="TILE_NAME">%1$s</xliff:g> auf Position <xliff:g id="POSITION">%2$d</xliff:g> verschieben"</string> <string name="accessibility_desc_quick_settings_edit" msgid="741658939453595297">"Editor für Schnelleinstellungen."</string> <string name="accessibility_desc_notification_icon" msgid="7331265967584178674">"Benachrichtigung von <xliff:g id="ID_1">%1$s</xliff:g>: <xliff:g id="ID_2">%2$s</xliff:g>"</string> - <string name="dock_forced_resizable" msgid="4689301323912928801">"Die App funktioniert unter Umständen bei geteiltem Bildschirm nicht."</string> - <string name="dock_non_resizeble_failed_to_dock_text" msgid="7284915968096153808">"Das Teilen des Bildschirms wird in dieser App nicht unterstützt."</string> - <string name="forced_resizable_secondary_display" msgid="522558907654394940">"Die App funktioniert auf einem sekundären Display möglicherweise nicht."</string> - <string name="activity_launch_on_secondary_display_failed_text" msgid="8446727617187998208">"Die App unterstützt den Start auf sekundären Displays nicht."</string> <string name="accessibility_quick_settings_settings" msgid="7098489591715844713">"Einstellungen öffnen."</string> <string name="accessibility_quick_settings_expand" msgid="2609275052412521467">"Schnelleinstellungen öffnen."</string> <string name="accessibility_quick_settings_collapse" msgid="4674876336725041982">"Schnelleinstellungen schließen."</string> diff --git a/packages/SystemUI/res/values-el/strings.xml b/packages/SystemUI/res/values-el/strings.xml index 5ca236b2514a..ac1a3ee4601e 100644 --- a/packages/SystemUI/res/values-el/strings.xml +++ b/packages/SystemUI/res/values-el/strings.xml @@ -879,17 +879,6 @@ </string-array> <string name="tuner_low_priority" msgid="8412666814123009820">"Εμφάνιση εικονιδίων ειδοποιήσεων χαμηλής προτεραιότητας"</string> <string name="other" msgid="429768510980739978">"Άλλο"</string> - <string name="accessibility_divider" msgid="2830785970889237307">"Διαχωριστικό οθόνης"</string> - <string name="accessibility_action_divider_left_full" msgid="7598733539422375847">"Αριστερή πλήρης οθόνη"</string> - <string name="accessibility_action_divider_left_70" msgid="4919312892541727761">"Αριστερή 70%"</string> - <string name="accessibility_action_divider_left_50" msgid="3664701169564893826">"Αριστερή 50%"</string> - <string name="accessibility_action_divider_left_30" msgid="4358145268046362088">"Αριστερή 30%"</string> - <string name="accessibility_action_divider_right_full" msgid="8576057422864896305">"Δεξιά πλήρης οθόνη"</string> - <string name="accessibility_action_divider_top_full" msgid="4243901660795169777">"Πάνω πλήρης οθόνη"</string> - <string name="accessibility_action_divider_top_70" msgid="6941226213260515072">"Πάνω 70%"</string> - <string name="accessibility_action_divider_top_50" msgid="6275211443706497621">"Πάνω 50%"</string> - <string name="accessibility_action_divider_top_30" msgid="5780597635887574916">"Πάνω 30%"</string> - <string name="accessibility_action_divider_bottom_full" msgid="7352434720610115395">"Κάτω πλήρης οθόνη"</string> <string name="accessibility_qs_edit_tile_label" msgid="9079791448815232967">"Θέση <xliff:g id="POSITION">%1$d</xliff:g>, <xliff:g id="TILE_NAME">%2$s</xliff:g>. Πατήστε δύο φορές για επεξεργασία."</string> <string name="accessibility_qs_edit_add_tile_label" msgid="8292218072049068613">"<xliff:g id="TILE_NAME">%1$s</xliff:g>. Πατήστε δύο φορές για προσθήκη."</string> <string name="accessibility_qs_edit_move_tile" msgid="6027997446473163426">"Μετακίνηση <xliff:g id="TILE_NAME">%1$s</xliff:g>"</string> @@ -898,10 +887,6 @@ <string name="accessibility_qs_edit_tile_move" msgid="4841770637244326837">"Μετακίνηση <xliff:g id="TILE_NAME">%1$s</xliff:g> στη θέση <xliff:g id="POSITION">%2$d</xliff:g>"</string> <string name="accessibility_desc_quick_settings_edit" msgid="741658939453595297">"Επεξεργασία γρήγορων ρυθμίσεων."</string> <string name="accessibility_desc_notification_icon" msgid="7331265967584178674">"Ειδοποίηση <xliff:g id="ID_1">%1$s</xliff:g>: <xliff:g id="ID_2">%2$s</xliff:g>"</string> - <string name="dock_forced_resizable" msgid="4689301323912928801">"Δεν είναι δυνατή η λειτουργία της εφαρμογής με διαχωρισμό οθόνης."</string> - <string name="dock_non_resizeble_failed_to_dock_text" msgid="7284915968096153808">"Η εφαρμογή δεν υποστηρίζει διαχωρισμό οθόνης."</string> - <string name="forced_resizable_secondary_display" msgid="522558907654394940">"Η εφαρμογή ίσως να μην λειτουργήσει σε δευτερεύουσα οθόνη."</string> - <string name="activity_launch_on_secondary_display_failed_text" msgid="8446727617187998208">"Η εφαρμογή δεν υποστηρίζει την εκκίνηση σε δευτερεύουσες οθόνες."</string> <string name="accessibility_quick_settings_settings" msgid="7098489591715844713">"Άνοιγμα ρυθμίσεων."</string> <string name="accessibility_quick_settings_expand" msgid="2609275052412521467">"Άνοιγμα γρήγορων ρυθμίσεων."</string> <string name="accessibility_quick_settings_collapse" msgid="4674876336725041982">"Κλείσιμο γρήγορων ρυθμίσεων."</string> diff --git a/packages/SystemUI/res/values-en-rAU/strings.xml b/packages/SystemUI/res/values-en-rAU/strings.xml index 8a7963a1f845..3a76d75ac043 100644 --- a/packages/SystemUI/res/values-en-rAU/strings.xml +++ b/packages/SystemUI/res/values-en-rAU/strings.xml @@ -879,17 +879,6 @@ </string-array> <string name="tuner_low_priority" msgid="8412666814123009820">"Show low-priority notification icons"</string> <string name="other" msgid="429768510980739978">"Other"</string> - <string name="accessibility_divider" msgid="2830785970889237307">"Split screen divider"</string> - <string name="accessibility_action_divider_left_full" msgid="7598733539422375847">"Left full screen"</string> - <string name="accessibility_action_divider_left_70" msgid="4919312892541727761">"Left 70%"</string> - <string name="accessibility_action_divider_left_50" msgid="3664701169564893826">"Left 50%"</string> - <string name="accessibility_action_divider_left_30" msgid="4358145268046362088">"Left 30%"</string> - <string name="accessibility_action_divider_right_full" msgid="8576057422864896305">"Right full screen"</string> - <string name="accessibility_action_divider_top_full" msgid="4243901660795169777">"Top full screen"</string> - <string name="accessibility_action_divider_top_70" msgid="6941226213260515072">"Top 70%"</string> - <string name="accessibility_action_divider_top_50" msgid="6275211443706497621">"Top 50%"</string> - <string name="accessibility_action_divider_top_30" msgid="5780597635887574916">"Top 30%"</string> - <string name="accessibility_action_divider_bottom_full" msgid="7352434720610115395">"Bottom full screen"</string> <string name="accessibility_qs_edit_tile_label" msgid="9079791448815232967">"Position <xliff:g id="POSITION">%1$d</xliff:g>, <xliff:g id="TILE_NAME">%2$s</xliff:g>. Double tap to edit."</string> <string name="accessibility_qs_edit_add_tile_label" msgid="8292218072049068613">"<xliff:g id="TILE_NAME">%1$s</xliff:g>. Double tap to add."</string> <string name="accessibility_qs_edit_move_tile" msgid="6027997446473163426">"Move <xliff:g id="TILE_NAME">%1$s</xliff:g>"</string> @@ -898,10 +887,6 @@ <string name="accessibility_qs_edit_tile_move" msgid="4841770637244326837">"Move <xliff:g id="TILE_NAME">%1$s</xliff:g> to position <xliff:g id="POSITION">%2$d</xliff:g>"</string> <string name="accessibility_desc_quick_settings_edit" msgid="741658939453595297">"Quick settings editor."</string> <string name="accessibility_desc_notification_icon" msgid="7331265967584178674">"<xliff:g id="ID_1">%1$s</xliff:g> notification: <xliff:g id="ID_2">%2$s</xliff:g>"</string> - <string name="dock_forced_resizable" msgid="4689301323912928801">"App may not work with split-screen."</string> - <string name="dock_non_resizeble_failed_to_dock_text" msgid="7284915968096153808">"App does not support split-screen."</string> - <string name="forced_resizable_secondary_display" msgid="522558907654394940">"App may not work on a secondary display."</string> - <string name="activity_launch_on_secondary_display_failed_text" msgid="8446727617187998208">"App does not support launch on secondary displays."</string> <string name="accessibility_quick_settings_settings" msgid="7098489591715844713">"Open settings."</string> <string name="accessibility_quick_settings_expand" msgid="2609275052412521467">"Open quick settings."</string> <string name="accessibility_quick_settings_collapse" msgid="4674876336725041982">"Close quick settings."</string> diff --git a/packages/SystemUI/res/values-en-rCA/strings.xml b/packages/SystemUI/res/values-en-rCA/strings.xml index 7b2b25a0e678..ac6519394268 100644 --- a/packages/SystemUI/res/values-en-rCA/strings.xml +++ b/packages/SystemUI/res/values-en-rCA/strings.xml @@ -879,17 +879,6 @@ </string-array> <string name="tuner_low_priority" msgid="8412666814123009820">"Show low-priority notification icons"</string> <string name="other" msgid="429768510980739978">"Other"</string> - <string name="accessibility_divider" msgid="2830785970889237307">"Split screen divider"</string> - <string name="accessibility_action_divider_left_full" msgid="7598733539422375847">"Left full screen"</string> - <string name="accessibility_action_divider_left_70" msgid="4919312892541727761">"Left 70%"</string> - <string name="accessibility_action_divider_left_50" msgid="3664701169564893826">"Left 50%"</string> - <string name="accessibility_action_divider_left_30" msgid="4358145268046362088">"Left 30%"</string> - <string name="accessibility_action_divider_right_full" msgid="8576057422864896305">"Right full screen"</string> - <string name="accessibility_action_divider_top_full" msgid="4243901660795169777">"Top full screen"</string> - <string name="accessibility_action_divider_top_70" msgid="6941226213260515072">"Top 70%"</string> - <string name="accessibility_action_divider_top_50" msgid="6275211443706497621">"Top 50%"</string> - <string name="accessibility_action_divider_top_30" msgid="5780597635887574916">"Top 30%"</string> - <string name="accessibility_action_divider_bottom_full" msgid="7352434720610115395">"Bottom full screen"</string> <string name="accessibility_qs_edit_tile_label" msgid="9079791448815232967">"Position <xliff:g id="POSITION">%1$d</xliff:g>, <xliff:g id="TILE_NAME">%2$s</xliff:g>. Double tap to edit."</string> <string name="accessibility_qs_edit_add_tile_label" msgid="8292218072049068613">"<xliff:g id="TILE_NAME">%1$s</xliff:g>. Double tap to add."</string> <string name="accessibility_qs_edit_move_tile" msgid="6027997446473163426">"Move <xliff:g id="TILE_NAME">%1$s</xliff:g>"</string> @@ -898,10 +887,6 @@ <string name="accessibility_qs_edit_tile_move" msgid="4841770637244326837">"Move <xliff:g id="TILE_NAME">%1$s</xliff:g> to position <xliff:g id="POSITION">%2$d</xliff:g>"</string> <string name="accessibility_desc_quick_settings_edit" msgid="741658939453595297">"Quick settings editor."</string> <string name="accessibility_desc_notification_icon" msgid="7331265967584178674">"<xliff:g id="ID_1">%1$s</xliff:g> notification: <xliff:g id="ID_2">%2$s</xliff:g>"</string> - <string name="dock_forced_resizable" msgid="4689301323912928801">"App may not work with split-screen."</string> - <string name="dock_non_resizeble_failed_to_dock_text" msgid="7284915968096153808">"App does not support split-screen."</string> - <string name="forced_resizable_secondary_display" msgid="522558907654394940">"App may not work on a secondary display."</string> - <string name="activity_launch_on_secondary_display_failed_text" msgid="8446727617187998208">"App does not support launch on secondary displays."</string> <string name="accessibility_quick_settings_settings" msgid="7098489591715844713">"Open settings."</string> <string name="accessibility_quick_settings_expand" msgid="2609275052412521467">"Open quick settings."</string> <string name="accessibility_quick_settings_collapse" msgid="4674876336725041982">"Close quick settings."</string> diff --git a/packages/SystemUI/res/values-en-rGB/strings.xml b/packages/SystemUI/res/values-en-rGB/strings.xml index 8a7963a1f845..3a76d75ac043 100644 --- a/packages/SystemUI/res/values-en-rGB/strings.xml +++ b/packages/SystemUI/res/values-en-rGB/strings.xml @@ -879,17 +879,6 @@ </string-array> <string name="tuner_low_priority" msgid="8412666814123009820">"Show low-priority notification icons"</string> <string name="other" msgid="429768510980739978">"Other"</string> - <string name="accessibility_divider" msgid="2830785970889237307">"Split screen divider"</string> - <string name="accessibility_action_divider_left_full" msgid="7598733539422375847">"Left full screen"</string> - <string name="accessibility_action_divider_left_70" msgid="4919312892541727761">"Left 70%"</string> - <string name="accessibility_action_divider_left_50" msgid="3664701169564893826">"Left 50%"</string> - <string name="accessibility_action_divider_left_30" msgid="4358145268046362088">"Left 30%"</string> - <string name="accessibility_action_divider_right_full" msgid="8576057422864896305">"Right full screen"</string> - <string name="accessibility_action_divider_top_full" msgid="4243901660795169777">"Top full screen"</string> - <string name="accessibility_action_divider_top_70" msgid="6941226213260515072">"Top 70%"</string> - <string name="accessibility_action_divider_top_50" msgid="6275211443706497621">"Top 50%"</string> - <string name="accessibility_action_divider_top_30" msgid="5780597635887574916">"Top 30%"</string> - <string name="accessibility_action_divider_bottom_full" msgid="7352434720610115395">"Bottom full screen"</string> <string name="accessibility_qs_edit_tile_label" msgid="9079791448815232967">"Position <xliff:g id="POSITION">%1$d</xliff:g>, <xliff:g id="TILE_NAME">%2$s</xliff:g>. Double tap to edit."</string> <string name="accessibility_qs_edit_add_tile_label" msgid="8292218072049068613">"<xliff:g id="TILE_NAME">%1$s</xliff:g>. Double tap to add."</string> <string name="accessibility_qs_edit_move_tile" msgid="6027997446473163426">"Move <xliff:g id="TILE_NAME">%1$s</xliff:g>"</string> @@ -898,10 +887,6 @@ <string name="accessibility_qs_edit_tile_move" msgid="4841770637244326837">"Move <xliff:g id="TILE_NAME">%1$s</xliff:g> to position <xliff:g id="POSITION">%2$d</xliff:g>"</string> <string name="accessibility_desc_quick_settings_edit" msgid="741658939453595297">"Quick settings editor."</string> <string name="accessibility_desc_notification_icon" msgid="7331265967584178674">"<xliff:g id="ID_1">%1$s</xliff:g> notification: <xliff:g id="ID_2">%2$s</xliff:g>"</string> - <string name="dock_forced_resizable" msgid="4689301323912928801">"App may not work with split-screen."</string> - <string name="dock_non_resizeble_failed_to_dock_text" msgid="7284915968096153808">"App does not support split-screen."</string> - <string name="forced_resizable_secondary_display" msgid="522558907654394940">"App may not work on a secondary display."</string> - <string name="activity_launch_on_secondary_display_failed_text" msgid="8446727617187998208">"App does not support launch on secondary displays."</string> <string name="accessibility_quick_settings_settings" msgid="7098489591715844713">"Open settings."</string> <string name="accessibility_quick_settings_expand" msgid="2609275052412521467">"Open quick settings."</string> <string name="accessibility_quick_settings_collapse" msgid="4674876336725041982">"Close quick settings."</string> diff --git a/packages/SystemUI/res/values-en-rIN/strings.xml b/packages/SystemUI/res/values-en-rIN/strings.xml index 8a7963a1f845..3a76d75ac043 100644 --- a/packages/SystemUI/res/values-en-rIN/strings.xml +++ b/packages/SystemUI/res/values-en-rIN/strings.xml @@ -879,17 +879,6 @@ </string-array> <string name="tuner_low_priority" msgid="8412666814123009820">"Show low-priority notification icons"</string> <string name="other" msgid="429768510980739978">"Other"</string> - <string name="accessibility_divider" msgid="2830785970889237307">"Split screen divider"</string> - <string name="accessibility_action_divider_left_full" msgid="7598733539422375847">"Left full screen"</string> - <string name="accessibility_action_divider_left_70" msgid="4919312892541727761">"Left 70%"</string> - <string name="accessibility_action_divider_left_50" msgid="3664701169564893826">"Left 50%"</string> - <string name="accessibility_action_divider_left_30" msgid="4358145268046362088">"Left 30%"</string> - <string name="accessibility_action_divider_right_full" msgid="8576057422864896305">"Right full screen"</string> - <string name="accessibility_action_divider_top_full" msgid="4243901660795169777">"Top full screen"</string> - <string name="accessibility_action_divider_top_70" msgid="6941226213260515072">"Top 70%"</string> - <string name="accessibility_action_divider_top_50" msgid="6275211443706497621">"Top 50%"</string> - <string name="accessibility_action_divider_top_30" msgid="5780597635887574916">"Top 30%"</string> - <string name="accessibility_action_divider_bottom_full" msgid="7352434720610115395">"Bottom full screen"</string> <string name="accessibility_qs_edit_tile_label" msgid="9079791448815232967">"Position <xliff:g id="POSITION">%1$d</xliff:g>, <xliff:g id="TILE_NAME">%2$s</xliff:g>. Double tap to edit."</string> <string name="accessibility_qs_edit_add_tile_label" msgid="8292218072049068613">"<xliff:g id="TILE_NAME">%1$s</xliff:g>. Double tap to add."</string> <string name="accessibility_qs_edit_move_tile" msgid="6027997446473163426">"Move <xliff:g id="TILE_NAME">%1$s</xliff:g>"</string> @@ -898,10 +887,6 @@ <string name="accessibility_qs_edit_tile_move" msgid="4841770637244326837">"Move <xliff:g id="TILE_NAME">%1$s</xliff:g> to position <xliff:g id="POSITION">%2$d</xliff:g>"</string> <string name="accessibility_desc_quick_settings_edit" msgid="741658939453595297">"Quick settings editor."</string> <string name="accessibility_desc_notification_icon" msgid="7331265967584178674">"<xliff:g id="ID_1">%1$s</xliff:g> notification: <xliff:g id="ID_2">%2$s</xliff:g>"</string> - <string name="dock_forced_resizable" msgid="4689301323912928801">"App may not work with split-screen."</string> - <string name="dock_non_resizeble_failed_to_dock_text" msgid="7284915968096153808">"App does not support split-screen."</string> - <string name="forced_resizable_secondary_display" msgid="522558907654394940">"App may not work on a secondary display."</string> - <string name="activity_launch_on_secondary_display_failed_text" msgid="8446727617187998208">"App does not support launch on secondary displays."</string> <string name="accessibility_quick_settings_settings" msgid="7098489591715844713">"Open settings."</string> <string name="accessibility_quick_settings_expand" msgid="2609275052412521467">"Open quick settings."</string> <string name="accessibility_quick_settings_collapse" msgid="4674876336725041982">"Close quick settings."</string> diff --git a/packages/SystemUI/res/values-en-rXC/strings.xml b/packages/SystemUI/res/values-en-rXC/strings.xml index 15738f2512f4..211a27c69b7e 100644 --- a/packages/SystemUI/res/values-en-rXC/strings.xml +++ b/packages/SystemUI/res/values-en-rXC/strings.xml @@ -879,17 +879,6 @@ </string-array> <string name="tuner_low_priority" msgid="8412666814123009820">"Show low-priority notification icons"</string> <string name="other" msgid="429768510980739978">"Other"</string> - <string name="accessibility_divider" msgid="2830785970889237307">"Split-screen divider"</string> - <string name="accessibility_action_divider_left_full" msgid="7598733539422375847">"Left full screen"</string> - <string name="accessibility_action_divider_left_70" msgid="4919312892541727761">"Left 70%"</string> - <string name="accessibility_action_divider_left_50" msgid="3664701169564893826">"Left 50%"</string> - <string name="accessibility_action_divider_left_30" msgid="4358145268046362088">"Left 30%"</string> - <string name="accessibility_action_divider_right_full" msgid="8576057422864896305">"Right full screen"</string> - <string name="accessibility_action_divider_top_full" msgid="4243901660795169777">"Top full screen"</string> - <string name="accessibility_action_divider_top_70" msgid="6941226213260515072">"Top 70%"</string> - <string name="accessibility_action_divider_top_50" msgid="6275211443706497621">"Top 50%"</string> - <string name="accessibility_action_divider_top_30" msgid="5780597635887574916">"Top 30%"</string> - <string name="accessibility_action_divider_bottom_full" msgid="7352434720610115395">"Bottom full screen"</string> <string name="accessibility_qs_edit_tile_label" msgid="9079791448815232967">"Position <xliff:g id="POSITION">%1$d</xliff:g>, <xliff:g id="TILE_NAME">%2$s</xliff:g>. Double tap to edit."</string> <string name="accessibility_qs_edit_add_tile_label" msgid="8292218072049068613">"<xliff:g id="TILE_NAME">%1$s</xliff:g>. Double tap to add."</string> <string name="accessibility_qs_edit_move_tile" msgid="6027997446473163426">"Move <xliff:g id="TILE_NAME">%1$s</xliff:g>"</string> @@ -898,10 +887,6 @@ <string name="accessibility_qs_edit_tile_move" msgid="4841770637244326837">"Move <xliff:g id="TILE_NAME">%1$s</xliff:g> to position <xliff:g id="POSITION">%2$d</xliff:g>"</string> <string name="accessibility_desc_quick_settings_edit" msgid="741658939453595297">"Quick settings editor."</string> <string name="accessibility_desc_notification_icon" msgid="7331265967584178674">"<xliff:g id="ID_1">%1$s</xliff:g> notification: <xliff:g id="ID_2">%2$s</xliff:g>"</string> - <string name="dock_forced_resizable" msgid="4689301323912928801">"App may not work with split-screen."</string> - <string name="dock_non_resizeble_failed_to_dock_text" msgid="7284915968096153808">"App does not support split-screen."</string> - <string name="forced_resizable_secondary_display" msgid="522558907654394940">"App may not work on a secondary display."</string> - <string name="activity_launch_on_secondary_display_failed_text" msgid="8446727617187998208">"App does not support launch on secondary displays."</string> <string name="accessibility_quick_settings_settings" msgid="7098489591715844713">"Open settings."</string> <string name="accessibility_quick_settings_expand" msgid="2609275052412521467">"Open quick settings."</string> <string name="accessibility_quick_settings_collapse" msgid="4674876336725041982">"Close quick settings."</string> diff --git a/packages/SystemUI/res/values-es-rUS/strings.xml b/packages/SystemUI/res/values-es-rUS/strings.xml index aa81ab8efadd..ccc46266f7fe 100644 --- a/packages/SystemUI/res/values-es-rUS/strings.xml +++ b/packages/SystemUI/res/values-es-rUS/strings.xml @@ -879,17 +879,6 @@ </string-array> <string name="tuner_low_priority" msgid="8412666814123009820">"Mostrar íconos de notificaciones con prioridad baja"</string> <string name="other" msgid="429768510980739978">"Otros"</string> - <string name="accessibility_divider" msgid="2830785970889237307">"Divisor de pantalla dividida"</string> - <string name="accessibility_action_divider_left_full" msgid="7598733539422375847">"Pantalla izquierda completa"</string> - <string name="accessibility_action_divider_left_70" msgid="4919312892541727761">"Izquierda: 70%"</string> - <string name="accessibility_action_divider_left_50" msgid="3664701169564893826">"Izquierda: 50%"</string> - <string name="accessibility_action_divider_left_30" msgid="4358145268046362088">"Izquierda: 30%"</string> - <string name="accessibility_action_divider_right_full" msgid="8576057422864896305">"Pantalla derecha completa"</string> - <string name="accessibility_action_divider_top_full" msgid="4243901660795169777">"Pantalla superior completa"</string> - <string name="accessibility_action_divider_top_70" msgid="6941226213260515072">"Superior: 70%"</string> - <string name="accessibility_action_divider_top_50" msgid="6275211443706497621">"Superior: 50%"</string> - <string name="accessibility_action_divider_top_30" msgid="5780597635887574916">"Superior: 30%"</string> - <string name="accessibility_action_divider_bottom_full" msgid="7352434720610115395">"Pantalla inferior completa"</string> <string name="accessibility_qs_edit_tile_label" msgid="9079791448815232967">"Posición <xliff:g id="POSITION">%1$d</xliff:g>, <xliff:g id="TILE_NAME">%2$s</xliff:g>. Presiona dos veces para editarla."</string> <string name="accessibility_qs_edit_add_tile_label" msgid="8292218072049068613">"<xliff:g id="TILE_NAME">%1$s</xliff:g>. Presiona dos veces para agregarlo."</string> <string name="accessibility_qs_edit_move_tile" msgid="6027997446473163426">"Mover <xliff:g id="TILE_NAME">%1$s</xliff:g>"</string> @@ -898,10 +887,6 @@ <string name="accessibility_qs_edit_tile_move" msgid="4841770637244326837">"Mover <xliff:g id="TILE_NAME">%1$s</xliff:g> a la posición <xliff:g id="POSITION">%2$d</xliff:g>"</string> <string name="accessibility_desc_quick_settings_edit" msgid="741658939453595297">"Editor de Configuración rápida"</string> <string name="accessibility_desc_notification_icon" msgid="7331265967584178674">"Notificación de <xliff:g id="ID_1">%1$s</xliff:g>: <xliff:g id="ID_2">%2$s</xliff:g>"</string> - <string name="dock_forced_resizable" msgid="4689301323912928801">"Es posible que la app no funcione en el modo de pantalla dividida."</string> - <string name="dock_non_resizeble_failed_to_dock_text" msgid="7284915968096153808">"La app no es compatible con la función de pantalla dividida."</string> - <string name="forced_resizable_secondary_display" msgid="522558907654394940">"Es posible que la app no funcione en una pantalla secundaria."</string> - <string name="activity_launch_on_secondary_display_failed_text" msgid="8446727617187998208">"La app no puede iniciarse en pantallas secundarias."</string> <string name="accessibility_quick_settings_settings" msgid="7098489591715844713">"Abrir Configuración"</string> <string name="accessibility_quick_settings_expand" msgid="2609275052412521467">"Abrir la configuración rápida"</string> <string name="accessibility_quick_settings_collapse" msgid="4674876336725041982">"Cerrar configuración rápida"</string> diff --git a/packages/SystemUI/res/values-es/strings.xml b/packages/SystemUI/res/values-es/strings.xml index 863857016388..4e9347cb01e6 100644 --- a/packages/SystemUI/res/values-es/strings.xml +++ b/packages/SystemUI/res/values-es/strings.xml @@ -98,7 +98,7 @@ <string name="screenrecord_device_audio_description" msgid="4922694220572186193">"Sonido de tu dispositivo, como música, llamadas y tonos de llamada"</string> <string name="screenrecord_mic_label" msgid="2111264835791332350">"Micrófono"</string> <string name="screenrecord_device_audio_and_mic_label" msgid="1831323771978646841">"Audio y micrófono del dispositivo"</string> - <string name="screenrecord_start" msgid="330991441575775004">"Empezar"</string> + <string name="screenrecord_start" msgid="330991441575775004">"Iniciar"</string> <string name="screenrecord_ongoing_screen_only" msgid="4459670242451527727">"Grabando pantalla"</string> <string name="screenrecord_ongoing_screen_and_audio" msgid="5351133763125180920">"Grabando pantalla y audio"</string> <string name="screenrecord_taps_label" msgid="1595690528298857649">"Mostrar toques en la pantalla"</string> @@ -879,17 +879,6 @@ </string-array> <string name="tuner_low_priority" msgid="8412666814123009820">"Mostrar iconos de notificaciones con prioridad baja"</string> <string name="other" msgid="429768510980739978">"Otros"</string> - <string name="accessibility_divider" msgid="2830785970889237307">"Dividir la pantalla"</string> - <string name="accessibility_action_divider_left_full" msgid="7598733539422375847">"Pantalla izquierda completa"</string> - <string name="accessibility_action_divider_left_70" msgid="4919312892541727761">"Izquierda 70%"</string> - <string name="accessibility_action_divider_left_50" msgid="3664701169564893826">"Izquierda 50%"</string> - <string name="accessibility_action_divider_left_30" msgid="4358145268046362088">"Izquierda 30%"</string> - <string name="accessibility_action_divider_right_full" msgid="8576057422864896305">"Pantalla derecha completa"</string> - <string name="accessibility_action_divider_top_full" msgid="4243901660795169777">"Pantalla superior completa"</string> - <string name="accessibility_action_divider_top_70" msgid="6941226213260515072">"Superior 70%"</string> - <string name="accessibility_action_divider_top_50" msgid="6275211443706497621">"Superior 50%"</string> - <string name="accessibility_action_divider_top_30" msgid="5780597635887574916">"Superior 30%"</string> - <string name="accessibility_action_divider_bottom_full" msgid="7352434720610115395">"Pantalla inferior completa"</string> <string name="accessibility_qs_edit_tile_label" msgid="9079791448815232967">"Posición <xliff:g id="POSITION">%1$d</xliff:g>, <xliff:g id="TILE_NAME">%2$s</xliff:g>. Toca dos veces para cambiarla."</string> <string name="accessibility_qs_edit_add_tile_label" msgid="8292218072049068613">"<xliff:g id="TILE_NAME">%1$s</xliff:g>. Toca dos veces para añadirlo."</string> <string name="accessibility_qs_edit_move_tile" msgid="6027997446473163426">"Mover <xliff:g id="TILE_NAME">%1$s</xliff:g>"</string> @@ -898,10 +887,6 @@ <string name="accessibility_qs_edit_tile_move" msgid="4841770637244326837">"Mover <xliff:g id="TILE_NAME">%1$s</xliff:g> a la posición <xliff:g id="POSITION">%2$d</xliff:g>"</string> <string name="accessibility_desc_quick_settings_edit" msgid="741658939453595297">"Editor de ajustes rápidos."</string> <string name="accessibility_desc_notification_icon" msgid="7331265967584178674">"Notificación de <xliff:g id="ID_1">%1$s</xliff:g>: <xliff:g id="ID_2">%2$s</xliff:g>"</string> - <string name="dock_forced_resizable" msgid="4689301323912928801">"Es posible que la aplicación no funcione con la pantalla dividida."</string> - <string name="dock_non_resizeble_failed_to_dock_text" msgid="7284915968096153808">"La aplicación no admite la pantalla dividida."</string> - <string name="forced_resizable_secondary_display" msgid="522558907654394940">"Es posible que la aplicación no funcione en una pantalla secundaria."</string> - <string name="activity_launch_on_secondary_display_failed_text" msgid="8446727617187998208">"La aplicación no se puede abrir en pantallas secundarias."</string> <string name="accessibility_quick_settings_settings" msgid="7098489591715844713">"Abrir ajustes."</string> <string name="accessibility_quick_settings_expand" msgid="2609275052412521467">"Abrir ajustes rápidos."</string> <string name="accessibility_quick_settings_collapse" msgid="4674876336725041982">"Cerrar ajustes rápidos."</string> diff --git a/packages/SystemUI/res/values-et/strings.xml b/packages/SystemUI/res/values-et/strings.xml index f5ffad255cf6..21189f1ea5f6 100644 --- a/packages/SystemUI/res/values-et/strings.xml +++ b/packages/SystemUI/res/values-et/strings.xml @@ -879,17 +879,6 @@ </string-array> <string name="tuner_low_priority" msgid="8412666814123009820">"Kuva madala prioriteediga märguande ikoonid"</string> <string name="other" msgid="429768510980739978">"Muu"</string> - <string name="accessibility_divider" msgid="2830785970889237307">"Ekraanijagaja"</string> - <string name="accessibility_action_divider_left_full" msgid="7598733539422375847">"Vasak täisekraan"</string> - <string name="accessibility_action_divider_left_70" msgid="4919312892541727761">"Vasak: 70%"</string> - <string name="accessibility_action_divider_left_50" msgid="3664701169564893826">"Vasak: 50%"</string> - <string name="accessibility_action_divider_left_30" msgid="4358145268046362088">"Vasak: 30%"</string> - <string name="accessibility_action_divider_right_full" msgid="8576057422864896305">"Parem täisekraan"</string> - <string name="accessibility_action_divider_top_full" msgid="4243901660795169777">"Ülemine täisekraan"</string> - <string name="accessibility_action_divider_top_70" msgid="6941226213260515072">"Ülemine: 70%"</string> - <string name="accessibility_action_divider_top_50" msgid="6275211443706497621">"Ülemine: 50%"</string> - <string name="accessibility_action_divider_top_30" msgid="5780597635887574916">"Ülemine: 30%"</string> - <string name="accessibility_action_divider_bottom_full" msgid="7352434720610115395">"Alumine täisekraan"</string> <string name="accessibility_qs_edit_tile_label" msgid="9079791448815232967">"Asend <xliff:g id="POSITION">%1$d</xliff:g>, paan <xliff:g id="TILE_NAME">%2$s</xliff:g>. Topeltpuudutage muutmiseks."</string> <string name="accessibility_qs_edit_add_tile_label" msgid="8292218072049068613">"<xliff:g id="TILE_NAME">%1$s</xliff:g>. Topeltpuudutage lisamiseks."</string> <string name="accessibility_qs_edit_move_tile" msgid="6027997446473163426">"Paani <xliff:g id="TILE_NAME">%1$s</xliff:g> teisaldamine"</string> @@ -898,10 +887,6 @@ <string name="accessibility_qs_edit_tile_move" msgid="4841770637244326837">"Teisaldage <xliff:g id="TILE_NAME">%1$s</xliff:g> asendisse <xliff:g id="POSITION">%2$d</xliff:g>"</string> <string name="accessibility_desc_quick_settings_edit" msgid="741658939453595297">"Kiirseadete redigeerija."</string> <string name="accessibility_desc_notification_icon" msgid="7331265967584178674">"Teenuse <xliff:g id="ID_1">%1$s</xliff:g> märguanne: <xliff:g id="ID_2">%2$s</xliff:g>"</string> - <string name="dock_forced_resizable" msgid="4689301323912928801">"Rakendus ei pruugi poolitatud ekraaniga töötada."</string> - <string name="dock_non_resizeble_failed_to_dock_text" msgid="7284915968096153808">"Rakendus ei toeta jagatud ekraani."</string> - <string name="forced_resizable_secondary_display" msgid="522558907654394940">"Rakendus ei pruugi teisesel ekraanil töötada."</string> - <string name="activity_launch_on_secondary_display_failed_text" msgid="8446727617187998208">"Rakendus ei toeta teisestel ekraanidel käivitamist."</string> <string name="accessibility_quick_settings_settings" msgid="7098489591715844713">"Ava seaded."</string> <string name="accessibility_quick_settings_expand" msgid="2609275052412521467">"Ava kiirseaded."</string> <string name="accessibility_quick_settings_collapse" msgid="4674876336725041982">"Sule kiirseaded."</string> diff --git a/packages/SystemUI/res/values-eu/strings.xml b/packages/SystemUI/res/values-eu/strings.xml index 23bcd2c32c76..8a372361daac 100644 --- a/packages/SystemUI/res/values-eu/strings.xml +++ b/packages/SystemUI/res/values-eu/strings.xml @@ -879,17 +879,6 @@ </string-array> <string name="tuner_low_priority" msgid="8412666814123009820">"Erakutsi lehentasun txikiko jakinarazpenen ikonoak"</string> <string name="other" msgid="429768510980739978">"Beste bat"</string> - <string name="accessibility_divider" msgid="2830785970889237307">"Pantaila-zatitzailea"</string> - <string name="accessibility_action_divider_left_full" msgid="7598733539422375847">"Ezarri ezkerraldea pantaila osoan"</string> - <string name="accessibility_action_divider_left_70" msgid="4919312892541727761">"Ezarri ezkerraldea % 70en"</string> - <string name="accessibility_action_divider_left_50" msgid="3664701169564893826">"Ezarri ezkerraldea % 50en"</string> - <string name="accessibility_action_divider_left_30" msgid="4358145268046362088">"Ezarri ezkerraldea % 30en"</string> - <string name="accessibility_action_divider_right_full" msgid="8576057422864896305">"Ezarri eskuinaldea pantaila osoan"</string> - <string name="accessibility_action_divider_top_full" msgid="4243901660795169777">"Ezarri goialdea pantaila osoan"</string> - <string name="accessibility_action_divider_top_70" msgid="6941226213260515072">"Ezarri goialdea % 70en"</string> - <string name="accessibility_action_divider_top_50" msgid="6275211443706497621">"Ezarri goialdea % 50en"</string> - <string name="accessibility_action_divider_top_30" msgid="5780597635887574916">"Ezarri goialdea % 30en"</string> - <string name="accessibility_action_divider_bottom_full" msgid="7352434720610115395">"Ezarri behealdea pantaila osoan"</string> <string name="accessibility_qs_edit_tile_label" msgid="9079791448815232967">"<xliff:g id="POSITION">%1$d</xliff:g>. posizioa, <xliff:g id="TILE_NAME">%2$s</xliff:g>. Editatzeko, sakatu birritan."</string> <string name="accessibility_qs_edit_add_tile_label" msgid="8292218072049068613">"<xliff:g id="TILE_NAME">%1$s</xliff:g>. Gehitzeko, sakatu birritan."</string> <string name="accessibility_qs_edit_move_tile" msgid="6027997446473163426">"Mugitu <xliff:g id="TILE_NAME">%1$s</xliff:g>"</string> @@ -898,10 +887,6 @@ <string name="accessibility_qs_edit_tile_move" msgid="4841770637244326837">"Eraman <xliff:g id="TILE_NAME">%1$s</xliff:g> <xliff:g id="POSITION">%2$d</xliff:g>garren postura"</string> <string name="accessibility_desc_quick_settings_edit" msgid="741658939453595297">"Ezarpen bizkorren editorea."</string> <string name="accessibility_desc_notification_icon" msgid="7331265967584178674">"<xliff:g id="ID_1">%1$s</xliff:g> zerbitzuaren jakinarazpena: <xliff:g id="ID_2">%2$s</xliff:g>"</string> - <string name="dock_forced_resizable" msgid="4689301323912928801">"Baliteke aplikazioak ez funtzionatzea pantaila zatituan."</string> - <string name="dock_non_resizeble_failed_to_dock_text" msgid="7284915968096153808">"Aplikazioak ez du onartzen pantaila zatitua"</string> - <string name="forced_resizable_secondary_display" msgid="522558907654394940">"Baliteke aplikazioak ez funtzionatzea bigarren mailako pantailetan."</string> - <string name="activity_launch_on_secondary_display_failed_text" msgid="8446727617187998208">"Aplikazioa ezin da abiarazi bigarren mailako pantailatan."</string> <string name="accessibility_quick_settings_settings" msgid="7098489591715844713">"Ireki ezarpenak."</string> <string name="accessibility_quick_settings_expand" msgid="2609275052412521467">"Ireki ezarpen bizkorrak."</string> <string name="accessibility_quick_settings_collapse" msgid="4674876336725041982">"Itxi ezarpen bizkorrak."</string> diff --git a/packages/SystemUI/res/values-fa/strings.xml b/packages/SystemUI/res/values-fa/strings.xml index 55d8ab2566c6..7f85959af7aa 100644 --- a/packages/SystemUI/res/values-fa/strings.xml +++ b/packages/SystemUI/res/values-fa/strings.xml @@ -808,7 +808,7 @@ <string name="keyboard_shortcut_group_system_back" msgid="1055709713218453863">"برگشت"</string> <string name="keyboard_shortcut_group_system_notifications" msgid="3615971650562485878">"اعلانها"</string> <string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4856808328618265589">"میانبرهای صفحهکلید"</string> - <string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"تغییر طرحبندی صفحهکلید"</string> + <string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"تغییر جانمایی صفحهکلید"</string> <string name="keyboard_shortcut_group_applications" msgid="7386239431100651266">"برنامهها"</string> <string name="keyboard_shortcut_group_applications_assist" msgid="771606231466098742">"دستیار"</string> <string name="keyboard_shortcut_group_applications_browser" msgid="2776211137869809251">"مرورگر"</string> @@ -879,17 +879,6 @@ </string-array> <string name="tuner_low_priority" msgid="8412666814123009820">"نمایش نمادهای اعلان کماهمیت"</string> <string name="other" msgid="429768510980739978">"موارد دیگر"</string> - <string name="accessibility_divider" msgid="2830785970889237307">"تقسیمکننده صفحه"</string> - <string name="accessibility_action_divider_left_full" msgid="7598733539422375847">"تمامصفحه چپ"</string> - <string name="accessibility_action_divider_left_70" msgid="4919312892541727761">"٪۷۰ چپ"</string> - <string name="accessibility_action_divider_left_50" msgid="3664701169564893826">"٪۵۰ چپ"</string> - <string name="accessibility_action_divider_left_30" msgid="4358145268046362088">"٪۳۰ چپ"</string> - <string name="accessibility_action_divider_right_full" msgid="8576057422864896305">"تمامصفحه راست"</string> - <string name="accessibility_action_divider_top_full" msgid="4243901660795169777">"تمامصفحه بالا"</string> - <string name="accessibility_action_divider_top_70" msgid="6941226213260515072">"٪۷۰ بالا"</string> - <string name="accessibility_action_divider_top_50" msgid="6275211443706497621">"٪۵۰ بالا"</string> - <string name="accessibility_action_divider_top_30" msgid="5780597635887574916">"٪۳۰ بالا"</string> - <string name="accessibility_action_divider_bottom_full" msgid="7352434720610115395">"تمامصفحه پایین"</string> <string name="accessibility_qs_edit_tile_label" msgid="9079791448815232967">"موقعیت <xliff:g id="POSITION">%1$d</xliff:g>، <xliff:g id="TILE_NAME">%2$s</xliff:g>. برای ویرایش دو ضربه سریع بزنید."</string> <string name="accessibility_qs_edit_add_tile_label" msgid="8292218072049068613">"<xliff:g id="TILE_NAME">%1$s</xliff:g>. برای افزودن دو ضربه سریع بزنید."</string> <string name="accessibility_qs_edit_move_tile" msgid="6027997446473163426">"انتقال <xliff:g id="TILE_NAME">%1$s</xliff:g>"</string> @@ -898,10 +887,6 @@ <string name="accessibility_qs_edit_tile_move" msgid="4841770637244326837">"انتقال <xliff:g id="TILE_NAME">%1$s</xliff:g> به موقعیت <xliff:g id="POSITION">%2$d</xliff:g>"</string> <string name="accessibility_desc_quick_settings_edit" msgid="741658939453595297">"ویرایشگر تنظیمات سریع."</string> <string name="accessibility_desc_notification_icon" msgid="7331265967584178674">"اعلان <xliff:g id="ID_1">%1$s</xliff:g>: <xliff:g id="ID_2">%2$s</xliff:g>"</string> - <string name="dock_forced_resizable" msgid="4689301323912928801">"ممکن است برنامه با تقسیم صفحه کار نکند."</string> - <string name="dock_non_resizeble_failed_to_dock_text" msgid="7284915968096153808">"برنامه از تقسیم صفحه پشتیبانی نمیکند."</string> - <string name="forced_resizable_secondary_display" msgid="522558907654394940">"ممکن است برنامه در نمایشگر ثانویه کار نکند."</string> - <string name="activity_launch_on_secondary_display_failed_text" msgid="8446727617187998208">"برنامه از راهاندازی در نمایشگرهای ثانویه پشتیبانی نمیکند."</string> <string name="accessibility_quick_settings_settings" msgid="7098489591715844713">"باز کردن تنظیمات."</string> <string name="accessibility_quick_settings_expand" msgid="2609275052412521467">"باز کردن تنظیمات سریع."</string> <string name="accessibility_quick_settings_collapse" msgid="4674876336725041982">"بستن تنظیمات سریع."</string> diff --git a/packages/SystemUI/res/values-fi/strings.xml b/packages/SystemUI/res/values-fi/strings.xml index f30c44b3ffba..fd9bbd94625c 100644 --- a/packages/SystemUI/res/values-fi/strings.xml +++ b/packages/SystemUI/res/values-fi/strings.xml @@ -879,17 +879,6 @@ </string-array> <string name="tuner_low_priority" msgid="8412666814123009820">"Näytä vähemmän tärkeät ilmoituskuvakkeet"</string> <string name="other" msgid="429768510980739978">"Muu"</string> - <string name="accessibility_divider" msgid="2830785970889237307">"Näytön jakaja"</string> - <string name="accessibility_action_divider_left_full" msgid="7598733539422375847">"Vasen koko näytölle"</string> - <string name="accessibility_action_divider_left_70" msgid="4919312892541727761">"Vasen 70 %"</string> - <string name="accessibility_action_divider_left_50" msgid="3664701169564893826">"Vasen 50 %"</string> - <string name="accessibility_action_divider_left_30" msgid="4358145268046362088">"Vasen 30 %"</string> - <string name="accessibility_action_divider_right_full" msgid="8576057422864896305">"Oikea koko näytölle"</string> - <string name="accessibility_action_divider_top_full" msgid="4243901660795169777">"Yläosa koko näytölle"</string> - <string name="accessibility_action_divider_top_70" msgid="6941226213260515072">"Yläosa 70 %"</string> - <string name="accessibility_action_divider_top_50" msgid="6275211443706497621">"Yläosa 50 %"</string> - <string name="accessibility_action_divider_top_30" msgid="5780597635887574916">"Yläosa 30 %"</string> - <string name="accessibility_action_divider_bottom_full" msgid="7352434720610115395">"Alaosa koko näytölle"</string> <string name="accessibility_qs_edit_tile_label" msgid="9079791448815232967">"Paikka <xliff:g id="POSITION">%1$d</xliff:g>, <xliff:g id="TILE_NAME">%2$s</xliff:g>. Muokkaa kaksoisnapauttamalla."</string> <string name="accessibility_qs_edit_add_tile_label" msgid="8292218072049068613">"<xliff:g id="TILE_NAME">%1$s</xliff:g>. Lisää kaksoisnapauttamalla."</string> <string name="accessibility_qs_edit_move_tile" msgid="6027997446473163426">"Siirrä <xliff:g id="TILE_NAME">%1$s</xliff:g>."</string> @@ -898,10 +887,6 @@ <string name="accessibility_qs_edit_tile_move" msgid="4841770637244326837">"Siirrä <xliff:g id="TILE_NAME">%1$s</xliff:g> kohtaan <xliff:g id="POSITION">%2$d</xliff:g>"</string> <string name="accessibility_desc_quick_settings_edit" msgid="741658939453595297">"Pika-asetusten muokkausnäkymä"</string> <string name="accessibility_desc_notification_icon" msgid="7331265967584178674">"Ilmoitus kohteesta <xliff:g id="ID_1">%1$s</xliff:g>: <xliff:g id="ID_2">%2$s</xliff:g>"</string> - <string name="dock_forced_resizable" msgid="4689301323912928801">"Sovellus ei ehkä toimi jaetulla näytöllä."</string> - <string name="dock_non_resizeble_failed_to_dock_text" msgid="7284915968096153808">"Sovellus ei tue jaetun näytön tilaa."</string> - <string name="forced_resizable_secondary_display" msgid="522558907654394940">"Sovellus ei ehkä toimi toissijaisella näytöllä."</string> - <string name="activity_launch_on_secondary_display_failed_text" msgid="8446727617187998208">"Sovellus ei tue käynnistämistä toissijaisilla näytöillä."</string> <string name="accessibility_quick_settings_settings" msgid="7098489591715844713">"Avaa asetukset."</string> <string name="accessibility_quick_settings_expand" msgid="2609275052412521467">"Avaa pika-asetukset."</string> <string name="accessibility_quick_settings_collapse" msgid="4674876336725041982">"Sulje pika-asetukset."</string> diff --git a/packages/SystemUI/res/values-fr-rCA/strings.xml b/packages/SystemUI/res/values-fr-rCA/strings.xml index f6196dd63695..8817cebdcf4d 100644 --- a/packages/SystemUI/res/values-fr-rCA/strings.xml +++ b/packages/SystemUI/res/values-fr-rCA/strings.xml @@ -879,17 +879,6 @@ </string-array> <string name="tuner_low_priority" msgid="8412666814123009820">"Afficher les icônes de notification de faible priorité"</string> <string name="other" msgid="429768510980739978">"Autre"</string> - <string name="accessibility_divider" msgid="2830785970889237307">"Séparateur d\'écran partagé"</string> - <string name="accessibility_action_divider_left_full" msgid="7598733539422375847">"Plein écran à la gauche"</string> - <string name="accessibility_action_divider_left_70" msgid="4919312892541727761">"70 % à la gauche"</string> - <string name="accessibility_action_divider_left_50" msgid="3664701169564893826">"50 % à la gauche"</string> - <string name="accessibility_action_divider_left_30" msgid="4358145268046362088">"30 % à la gauche"</string> - <string name="accessibility_action_divider_right_full" msgid="8576057422864896305">"Plein écran à la droite"</string> - <string name="accessibility_action_divider_top_full" msgid="4243901660795169777">"Plein écran dans le haut"</string> - <string name="accessibility_action_divider_top_70" msgid="6941226213260515072">"70 % dans le haut"</string> - <string name="accessibility_action_divider_top_50" msgid="6275211443706497621">"50 % dans le haut"</string> - <string name="accessibility_action_divider_top_30" msgid="5780597635887574916">"30 % dans le haut"</string> - <string name="accessibility_action_divider_bottom_full" msgid="7352434720610115395">"Plein écran dans le bas"</string> <string name="accessibility_qs_edit_tile_label" msgid="9079791448815232967">"Position <xliff:g id="POSITION">%1$d</xliff:g>, <xliff:g id="TILE_NAME">%2$s</xliff:g>. Touchez deux fois pour modifier."</string> <string name="accessibility_qs_edit_add_tile_label" msgid="8292218072049068613">"<xliff:g id="TILE_NAME">%1$s</xliff:g>. Touchez deux fois pour ajouter."</string> <string name="accessibility_qs_edit_move_tile" msgid="6027997446473163426">"Déplacer <xliff:g id="TILE_NAME">%1$s</xliff:g>"</string> @@ -898,10 +887,6 @@ <string name="accessibility_qs_edit_tile_move" msgid="4841770637244326837">"Déplacer <xliff:g id="TILE_NAME">%1$s</xliff:g> à la position <xliff:g id="POSITION">%2$d</xliff:g>"</string> <string name="accessibility_desc_quick_settings_edit" msgid="741658939453595297">"Éditeur de paramètres rapides."</string> <string name="accessibility_desc_notification_icon" msgid="7331265967584178674">"Notification <xliff:g id="ID_1">%1$s</xliff:g> : <xliff:g id="ID_2">%2$s</xliff:g>"</string> - <string name="dock_forced_resizable" msgid="4689301323912928801">"Il est possible que l\'application ne fonctionne pas en mode Écran partagé."</string> - <string name="dock_non_resizeble_failed_to_dock_text" msgid="7284915968096153808">"L\'application n\'est pas compatible avec l\'écran partagé."</string> - <string name="forced_resizable_secondary_display" msgid="522558907654394940">"Il est possible que l\'application ne fonctionne pas sur un écran secondaire."</string> - <string name="activity_launch_on_secondary_display_failed_text" msgid="8446727617187998208">"L\'application ne peut pas être lancée sur des écrans secondaires."</string> <string name="accessibility_quick_settings_settings" msgid="7098489591715844713">"Ouvrir les paramètres."</string> <string name="accessibility_quick_settings_expand" msgid="2609275052412521467">"Ouvrir les réglages rapides."</string> <string name="accessibility_quick_settings_collapse" msgid="4674876336725041982">"Fermer les réglages rapides."</string> diff --git a/packages/SystemUI/res/values-fr/strings.xml b/packages/SystemUI/res/values-fr/strings.xml index 0146ce4d9a59..35176c79f987 100644 --- a/packages/SystemUI/res/values-fr/strings.xml +++ b/packages/SystemUI/res/values-fr/strings.xml @@ -879,17 +879,6 @@ </string-array> <string name="tuner_low_priority" msgid="8412666814123009820">"Afficher les icônes de notification à faible priorité"</string> <string name="other" msgid="429768510980739978">"Autre"</string> - <string name="accessibility_divider" msgid="2830785970889237307">"Séparateur d\'écran partagé"</string> - <string name="accessibility_action_divider_left_full" msgid="7598733539422375847">"Écran de gauche en plein écran"</string> - <string name="accessibility_action_divider_left_70" msgid="4919312892541727761">"Écran de gauche à 70 %"</string> - <string name="accessibility_action_divider_left_50" msgid="3664701169564893826">"Écran de gauche à 50 %"</string> - <string name="accessibility_action_divider_left_30" msgid="4358145268046362088">"Écran de gauche à 30 %"</string> - <string name="accessibility_action_divider_right_full" msgid="8576057422864896305">"Écran de droite en plein écran"</string> - <string name="accessibility_action_divider_top_full" msgid="4243901660795169777">"Écran du haut en plein écran"</string> - <string name="accessibility_action_divider_top_70" msgid="6941226213260515072">"Écran du haut à 70 %"</string> - <string name="accessibility_action_divider_top_50" msgid="6275211443706497621">"Écran du haut à 50 %"</string> - <string name="accessibility_action_divider_top_30" msgid="5780597635887574916">"Écran du haut à 30 %"</string> - <string name="accessibility_action_divider_bottom_full" msgid="7352434720610115395">"Écran du bas en plein écran"</string> <string name="accessibility_qs_edit_tile_label" msgid="9079791448815232967">"Position <xliff:g id="POSITION">%1$d</xliff:g>, \"<xliff:g id="TILE_NAME">%2$s</xliff:g>\". Appuyer deux fois pour modifier."</string> <string name="accessibility_qs_edit_add_tile_label" msgid="8292218072049068613">"<xliff:g id="TILE_NAME">%1$s</xliff:g>. Appuyer deux fois pour ajouter."</string> <string name="accessibility_qs_edit_move_tile" msgid="6027997446473163426">"Déplacer \"<xliff:g id="TILE_NAME">%1$s</xliff:g>\""</string> @@ -898,10 +887,6 @@ <string name="accessibility_qs_edit_tile_move" msgid="4841770637244326837">"Déplacer l\'élément \"<xliff:g id="TILE_NAME">%1$s</xliff:g>\" à la position <xliff:g id="POSITION">%2$d</xliff:g>"</string> <string name="accessibility_desc_quick_settings_edit" msgid="741658939453595297">"Éditeur de configuration rapide."</string> <string name="accessibility_desc_notification_icon" msgid="7331265967584178674">"Notification <xliff:g id="ID_1">%1$s</xliff:g> : <xliff:g id="ID_2">%2$s</xliff:g>"</string> - <string name="dock_forced_resizable" msgid="4689301323912928801">"Il est possible que l\'application ne fonctionne pas en mode Écran partagé."</string> - <string name="dock_non_resizeble_failed_to_dock_text" msgid="7284915968096153808">"Application incompatible avec l\'écran partagé."</string> - <string name="forced_resizable_secondary_display" msgid="522558907654394940">"Il est possible que l\'application ne fonctionne pas sur un écran secondaire."</string> - <string name="activity_launch_on_secondary_display_failed_text" msgid="8446727617187998208">"L\'application ne peut pas être lancée sur des écrans secondaires."</string> <string name="accessibility_quick_settings_settings" msgid="7098489591715844713">"Ouvrir les paramètres."</string> <string name="accessibility_quick_settings_expand" msgid="2609275052412521467">"Ouvrir la fenêtre de configuration rapide."</string> <string name="accessibility_quick_settings_collapse" msgid="4674876336725041982">"Fermer la fenêtre de configuration rapide."</string> diff --git a/packages/SystemUI/res/values-gl/strings.xml b/packages/SystemUI/res/values-gl/strings.xml index fd4d3c6a4ad5..7c6279894069 100644 --- a/packages/SystemUI/res/values-gl/strings.xml +++ b/packages/SystemUI/res/values-gl/strings.xml @@ -879,17 +879,6 @@ </string-array> <string name="tuner_low_priority" msgid="8412666814123009820">"Mostrar iconas das notificacións que teñan baixa prioridade"</string> <string name="other" msgid="429768510980739978">"Outros"</string> - <string name="accessibility_divider" msgid="2830785970889237307">"Divisor de pantalla dividida"</string> - <string name="accessibility_action_divider_left_full" msgid="7598733539422375847">"Pantalla completa á esquerda"</string> - <string name="accessibility_action_divider_left_70" msgid="4919312892541727761">"70 % á esquerda"</string> - <string name="accessibility_action_divider_left_50" msgid="3664701169564893826">"50 % á esquerda"</string> - <string name="accessibility_action_divider_left_30" msgid="4358145268046362088">"30 % á esquerda"</string> - <string name="accessibility_action_divider_right_full" msgid="8576057422864896305">"Pantalla completa á dereita"</string> - <string name="accessibility_action_divider_top_full" msgid="4243901660795169777">"Pantalla completa arriba"</string> - <string name="accessibility_action_divider_top_70" msgid="6941226213260515072">"70 % arriba"</string> - <string name="accessibility_action_divider_top_50" msgid="6275211443706497621">"50 % arriba"</string> - <string name="accessibility_action_divider_top_30" msgid="5780597635887574916">"30 % arriba"</string> - <string name="accessibility_action_divider_bottom_full" msgid="7352434720610115395">"Pantalla completa abaixo"</string> <string name="accessibility_qs_edit_tile_label" msgid="9079791448815232967">"Posición <xliff:g id="POSITION">%1$d</xliff:g>, <xliff:g id="TILE_NAME">%2$s</xliff:g>. Toca dúas veces o elemento para editalo."</string> <string name="accessibility_qs_edit_add_tile_label" msgid="8292218072049068613">"<xliff:g id="TILE_NAME">%1$s</xliff:g>. Toca dúas veces o elemento para engadilo"</string> <string name="accessibility_qs_edit_move_tile" msgid="6027997446473163426">"Move <xliff:g id="TILE_NAME">%1$s</xliff:g>"</string> @@ -898,10 +887,6 @@ <string name="accessibility_qs_edit_tile_move" msgid="4841770637244326837">"Mover \"<xliff:g id="TILE_NAME">%1$s</xliff:g>\" á posición <xliff:g id="POSITION">%2$d</xliff:g>"</string> <string name="accessibility_desc_quick_settings_edit" msgid="741658939453595297">"Editor de configuración rápida."</string> <string name="accessibility_desc_notification_icon" msgid="7331265967584178674">"Notificación de <xliff:g id="ID_1">%1$s</xliff:g>: <xliff:g id="ID_2">%2$s</xliff:g>"</string> - <string name="dock_forced_resizable" msgid="4689301323912928801">"Pode que a aplicación non funcione coa pantalla dividida."</string> - <string name="dock_non_resizeble_failed_to_dock_text" msgid="7284915968096153808">"A aplicación non é compatible coa función de pantalla dividida."</string> - <string name="forced_resizable_secondary_display" msgid="522558907654394940">"É posible que a aplicación non funcione nunha pantalla secundaria."</string> - <string name="activity_launch_on_secondary_display_failed_text" msgid="8446727617187998208">"A aplicación non se pode iniciar en pantallas secundarias."</string> <string name="accessibility_quick_settings_settings" msgid="7098489591715844713">"Abrir configuración."</string> <string name="accessibility_quick_settings_expand" msgid="2609275052412521467">"Abrir configuración rápida."</string> <string name="accessibility_quick_settings_collapse" msgid="4674876336725041982">"Pechar a configuración rápida."</string> diff --git a/packages/SystemUI/res/values-gu/strings.xml b/packages/SystemUI/res/values-gu/strings.xml index 46f7a2bde43c..af0d7d3e1b10 100644 --- a/packages/SystemUI/res/values-gu/strings.xml +++ b/packages/SystemUI/res/values-gu/strings.xml @@ -879,17 +879,6 @@ </string-array> <string name="tuner_low_priority" msgid="8412666814123009820">"ઓછી પ્રાધાન્યતાનું નોટિફિકેશન આઇકન બતાવો"</string> <string name="other" msgid="429768510980739978">"અન્ય"</string> - <string name="accessibility_divider" msgid="2830785970889237307">"સ્પ્લિટ-સ્ક્રીન વિભાજક"</string> - <string name="accessibility_action_divider_left_full" msgid="7598733539422375847">"ડાબી પૂર્ણ સ્ક્રીન"</string> - <string name="accessibility_action_divider_left_70" msgid="4919312892541727761">"ડાબે 70%"</string> - <string name="accessibility_action_divider_left_50" msgid="3664701169564893826">"ડાબે 50%"</string> - <string name="accessibility_action_divider_left_30" msgid="4358145268046362088">"ડાબે 30%"</string> - <string name="accessibility_action_divider_right_full" msgid="8576057422864896305">"જમણી સ્ક્રીન સ્ક્રીન"</string> - <string name="accessibility_action_divider_top_full" msgid="4243901660795169777">"શીર્ષ પૂર્ણ સ્ક્રીન"</string> - <string name="accessibility_action_divider_top_70" msgid="6941226213260515072">"શીર્ષ 70%"</string> - <string name="accessibility_action_divider_top_50" msgid="6275211443706497621">"શીર્ષ 50%"</string> - <string name="accessibility_action_divider_top_30" msgid="5780597635887574916">"શીર્ષ 30%"</string> - <string name="accessibility_action_divider_bottom_full" msgid="7352434720610115395">"તળિયાની પૂર્ણ સ્ક્રીન"</string> <string name="accessibility_qs_edit_tile_label" msgid="9079791448815232967">"સ્થિતિ <xliff:g id="POSITION">%1$d</xliff:g>, <xliff:g id="TILE_NAME">%2$s</xliff:g>. સંપાદિત કરવા માટે બે વાર ટૅપ કરો."</string> <string name="accessibility_qs_edit_add_tile_label" msgid="8292218072049068613">"<xliff:g id="TILE_NAME">%1$s</xliff:g>. ઉમેરવા માટે બે વાર ટૅપ કરો."</string> <string name="accessibility_qs_edit_move_tile" msgid="6027997446473163426">"<xliff:g id="TILE_NAME">%1$s</xliff:g> ખસેડો"</string> @@ -898,10 +887,6 @@ <string name="accessibility_qs_edit_tile_move" msgid="4841770637244326837">"<xliff:g id="POSITION">%2$d</xliff:g> જગ્યા પર <xliff:g id="TILE_NAME">%1$s</xliff:g>ને ખસેડો"</string> <string name="accessibility_desc_quick_settings_edit" msgid="741658939453595297">"ઝડપી સેટિંગ્સ સંપાદક."</string> <string name="accessibility_desc_notification_icon" msgid="7331265967584178674">"<xliff:g id="ID_1">%1$s</xliff:g> નોટિફિકેશન: <xliff:g id="ID_2">%2$s</xliff:g>"</string> - <string name="dock_forced_resizable" msgid="4689301323912928801">"વિભાજિત-સ્ક્રીન સાથે ઍપ્લિકેશન કદાચ કામ ન કરે."</string> - <string name="dock_non_resizeble_failed_to_dock_text" msgid="7284915968096153808">"ઍપ્લિકેશન સ્ક્રીન-વિભાજનનું સમર્થન કરતી નથી."</string> - <string name="forced_resizable_secondary_display" msgid="522558907654394940">"ઍપ્લિકેશન ગૌણ ડિસ્પ્લે પર કદાચ કામ ન કરે."</string> - <string name="activity_launch_on_secondary_display_failed_text" msgid="8446727617187998208">"ઍપ્લિકેશન ગૌણ ડિસ્પ્લે પર લૉન્ચનું સમર્થન કરતી નથી."</string> <string name="accessibility_quick_settings_settings" msgid="7098489591715844713">"સેટિંગ્સ ખોલો."</string> <string name="accessibility_quick_settings_expand" msgid="2609275052412521467">"ઝડપી સેટિંગ્સ ખોલો."</string> <string name="accessibility_quick_settings_collapse" msgid="4674876336725041982">"ઝડપી સેટિંગ્સ બંધ કરો."</string> diff --git a/packages/SystemUI/res/values-hi/strings.xml b/packages/SystemUI/res/values-hi/strings.xml index e4a6ed79848d..0a7515d03a65 100644 --- a/packages/SystemUI/res/values-hi/strings.xml +++ b/packages/SystemUI/res/values-hi/strings.xml @@ -881,17 +881,6 @@ </string-array> <string name="tuner_low_priority" msgid="8412666814123009820">"कम प्राथमिकता वाली सूचना के आइकॉन दिखाएं"</string> <string name="other" msgid="429768510980739978">"अन्य"</string> - <string name="accessibility_divider" msgid="2830785970889237307">"विभाजित स्क्रीन विभाजक"</string> - <string name="accessibility_action_divider_left_full" msgid="7598733539422375847">"बाईं स्क्रीन को फ़ुल स्क्रीन बनाएं"</string> - <string name="accessibility_action_divider_left_70" msgid="4919312892541727761">"बाईं स्क्रीन को 70% बनाएं"</string> - <string name="accessibility_action_divider_left_50" msgid="3664701169564893826">"बाईं स्क्रीन को 50% बनाएं"</string> - <string name="accessibility_action_divider_left_30" msgid="4358145268046362088">"बाईं स्क्रीन को 30% बनाएं"</string> - <string name="accessibility_action_divider_right_full" msgid="8576057422864896305">"दाईं स्क्रीन को फ़ुल स्क्रीन बनाएं"</string> - <string name="accessibility_action_divider_top_full" msgid="4243901660795169777">"ऊपर की स्क्रीन को फ़ुल स्क्रीन बनाएं"</string> - <string name="accessibility_action_divider_top_70" msgid="6941226213260515072">"ऊपर की स्क्रीन को 70% बनाएं"</string> - <string name="accessibility_action_divider_top_50" msgid="6275211443706497621">"ऊपर की स्क्रीन को 50% बनाएं"</string> - <string name="accessibility_action_divider_top_30" msgid="5780597635887574916">"ऊपर की स्क्रीन को 30% बनाएं"</string> - <string name="accessibility_action_divider_bottom_full" msgid="7352434720610115395">"नीचे की स्क्रीन को फ़ुल स्क्रीन बनाएं"</string> <string name="accessibility_qs_edit_tile_label" msgid="9079791448815232967">"स्थिति <xliff:g id="POSITION">%1$d</xliff:g>, <xliff:g id="TILE_NAME">%2$s</xliff:g>. में बदलाव करने के लिए दो बार छूएं."</string> <string name="accessibility_qs_edit_add_tile_label" msgid="8292218072049068613">"<xliff:g id="TILE_NAME">%1$s</xliff:g>. जोड़ने के लिए दो बार छूएं."</string> <string name="accessibility_qs_edit_move_tile" msgid="6027997446473163426">"<xliff:g id="TILE_NAME">%1$s</xliff:g> को ले जाएं"</string> @@ -900,10 +889,6 @@ <string name="accessibility_qs_edit_tile_move" msgid="4841770637244326837">"<xliff:g id="TILE_NAME">%1$s</xliff:g> काे क्रम संख्या <xliff:g id="POSITION">%2$d</xliff:g> पर ले जाएं"</string> <string name="accessibility_desc_quick_settings_edit" msgid="741658939453595297">"त्वरित सेटिंग संपादक."</string> <string name="accessibility_desc_notification_icon" msgid="7331265967584178674">"<xliff:g id="ID_1">%1$s</xliff:g> सूचना: <xliff:g id="ID_2">%2$s</xliff:g>"</string> - <string name="dock_forced_resizable" msgid="4689301323912928801">"हो सकता है कि ऐप्लिकेशन विभाजित स्क्रीन के साथ काम ना करे."</string> - <string name="dock_non_resizeble_failed_to_dock_text" msgid="7284915968096153808">"ऐप विभाजित स्क्रीन का समर्थन नहीं करता है."</string> - <string name="forced_resizable_secondary_display" msgid="522558907654394940">"हो सकता है कि ऐप प्राइमरी (मुख्य) डिस्प्ले के अलावा बाकी दूसरे डिस्प्ले पर काम न करे."</string> - <string name="activity_launch_on_secondary_display_failed_text" msgid="8446727617187998208">"प्राइमरी (मुख्य) डिस्प्ले के अलावा बाकी दूसरे डिस्प्ले पर ऐप लॉन्च नहीं किया जा सकता."</string> <string name="accessibility_quick_settings_settings" msgid="7098489591715844713">"सेटिंग खोलें."</string> <string name="accessibility_quick_settings_expand" msgid="2609275052412521467">"क्विक सेटिंग खोलें."</string> <string name="accessibility_quick_settings_collapse" msgid="4674876336725041982">"त्वरित सेटिंग बंद करें."</string> diff --git a/packages/SystemUI/res/values-hr/strings.xml b/packages/SystemUI/res/values-hr/strings.xml index a27b06694588..27b6909159aa 100644 --- a/packages/SystemUI/res/values-hr/strings.xml +++ b/packages/SystemUI/res/values-hr/strings.xml @@ -884,17 +884,6 @@ </string-array> <string name="tuner_low_priority" msgid="8412666814123009820">"Prikaži ikone obavijesti niskog prioriteta"</string> <string name="other" msgid="429768510980739978">"Ostalo"</string> - <string name="accessibility_divider" msgid="2830785970889237307">"Razdjelnik podijeljenog zaslona"</string> - <string name="accessibility_action_divider_left_full" msgid="7598733539422375847">"Lijevi zaslon u cijeli zaslon"</string> - <string name="accessibility_action_divider_left_70" msgid="4919312892541727761">"Lijevi zaslon na 70%"</string> - <string name="accessibility_action_divider_left_50" msgid="3664701169564893826">"Lijevi zaslon na 50%"</string> - <string name="accessibility_action_divider_left_30" msgid="4358145268046362088">"Lijevi zaslon na 30%"</string> - <string name="accessibility_action_divider_right_full" msgid="8576057422864896305">"Desni zaslon u cijeli zaslon"</string> - <string name="accessibility_action_divider_top_full" msgid="4243901660795169777">"Gornji zaslon u cijeli zaslon"</string> - <string name="accessibility_action_divider_top_70" msgid="6941226213260515072">"Gornji zaslon na 70%"</string> - <string name="accessibility_action_divider_top_50" msgid="6275211443706497621">"Gornji zaslon na 50%"</string> - <string name="accessibility_action_divider_top_30" msgid="5780597635887574916">"Gornji zaslon na 30%"</string> - <string name="accessibility_action_divider_bottom_full" msgid="7352434720610115395">"Donji zaslon u cijeli zaslon"</string> <string name="accessibility_qs_edit_tile_label" msgid="9079791448815232967">"Položaj <xliff:g id="POSITION">%1$d</xliff:g>, <xliff:g id="TILE_NAME">%2$s</xliff:g>. Dodirnite dvaput da biste uredili."</string> <string name="accessibility_qs_edit_add_tile_label" msgid="8292218072049068613">"<xliff:g id="TILE_NAME">%1$s</xliff:g>. Dodirnite dvaput da biste dodali."</string> <string name="accessibility_qs_edit_move_tile" msgid="6027997446473163426">"Premjesti <xliff:g id="TILE_NAME">%1$s</xliff:g>"</string> @@ -903,10 +892,6 @@ <string name="accessibility_qs_edit_tile_move" msgid="4841770637244326837">"Premjestite pločicu <xliff:g id="TILE_NAME">%1$s</xliff:g> na položaj <xliff:g id="POSITION">%2$d</xliff:g>"</string> <string name="accessibility_desc_quick_settings_edit" msgid="741658939453595297">"Uređivač brzih postavki."</string> <string name="accessibility_desc_notification_icon" msgid="7331265967584178674">"<xliff:g id="ID_1">%1$s</xliff:g> obavijest: <xliff:g id="ID_2">%2$s</xliff:g>"</string> - <string name="dock_forced_resizable" msgid="4689301323912928801">"Aplikacija možda neće funkcionirati s podijeljenim zaslonom."</string> - <string name="dock_non_resizeble_failed_to_dock_text" msgid="7284915968096153808">"Aplikacija ne podržava podijeljeni zaslon."</string> - <string name="forced_resizable_secondary_display" msgid="522558907654394940">"Aplikacija možda neće funkcionirati na sekundarnom zaslonu."</string> - <string name="activity_launch_on_secondary_display_failed_text" msgid="8446727617187998208">"Aplikacija ne podržava pokretanje na sekundarnim zaslonima."</string> <string name="accessibility_quick_settings_settings" msgid="7098489591715844713">"Otvaranje postavki."</string> <string name="accessibility_quick_settings_expand" msgid="2609275052412521467">"Otvaranje brzih postavki."</string> <string name="accessibility_quick_settings_collapse" msgid="4674876336725041982">"Zatvaranje brzih postavki."</string> diff --git a/packages/SystemUI/res/values-hu/strings.xml b/packages/SystemUI/res/values-hu/strings.xml index 0d1f50acc1c7..1f52b2cbe78b 100644 --- a/packages/SystemUI/res/values-hu/strings.xml +++ b/packages/SystemUI/res/values-hu/strings.xml @@ -428,7 +428,7 @@ <string name="quick_settings_nfc_off" msgid="3465000058515424663">"Az NFC ki van kapcsolva"</string> <string name="quick_settings_nfc_on" msgid="1004976611203202230">"Az NFC be van kapcsolva"</string> <string name="quick_settings_screen_record_label" msgid="1594046461509776676">"Képernyő rögzítése"</string> - <string name="quick_settings_screen_record_start" msgid="1574725369331638985">"Kezdés"</string> + <string name="quick_settings_screen_record_start" msgid="1574725369331638985">"Indítás"</string> <string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"Leállítás"</string> <string name="media_seamless_remote_device" msgid="177033467332920464">"Eszköz"</string> <string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"Váltás az alkalmazások között felfelé csúsztatással"</string> @@ -879,17 +879,6 @@ </string-array> <string name="tuner_low_priority" msgid="8412666814123009820">"Alacsony prioritású értesítési ikonok mutatása"</string> <string name="other" msgid="429768510980739978">"Egyéb"</string> - <string name="accessibility_divider" msgid="2830785970889237307">"Elválasztó az osztott nézetben"</string> - <string name="accessibility_action_divider_left_full" msgid="7598733539422375847">"Bal oldali teljes képernyőre"</string> - <string name="accessibility_action_divider_left_70" msgid="4919312892541727761">"Bal oldali 70%-ra"</string> - <string name="accessibility_action_divider_left_50" msgid="3664701169564893826">"Bal oldali 50%-ra"</string> - <string name="accessibility_action_divider_left_30" msgid="4358145268046362088">"Bal oldali 30%-ra"</string> - <string name="accessibility_action_divider_right_full" msgid="8576057422864896305">"Jobb oldali teljes képernyőre"</string> - <string name="accessibility_action_divider_top_full" msgid="4243901660795169777">"Felső teljes képernyőre"</string> - <string name="accessibility_action_divider_top_70" msgid="6941226213260515072">"Felső 70%-ra"</string> - <string name="accessibility_action_divider_top_50" msgid="6275211443706497621">"Felső 50%-ra"</string> - <string name="accessibility_action_divider_top_30" msgid="5780597635887574916">"Felső 30%-ra"</string> - <string name="accessibility_action_divider_bottom_full" msgid="7352434720610115395">"Alsó teljes képernyőre"</string> <string name="accessibility_qs_edit_tile_label" msgid="9079791448815232967">"<xliff:g id="POSITION">%1$d</xliff:g>. pozíció: <xliff:g id="TILE_NAME">%2$s</xliff:g>. Koppintson duplán a szerkesztéshez."</string> <string name="accessibility_qs_edit_add_tile_label" msgid="8292218072049068613">"<xliff:g id="TILE_NAME">%1$s</xliff:g>. Koppintson duplán a hozzáadáshoz."</string> <string name="accessibility_qs_edit_move_tile" msgid="6027997446473163426">"A(z) <xliff:g id="TILE_NAME">%1$s</xliff:g> áthelyezése"</string> @@ -898,10 +887,6 @@ <string name="accessibility_qs_edit_tile_move" msgid="4841770637244326837">"<xliff:g id="TILE_NAME">%1$s</xliff:g> áthelyezése a következő pozícióba: <xliff:g id="POSITION">%2$d</xliff:g>"</string> <string name="accessibility_desc_quick_settings_edit" msgid="741658939453595297">"Gyorsbeállítások szerkesztője"</string> <string name="accessibility_desc_notification_icon" msgid="7331265967584178674">"<xliff:g id="ID_1">%1$s</xliff:g>-értesítések: <xliff:g id="ID_2">%2$s</xliff:g>"</string> - <string name="dock_forced_resizable" msgid="4689301323912928801">"Lehet, hogy az alkalmazás nem működik osztott képernyős nézetben."</string> - <string name="dock_non_resizeble_failed_to_dock_text" msgid="7284915968096153808">"Az alkalmazás nem támogatja az osztott képernyős nézetet."</string> - <string name="forced_resizable_secondary_display" msgid="522558907654394940">"Előfordulhat, hogy az alkalmazás nem működik másodlagos kijelzőn."</string> - <string name="activity_launch_on_secondary_display_failed_text" msgid="8446727617187998208">"Az alkalmazást nem lehet másodlagos kijelzőn elindítani."</string> <string name="accessibility_quick_settings_settings" msgid="7098489591715844713">"Beállítások megnyitása."</string> <string name="accessibility_quick_settings_expand" msgid="2609275052412521467">"Gyorsbeállítások megnyitása."</string> <string name="accessibility_quick_settings_collapse" msgid="4674876336725041982">"Gyorsbeállítások bezárása"</string> diff --git a/packages/SystemUI/res/values-hy/strings.xml b/packages/SystemUI/res/values-hy/strings.xml index f9a10fa1578e..d4a093f78659 100644 --- a/packages/SystemUI/res/values-hy/strings.xml +++ b/packages/SystemUI/res/values-hy/strings.xml @@ -879,17 +879,6 @@ </string-array> <string name="tuner_low_priority" msgid="8412666814123009820">"Ցուցադրել ցածր առաջնահերթության ծանուցումների պատկերակները"</string> <string name="other" msgid="429768510980739978">"Այլ"</string> - <string name="accessibility_divider" msgid="2830785970889237307">"Տրոհված էկրանի բաժանիչ"</string> - <string name="accessibility_action_divider_left_full" msgid="7598733539422375847">"Ձախ էկրանը՝ լիաէկրան"</string> - <string name="accessibility_action_divider_left_70" msgid="4919312892541727761">"Ձախ էկրանը՝ 70%"</string> - <string name="accessibility_action_divider_left_50" msgid="3664701169564893826">"Ձախ էկրանը՝ 50%"</string> - <string name="accessibility_action_divider_left_30" msgid="4358145268046362088">"Ձախ էկրանը՝ 30%"</string> - <string name="accessibility_action_divider_right_full" msgid="8576057422864896305">"Աջ էկրանը՝ լիաէկրան"</string> - <string name="accessibility_action_divider_top_full" msgid="4243901660795169777">"Վերևի էկրանը՝ լիաէկրան"</string> - <string name="accessibility_action_divider_top_70" msgid="6941226213260515072">"Վերևի էկրանը՝ 70%"</string> - <string name="accessibility_action_divider_top_50" msgid="6275211443706497621">"Վերևի էկրանը՝ 50%"</string> - <string name="accessibility_action_divider_top_30" msgid="5780597635887574916">"Վերևի էկրանը՝ 30%"</string> - <string name="accessibility_action_divider_bottom_full" msgid="7352434720610115395">"Ներքևի էկրանը՝ լիաէկրան"</string> <string name="accessibility_qs_edit_tile_label" msgid="9079791448815232967">"Դիրք <xliff:g id="POSITION">%1$d</xliff:g>, <xliff:g id="TILE_NAME">%2$s</xliff:g>: Կրկնակի հպեք՝ փոխելու համար:"</string> <string name="accessibility_qs_edit_add_tile_label" msgid="8292218072049068613">"<xliff:g id="TILE_NAME">%1$s</xliff:g>: Կրկնակի հպեք՝ ավելացնելու համար:"</string> <string name="accessibility_qs_edit_move_tile" msgid="6027997446473163426">"Տեղափոխել <xliff:g id="TILE_NAME">%1$s</xliff:g> սալիկը"</string> @@ -898,10 +887,6 @@ <string name="accessibility_qs_edit_tile_move" msgid="4841770637244326837">"<xliff:g id="TILE_NAME">%1$s</xliff:g> սալիկը տեղափոխել դիրք <xliff:g id="POSITION">%2$d</xliff:g>"</string> <string name="accessibility_desc_quick_settings_edit" msgid="741658939453595297">"Արագ կարգավորումների խմբագրիչ:"</string> <string name="accessibility_desc_notification_icon" msgid="7331265967584178674">"<xliff:g id="ID_1">%1$s</xliff:g> ծանուցում՝ <xliff:g id="ID_2">%2$s</xliff:g>"</string> - <string name="dock_forced_resizable" msgid="4689301323912928801">"Հավելվածը չի կարող աշխատել տրոհված էկրանի ռեժիմում:"</string> - <string name="dock_non_resizeble_failed_to_dock_text" msgid="7284915968096153808">"Հավելվածը չի աջակցում էկրանի տրոհումը:"</string> - <string name="forced_resizable_secondary_display" msgid="522558907654394940">"Հավելվածը կարող է չաշխատել լրացուցիչ էկրանի վրա"</string> - <string name="activity_launch_on_secondary_display_failed_text" msgid="8446727617187998208">"Հավելվածը չի աջակցում գործարկումը լրացուցիչ էկրանների վրա"</string> <string name="accessibility_quick_settings_settings" msgid="7098489591715844713">"Բացել կարգավորումները:"</string> <string name="accessibility_quick_settings_expand" msgid="2609275052412521467">"Բացել արագ կարգավորումները:"</string> <string name="accessibility_quick_settings_collapse" msgid="4674876336725041982">"Փակել արագ կարգավորումները:"</string> diff --git a/packages/SystemUI/res/values-in/strings.xml b/packages/SystemUI/res/values-in/strings.xml index f65be90bb00e..3b89b3d5e9fc 100644 --- a/packages/SystemUI/res/values-in/strings.xml +++ b/packages/SystemUI/res/values-in/strings.xml @@ -879,17 +879,6 @@ </string-array> <string name="tuner_low_priority" msgid="8412666814123009820">"Tampilkan ikon notifikasi prioritas rendah"</string> <string name="other" msgid="429768510980739978">"Lainnya"</string> - <string name="accessibility_divider" msgid="2830785970889237307">"Pembagi layar terpisah"</string> - <string name="accessibility_action_divider_left_full" msgid="7598733539422375847">"Layar penuh di kiri"</string> - <string name="accessibility_action_divider_left_70" msgid="4919312892541727761">"Kiri 70%"</string> - <string name="accessibility_action_divider_left_50" msgid="3664701169564893826">"Kiri 50%"</string> - <string name="accessibility_action_divider_left_30" msgid="4358145268046362088">"Kiri 30%"</string> - <string name="accessibility_action_divider_right_full" msgid="8576057422864896305">"Layar penuh di kanan"</string> - <string name="accessibility_action_divider_top_full" msgid="4243901660795169777">"Layar penuh di atas"</string> - <string name="accessibility_action_divider_top_70" msgid="6941226213260515072">"Atas 70%"</string> - <string name="accessibility_action_divider_top_50" msgid="6275211443706497621">"Atas 50%"</string> - <string name="accessibility_action_divider_top_30" msgid="5780597635887574916">"Atas 30%"</string> - <string name="accessibility_action_divider_bottom_full" msgid="7352434720610115395">"Layar penuh di bawah"</string> <string name="accessibility_qs_edit_tile_label" msgid="9079791448815232967">"Posisi <xliff:g id="POSITION">%1$d</xliff:g>, <xliff:g id="TILE_NAME">%2$s</xliff:g>. Ketuk dua kali untuk mengedit."</string> <string name="accessibility_qs_edit_add_tile_label" msgid="8292218072049068613">"<xliff:g id="TILE_NAME">%1$s</xliff:g>. Ketuk dua kali untuk menambahkan."</string> <string name="accessibility_qs_edit_move_tile" msgid="6027997446473163426">"Pindahkan <xliff:g id="TILE_NAME">%1$s</xliff:g>"</string> @@ -898,10 +887,6 @@ <string name="accessibility_qs_edit_tile_move" msgid="4841770637244326837">"Pindahkan <xliff:g id="TILE_NAME">%1$s</xliff:g> ke posisi <xliff:g id="POSITION">%2$d</xliff:g>"</string> <string name="accessibility_desc_quick_settings_edit" msgid="741658939453595297">"Editor setelan cepat."</string> <string name="accessibility_desc_notification_icon" msgid="7331265967584178674">"Notifikasi <xliff:g id="ID_1">%1$s</xliff:g>: <xliff:g id="ID_2">%2$s</xliff:g>"</string> - <string name="dock_forced_resizable" msgid="4689301323912928801">"Aplikasi mungkin tidak berfungsi dengan layar terpisah."</string> - <string name="dock_non_resizeble_failed_to_dock_text" msgid="7284915968096153808">"App tidak mendukung layar terpisah."</string> - <string name="forced_resizable_secondary_display" msgid="522558907654394940">"Aplikasi mungkin tidak berfungsi pada layar sekunder."</string> - <string name="activity_launch_on_secondary_display_failed_text" msgid="8446727617187998208">"Aplikasi tidak mendukung peluncuran pada layar sekunder."</string> <string name="accessibility_quick_settings_settings" msgid="7098489591715844713">"Buka setelan."</string> <string name="accessibility_quick_settings_expand" msgid="2609275052412521467">"Buka setelan cepat."</string> <string name="accessibility_quick_settings_collapse" msgid="4674876336725041982">"Tutup setelan cepat."</string> diff --git a/packages/SystemUI/res/values-is/strings.xml b/packages/SystemUI/res/values-is/strings.xml index 66c91477c1e8..da8a092bcc47 100644 --- a/packages/SystemUI/res/values-is/strings.xml +++ b/packages/SystemUI/res/values-is/strings.xml @@ -879,17 +879,6 @@ </string-array> <string name="tuner_low_priority" msgid="8412666814123009820">"Sýna tákn fyrir tilkynningar með litlum forgangi"</string> <string name="other" msgid="429768510980739978">"Annað"</string> - <string name="accessibility_divider" msgid="2830785970889237307">"Skjáskipting"</string> - <string name="accessibility_action_divider_left_full" msgid="7598733539422375847">"Vinstri á öllum skjánum"</string> - <string name="accessibility_action_divider_left_70" msgid="4919312892541727761">"Vinstri 70%"</string> - <string name="accessibility_action_divider_left_50" msgid="3664701169564893826">"Vinstri 50%"</string> - <string name="accessibility_action_divider_left_30" msgid="4358145268046362088">"Vinstri 30%"</string> - <string name="accessibility_action_divider_right_full" msgid="8576057422864896305">"Hægri á öllum skjánum"</string> - <string name="accessibility_action_divider_top_full" msgid="4243901660795169777">"Efri á öllum skjánum"</string> - <string name="accessibility_action_divider_top_70" msgid="6941226213260515072">"Efri 70%"</string> - <string name="accessibility_action_divider_top_50" msgid="6275211443706497621">"Efri 50%"</string> - <string name="accessibility_action_divider_top_30" msgid="5780597635887574916">"Efri 30%"</string> - <string name="accessibility_action_divider_bottom_full" msgid="7352434720610115395">"Neðri á öllum skjánum"</string> <string name="accessibility_qs_edit_tile_label" msgid="9079791448815232967">"Staða <xliff:g id="POSITION">%1$d</xliff:g>, <xliff:g id="TILE_NAME">%2$s</xliff:g>. Ýttu tvisvar til að breyta."</string> <string name="accessibility_qs_edit_add_tile_label" msgid="8292218072049068613">"<xliff:g id="TILE_NAME">%1$s</xliff:g>. Ýttu tvisvar til að bæta við."</string> <string name="accessibility_qs_edit_move_tile" msgid="6027997446473163426">"Færa <xliff:g id="TILE_NAME">%1$s</xliff:g>"</string> @@ -898,10 +887,6 @@ <string name="accessibility_qs_edit_tile_move" msgid="4841770637244326837">"Færa <xliff:g id="TILE_NAME">%1$s</xliff:g> í stöðu <xliff:g id="POSITION">%2$d</xliff:g>"</string> <string name="accessibility_desc_quick_settings_edit" msgid="741658939453595297">"Flýtistillingaritill."</string> <string name="accessibility_desc_notification_icon" msgid="7331265967584178674">"<xliff:g id="ID_1">%1$s</xliff:g> tilkynning: <xliff:g id="ID_2">%2$s</xliff:g>"</string> - <string name="dock_forced_resizable" msgid="4689301323912928801">"Hugsanlega virkar forritið ekki ef skjánum er skipt upp."</string> - <string name="dock_non_resizeble_failed_to_dock_text" msgid="7284915968096153808">"Forritið styður ekki að skjánum sé skipt."</string> - <string name="forced_resizable_secondary_display" msgid="522558907654394940">"Hugsanlegt er að forritið virki ekki á öðrum skjá."</string> - <string name="activity_launch_on_secondary_display_failed_text" msgid="8446727617187998208">"Forrit styður ekki opnun á öðrum skjá."</string> <string name="accessibility_quick_settings_settings" msgid="7098489591715844713">"Opna stillingar."</string> <string name="accessibility_quick_settings_expand" msgid="2609275052412521467">"Opna flýtistillingar."</string> <string name="accessibility_quick_settings_collapse" msgid="4674876336725041982">"Loka flýtistillingum."</string> diff --git a/packages/SystemUI/res/values-it/strings.xml b/packages/SystemUI/res/values-it/strings.xml index b0e64a27f154..0ec9c236f761 100644 --- a/packages/SystemUI/res/values-it/strings.xml +++ b/packages/SystemUI/res/values-it/strings.xml @@ -879,17 +879,6 @@ </string-array> <string name="tuner_low_priority" msgid="8412666814123009820">"Mostra icone di notifiche con priorità bassa"</string> <string name="other" msgid="429768510980739978">"Altro"</string> - <string name="accessibility_divider" msgid="2830785970889237307">"Strumento per schermo diviso"</string> - <string name="accessibility_action_divider_left_full" msgid="7598733539422375847">"Schermata sinistra a schermo intero"</string> - <string name="accessibility_action_divider_left_70" msgid="4919312892541727761">"Schermata sinistra al 70%"</string> - <string name="accessibility_action_divider_left_50" msgid="3664701169564893826">"Schermata sinistra al 50%"</string> - <string name="accessibility_action_divider_left_30" msgid="4358145268046362088">"Schermata sinistra al 30%"</string> - <string name="accessibility_action_divider_right_full" msgid="8576057422864896305">"Schermata destra a schermo intero"</string> - <string name="accessibility_action_divider_top_full" msgid="4243901660795169777">"Schermata superiore a schermo intero"</string> - <string name="accessibility_action_divider_top_70" msgid="6941226213260515072">"Schermata superiore al 70%"</string> - <string name="accessibility_action_divider_top_50" msgid="6275211443706497621">"Schermata superiore al 50%"</string> - <string name="accessibility_action_divider_top_30" msgid="5780597635887574916">"Schermata superiore al 30%"</string> - <string name="accessibility_action_divider_bottom_full" msgid="7352434720610115395">"Schermata inferiore a schermo intero"</string> <string name="accessibility_qs_edit_tile_label" msgid="9079791448815232967">"Posizione <xliff:g id="POSITION">%1$d</xliff:g>, <xliff:g id="TILE_NAME">%2$s</xliff:g>. Tocca due volte per modificare."</string> <string name="accessibility_qs_edit_add_tile_label" msgid="8292218072049068613">"<xliff:g id="TILE_NAME">%1$s</xliff:g>. Tocca due volte per aggiungere."</string> <string name="accessibility_qs_edit_move_tile" msgid="6027997446473163426">"Sposta <xliff:g id="TILE_NAME">%1$s</xliff:g>"</string> @@ -898,10 +887,6 @@ <string name="accessibility_qs_edit_tile_move" msgid="4841770637244326837">"Sposta il riquadro <xliff:g id="TILE_NAME">%1$s</xliff:g> nella posizione <xliff:g id="POSITION">%2$d</xliff:g>"</string> <string name="accessibility_desc_quick_settings_edit" msgid="741658939453595297">"Editor di impostazioni rapide."</string> <string name="accessibility_desc_notification_icon" msgid="7331265967584178674">"Notifica di <xliff:g id="ID_1">%1$s</xliff:g>: <xliff:g id="ID_2">%2$s</xliff:g>"</string> - <string name="dock_forced_resizable" msgid="4689301323912928801">"L\'app potrebbe non funzionare con lo schermo diviso."</string> - <string name="dock_non_resizeble_failed_to_dock_text" msgid="7284915968096153808">"L\'app non supporta la modalità Schermo diviso."</string> - <string name="forced_resizable_secondary_display" msgid="522558907654394940">"L\'app potrebbe non funzionare su un display secondario."</string> - <string name="activity_launch_on_secondary_display_failed_text" msgid="8446727617187998208">"L\'app non supporta l\'avvio su display secondari."</string> <string name="accessibility_quick_settings_settings" msgid="7098489591715844713">"Apri le impostazioni."</string> <string name="accessibility_quick_settings_expand" msgid="2609275052412521467">"Apri le impostazioni rapide."</string> <string name="accessibility_quick_settings_collapse" msgid="4674876336725041982">"Chiudi le impostazioni rapide."</string> diff --git a/packages/SystemUI/res/values-iw/strings.xml b/packages/SystemUI/res/values-iw/strings.xml index 92fa09b81e39..193c5f61fe3e 100644 --- a/packages/SystemUI/res/values-iw/strings.xml +++ b/packages/SystemUI/res/values-iw/strings.xml @@ -889,17 +889,6 @@ </string-array> <string name="tuner_low_priority" msgid="8412666814123009820">"הצגת סמלי התראות בעדיפות נמוכה"</string> <string name="other" msgid="429768510980739978">"אחר"</string> - <string name="accessibility_divider" msgid="2830785970889237307">"מחלק מסך מפוצל"</string> - <string name="accessibility_action_divider_left_full" msgid="7598733539422375847">"מסך שמאלי מלא"</string> - <string name="accessibility_action_divider_left_70" msgid="4919312892541727761">"שמאלה 70%"</string> - <string name="accessibility_action_divider_left_50" msgid="3664701169564893826">"שמאלה 50%"</string> - <string name="accessibility_action_divider_left_30" msgid="4358145268046362088">"שמאלה 30%"</string> - <string name="accessibility_action_divider_right_full" msgid="8576057422864896305">"מסך ימני מלא"</string> - <string name="accessibility_action_divider_top_full" msgid="4243901660795169777">"מסך עליון מלא"</string> - <string name="accessibility_action_divider_top_70" msgid="6941226213260515072">"עליון 70%"</string> - <string name="accessibility_action_divider_top_50" msgid="6275211443706497621">"עליון 50%"</string> - <string name="accessibility_action_divider_top_30" msgid="5780597635887574916">"עליון 30%"</string> - <string name="accessibility_action_divider_bottom_full" msgid="7352434720610115395">"מסך תחתון מלא"</string> <string name="accessibility_qs_edit_tile_label" msgid="9079791448815232967">"מיקום <xliff:g id="POSITION">%1$d</xliff:g>, <xliff:g id="TILE_NAME">%2$s</xliff:g>. הקש פעמיים כדי לערוך."</string> <string name="accessibility_qs_edit_add_tile_label" msgid="8292218072049068613">"<xliff:g id="TILE_NAME">%1$s</xliff:g>. הקש פעמיים כדי להוסיף."</string> <string name="accessibility_qs_edit_move_tile" msgid="6027997446473163426">"הזזת <xliff:g id="TILE_NAME">%1$s</xliff:g>"</string> @@ -908,10 +897,6 @@ <string name="accessibility_qs_edit_tile_move" msgid="4841770637244326837">"העברת <xliff:g id="TILE_NAME">%1$s</xliff:g> למיקום <xliff:g id="POSITION">%2$d</xliff:g>"</string> <string name="accessibility_desc_quick_settings_edit" msgid="741658939453595297">"עורך הגדרות מהירות."</string> <string name="accessibility_desc_notification_icon" msgid="7331265967584178674">"התראות <xliff:g id="ID_1">%1$s</xliff:g>: <xliff:g id="ID_2">%2$s</xliff:g>"</string> - <string name="dock_forced_resizable" msgid="4689301323912928801">"ייתכן שהיישום לא יפעל עם מסך מפוצל."</string> - <string name="dock_non_resizeble_failed_to_dock_text" msgid="7284915968096153808">"האפליקציה אינה תומכת במסך מפוצל."</string> - <string name="forced_resizable_secondary_display" msgid="522558907654394940">"ייתכן שהאפליקציה לא תפעל במסך משני."</string> - <string name="activity_launch_on_secondary_display_failed_text" msgid="8446727617187998208">"האפליקציה אינה תומכת בהפעלה במסכים משניים."</string> <string name="accessibility_quick_settings_settings" msgid="7098489591715844713">"פתיחת הגדרות."</string> <string name="accessibility_quick_settings_expand" msgid="2609275052412521467">"פתיחה של \'הגדרות מהירות\'."</string> <string name="accessibility_quick_settings_collapse" msgid="4674876336725041982">"סגירה של \'הגדרות מהירות\'."</string> diff --git a/packages/SystemUI/res/values-ja/strings.xml b/packages/SystemUI/res/values-ja/strings.xml index e427c8f950e5..9aa9e76c1597 100644 --- a/packages/SystemUI/res/values-ja/strings.xml +++ b/packages/SystemUI/res/values-ja/strings.xml @@ -879,17 +879,6 @@ </string-array> <string name="tuner_low_priority" msgid="8412666814123009820">"優先度の低い通知アイコンを表示"</string> <string name="other" msgid="429768510980739978">"その他"</string> - <string name="accessibility_divider" msgid="2830785970889237307">"分割画面の分割線"</string> - <string name="accessibility_action_divider_left_full" msgid="7598733539422375847">"左全画面"</string> - <string name="accessibility_action_divider_left_70" msgid="4919312892541727761">"左 70%"</string> - <string name="accessibility_action_divider_left_50" msgid="3664701169564893826">"左 50%"</string> - <string name="accessibility_action_divider_left_30" msgid="4358145268046362088">"左 30%"</string> - <string name="accessibility_action_divider_right_full" msgid="8576057422864896305">"右全画面"</string> - <string name="accessibility_action_divider_top_full" msgid="4243901660795169777">"上部全画面"</string> - <string name="accessibility_action_divider_top_70" msgid="6941226213260515072">"上 70%"</string> - <string name="accessibility_action_divider_top_50" msgid="6275211443706497621">"上 50%"</string> - <string name="accessibility_action_divider_top_30" msgid="5780597635887574916">"上 30%"</string> - <string name="accessibility_action_divider_bottom_full" msgid="7352434720610115395">"下部全画面"</string> <string name="accessibility_qs_edit_tile_label" msgid="9079791448815232967">"ポジション <xliff:g id="POSITION">%1$d</xliff:g> の <xliff:g id="TILE_NAME">%2$s</xliff:g> を編集するにはダブルタップします。"</string> <string name="accessibility_qs_edit_add_tile_label" msgid="8292218072049068613">"<xliff:g id="TILE_NAME">%1$s</xliff:g> を追加するにはダブルタップします。"</string> <string name="accessibility_qs_edit_move_tile" msgid="6027997446473163426">"<xliff:g id="TILE_NAME">%1$s</xliff:g> を移動します"</string> @@ -898,10 +887,6 @@ <string name="accessibility_qs_edit_tile_move" msgid="4841770637244326837">"<xliff:g id="TILE_NAME">%1$s</xliff:g> をポジション <xliff:g id="POSITION">%2$d</xliff:g> に移動"</string> <string name="accessibility_desc_quick_settings_edit" msgid="741658939453595297">"クイック設定エディタ"</string> <string name="accessibility_desc_notification_icon" msgid="7331265967584178674">"<xliff:g id="ID_1">%1$s</xliff:g> の通知: <xliff:g id="ID_2">%2$s</xliff:g>"</string> - <string name="dock_forced_resizable" msgid="4689301323912928801">"アプリは分割画面では動作しないことがあります。"</string> - <string name="dock_non_resizeble_failed_to_dock_text" msgid="7284915968096153808">"アプリで分割画面がサポートされていません。"</string> - <string name="forced_resizable_secondary_display" msgid="522558907654394940">"アプリはセカンダリ ディスプレイでは動作しないことがあります。"</string> - <string name="activity_launch_on_secondary_display_failed_text" msgid="8446727617187998208">"アプリはセカンダリ ディスプレイでの起動に対応していません。"</string> <string name="accessibility_quick_settings_settings" msgid="7098489591715844713">"設定を開きます。"</string> <string name="accessibility_quick_settings_expand" msgid="2609275052412521467">"クイック設定を開きます。"</string> <string name="accessibility_quick_settings_collapse" msgid="4674876336725041982">"クイック設定を閉じます。"</string> diff --git a/packages/SystemUI/res/values-ka/strings.xml b/packages/SystemUI/res/values-ka/strings.xml index b86bf8c32a75..aa6f35d00826 100644 --- a/packages/SystemUI/res/values-ka/strings.xml +++ b/packages/SystemUI/res/values-ka/strings.xml @@ -879,17 +879,6 @@ </string-array> <string name="tuner_low_priority" msgid="8412666814123009820">"დაბალი პრიორიტეტის მქონე შეტყობინებების ხატულების ჩვენება"</string> <string name="other" msgid="429768510980739978">"სხვა"</string> - <string name="accessibility_divider" msgid="2830785970889237307">"გაყოფილი ეკრანის რეჟიმის გამყოფი"</string> - <string name="accessibility_action_divider_left_full" msgid="7598733539422375847">"მარცხენა ნაწილის სრულ ეკრანზე გაშლა"</string> - <string name="accessibility_action_divider_left_70" msgid="4919312892541727761">"მარცხენა ეკრანი — 70%"</string> - <string name="accessibility_action_divider_left_50" msgid="3664701169564893826">"მარცხენა ეკრანი — 50%"</string> - <string name="accessibility_action_divider_left_30" msgid="4358145268046362088">"მარცხენა ეკრანი — 30%"</string> - <string name="accessibility_action_divider_right_full" msgid="8576057422864896305">"მარჯვენა ნაწილის სრულ ეკრანზე გაშლა"</string> - <string name="accessibility_action_divider_top_full" msgid="4243901660795169777">"ზედა ნაწილის სრულ ეკრანზე გაშლა"</string> - <string name="accessibility_action_divider_top_70" msgid="6941226213260515072">"ზედა ეკრანი — 70%"</string> - <string name="accessibility_action_divider_top_50" msgid="6275211443706497621">"ზედა ეკრანი — 50%"</string> - <string name="accessibility_action_divider_top_30" msgid="5780597635887574916">"ზედა ეკრანი — 30%"</string> - <string name="accessibility_action_divider_bottom_full" msgid="7352434720610115395">"ქვედა ნაწილის სრულ ეკრანზე გაშლა"</string> <string name="accessibility_qs_edit_tile_label" msgid="9079791448815232967">"პოზიცია <xliff:g id="POSITION">%1$d</xliff:g>, <xliff:g id="TILE_NAME">%2$s</xliff:g>. რედაქტირებისთვის, შეეხეთ ორმაგად."</string> <string name="accessibility_qs_edit_add_tile_label" msgid="8292218072049068613">"<xliff:g id="TILE_NAME">%1$s</xliff:g>. დასამატებლად, შეეხეთ ორმაგად."</string> <string name="accessibility_qs_edit_move_tile" msgid="6027997446473163426">"<xliff:g id="TILE_NAME">%1$s</xliff:g>-ის გადატანა"</string> @@ -898,10 +887,6 @@ <string name="accessibility_qs_edit_tile_move" msgid="4841770637244326837">"<xliff:g id="TILE_NAME">%1$s</xliff:g>-ის გადატანა პოზიციაზე <xliff:g id="POSITION">%2$d</xliff:g>"</string> <string name="accessibility_desc_quick_settings_edit" msgid="741658939453595297">"სწრაფი პარამეტრების რედაქტორი."</string> <string name="accessibility_desc_notification_icon" msgid="7331265967584178674">"<xliff:g id="ID_1">%1$s</xliff:g> შეტყობინება: <xliff:g id="ID_2">%2$s</xliff:g>"</string> - <string name="dock_forced_resizable" msgid="4689301323912928801">"აპმა შეიძლება არ იმუშაოს გაყოფილი ეკრანის რეჟიმში."</string> - <string name="dock_non_resizeble_failed_to_dock_text" msgid="7284915968096153808">"ეკრანის გაყოფა არ არის მხარდაჭერილი აპის მიერ."</string> - <string name="forced_resizable_secondary_display" msgid="522558907654394940">"აპმა შეიძლება არ იმუშაოს მეორეულ ეკრანზე."</string> - <string name="activity_launch_on_secondary_display_failed_text" msgid="8446727617187998208">"აპს არ გააჩნია მეორეული ეკრანის მხარდაჭერა."</string> <string name="accessibility_quick_settings_settings" msgid="7098489591715844713">"პარამეტრების გახსნა."</string> <string name="accessibility_quick_settings_expand" msgid="2609275052412521467">"სწრაფი პარამეტრების გახსნა."</string> <string name="accessibility_quick_settings_collapse" msgid="4674876336725041982">"სწრაფი პარამეტრების დახურვა."</string> diff --git a/packages/SystemUI/res/values-kk/strings.xml b/packages/SystemUI/res/values-kk/strings.xml index 1adaf2bc2755..cafbc2b56732 100644 --- a/packages/SystemUI/res/values-kk/strings.xml +++ b/packages/SystemUI/res/values-kk/strings.xml @@ -879,17 +879,6 @@ </string-array> <string name="tuner_low_priority" msgid="8412666814123009820">"Маңызды емес хабарландыру белгішелерін көрсету"</string> <string name="other" msgid="429768510980739978">"Басқа"</string> - <string name="accessibility_divider" msgid="2830785970889237307">"Бөлінген экран бөлгіші"</string> - <string name="accessibility_action_divider_left_full" msgid="7598733539422375847">"Сол жағын толық экранға шығару"</string> - <string name="accessibility_action_divider_left_70" msgid="4919312892541727761">"70% сол жақта"</string> - <string name="accessibility_action_divider_left_50" msgid="3664701169564893826">"50% сол жақта"</string> - <string name="accessibility_action_divider_left_30" msgid="4358145268046362088">"30% сол жақта"</string> - <string name="accessibility_action_divider_right_full" msgid="8576057422864896305">"Оң жағын толық экранға шығару"</string> - <string name="accessibility_action_divider_top_full" msgid="4243901660795169777">"Жоғарғы жағын толық экранға шығару"</string> - <string name="accessibility_action_divider_top_70" msgid="6941226213260515072">"70% жоғарғы жақта"</string> - <string name="accessibility_action_divider_top_50" msgid="6275211443706497621">"50% жоғарғы жақта"</string> - <string name="accessibility_action_divider_top_30" msgid="5780597635887574916">"30% жоғарғы жақта"</string> - <string name="accessibility_action_divider_bottom_full" msgid="7352434720610115395">"Төменгісін толық экранға шығару"</string> <string name="accessibility_qs_edit_tile_label" msgid="9079791448815232967">"<xliff:g id="POSITION">%1$d</xliff:g> орны, <xliff:g id="TILE_NAME">%2$s</xliff:g>. Өңдеу үшін екі рет түртіңіз."</string> <string name="accessibility_qs_edit_add_tile_label" msgid="8292218072049068613">"<xliff:g id="TILE_NAME">%1$s</xliff:g>. Қосу үшін екі рет түртіңіз."</string> <string name="accessibility_qs_edit_move_tile" msgid="6027997446473163426">"<xliff:g id="TILE_NAME">%1$s</xliff:g> жылжыту"</string> @@ -898,10 +887,6 @@ <string name="accessibility_qs_edit_tile_move" msgid="4841770637244326837">"<xliff:g id="TILE_NAME">%1$s</xliff:g> бөлшегін <xliff:g id="POSITION">%2$d</xliff:g>-позицияға жылжыту"</string> <string name="accessibility_desc_quick_settings_edit" msgid="741658939453595297">"Жылдам параметрлер өңдегіші."</string> <string name="accessibility_desc_notification_icon" msgid="7331265967584178674">"<xliff:g id="ID_1">%1$s</xliff:g> хабарландыруы: <xliff:g id="ID_2">%2$s</xliff:g>"</string> - <string name="dock_forced_resizable" msgid="4689301323912928801">"Қолданба бөлінген экранда жұмыс істемеуі мүмкін."</string> - <string name="dock_non_resizeble_failed_to_dock_text" msgid="7284915968096153808">"Қодланба бөлінген экранды қолдамайды."</string> - <string name="forced_resizable_secondary_display" msgid="522558907654394940">"Қолданба қосымша дисплейде жұмыс істемеуі мүмкін."</string> - <string name="activity_launch_on_secondary_display_failed_text" msgid="8446727617187998208">"Қолданба қосымша дисплейлерде іске қосуды қолдамайды."</string> <string name="accessibility_quick_settings_settings" msgid="7098489591715844713">"Параметрлерді ашу."</string> <string name="accessibility_quick_settings_expand" msgid="2609275052412521467">"Жылдам параметрлерді ашу."</string> <string name="accessibility_quick_settings_collapse" msgid="4674876336725041982">"Жылдам параметрлерді жабу."</string> diff --git a/packages/SystemUI/res/values-km/strings.xml b/packages/SystemUI/res/values-km/strings.xml index 961a37b3cd57..5f16c7645511 100644 --- a/packages/SystemUI/res/values-km/strings.xml +++ b/packages/SystemUI/res/values-km/strings.xml @@ -879,17 +879,6 @@ </string-array> <string name="tuner_low_priority" msgid="8412666814123009820">"បង្ហាញរូបការជូនដំណឹងដែលមានអាទិភាពទាប"</string> <string name="other" msgid="429768510980739978">"ផ្សេងៗ"</string> - <string name="accessibility_divider" msgid="2830785970889237307">"កម្មវិធីចែកអេក្រង់បំបែក"</string> - <string name="accessibility_action_divider_left_full" msgid="7598733539422375847">"អេក្រង់ពេញខាងឆ្វេង"</string> - <string name="accessibility_action_divider_left_70" msgid="4919312892541727761">"ឆ្វេង 70%"</string> - <string name="accessibility_action_divider_left_50" msgid="3664701169564893826">"ឆ្វេង 50%"</string> - <string name="accessibility_action_divider_left_30" msgid="4358145268046362088">"ឆ្វេង 30%"</string> - <string name="accessibility_action_divider_right_full" msgid="8576057422864896305">"អេក្រង់ពេញខាងស្តាំ"</string> - <string name="accessibility_action_divider_top_full" msgid="4243901660795169777">"អេក្រង់ពេញខាងលើ"</string> - <string name="accessibility_action_divider_top_70" msgid="6941226213260515072">"ខាងលើ 70%"</string> - <string name="accessibility_action_divider_top_50" msgid="6275211443706497621">"ខាងលើ 50%"</string> - <string name="accessibility_action_divider_top_30" msgid="5780597635887574916">"ខាងលើ 30%"</string> - <string name="accessibility_action_divider_bottom_full" msgid="7352434720610115395">"អេក្រង់ពេញខាងក្រោម"</string> <string name="accessibility_qs_edit_tile_label" msgid="9079791448815232967">"ទីតាំង <xliff:g id="POSITION">%1$d</xliff:g>, <xliff:g id="TILE_NAME">%2$s</xliff:g>, ប៉ះពីរដងដើម្បីកែ"</string> <string name="accessibility_qs_edit_add_tile_label" msgid="8292218072049068613">"<xliff:g id="TILE_NAME">%1$s</xliff:g>, ប៉ះពីរដងដើម្បីបន្ថែម"</string> <string name="accessibility_qs_edit_move_tile" msgid="6027997446473163426">"ផ្លាស់ទី <xliff:g id="TILE_NAME">%1$s</xliff:g>"</string> @@ -898,10 +887,6 @@ <string name="accessibility_qs_edit_tile_move" msgid="4841770637244326837">"ផ្លាស់ទី <xliff:g id="TILE_NAME">%1$s</xliff:g> ទៅទីតាំង <xliff:g id="POSITION">%2$d</xliff:g>"</string> <string name="accessibility_desc_quick_settings_edit" msgid="741658939453595297">"កម្មវិធីកែការកំណត់រហ័ស"</string> <string name="accessibility_desc_notification_icon" msgid="7331265967584178674">"<xliff:g id="ID_1">%1$s</xliff:g> ការជូនដំណឹង៖ <xliff:g id="ID_2">%2$s</xliff:g>"</string> - <string name="dock_forced_resizable" msgid="4689301323912928801">"កម្មវិធីអាចនឹងមិនដំណើរការនៅលើអេក្រង់បំបែកទេ"</string> - <string name="dock_non_resizeble_failed_to_dock_text" msgid="7284915968096153808">"កម្មវិធីមិនគាំទ្រអេក្រង់បំបែកជាពីរទេ"</string> - <string name="forced_resizable_secondary_display" msgid="522558907654394940">"កម្មវិធីនេះប្រហែលជាមិនដំណើរការនៅលើអេក្រង់បន្ទាប់បន្សំទេ។"</string> - <string name="activity_launch_on_secondary_display_failed_text" msgid="8446727617187998208">"កម្មវិធីនេះមិនអាចចាប់ផ្តើមនៅលើអេក្រង់បន្ទាប់បន្សំបានទេ។"</string> <string name="accessibility_quick_settings_settings" msgid="7098489591715844713">"បើកការកំណត់"</string> <string name="accessibility_quick_settings_expand" msgid="2609275052412521467">"បើកការកំណត់រហ័ស"</string> <string name="accessibility_quick_settings_collapse" msgid="4674876336725041982">"បិទការកំណត់រហ័ស"</string> diff --git a/packages/SystemUI/res/values-kn/strings.xml b/packages/SystemUI/res/values-kn/strings.xml index 7ec6a9f54a74..dff9ebd1a072 100644 --- a/packages/SystemUI/res/values-kn/strings.xml +++ b/packages/SystemUI/res/values-kn/strings.xml @@ -879,17 +879,6 @@ </string-array> <string name="tuner_low_priority" msgid="8412666814123009820">"ಕಡಿಮೆ-ಆದ್ಯತೆ ಸೂಚನೆಯ ಐಕಾನ್ಗಳನ್ನು ತೋರಿಸಿ"</string> <string name="other" msgid="429768510980739978">"ಇತರ"</string> - <string name="accessibility_divider" msgid="2830785970889237307">"ಸ್ಪ್ಲಿಟ್-ಪರದೆ ಡಿವೈಡರ್"</string> - <string name="accessibility_action_divider_left_full" msgid="7598733539422375847">"ಎಡ ಪೂರ್ಣ ಪರದೆ"</string> - <string name="accessibility_action_divider_left_70" msgid="4919312892541727761">"70% ಎಡಕ್ಕೆ"</string> - <string name="accessibility_action_divider_left_50" msgid="3664701169564893826">"50% ಎಡಕ್ಕೆ"</string> - <string name="accessibility_action_divider_left_30" msgid="4358145268046362088">"30% ಎಡಕ್ಕೆ"</string> - <string name="accessibility_action_divider_right_full" msgid="8576057422864896305">"ಬಲ ಪೂರ್ಣ ಪರದೆ"</string> - <string name="accessibility_action_divider_top_full" msgid="4243901660795169777">"ಮೇಲಿನ ಪೂರ್ಣ ಪರದೆ"</string> - <string name="accessibility_action_divider_top_70" msgid="6941226213260515072">"70% ಮೇಲಕ್ಕೆ"</string> - <string name="accessibility_action_divider_top_50" msgid="6275211443706497621">"50% ಮೇಲಕ್ಕೆ"</string> - <string name="accessibility_action_divider_top_30" msgid="5780597635887574916">"30% ಮೇಲಕ್ಕೆ"</string> - <string name="accessibility_action_divider_bottom_full" msgid="7352434720610115395">"ಕೆಳಗಿನ ಪೂರ್ಣ ಪರದೆ"</string> <string name="accessibility_qs_edit_tile_label" msgid="9079791448815232967">"ಸ್ಥಳ <xliff:g id="POSITION">%1$d</xliff:g>, <xliff:g id="TILE_NAME">%2$s</xliff:g>. ಎಡಿಟ್ ಮಾಡಲು ಡಬಲ್ ಟ್ಯಾಪ್ ಮಾಡಿ."</string> <string name="accessibility_qs_edit_add_tile_label" msgid="8292218072049068613">"<xliff:g id="TILE_NAME">%1$s</xliff:g>. ಸೇರಿಸಲು ಡಬಲ್ ಟ್ಯಾಪ್ ಮಾಡಿ."</string> <string name="accessibility_qs_edit_move_tile" msgid="6027997446473163426">"<xliff:g id="TILE_NAME">%1$s</xliff:g> ಸರಿಸಿ"</string> @@ -898,10 +887,6 @@ <string name="accessibility_qs_edit_tile_move" msgid="4841770637244326837">"<xliff:g id="TILE_NAME">%1$s</xliff:g> ಅನ್ನು <xliff:g id="POSITION">%2$d</xliff:g> ಗೆ ಸರಿಸಿ"</string> <string name="accessibility_desc_quick_settings_edit" msgid="741658939453595297">"ತ್ವರಿತ ಸೆಟ್ಟಿಂಗ್ಗಳ ಎಡಿಟರ್."</string> <string name="accessibility_desc_notification_icon" msgid="7331265967584178674">"<xliff:g id="ID_1">%1$s</xliff:g> ಅಧಿಸೂಚನೆ: <xliff:g id="ID_2">%2$s</xliff:g>"</string> - <string name="dock_forced_resizable" msgid="4689301323912928801">"ವಿಭಜಿಸಿದ ಪರದೆಯಲ್ಲಿ ಅಪ್ಲಿಕೇಶನ್ ಕೆಲಸ ಮಾಡದೇ ಇರಬಹುದು."</string> - <string name="dock_non_resizeble_failed_to_dock_text" msgid="7284915968096153808">"ಅಪ್ಲಿಕೇಶನ್ ಸ್ಪ್ಲಿಟ್ ಸ್ಕ್ರೀನ್ ಅನ್ನು ಬೆಂಬಲಿಸುವುದಿಲ್ಲ."</string> - <string name="forced_resizable_secondary_display" msgid="522558907654394940">"ಸೆಕೆಂಡರಿ ಡಿಸ್ಪ್ಲೇಗಳಲ್ಲಿ ಅಪ್ಲಿಕೇಶನ್ ಕಾರ್ಯ ನಿರ್ವಹಿಸದೇ ಇರಬಹುದು."</string> - <string name="activity_launch_on_secondary_display_failed_text" msgid="8446727617187998208">"ಸೆಕೆಂಡರಿ ಡಿಸ್ಪ್ಲೇಗಳಲ್ಲಿ ಪ್ರಾರಂಭಿಸುವಿಕೆಯನ್ನು ಅಪ್ಲಿಕೇಶನ್ ಬೆಂಬಲಿಸುವುದಿಲ್ಲ."</string> <string name="accessibility_quick_settings_settings" msgid="7098489591715844713">"ಸೆಟ್ಟಿಂಗ್ಗಳನ್ನು ತೆರೆಯಿರಿ."</string> <string name="accessibility_quick_settings_expand" msgid="2609275052412521467">"ತ್ವರಿತ ಸೆಟ್ಟಿಂಗ್ಗಳನ್ನು ತೆರೆಯಿರಿ."</string> <string name="accessibility_quick_settings_collapse" msgid="4674876336725041982">"ತ್ವರಿತ ಸೆಟ್ಟಿಂಗ್ಗಳನ್ನು ಮುಚ್ಚಿ."</string> diff --git a/packages/SystemUI/res/values-ko/strings.xml b/packages/SystemUI/res/values-ko/strings.xml index 840a98e32e23..181888f29161 100644 --- a/packages/SystemUI/res/values-ko/strings.xml +++ b/packages/SystemUI/res/values-ko/strings.xml @@ -879,17 +879,6 @@ </string-array> <string name="tuner_low_priority" msgid="8412666814123009820">"우선순위가 낮은 알림 아이콘 표시"</string> <string name="other" msgid="429768510980739978">"기타"</string> - <string name="accessibility_divider" msgid="2830785970889237307">"화면 분할기"</string> - <string name="accessibility_action_divider_left_full" msgid="7598733539422375847">"왼쪽 화면 전체화면"</string> - <string name="accessibility_action_divider_left_70" msgid="4919312892541727761">"왼쪽 화면 70%"</string> - <string name="accessibility_action_divider_left_50" msgid="3664701169564893826">"왼쪽 화면 50%"</string> - <string name="accessibility_action_divider_left_30" msgid="4358145268046362088">"왼쪽 화면 30%"</string> - <string name="accessibility_action_divider_right_full" msgid="8576057422864896305">"오른쪽 화면 전체화면"</string> - <string name="accessibility_action_divider_top_full" msgid="4243901660795169777">"위쪽 화면 전체화면"</string> - <string name="accessibility_action_divider_top_70" msgid="6941226213260515072">"위쪽 화면 70%"</string> - <string name="accessibility_action_divider_top_50" msgid="6275211443706497621">"위쪽 화면 50%"</string> - <string name="accessibility_action_divider_top_30" msgid="5780597635887574916">"위쪽 화면 30%"</string> - <string name="accessibility_action_divider_bottom_full" msgid="7352434720610115395">"아래쪽 화면 전체화면"</string> <string name="accessibility_qs_edit_tile_label" msgid="9079791448815232967">"위치 <xliff:g id="POSITION">%1$d</xliff:g>, <xliff:g id="TILE_NAME">%2$s</xliff:g>. 수정하려면 두 번 탭하세요."</string> <string name="accessibility_qs_edit_add_tile_label" msgid="8292218072049068613">"<xliff:g id="TILE_NAME">%1$s</xliff:g>. 추가하려면 두 번 탭하세요."</string> <string name="accessibility_qs_edit_move_tile" msgid="6027997446473163426">"<xliff:g id="TILE_NAME">%1$s</xliff:g> 이동"</string> @@ -898,10 +887,6 @@ <string name="accessibility_qs_edit_tile_move" msgid="4841770637244326837">"<xliff:g id="TILE_NAME">%1$s</xliff:g> 타일을 위치 <xliff:g id="POSITION">%2$d</xliff:g>(으)로 이동"</string> <string name="accessibility_desc_quick_settings_edit" msgid="741658939453595297">"빠른 설정 편집기"</string> <string name="accessibility_desc_notification_icon" msgid="7331265967584178674">"<xliff:g id="ID_1">%1$s</xliff:g> 알림: <xliff:g id="ID_2">%2$s</xliff:g>"</string> - <string name="dock_forced_resizable" msgid="4689301323912928801">"앱이 분할 화면에서 작동하지 않을 수 있습니다."</string> - <string name="dock_non_resizeble_failed_to_dock_text" msgid="7284915968096153808">"앱이 화면 분할을 지원하지 않습니다."</string> - <string name="forced_resizable_secondary_display" msgid="522558907654394940">"앱이 보조 디스플레이에서 작동하지 않을 수도 있습니다."</string> - <string name="activity_launch_on_secondary_display_failed_text" msgid="8446727617187998208">"앱이 보조 디스플레이에서의 실행을 지원하지 않습니다."</string> <string name="accessibility_quick_settings_settings" msgid="7098489591715844713">"설정 열기"</string> <string name="accessibility_quick_settings_expand" msgid="2609275052412521467">"빠른 설정 열기"</string> <string name="accessibility_quick_settings_collapse" msgid="4674876336725041982">"빠른 설정 닫기"</string> diff --git a/packages/SystemUI/res/values-ky/strings.xml b/packages/SystemUI/res/values-ky/strings.xml index 14ee566d305c..47fc3a8fbf31 100644 --- a/packages/SystemUI/res/values-ky/strings.xml +++ b/packages/SystemUI/res/values-ky/strings.xml @@ -879,17 +879,6 @@ </string-array> <string name="tuner_low_priority" msgid="8412666814123009820">"Анча маанилүү эмес билдирменин сүрөтчөлөрүн көрсөтүү"</string> <string name="other" msgid="429768510980739978">"Башка"</string> - <string name="accessibility_divider" msgid="2830785970889237307">"Экранды бөлгүч"</string> - <string name="accessibility_action_divider_left_full" msgid="7598733539422375847">"Сол жактагы экранды толук экран режимине өткөрүү"</string> - <string name="accessibility_action_divider_left_70" msgid="4919312892541727761">"Сол жактагы экранды 70%"</string> - <string name="accessibility_action_divider_left_50" msgid="3664701169564893826">"Сол жактагы экранды 50%"</string> - <string name="accessibility_action_divider_left_30" msgid="4358145268046362088">"Сол жактагы экранды 30%"</string> - <string name="accessibility_action_divider_right_full" msgid="8576057422864896305">"Оң жактагы экранды толук экран режимине өткөрүү"</string> - <string name="accessibility_action_divider_top_full" msgid="4243901660795169777">"Үстүнкү экранды толук экран режимине өткөрүү"</string> - <string name="accessibility_action_divider_top_70" msgid="6941226213260515072">"Үстүнкү экранды 70%"</string> - <string name="accessibility_action_divider_top_50" msgid="6275211443706497621">"Үстүнкү экранды 50%"</string> - <string name="accessibility_action_divider_top_30" msgid="5780597635887574916">"Үстүнкү экранды 30%"</string> - <string name="accessibility_action_divider_bottom_full" msgid="7352434720610115395">"Ылдыйкы экранды толук экран режимине өткөрүү"</string> <string name="accessibility_qs_edit_tile_label" msgid="9079791448815232967">"Орду - <xliff:g id="POSITION">%1$d</xliff:g>, <xliff:g id="TILE_NAME">%2$s</xliff:g>. Түзөтүү үчүн эки жолу таптаңыз."</string> <string name="accessibility_qs_edit_add_tile_label" msgid="8292218072049068613">"<xliff:g id="TILE_NAME">%1$s</xliff:g>. Кошуу үчүн эки жолу таптаңыз."</string> <string name="accessibility_qs_edit_move_tile" msgid="6027997446473163426">"<xliff:g id="TILE_NAME">%1$s</xliff:g> дегенди жылдыруу"</string> @@ -898,10 +887,6 @@ <string name="accessibility_qs_edit_tile_move" msgid="4841770637244326837">"<xliff:g id="TILE_NAME">%1$s</xliff:g> плиткасы <xliff:g id="POSITION">%2$d</xliff:g>-позицияга кошулсун"</string> <string name="accessibility_desc_quick_settings_edit" msgid="741658939453595297">"Ыкчам жөндөөлөр түзөткүчү."</string> <string name="accessibility_desc_notification_icon" msgid="7331265967584178674">"<xliff:g id="ID_1">%1$s</xliff:g> эскертмеси: <xliff:g id="ID_2">%2$s</xliff:g>"</string> - <string name="dock_forced_resizable" msgid="4689301323912928801">"Колдонмодо экран бөлүнбөшү мүмкүн."</string> - <string name="dock_non_resizeble_failed_to_dock_text" msgid="7284915968096153808">"Колдонмодо экран бөлүнбөйт."</string> - <string name="forced_resizable_secondary_display" msgid="522558907654394940">"Колдонмо кошумча экранда иштебей коюшу мүмкүн."</string> - <string name="activity_launch_on_secondary_display_failed_text" msgid="8446727617187998208">"Колдонмону кошумча экрандарда иштетүүгө болбойт."</string> <string name="accessibility_quick_settings_settings" msgid="7098489591715844713">"Жөндөөлөрдү ачуу."</string> <string name="accessibility_quick_settings_expand" msgid="2609275052412521467">"Ыкчам жөндөөлөрдү ачуу."</string> <string name="accessibility_quick_settings_collapse" msgid="4674876336725041982">"Ыкчам жөндөөлөрдү жабуу."</string> diff --git a/packages/SystemUI/res/values-lo/strings.xml b/packages/SystemUI/res/values-lo/strings.xml index 553d0da2e295..cb875559011d 100644 --- a/packages/SystemUI/res/values-lo/strings.xml +++ b/packages/SystemUI/res/values-lo/strings.xml @@ -879,17 +879,6 @@ </string-array> <string name="tuner_low_priority" msgid="8412666814123009820">"ສະແດງໄອຄອນການແຈ້ງເຕືອນຄວາມສຳຄັນຕ່ຳ"</string> <string name="other" msgid="429768510980739978">"ອື່ນໆ"</string> - <string name="accessibility_divider" msgid="2830785970889237307">"ຕົວຂັ້ນການແບ່ງໜ້າຈໍ"</string> - <string name="accessibility_action_divider_left_full" msgid="7598733539422375847">"ເຕັມໜ້າຈໍຊ້າຍ"</string> - <string name="accessibility_action_divider_left_70" msgid="4919312892541727761">"ຊ້າຍ 70%"</string> - <string name="accessibility_action_divider_left_50" msgid="3664701169564893826">"ຊ້າຍ 50%"</string> - <string name="accessibility_action_divider_left_30" msgid="4358145268046362088">"ຊ້າຍ 30%"</string> - <string name="accessibility_action_divider_right_full" msgid="8576057422864896305">"ເຕັມໜ້າຈໍຂວາ"</string> - <string name="accessibility_action_divider_top_full" msgid="4243901660795169777">"ເຕັມໜ້າຈໍເທິງສຸດ"</string> - <string name="accessibility_action_divider_top_70" msgid="6941226213260515072">"ເທິງສຸດ 70%"</string> - <string name="accessibility_action_divider_top_50" msgid="6275211443706497621">"ເທິງສຸດ 50%"</string> - <string name="accessibility_action_divider_top_30" msgid="5780597635887574916">"ເທິງສຸດ 30%"</string> - <string name="accessibility_action_divider_bottom_full" msgid="7352434720610115395">"ເຕັມໜ້າຈໍລຸ່ມສຸດ"</string> <string name="accessibility_qs_edit_tile_label" msgid="9079791448815232967">"ຕຳແໜ່ງ <xliff:g id="POSITION">%1$d</xliff:g>, <xliff:g id="TILE_NAME">%2$s</xliff:g>. ແຕະສອງເທື່ອເພື່ອແກ້ໄຂ."</string> <string name="accessibility_qs_edit_add_tile_label" msgid="8292218072049068613">"<xliff:g id="TILE_NAME">%1$s</xliff:g>. ແຕະສອງເທື່ອເພື່ອເພີ່ມ."</string> <string name="accessibility_qs_edit_move_tile" msgid="6027997446473163426">"ຍ້າຍ <xliff:g id="TILE_NAME">%1$s</xliff:g>"</string> @@ -898,10 +887,6 @@ <string name="accessibility_qs_edit_tile_move" msgid="4841770637244326837">"ຍ້າຍ <xliff:g id="TILE_NAME">%1$s</xliff:g> ໄປຕຳແໜ່ງ <xliff:g id="POSITION">%2$d</xliff:g>"</string> <string name="accessibility_desc_quick_settings_edit" msgid="741658939453595297">"ຕົວແກ້ໄຂການຕັ້ງຄ່າດ່ວນ"</string> <string name="accessibility_desc_notification_icon" msgid="7331265967584178674">"ການແຈ້ງເຕືອນ <xliff:g id="ID_1">%1$s</xliff:g>: <xliff:g id="ID_2">%2$s</xliff:g>"</string> - <string name="dock_forced_resizable" msgid="4689301323912928801">"ແອັບອາດໃຊ້ບໍ່ໄດ້ກັບການແບ່ງໜ້າຈໍ."</string> - <string name="dock_non_resizeble_failed_to_dock_text" msgid="7284915968096153808">"ແອັບບໍ່ຮອງຮັບໜ້າຈໍແບບແຍກກັນ."</string> - <string name="forced_resizable_secondary_display" msgid="522558907654394940">"ແອັບອາດບໍ່ສາມາດໃຊ້ໄດ້ໃນໜ້າຈໍທີສອງ."</string> - <string name="activity_launch_on_secondary_display_failed_text" msgid="8446727617187998208">"ແອັບບໍ່ຮອງຮັບການເປີດໃນໜ້າຈໍທີສອງ."</string> <string name="accessibility_quick_settings_settings" msgid="7098489591715844713">"ເປີດການຕັ້ງຄ່າ."</string> <string name="accessibility_quick_settings_expand" msgid="2609275052412521467">"ເປີດການຕັ້ງຄ່າດ່ວນ."</string> <string name="accessibility_quick_settings_collapse" msgid="4674876336725041982">"ປິດການຕັ້ງຄ່າດ່ວນ."</string> diff --git a/packages/SystemUI/res/values-lt/strings.xml b/packages/SystemUI/res/values-lt/strings.xml index 28d6e6b35431..ac90c0f58e68 100644 --- a/packages/SystemUI/res/values-lt/strings.xml +++ b/packages/SystemUI/res/values-lt/strings.xml @@ -889,17 +889,6 @@ </string-array> <string name="tuner_low_priority" msgid="8412666814123009820">"Rodyti mažo prioriteto pranešimų piktogramas"</string> <string name="other" msgid="429768510980739978">"Kita"</string> - <string name="accessibility_divider" msgid="2830785970889237307">"Skaidyto ekrano daliklis"</string> - <string name="accessibility_action_divider_left_full" msgid="7598733539422375847">"Kairysis ekranas viso ekrano režimu"</string> - <string name="accessibility_action_divider_left_70" msgid="4919312892541727761">"Kairysis ekranas 70 %"</string> - <string name="accessibility_action_divider_left_50" msgid="3664701169564893826">"Kairysis ekranas 50 %"</string> - <string name="accessibility_action_divider_left_30" msgid="4358145268046362088">"Kairysis ekranas 30 %"</string> - <string name="accessibility_action_divider_right_full" msgid="8576057422864896305">"Dešinysis ekranas viso ekrano režimu"</string> - <string name="accessibility_action_divider_top_full" msgid="4243901660795169777">"Viršutinis ekranas viso ekrano režimu"</string> - <string name="accessibility_action_divider_top_70" msgid="6941226213260515072">"Viršutinis ekranas 70 %"</string> - <string name="accessibility_action_divider_top_50" msgid="6275211443706497621">"Viršutinis ekranas 50 %"</string> - <string name="accessibility_action_divider_top_30" msgid="5780597635887574916">"Viršutinis ekranas 30 %"</string> - <string name="accessibility_action_divider_bottom_full" msgid="7352434720610115395">"Apatinis ekranas viso ekrano režimu"</string> <string name="accessibility_qs_edit_tile_label" msgid="9079791448815232967">"<xliff:g id="POSITION">%1$d</xliff:g> padėtis, išklotinės elementas „<xliff:g id="TILE_NAME">%2$s</xliff:g>“. Dukart palieskite, kad redaguotumėte."</string> <string name="accessibility_qs_edit_add_tile_label" msgid="8292218072049068613">"Išklotinės elementas „<xliff:g id="TILE_NAME">%1$s</xliff:g>“. Dukart palieskite, kad pridėtumėte."</string> <string name="accessibility_qs_edit_move_tile" msgid="6027997446473163426">"Perkelti išklotinės elementą „<xliff:g id="TILE_NAME">%1$s</xliff:g>“"</string> @@ -908,10 +897,6 @@ <string name="accessibility_qs_edit_tile_move" msgid="4841770637244326837">"Perkelti išklotinės elementą „<xliff:g id="TILE_NAME">%1$s</xliff:g>“ į <xliff:g id="POSITION">%2$d</xliff:g> padėtį"</string> <string name="accessibility_desc_quick_settings_edit" msgid="741658939453595297">"Sparčiųjų nustatymų redagavimo priemonė."</string> <string name="accessibility_desc_notification_icon" msgid="7331265967584178674">"„<xliff:g id="ID_1">%1$s</xliff:g>“ pranešimas: <xliff:g id="ID_2">%2$s</xliff:g>"</string> - <string name="dock_forced_resizable" msgid="4689301323912928801">"Programa gali neveikti naudojant skaidytą ekraną."</string> - <string name="dock_non_resizeble_failed_to_dock_text" msgid="7284915968096153808">"Programoje nepalaikomas skaidytas ekranas."</string> - <string name="forced_resizable_secondary_display" msgid="522558907654394940">"Programa gali neveikti antriniame ekrane."</string> - <string name="activity_launch_on_secondary_display_failed_text" msgid="8446727617187998208">"Programa nepalaiko paleisties antriniuose ekranuose."</string> <string name="accessibility_quick_settings_settings" msgid="7098489591715844713">"Atidaryti nustatymus."</string> <string name="accessibility_quick_settings_expand" msgid="2609275052412521467">"Atidaryti sparčiuosius nustatymus."</string> <string name="accessibility_quick_settings_collapse" msgid="4674876336725041982">"Uždaryti sparčiuosius nustatymus."</string> diff --git a/packages/SystemUI/res/values-lv/strings.xml b/packages/SystemUI/res/values-lv/strings.xml index 223a57fdb640..2f5edd3f0d9f 100644 --- a/packages/SystemUI/res/values-lv/strings.xml +++ b/packages/SystemUI/res/values-lv/strings.xml @@ -884,17 +884,6 @@ </string-array> <string name="tuner_low_priority" msgid="8412666814123009820">"Rādīt zemas prioritātes paziņojumu ikonas"</string> <string name="other" msgid="429768510980739978">"Citi"</string> - <string name="accessibility_divider" msgid="2830785970889237307">"Ekrāna sadalītājs"</string> - <string name="accessibility_action_divider_left_full" msgid="7598733539422375847">"Kreisā daļa pa visu ekrānu"</string> - <string name="accessibility_action_divider_left_70" msgid="4919312892541727761">"Pa kreisi 70%"</string> - <string name="accessibility_action_divider_left_50" msgid="3664701169564893826">"Pa kreisi 50%"</string> - <string name="accessibility_action_divider_left_30" msgid="4358145268046362088">"Pa kreisi 30%"</string> - <string name="accessibility_action_divider_right_full" msgid="8576057422864896305">"Labā daļa pa visu ekrānu"</string> - <string name="accessibility_action_divider_top_full" msgid="4243901660795169777">"Augšdaļa pa visu ekrānu"</string> - <string name="accessibility_action_divider_top_70" msgid="6941226213260515072">"Augšdaļa 70%"</string> - <string name="accessibility_action_divider_top_50" msgid="6275211443706497621">"Augšdaļa 50%"</string> - <string name="accessibility_action_divider_top_30" msgid="5780597635887574916">"Augšdaļa 30%"</string> - <string name="accessibility_action_divider_bottom_full" msgid="7352434720610115395">"Apakšdaļu pa visu ekrānu"</string> <string name="accessibility_qs_edit_tile_label" msgid="9079791448815232967">"<xliff:g id="POSITION">%1$d</xliff:g>. pozīcija, <xliff:g id="TILE_NAME">%2$s</xliff:g>. Lai rediģētu, veiciet dubultskārienu."</string> <string name="accessibility_qs_edit_add_tile_label" msgid="8292218072049068613">"<xliff:g id="TILE_NAME">%1$s</xliff:g>. Lai pievienotu, veiciet dubultskārienu."</string> <string name="accessibility_qs_edit_move_tile" msgid="6027997446473163426">"Pārvietot elementu <xliff:g id="TILE_NAME">%1$s</xliff:g>"</string> @@ -903,10 +892,6 @@ <string name="accessibility_qs_edit_tile_move" msgid="4841770637244326837">"Pārvietot elementu “<xliff:g id="TILE_NAME">%1$s</xliff:g>” uz <xliff:g id="POSITION">%2$d</xliff:g>. pozīciju"</string> <string name="accessibility_desc_quick_settings_edit" msgid="741658939453595297">"Ātro iestatījumu redaktors."</string> <string name="accessibility_desc_notification_icon" msgid="7331265967584178674">"<xliff:g id="ID_1">%1$s</xliff:g> paziņojums: <xliff:g id="ID_2">%2$s</xliff:g>"</string> - <string name="dock_forced_resizable" msgid="4689301323912928801">"Iespējams, lietotnē nedarbosies ekrāna sadalīšana."</string> - <string name="dock_non_resizeble_failed_to_dock_text" msgid="7284915968096153808">"Lietotnē netiek atbalstīta ekrāna sadalīšana."</string> - <string name="forced_resizable_secondary_display" msgid="522558907654394940">"Lietotne, iespējams, nedarbosies sekundārajā displejā."</string> - <string name="activity_launch_on_secondary_display_failed_text" msgid="8446727617187998208">"Lietotnē netiek atbalstīta palaišana sekundārajos displejos."</string> <string name="accessibility_quick_settings_settings" msgid="7098489591715844713">"Atvērt iestatījumus."</string> <string name="accessibility_quick_settings_expand" msgid="2609275052412521467">"Atvērt ātros iestatījumus."</string> <string name="accessibility_quick_settings_collapse" msgid="4674876336725041982">"Aizvērt ātros iestatījumus."</string> diff --git a/packages/SystemUI/res/values-mk/strings.xml b/packages/SystemUI/res/values-mk/strings.xml index a591031cabba..de9cf0fb57bf 100644 --- a/packages/SystemUI/res/values-mk/strings.xml +++ b/packages/SystemUI/res/values-mk/strings.xml @@ -879,17 +879,6 @@ </string-array> <string name="tuner_low_priority" msgid="8412666814123009820">"Прикажувај икони за известувања со низок приоритет"</string> <string name="other" msgid="429768510980739978">"Друго"</string> - <string name="accessibility_divider" msgid="2830785970889237307">"Разделник на поделен екран"</string> - <string name="accessibility_action_divider_left_full" msgid="7598733539422375847">"Левиот на цел екран"</string> - <string name="accessibility_action_divider_left_70" msgid="4919312892541727761">"Левиот 70%"</string> - <string name="accessibility_action_divider_left_50" msgid="3664701169564893826">"Левиот 50%"</string> - <string name="accessibility_action_divider_left_30" msgid="4358145268046362088">"Левиот 30%"</string> - <string name="accessibility_action_divider_right_full" msgid="8576057422864896305">"Десниот на цел екран"</string> - <string name="accessibility_action_divider_top_full" msgid="4243901660795169777">"Горниот на цел екран"</string> - <string name="accessibility_action_divider_top_70" msgid="6941226213260515072">"Горниот 70%"</string> - <string name="accessibility_action_divider_top_50" msgid="6275211443706497621">"Горниот 50%"</string> - <string name="accessibility_action_divider_top_30" msgid="5780597635887574916">"Горниот 30%"</string> - <string name="accessibility_action_divider_bottom_full" msgid="7352434720610115395">"Долниот на цел екран"</string> <string name="accessibility_qs_edit_tile_label" msgid="9079791448815232967">"Место <xliff:g id="POSITION">%1$d</xliff:g>, <xliff:g id="TILE_NAME">%2$s</xliff:g>. Допрете двапати за уредување."</string> <string name="accessibility_qs_edit_add_tile_label" msgid="8292218072049068613">"<xliff:g id="TILE_NAME">%1$s</xliff:g>. Допрете двапати за додавање."</string> <string name="accessibility_qs_edit_move_tile" msgid="6027997446473163426">"Преместете <xliff:g id="TILE_NAME">%1$s</xliff:g>"</string> @@ -898,10 +887,6 @@ <string name="accessibility_qs_edit_tile_move" msgid="4841770637244326837">"Преместете <xliff:g id="TILE_NAME">%1$s</xliff:g> на позицијата <xliff:g id="POSITION">%2$d</xliff:g>"</string> <string name="accessibility_desc_quick_settings_edit" msgid="741658939453595297">"Уредник за брзи поставки."</string> <string name="accessibility_desc_notification_icon" msgid="7331265967584178674">"Известување од <xliff:g id="ID_1">%1$s</xliff:g>: <xliff:g id="ID_2">%2$s</xliff:g>"</string> - <string name="dock_forced_resizable" msgid="4689301323912928801">"Апликацијата можеби нема да работи во поделен екран."</string> - <string name="dock_non_resizeble_failed_to_dock_text" msgid="7284915968096153808">"Апликацијата не поддржува поделен екран."</string> - <string name="forced_resizable_secondary_display" msgid="522558907654394940">"Апликацијата може да не функционира на друг екран."</string> - <string name="activity_launch_on_secondary_display_failed_text" msgid="8446727617187998208">"Апликацијата не поддржува стартување на други екрани."</string> <string name="accessibility_quick_settings_settings" msgid="7098489591715844713">"Отворете ги поставките."</string> <string name="accessibility_quick_settings_expand" msgid="2609275052412521467">"Отворете ги брзите поставки."</string> <string name="accessibility_quick_settings_collapse" msgid="4674876336725041982">"Затворете ги брзите поставки."</string> diff --git a/packages/SystemUI/res/values-ml/strings.xml b/packages/SystemUI/res/values-ml/strings.xml index 47d220df5bde..bd5187456574 100644 --- a/packages/SystemUI/res/values-ml/strings.xml +++ b/packages/SystemUI/res/values-ml/strings.xml @@ -879,17 +879,6 @@ </string-array> <string name="tuner_low_priority" msgid="8412666814123009820">"പ്രാധാന്യം കുറഞ്ഞ അറിയിപ്പ് ചിഹ്നങ്ങൾ"</string> <string name="other" msgid="429768510980739978">"മറ്റുള്ളവ"</string> - <string name="accessibility_divider" msgid="2830785970889237307">"സ്പ്ലിറ്റ്-സ്ക്രീൻ ഡിവൈഡർ"</string> - <string name="accessibility_action_divider_left_full" msgid="7598733539422375847">"ഇടത് പൂർണ്ണ സ്ക്രീൻ"</string> - <string name="accessibility_action_divider_left_70" msgid="4919312892541727761">"ഇടത് 70%"</string> - <string name="accessibility_action_divider_left_50" msgid="3664701169564893826">"ഇടത് 50%"</string> - <string name="accessibility_action_divider_left_30" msgid="4358145268046362088">"ഇടത് 30%"</string> - <string name="accessibility_action_divider_right_full" msgid="8576057422864896305">"വലത് പൂർണ്ണ സ്ക്രീൻ"</string> - <string name="accessibility_action_divider_top_full" msgid="4243901660795169777">"മുകളിൽ പൂർണ്ണ സ്ക്രീൻ"</string> - <string name="accessibility_action_divider_top_70" msgid="6941226213260515072">"മുകളിൽ 70%"</string> - <string name="accessibility_action_divider_top_50" msgid="6275211443706497621">"മുകളിൽ 50%"</string> - <string name="accessibility_action_divider_top_30" msgid="5780597635887574916">"മുകളിൽ 30%"</string> - <string name="accessibility_action_divider_bottom_full" msgid="7352434720610115395">"താഴെ പൂർണ്ണ സ്ക്രീൻ"</string> <string name="accessibility_qs_edit_tile_label" msgid="9079791448815232967">"സ്ഥാനം <xliff:g id="POSITION">%1$d</xliff:g>, <xliff:g id="TILE_NAME">%2$s</xliff:g>. എഡിറ്റുചെയ്യുന്നതിന് രണ്ടുതവണ ടാപ്പുചെയ്യുക."</string> <string name="accessibility_qs_edit_add_tile_label" msgid="8292218072049068613">"<xliff:g id="TILE_NAME">%1$s</xliff:g>. ചേർക്കാൻ രണ്ടുതവണ ടാപ്പുചെയ്യുക."</string> <string name="accessibility_qs_edit_move_tile" msgid="6027997446473163426">"<xliff:g id="TILE_NAME">%1$s</xliff:g> നീക്കുക"</string> @@ -898,10 +887,6 @@ <string name="accessibility_qs_edit_tile_move" msgid="4841770637244326837">"<xliff:g id="POSITION">%2$d</xliff:g> സ്ഥാനത്തേയ്ക്ക് <xliff:g id="TILE_NAME">%1$s</xliff:g> നീക്കുക"</string> <string name="accessibility_desc_quick_settings_edit" msgid="741658939453595297">"ദ്രുത ക്രമീകരണ എഡിറ്റർ."</string> <string name="accessibility_desc_notification_icon" msgid="7331265967584178674">"<xliff:g id="ID_1">%1$s</xliff:g> അറിയിപ്പ്: <xliff:g id="ID_2">%2$s</xliff:g>"</string> - <string name="dock_forced_resizable" msgid="4689301323912928801">"സ്പ്ലിറ്റ്-സ്ക്രീനിനൊപ്പം ആപ്പ് പ്രവർത്തിച്ചേക്കില്ല."</string> - <string name="dock_non_resizeble_failed_to_dock_text" msgid="7284915968096153808">"സ്പ്ലിറ്റ്-സ്ക്രീനിനെ ആപ്പ് പിന്തുണയ്ക്കുന്നില്ല."</string> - <string name="forced_resizable_secondary_display" msgid="522558907654394940">"രണ്ടാം ഡിസ്പ്ലേയിൽ ആപ്പ് പ്രവർത്തിച്ചേക്കില്ല."</string> - <string name="activity_launch_on_secondary_display_failed_text" msgid="8446727617187998208">"രണ്ടാം ഡിസ്പ്ലേകളിൽ സമാരംഭിക്കുന്നതിനെ ആപ്പ് അനുവദിക്കുന്നില്ല."</string> <string name="accessibility_quick_settings_settings" msgid="7098489591715844713">"ക്രമീകരണം തുറക്കുക."</string> <string name="accessibility_quick_settings_expand" msgid="2609275052412521467">"ദ്രുത ക്രമീകരണം തുറക്കുക."</string> <string name="accessibility_quick_settings_collapse" msgid="4674876336725041982">"ദ്രുത ക്രമീകരണം അടയ്ക്കുക."</string> diff --git a/packages/SystemUI/res/values-mn/strings.xml b/packages/SystemUI/res/values-mn/strings.xml index 202f292503b0..14401030fb21 100644 --- a/packages/SystemUI/res/values-mn/strings.xml +++ b/packages/SystemUI/res/values-mn/strings.xml @@ -879,17 +879,6 @@ </string-array> <string name="tuner_low_priority" msgid="8412666814123009820">"Бага ач холбогдолтой мэдэгдлийн дүрс тэмдгийг харуулах"</string> <string name="other" msgid="429768510980739978">"Бусад"</string> - <string name="accessibility_divider" msgid="2830785970889237307">"\"Дэлгэц хуваах\" хуваагч"</string> - <string name="accessibility_action_divider_left_full" msgid="7598733539422375847">"Зүүн талын бүтэн дэлгэц"</string> - <string name="accessibility_action_divider_left_70" msgid="4919312892541727761">"Зүүн 70%"</string> - <string name="accessibility_action_divider_left_50" msgid="3664701169564893826">"Зүүн 50%"</string> - <string name="accessibility_action_divider_left_30" msgid="4358145268046362088">"Зүүн 30%"</string> - <string name="accessibility_action_divider_right_full" msgid="8576057422864896305">"Баруун талын бүтэн дэлгэц"</string> - <string name="accessibility_action_divider_top_full" msgid="4243901660795169777">"Дээд талын бүтэн дэлгэц"</string> - <string name="accessibility_action_divider_top_70" msgid="6941226213260515072">"Дээд 70%"</string> - <string name="accessibility_action_divider_top_50" msgid="6275211443706497621">"Дээд 50%"</string> - <string name="accessibility_action_divider_top_30" msgid="5780597635887574916">"Дээд 30%"</string> - <string name="accessibility_action_divider_bottom_full" msgid="7352434720610115395">"Доод бүтэн дэлгэц"</string> <string name="accessibility_qs_edit_tile_label" msgid="9079791448815232967">"Байршил <xliff:g id="POSITION">%1$d</xliff:g>, <xliff:g id="TILE_NAME">%2$s</xliff:g>. Засахын тулд 2 удаа дарна уу."</string> <string name="accessibility_qs_edit_add_tile_label" msgid="8292218072049068613">"<xliff:g id="TILE_NAME">%1$s</xliff:g>. Нэмэхийн тулд 2 удаа дарна уу."</string> <string name="accessibility_qs_edit_move_tile" msgid="6027997446473163426">"<xliff:g id="TILE_NAME">%1$s</xliff:g>-г зөөх"</string> @@ -898,10 +887,6 @@ <string name="accessibility_qs_edit_tile_move" msgid="4841770637244326837">"<xliff:g id="TILE_NAME">%1$s</xliff:g>-г байрлал <xliff:g id="POSITION">%2$d</xliff:g> руу зөөх"</string> <string name="accessibility_desc_quick_settings_edit" msgid="741658939453595297">"Түргэн тохиргоо засварлагч."</string> <string name="accessibility_desc_notification_icon" msgid="7331265967584178674">"<xliff:g id="ID_1">%1$s</xliff:g> мэдэгдэл: <xliff:g id="ID_2">%2$s</xliff:g>"</string> - <string name="dock_forced_resizable" msgid="4689301323912928801">"Апп хуваагдсан дэлгэцэд ажиллахгүй."</string> - <string name="dock_non_resizeble_failed_to_dock_text" msgid="7284915968096153808">"Энэ апп нь дэлгэц хуваах тохиргоог дэмждэггүй."</string> - <string name="forced_resizable_secondary_display" msgid="522558907654394940">"Апп хоёрдогч дэлгэцэд ажиллахгүй."</string> - <string name="activity_launch_on_secondary_display_failed_text" msgid="8446727617187998208">"Аппыг хоёрдогч дэлгэцэд эхлүүлэх боломжгүй."</string> <string name="accessibility_quick_settings_settings" msgid="7098489591715844713">"Тохиргоог нээнэ үү."</string> <string name="accessibility_quick_settings_expand" msgid="2609275052412521467">"Шуурхай тохиргоог нээнэ үү."</string> <string name="accessibility_quick_settings_collapse" msgid="4674876336725041982">"Хурдан тохиргоог хаана уу."</string> diff --git a/packages/SystemUI/res/values-mr/strings.xml b/packages/SystemUI/res/values-mr/strings.xml index e4120726c66c..32fe7bdecb42 100644 --- a/packages/SystemUI/res/values-mr/strings.xml +++ b/packages/SystemUI/res/values-mr/strings.xml @@ -879,17 +879,6 @@ </string-array> <string name="tuner_low_priority" msgid="8412666814123009820">"कमी प्राधान्य सूचना आयकन दर्शवा"</string> <string name="other" msgid="429768510980739978">"अन्य"</string> - <string name="accessibility_divider" msgid="2830785970889237307">"विभाजित-स्क्रीन विभाजक"</string> - <string name="accessibility_action_divider_left_full" msgid="7598733539422375847">"डावी फुल स्क्रीन"</string> - <string name="accessibility_action_divider_left_70" msgid="4919312892541727761">"डावी 70%"</string> - <string name="accessibility_action_divider_left_50" msgid="3664701169564893826">"डावी 50%"</string> - <string name="accessibility_action_divider_left_30" msgid="4358145268046362088">"डावी 30%"</string> - <string name="accessibility_action_divider_right_full" msgid="8576057422864896305">"उजवी फुल स्क्रीन"</string> - <string name="accessibility_action_divider_top_full" msgid="4243901660795169777">"शीर्ष फुल स्क्रीन"</string> - <string name="accessibility_action_divider_top_70" msgid="6941226213260515072">"शीर्ष 70%"</string> - <string name="accessibility_action_divider_top_50" msgid="6275211443706497621">"शीर्ष 50%"</string> - <string name="accessibility_action_divider_top_30" msgid="5780597635887574916">"शीर्ष 10"</string> - <string name="accessibility_action_divider_bottom_full" msgid="7352434720610115395">"तळाशी फुल स्क्रीन"</string> <string name="accessibility_qs_edit_tile_label" msgid="9079791448815232967">"स्थिती <xliff:g id="POSITION">%1$d</xliff:g>, <xliff:g id="TILE_NAME">%2$s</xliff:g>. संपादित करण्यासाठी दोनदा टॅप करा."</string> <string name="accessibility_qs_edit_add_tile_label" msgid="8292218072049068613">"<xliff:g id="TILE_NAME">%1$s</xliff:g> . जोडण्यासाठी दोनदा टॅप करा."</string> <string name="accessibility_qs_edit_move_tile" msgid="6027997446473163426">"<xliff:g id="TILE_NAME">%1$s</xliff:g> हलवा"</string> @@ -898,10 +887,6 @@ <string name="accessibility_qs_edit_tile_move" msgid="4841770637244326837">"<xliff:g id="TILE_NAME">%1$s</xliff:g> <xliff:g id="POSITION">%2$d</xliff:g> स्थानावर हलवा"</string> <string name="accessibility_desc_quick_settings_edit" msgid="741658939453595297">"द्रुत सेटिंग्ज संपादक."</string> <string name="accessibility_desc_notification_icon" msgid="7331265967584178674">"<xliff:g id="ID_1">%1$s</xliff:g> सूचना: <xliff:g id="ID_2">%2$s</xliff:g>"</string> - <string name="dock_forced_resizable" msgid="4689301323912928801">"अॅप कदाचित विभाजित-स्क्रीनसह कार्य करू शकत नाही."</string> - <string name="dock_non_resizeble_failed_to_dock_text" msgid="7284915968096153808">"अॅप स्क्रीन-विभाजनास समर्थन देत नाही."</string> - <string name="forced_resizable_secondary_display" msgid="522558907654394940">"दुसऱ्या डिस्प्लेवर अॅप कदाचित चालणार नाही."</string> - <string name="activity_launch_on_secondary_display_failed_text" msgid="8446727617187998208">"दुसऱ्या डिस्प्लेवर अॅप लाँच होणार नाही."</string> <string name="accessibility_quick_settings_settings" msgid="7098489591715844713">"सेटिंग्ज उघडा."</string> <string name="accessibility_quick_settings_expand" msgid="2609275052412521467">"जलद सेटिंग्ज उघडा."</string> <string name="accessibility_quick_settings_collapse" msgid="4674876336725041982">"जलद सेटिंग्ज बंद करा."</string> diff --git a/packages/SystemUI/res/values-ms/strings.xml b/packages/SystemUI/res/values-ms/strings.xml index 0331d26e4ec7..fe246d1a6129 100644 --- a/packages/SystemUI/res/values-ms/strings.xml +++ b/packages/SystemUI/res/values-ms/strings.xml @@ -879,17 +879,6 @@ </string-array> <string name="tuner_low_priority" msgid="8412666814123009820">"Tunjukkan ikon pemberitahuan keutamaan rendah"</string> <string name="other" msgid="429768510980739978">"Lain-lain"</string> - <string name="accessibility_divider" msgid="2830785970889237307">"Pembahagi skrin pisah"</string> - <string name="accessibility_action_divider_left_full" msgid="7598733539422375847">"Skrin penuh kiri"</string> - <string name="accessibility_action_divider_left_70" msgid="4919312892541727761">"Kiri 70%"</string> - <string name="accessibility_action_divider_left_50" msgid="3664701169564893826">"Kiri 50%"</string> - <string name="accessibility_action_divider_left_30" msgid="4358145268046362088">"Kiri 30%"</string> - <string name="accessibility_action_divider_right_full" msgid="8576057422864896305">"Skrin penuh kanan"</string> - <string name="accessibility_action_divider_top_full" msgid="4243901660795169777">"Skrin penuh atas"</string> - <string name="accessibility_action_divider_top_70" msgid="6941226213260515072">"Atas 70%"</string> - <string name="accessibility_action_divider_top_50" msgid="6275211443706497621">"Atas 50%"</string> - <string name="accessibility_action_divider_top_30" msgid="5780597635887574916">"Atas 30%"</string> - <string name="accessibility_action_divider_bottom_full" msgid="7352434720610115395">"Skrin penuh bawah"</string> <string name="accessibility_qs_edit_tile_label" msgid="9079791448815232967">"Kedudukan <xliff:g id="POSITION">%1$d</xliff:g>, <xliff:g id="TILE_NAME">%2$s</xliff:g>. Dwiketik untuk mengedit."</string> <string name="accessibility_qs_edit_add_tile_label" msgid="8292218072049068613">"<xliff:g id="TILE_NAME">%1$s</xliff:g>. Dwiketik untuk menambah."</string> <string name="accessibility_qs_edit_move_tile" msgid="6027997446473163426">"Alihkan <xliff:g id="TILE_NAME">%1$s</xliff:g>"</string> @@ -898,10 +887,6 @@ <string name="accessibility_qs_edit_tile_move" msgid="4841770637244326837">"Alihkan <xliff:g id="TILE_NAME">%1$s</xliff:g> ke kedudukan <xliff:g id="POSITION">%2$d</xliff:g>"</string> <string name="accessibility_desc_quick_settings_edit" msgid="741658939453595297">"Editor tetapan pantas."</string> <string name="accessibility_desc_notification_icon" msgid="7331265967584178674">"Pemberitahuan <xliff:g id="ID_1">%1$s</xliff:g>: <xliff:g id="ID_2">%2$s</xliff:g>"</string> - <string name="dock_forced_resizable" msgid="4689301323912928801">"Apl mungkin tidak berfungsi dengan skrin pisah."</string> - <string name="dock_non_resizeble_failed_to_dock_text" msgid="7284915968096153808">"Apl tidak menyokong skrin pisah."</string> - <string name="forced_resizable_secondary_display" msgid="522558907654394940">"Apl mungkin tidak berfungsi pada paparan kedua."</string> - <string name="activity_launch_on_secondary_display_failed_text" msgid="8446727617187998208">"Apl tidak menyokong pelancaran pada paparan kedua."</string> <string name="accessibility_quick_settings_settings" msgid="7098489591715844713">"Buka tetapan."</string> <string name="accessibility_quick_settings_expand" msgid="2609275052412521467">"Buka tetapan pantas."</string> <string name="accessibility_quick_settings_collapse" msgid="4674876336725041982">"Tutup tetapan pantas."</string> diff --git a/packages/SystemUI/res/values-my/strings.xml b/packages/SystemUI/res/values-my/strings.xml index 83272f2a43c4..53c02a54ef7c 100644 --- a/packages/SystemUI/res/values-my/strings.xml +++ b/packages/SystemUI/res/values-my/strings.xml @@ -879,17 +879,6 @@ </string-array> <string name="tuner_low_priority" msgid="8412666814123009820">"အရေးမကြီးသော အကြောင်းကြားချက် သင်္ကေတများ ပြရန်"</string> <string name="other" msgid="429768510980739978">"အခြား"</string> - <string name="accessibility_divider" msgid="2830785970889237307">"မျက်နှာပြင်ခွဲခြမ်း ပိုင်းခြားပေးသည့်စနစ်"</string> - <string name="accessibility_action_divider_left_full" msgid="7598733539422375847">"ဘယ်ဘက် မျက်နှာပြင်အပြည့်"</string> - <string name="accessibility_action_divider_left_70" msgid="4919312892541727761">"ဘယ်ဘက်မျက်နှာပြင် ၇၀%"</string> - <string name="accessibility_action_divider_left_50" msgid="3664701169564893826">"ဘယ်ဘက် မျက်နှာပြင် ၅၀%"</string> - <string name="accessibility_action_divider_left_30" msgid="4358145268046362088">"ဘယ်ဘက် မျက်နှာပြင် ၃၀%"</string> - <string name="accessibility_action_divider_right_full" msgid="8576057422864896305">"ညာဘက် မျက်နှာပြင်အပြည့်"</string> - <string name="accessibility_action_divider_top_full" msgid="4243901660795169777">"အပေါ်ဘက် မျက်နှာပြင်အပြည့်"</string> - <string name="accessibility_action_divider_top_70" msgid="6941226213260515072">"အပေါ်ဘက် မျက်နှာပြင် ၇၀%"</string> - <string name="accessibility_action_divider_top_50" msgid="6275211443706497621">"အပေါ်ဘက် မျက်နှာပြင် ၅၀%"</string> - <string name="accessibility_action_divider_top_30" msgid="5780597635887574916">"အပေါ်ဘက် မျက်နှာပြင် ၃၀%"</string> - <string name="accessibility_action_divider_bottom_full" msgid="7352434720610115395">"အောက်ခြေ မျက်နှာပြင်အပြည့်"</string> <string name="accessibility_qs_edit_tile_label" msgid="9079791448815232967">"<xliff:g id="POSITION">%1$d</xliff:g>၊ <xliff:g id="TILE_NAME">%2$s</xliff:g> နေရာ။ တည်းဖြတ်ရန် နှစ်ချက်တို့ပါ။"</string> <string name="accessibility_qs_edit_add_tile_label" msgid="8292218072049068613">"<xliff:g id="TILE_NAME">%1$s</xliff:g>။ ပေါင်းထည့်ရန် နှစ်ချက်တို့ပါ။"</string> <string name="accessibility_qs_edit_move_tile" msgid="6027997446473163426">"<xliff:g id="TILE_NAME">%1$s</xliff:g> ကိုရွှေ့ပါ"</string> @@ -898,10 +887,6 @@ <string name="accessibility_qs_edit_tile_move" msgid="4841770637244326837">"<xliff:g id="TILE_NAME">%1$s</xliff:g> ကို အနေအထား <xliff:g id="POSITION">%2$d</xliff:g> သို့ ရွှေ့ရန်"</string> <string name="accessibility_desc_quick_settings_edit" msgid="741658939453595297">"မြန်ဆန်သည့် ဆက်တင်တည်းဖြတ်စနစ်"</string> <string name="accessibility_desc_notification_icon" msgid="7331265967584178674">"<xliff:g id="ID_1">%1$s</xliff:g> အကြောင်းကြားချက် − <xliff:g id="ID_2">%2$s</xliff:g>"</string> - <string name="dock_forced_resizable" msgid="4689301323912928801">"မျက်နှာပြင် ခွဲခြမ်းပြသမှုဖြင့် အက်ပ်သည် အလုပ်လုပ်မည် မဟုတ်ပါ။"</string> - <string name="dock_non_resizeble_failed_to_dock_text" msgid="7284915968096153808">"အက်ပ်သည် မျက်နှာပြင်ခွဲပြရန် ပံ့ပိုးထားခြင်းမရှိပါ။"</string> - <string name="forced_resizable_secondary_display" msgid="522558907654394940">"ဤအက်ပ်အနေဖြင့် ဒုတိယဖန်သားပြင်ပေါ်တွင် အလုပ်လုပ်မည် မဟုတ်ပါ။"</string> - <string name="activity_launch_on_secondary_display_failed_text" msgid="8446727617187998208">"ဤအက်ပ်အနေဖြင့် ဖွင့်ရန်စနစ်ကို ဒုတိယဖန်သားပြင်မှ အသုံးပြုရန် ပံ့ပိုးမထားပါ။"</string> <string name="accessibility_quick_settings_settings" msgid="7098489591715844713">"ဆက်တင်များကို ဖွင့်ပါ။"</string> <string name="accessibility_quick_settings_expand" msgid="2609275052412521467">"အမြန်ဆက်တင်များကို ဖွင့်ပါ။"</string> <string name="accessibility_quick_settings_collapse" msgid="4674876336725041982">"အမြန်ဆက်တင်များကို ပိတ်ပါ။"</string> diff --git a/packages/SystemUI/res/values-nb/strings.xml b/packages/SystemUI/res/values-nb/strings.xml index 01859ef5a13e..5c9f63f3a797 100644 --- a/packages/SystemUI/res/values-nb/strings.xml +++ b/packages/SystemUI/res/values-nb/strings.xml @@ -879,17 +879,6 @@ </string-array> <string name="tuner_low_priority" msgid="8412666814123009820">"Vis ikoner for varsler med lav prioritet"</string> <string name="other" msgid="429768510980739978">"Annet"</string> - <string name="accessibility_divider" msgid="2830785970889237307">"Skilleelement for delt skjerm"</string> - <string name="accessibility_action_divider_left_full" msgid="7598733539422375847">"Utvid den venstre delen av skjermen til hele skjermen"</string> - <string name="accessibility_action_divider_left_70" msgid="4919312892541727761">"Sett størrelsen på den venstre delen av skjermen til 70 %"</string> - <string name="accessibility_action_divider_left_50" msgid="3664701169564893826">"Sett størrelsen på den venstre delen av skjermen til 50 %"</string> - <string name="accessibility_action_divider_left_30" msgid="4358145268046362088">"Sett størrelsen på den venstre delen av skjermen til 30 %"</string> - <string name="accessibility_action_divider_right_full" msgid="8576057422864896305">"Utvid den høyre delen av skjermen til hele skjermen"</string> - <string name="accessibility_action_divider_top_full" msgid="4243901660795169777">"Utvid den øverste delen av skjermen til hele skjermen"</string> - <string name="accessibility_action_divider_top_70" msgid="6941226213260515072">"Sett størrelsen på den øverste delen av skjermen til 70 %"</string> - <string name="accessibility_action_divider_top_50" msgid="6275211443706497621">"Sett størrelsen på den øverste delen av skjermen til 50 %"</string> - <string name="accessibility_action_divider_top_30" msgid="5780597635887574916">"Sett størrelsen på den øverste delen av skjermen til 30 %"</string> - <string name="accessibility_action_divider_bottom_full" msgid="7352434720610115395">"Utvid den nederste delen av skjermen til hele skjermen"</string> <string name="accessibility_qs_edit_tile_label" msgid="9079791448815232967">"Plassering <xliff:g id="POSITION">%1$d</xliff:g>, <xliff:g id="TILE_NAME">%2$s</xliff:g>. Dobbelttrykk for å endre."</string> <string name="accessibility_qs_edit_add_tile_label" msgid="8292218072049068613">"<xliff:g id="TILE_NAME">%1$s</xliff:g>. Dobbelttrykk for å legge til."</string> <string name="accessibility_qs_edit_move_tile" msgid="6027997446473163426">"Flytt <xliff:g id="TILE_NAME">%1$s</xliff:g>"</string> @@ -898,10 +887,6 @@ <string name="accessibility_qs_edit_tile_move" msgid="4841770637244326837">"Flytt <xliff:g id="TILE_NAME">%1$s</xliff:g> til posisjon <xliff:g id="POSITION">%2$d</xliff:g>"</string> <string name="accessibility_desc_quick_settings_edit" msgid="741658939453595297">"Redigeringsvindu for hurtiginnstillinger."</string> <string name="accessibility_desc_notification_icon" msgid="7331265967584178674">"<xliff:g id="ID_1">%1$s</xliff:g>-varsel: <xliff:g id="ID_2">%2$s</xliff:g>"</string> - <string name="dock_forced_resizable" msgid="4689301323912928801">"Det kan hende at appen ikke fungerer med delt skjerm."</string> - <string name="dock_non_resizeble_failed_to_dock_text" msgid="7284915968096153808">"Appen støtter ikke delt skjerm."</string> - <string name="forced_resizable_secondary_display" msgid="522558907654394940">"Appen fungerer kanskje ikke på en sekundær skjerm."</string> - <string name="activity_launch_on_secondary_display_failed_text" msgid="8446727617187998208">"Appen kan ikke kjøres på sekundære skjermer."</string> <string name="accessibility_quick_settings_settings" msgid="7098489591715844713">"Åpne innstillingene."</string> <string name="accessibility_quick_settings_expand" msgid="2609275052412521467">"Åpner hurtiginnstillingene."</string> <string name="accessibility_quick_settings_collapse" msgid="4674876336725041982">"Lukk hurtiginnstillingene."</string> diff --git a/packages/SystemUI/res/values-ne/strings.xml b/packages/SystemUI/res/values-ne/strings.xml index 196b4ad2f94e..791e4d3d3f20 100644 --- a/packages/SystemUI/res/values-ne/strings.xml +++ b/packages/SystemUI/res/values-ne/strings.xml @@ -879,17 +879,6 @@ </string-array> <string name="tuner_low_priority" msgid="8412666814123009820">"कम प्राथमिकताका सूचना आइकनहरू देखाउनुहोस्"</string> <string name="other" msgid="429768510980739978">"अन्य"</string> - <string name="accessibility_divider" msgid="2830785970889237307">"विभाजित-स्क्रिन छुट्याउने"</string> - <string name="accessibility_action_divider_left_full" msgid="7598733539422375847">"बायाँ भाग फुल स्क्रिन"</string> - <string name="accessibility_action_divider_left_70" msgid="4919312892541727761">"बायाँ भाग ७०%"</string> - <string name="accessibility_action_divider_left_50" msgid="3664701169564893826">"बायाँ भाग ५०%"</string> - <string name="accessibility_action_divider_left_30" msgid="4358145268046362088">"बायाँ भाग ३०%"</string> - <string name="accessibility_action_divider_right_full" msgid="8576057422864896305">"दायाँ भाग फुल स्क्रिन"</string> - <string name="accessibility_action_divider_top_full" msgid="4243901660795169777">"माथिल्लो भाग फुल स्क्रिन"</string> - <string name="accessibility_action_divider_top_70" msgid="6941226213260515072">"माथिल्लो भाग ७०%"</string> - <string name="accessibility_action_divider_top_50" msgid="6275211443706497621">"माथिल्लो भाग ५०%"</string> - <string name="accessibility_action_divider_top_30" msgid="5780597635887574916">"माथिल्लो भाग ३०%"</string> - <string name="accessibility_action_divider_bottom_full" msgid="7352434720610115395">"तल्लो भाग फुल स्क्रिन"</string> <string name="accessibility_qs_edit_tile_label" msgid="9079791448815232967">"स्थिति <xliff:g id="POSITION">%1$d</xliff:g>, <xliff:g id="TILE_NAME">%2$s</xliff:g>। सम्पादन गर्नाका लागि डबल ट्याप गर्नुहोस्।"</string> <string name="accessibility_qs_edit_add_tile_label" msgid="8292218072049068613">"<xliff:g id="TILE_NAME">%1$s</xliff:g>। थप्नका लागि डबल ट्याप गर्नुहोस्।"</string> <string name="accessibility_qs_edit_move_tile" msgid="6027997446473163426">"<xliff:g id="TILE_NAME">%1$s</xliff:g> लाई सार्नुहोस्"</string> @@ -898,10 +887,6 @@ <string name="accessibility_qs_edit_tile_move" msgid="4841770637244326837">"<xliff:g id="TILE_NAME">%1$s</xliff:g> लाई <xliff:g id="POSITION">%2$d</xliff:g> स्थितिमा सार्नुहोस्"</string> <string name="accessibility_desc_quick_settings_edit" msgid="741658939453595297">"द्रुत सेटिङ सम्पादक।"</string> <string name="accessibility_desc_notification_icon" msgid="7331265967584178674">"<xliff:g id="ID_1">%1$s</xliff:g> को सूचना: <xliff:g id="ID_2">%2$s</xliff:g>"</string> - <string name="dock_forced_resizable" msgid="4689301323912928801">"अनुप्रयोगले विभाजित-स्क्रिनमा काम नगर्न सक्छ।"</string> - <string name="dock_non_resizeble_failed_to_dock_text" msgid="7284915968096153808">"अनुप्रयोगले विभाजित-स्क्रिनलाई समर्थन गर्दैन।"</string> - <string name="forced_resizable_secondary_display" msgid="522558907654394940">"यो अनुप्रयोगले सहायक प्रदर्शनमा काम नगर्नसक्छ।"</string> - <string name="activity_launch_on_secondary_display_failed_text" msgid="8446727617187998208">"अनुप्रयोगले सहायक प्रदर्शनहरूमा लञ्च सुविधालाई समर्थन गर्दैन।"</string> <string name="accessibility_quick_settings_settings" msgid="7098489591715844713">"सेटिङहरूलाई खोल्नुहोस्।"</string> <string name="accessibility_quick_settings_expand" msgid="2609275052412521467">"द्रुत सेटिङहरूलाई खोल्नुहोस्।"</string> <string name="accessibility_quick_settings_collapse" msgid="4674876336725041982">"द्रुत सेटिङहरूलाई बन्द गर्नुहोस्।"</string> diff --git a/packages/SystemUI/res/values-nl/strings.xml b/packages/SystemUI/res/values-nl/strings.xml index fa028c336594..b02be5d241d7 100644 --- a/packages/SystemUI/res/values-nl/strings.xml +++ b/packages/SystemUI/res/values-nl/strings.xml @@ -879,17 +879,6 @@ </string-array> <string name="tuner_low_priority" msgid="8412666814123009820">"Pictogrammen voor meldingen met lage prioriteit weergeven"</string> <string name="other" msgid="429768510980739978">"Overig"</string> - <string name="accessibility_divider" msgid="2830785970889237307">"Scheiding voor gesplitst scherm"</string> - <string name="accessibility_action_divider_left_full" msgid="7598733539422375847">"Linkerscherm op volledig scherm"</string> - <string name="accessibility_action_divider_left_70" msgid="4919312892541727761">"Linkerscherm 70%"</string> - <string name="accessibility_action_divider_left_50" msgid="3664701169564893826">"Linkerscherm 50%"</string> - <string name="accessibility_action_divider_left_30" msgid="4358145268046362088">"Linkerscherm 30%"</string> - <string name="accessibility_action_divider_right_full" msgid="8576057422864896305">"Rechterscherm op volledig scherm"</string> - <string name="accessibility_action_divider_top_full" msgid="4243901660795169777">"Bovenste scherm op volledig scherm"</string> - <string name="accessibility_action_divider_top_70" msgid="6941226213260515072">"Bovenste scherm 70%"</string> - <string name="accessibility_action_divider_top_50" msgid="6275211443706497621">"Bovenste scherm 50%"</string> - <string name="accessibility_action_divider_top_30" msgid="5780597635887574916">"Bovenste scherm 30%"</string> - <string name="accessibility_action_divider_bottom_full" msgid="7352434720610115395">"Onderste scherm op volledig scherm"</string> <string name="accessibility_qs_edit_tile_label" msgid="9079791448815232967">"Positie <xliff:g id="POSITION">%1$d</xliff:g>, <xliff:g id="TILE_NAME">%2$s</xliff:g>. Dubbeltik om te bewerken."</string> <string name="accessibility_qs_edit_add_tile_label" msgid="8292218072049068613">"<xliff:g id="TILE_NAME">%1$s</xliff:g>. Dubbeltik om toe te voegen."</string> <string name="accessibility_qs_edit_move_tile" msgid="6027997446473163426">"<xliff:g id="TILE_NAME">%1$s</xliff:g> verplaatsen"</string> @@ -898,10 +887,6 @@ <string name="accessibility_qs_edit_tile_move" msgid="4841770637244326837">"<xliff:g id="TILE_NAME">%1$s</xliff:g> verplaatsen naar positie <xliff:g id="POSITION">%2$d</xliff:g>"</string> <string name="accessibility_desc_quick_settings_edit" msgid="741658939453595297">"Editor voor \'Snelle instellingen\'."</string> <string name="accessibility_desc_notification_icon" msgid="7331265967584178674">"<xliff:g id="ID_1">%1$s</xliff:g>-melding: <xliff:g id="ID_2">%2$s</xliff:g>"</string> - <string name="dock_forced_resizable" msgid="4689301323912928801">"App werkt mogelijk niet met gesplitst scherm."</string> - <string name="dock_non_resizeble_failed_to_dock_text" msgid="7284915968096153808">"App biedt geen ondersteuning voor gesplitst scherm."</string> - <string name="forced_resizable_secondary_display" msgid="522558907654394940">"App werkt mogelijk niet op een secundair scherm."</string> - <string name="activity_launch_on_secondary_display_failed_text" msgid="8446727617187998208">"App kan niet op secundaire displays worden gestart."</string> <string name="accessibility_quick_settings_settings" msgid="7098489591715844713">"Instellingen openen."</string> <string name="accessibility_quick_settings_expand" msgid="2609275052412521467">"Snelle instellingen openen."</string> <string name="accessibility_quick_settings_collapse" msgid="4674876336725041982">"Snelle instellingen sluiten."</string> diff --git a/packages/SystemUI/res/values-or/strings.xml b/packages/SystemUI/res/values-or/strings.xml index 4c6ef486436a..c7de8ca38cb2 100644 --- a/packages/SystemUI/res/values-or/strings.xml +++ b/packages/SystemUI/res/values-or/strings.xml @@ -879,17 +879,6 @@ </string-array> <string name="tuner_low_priority" msgid="8412666814123009820">"କମ୍-ଅଗ୍ରାଧିକାର ବିଜ୍ଞପ୍ତି ଆଇକନ୍ ଦେଖାନ୍ତୁ"</string> <string name="other" msgid="429768510980739978">"ଅନ୍ୟାନ୍ୟ"</string> - <string name="accessibility_divider" msgid="2830785970889237307">"ସ୍ପ୍ଲିଟ୍-ସ୍କ୍ରୀନ ବିଭାଜକ"</string> - <string name="accessibility_action_divider_left_full" msgid="7598733539422375847">"ବାମ ପଟକୁ ପୂର୍ଣ୍ଣ ସ୍କ୍ରୀନ୍ କରନ୍ତୁ"</string> - <string name="accessibility_action_divider_left_70" msgid="4919312892541727761">"ବାମ ପଟକୁ 70% କରନ୍ତୁ"</string> - <string name="accessibility_action_divider_left_50" msgid="3664701169564893826">"ବାମ ପଟକୁ 50% କରନ୍ତୁ"</string> - <string name="accessibility_action_divider_left_30" msgid="4358145268046362088">"ବାମ ପଟେ 30%"</string> - <string name="accessibility_action_divider_right_full" msgid="8576057422864896305">"ଡାହାଣ ପଟକୁ ପୂର୍ଣ୍ଣ ସ୍କ୍ରୀନ୍ କରନ୍ତୁ"</string> - <string name="accessibility_action_divider_top_full" msgid="4243901660795169777">"ଉପର ଆଡ଼କୁ ପୂର୍ଣ୍ଣ ସ୍କ୍ରୀନ୍ କରନ୍ତୁ"</string> - <string name="accessibility_action_divider_top_70" msgid="6941226213260515072">"ଉପର ଆଡ଼କୁ 70% କରନ୍ତୁ"</string> - <string name="accessibility_action_divider_top_50" msgid="6275211443706497621">"ଉପର ଆଡ଼କୁ 50% କରନ୍ତୁ"</string> - <string name="accessibility_action_divider_top_30" msgid="5780597635887574916">"ଉପର ଆଡ଼କୁ 30% କରନ୍ତୁ"</string> - <string name="accessibility_action_divider_bottom_full" msgid="7352434720610115395">"ତଳ ଅଂଶର ପୂର୍ଣ୍ଣ ସ୍କ୍ରୀନ୍"</string> <string name="accessibility_qs_edit_tile_label" msgid="9079791448815232967">"ଅବସ୍ଥାନ <xliff:g id="POSITION">%1$d</xliff:g>, <xliff:g id="TILE_NAME">%2$s</xliff:g>। ଏଡିଟ୍ କରିବାକୁ ଡବଲ୍-ଟାପ୍ କରନ୍ତୁ।"</string> <string name="accessibility_qs_edit_add_tile_label" msgid="8292218072049068613">"<xliff:g id="TILE_NAME">%1$s</xliff:g>। ଯୋଡ଼ିବା ପାଇଁ ଡବଲ୍-ଟାପ୍ କରନ୍ତୁ।"</string> <string name="accessibility_qs_edit_move_tile" msgid="6027997446473163426">"<xliff:g id="TILE_NAME">%1$s</xliff:g> ନିଅନ୍ତୁ"</string> @@ -898,10 +887,6 @@ <string name="accessibility_qs_edit_tile_move" msgid="4841770637244326837">"<xliff:g id="POSITION">%2$d</xliff:g> ଅବସ୍ଥାନକୁ <xliff:g id="TILE_NAME">%1$s</xliff:g> ଘୁଞ୍ଚାନ୍ତୁ"</string> <string name="accessibility_desc_quick_settings_edit" msgid="741658939453595297">"ଦ୍ରୁତ ସେଟିଙ୍ଗ ଏଡିଟର୍।"</string> <string name="accessibility_desc_notification_icon" msgid="7331265967584178674">"<xliff:g id="ID_1">%1$s</xliff:g> ବିଜ୍ଞପ୍ତି: <xliff:g id="ID_2">%2$s</xliff:g>"</string> - <string name="dock_forced_resizable" msgid="4689301323912928801">"ସ୍ପ୍ଲିଟ୍-ସ୍କ୍ରୀନରେ ଆପ୍ କାମ କରିନପାରେ।"</string> - <string name="dock_non_resizeble_failed_to_dock_text" msgid="7284915968096153808">"ଆପ୍ ସ୍ପ୍ଲିଟ୍-ସ୍କ୍ରୀନକୁ ସପୋର୍ଟ କରେ ନାହିଁ।"</string> - <string name="forced_resizable_secondary_display" msgid="522558907654394940">"ସେକେଣ୍ଡାରୀ ଡିସପ୍ଲେରେ ଆପ୍ କାମ ନକରିପାରେ।"</string> - <string name="activity_launch_on_secondary_display_failed_text" msgid="8446727617187998208">"ସେକେଣ୍ଡାରୀ ଡିସପ୍ଲେରେ ଆପ୍ ଲଞ୍ଚ ସପୋର୍ଟ କରେ ନାହିଁ।"</string> <string name="accessibility_quick_settings_settings" msgid="7098489591715844713">"ସେଟିଂସ୍ ଖୋଲନ୍ତୁ।"</string> <string name="accessibility_quick_settings_expand" msgid="2609275052412521467">"ଦ୍ରୁତ ସେଟିଙ୍ଗ ଖୋଲନ୍ତୁ।"</string> <string name="accessibility_quick_settings_collapse" msgid="4674876336725041982">"ଦ୍ରୁତ ସେଟିଂସ୍ ବନ୍ଦ କରନ୍ତୁ।"</string> diff --git a/packages/SystemUI/res/values-pa/strings.xml b/packages/SystemUI/res/values-pa/strings.xml index 98583c0aedca..66333b9e09fe 100644 --- a/packages/SystemUI/res/values-pa/strings.xml +++ b/packages/SystemUI/res/values-pa/strings.xml @@ -879,17 +879,6 @@ </string-array> <string name="tuner_low_priority" msgid="8412666814123009820">"ਘੱਟ ਤਰਜੀਹ ਵਾਲੇ ਸੂਚਨਾ ਪ੍ਰਤੀਕਾਂ ਨੂੰ ਦਿਖਾਓ"</string> <string name="other" msgid="429768510980739978">"ਹੋਰ"</string> - <string name="accessibility_divider" msgid="2830785970889237307">"ਸਪਲਿਟ-ਸਕ੍ਰੀਨ ਡਿਵਾਈਡਰ"</string> - <string name="accessibility_action_divider_left_full" msgid="7598733539422375847">"ਖੱਬੇ ਪੂਰੀ ਸਕ੍ਰੀਨ"</string> - <string name="accessibility_action_divider_left_70" msgid="4919312892541727761">"ਖੱਬੇ 70%"</string> - <string name="accessibility_action_divider_left_50" msgid="3664701169564893826">"ਖੱਬੇ 50%"</string> - <string name="accessibility_action_divider_left_30" msgid="4358145268046362088">"ਖੱਬੇ 30%"</string> - <string name="accessibility_action_divider_right_full" msgid="8576057422864896305">"ਸੱਜੇ ਪੂਰੀ ਸਕ੍ਰੀਨ"</string> - <string name="accessibility_action_divider_top_full" msgid="4243901660795169777">"ਉੱਪਰ ਪੂਰੀ ਸਕ੍ਰੀਨ"</string> - <string name="accessibility_action_divider_top_70" msgid="6941226213260515072">"ਉੱਪਰ 70%"</string> - <string name="accessibility_action_divider_top_50" msgid="6275211443706497621">"ਉੱਪਰ 50%"</string> - <string name="accessibility_action_divider_top_30" msgid="5780597635887574916">"ਉੱਪਰ 30%"</string> - <string name="accessibility_action_divider_bottom_full" msgid="7352434720610115395">"ਹੇਠਾਂ ਪੂਰੀ ਸਕ੍ਰੀਨ"</string> <string name="accessibility_qs_edit_tile_label" msgid="9079791448815232967">"ਸਥਿਤੀ <xliff:g id="POSITION">%1$d</xliff:g>, <xliff:g id="TILE_NAME">%2$s</xliff:g>। ਸੰਪਾਦਨ ਲਈ ਦੋ ਵਾਰ ਟੈਪ ਕਰੋ।"</string> <string name="accessibility_qs_edit_add_tile_label" msgid="8292218072049068613">"<xliff:g id="TILE_NAME">%1$s</xliff:g>। ਸ਼ਾਮਲ ਕਰਨ ਲਈ ਦੋ ਵਾਰ ਟੈਪ ਕਰੋ।"</string> <string name="accessibility_qs_edit_move_tile" msgid="6027997446473163426">"<xliff:g id="TILE_NAME">%1$s</xliff:g> ਨੂੰ ਤਬਦੀਲ ਕਰੋ"</string> @@ -898,10 +887,6 @@ <string name="accessibility_qs_edit_tile_move" msgid="4841770637244326837">"<xliff:g id="TILE_NAME">%1$s</xliff:g> ਨੂੰ <xliff:g id="POSITION">%2$d</xliff:g> ਸਥਾਨ \'ਤੇ ਲਿਜਾਓ"</string> <string name="accessibility_desc_quick_settings_edit" msgid="741658939453595297">"ਤਤਕਾਲ ਸੈਟਿੰਗਾਂ ਸੰਪਾਦਕ।"</string> <string name="accessibility_desc_notification_icon" msgid="7331265967584178674">"<xliff:g id="ID_1">%1$s</xliff:g> ਸੂਚਨਾ: <xliff:g id="ID_2">%2$s</xliff:g>"</string> - <string name="dock_forced_resizable" msgid="4689301323912928801">"ਹੋ ਸਕਦਾ ਹੈ ਕਿ ਐਪ ਸਪਲਿਟ-ਸਕ੍ਰੀਨ ਨਾਲ ਕੰਮ ਨਾ ਕਰੇ।"</string> - <string name="dock_non_resizeble_failed_to_dock_text" msgid="7284915968096153808">"ਐਪ ਸਪਲਿਟ-ਸਕ੍ਰੀਨ ਨੂੰ ਸਮਰਥਨ ਨਹੀਂ ਕਰਦੀ।"</string> - <string name="forced_resizable_secondary_display" msgid="522558907654394940">"ਹੋ ਸਕਦਾ ਹੈ ਕਿ ਐਪ ਸੈਕੰਡਰੀ ਡਿਸਪਲੇ \'ਤੇ ਕੰਮ ਨਾ ਕਰੇ।"</string> - <string name="activity_launch_on_secondary_display_failed_text" msgid="8446727617187998208">"ਐਪ ਸੈਕੰਡਰੀ ਡਿਸਪਲੇਆਂ \'ਤੇ ਲਾਂਚ ਕਰਨ ਦਾ ਸਮਰਥਨ ਨਹੀਂ ਕਰਦੀ"</string> <string name="accessibility_quick_settings_settings" msgid="7098489591715844713">"ਸੈਟਿੰਗਾਂ ਖੋਲ੍ਹੋ।"</string> <string name="accessibility_quick_settings_expand" msgid="2609275052412521467">"ਤਤਕਾਲ ਸੈਟਿੰਗਾਂ ਨੂੰ ਖੋਲ੍ਹੋ।"</string> <string name="accessibility_quick_settings_collapse" msgid="4674876336725041982">"ਤਤਕਾਲ ਸੈਟਿੰਗਾਂ ਨੂੰ ਬੰਦ ਕਰੋ।"</string> diff --git a/packages/SystemUI/res/values-pl/strings.xml b/packages/SystemUI/res/values-pl/strings.xml index 4d5a2ae88949..c68e3ac46932 100644 --- a/packages/SystemUI/res/values-pl/strings.xml +++ b/packages/SystemUI/res/values-pl/strings.xml @@ -889,17 +889,6 @@ </string-array> <string name="tuner_low_priority" msgid="8412666814123009820">"Pokazuj ikony powiadomień o niskim priorytecie"</string> <string name="other" msgid="429768510980739978">"Inne"</string> - <string name="accessibility_divider" msgid="2830785970889237307">"Linia dzielenia ekranu"</string> - <string name="accessibility_action_divider_left_full" msgid="7598733539422375847">"Lewa część ekranu na pełnym ekranie"</string> - <string name="accessibility_action_divider_left_70" msgid="4919312892541727761">"70% lewej części ekranu"</string> - <string name="accessibility_action_divider_left_50" msgid="3664701169564893826">"50% lewej części ekranu"</string> - <string name="accessibility_action_divider_left_30" msgid="4358145268046362088">"30% lewej części ekranu"</string> - <string name="accessibility_action_divider_right_full" msgid="8576057422864896305">"Prawa część ekranu na pełnym ekranie"</string> - <string name="accessibility_action_divider_top_full" msgid="4243901660795169777">"Górna część ekranu na pełnym ekranie"</string> - <string name="accessibility_action_divider_top_70" msgid="6941226213260515072">"70% górnej części ekranu"</string> - <string name="accessibility_action_divider_top_50" msgid="6275211443706497621">"50% górnej części ekranu"</string> - <string name="accessibility_action_divider_top_30" msgid="5780597635887574916">"30% górnej części ekranu"</string> - <string name="accessibility_action_divider_bottom_full" msgid="7352434720610115395">"Dolna część ekranu na pełnym ekranie"</string> <string name="accessibility_qs_edit_tile_label" msgid="9079791448815232967">"Położenie <xliff:g id="POSITION">%1$d</xliff:g>, kafelek <xliff:g id="TILE_NAME">%2$s</xliff:g>. Kliknij dwukrotnie, by edytować."</string> <string name="accessibility_qs_edit_add_tile_label" msgid="8292218072049068613">"Kafelek <xliff:g id="TILE_NAME">%1$s</xliff:g>. Kliknij dwukrotnie, by dodać."</string> <string name="accessibility_qs_edit_move_tile" msgid="6027997446473163426">"Przenieś kafelek <xliff:g id="TILE_NAME">%1$s</xliff:g>"</string> @@ -908,10 +897,6 @@ <string name="accessibility_qs_edit_tile_move" msgid="4841770637244326837">"Przenieś kafelek <xliff:g id="TILE_NAME">%1$s</xliff:g> w położenie <xliff:g id="POSITION">%2$d</xliff:g>"</string> <string name="accessibility_desc_quick_settings_edit" msgid="741658939453595297">"Edytor szybkich ustawień."</string> <string name="accessibility_desc_notification_icon" msgid="7331265967584178674">"Powiadomienie z aplikacji <xliff:g id="ID_1">%1$s</xliff:g>: <xliff:g id="ID_2">%2$s</xliff:g>"</string> - <string name="dock_forced_resizable" msgid="4689301323912928801">"Aplikacja może nie działać przy podzielonym ekranie."</string> - <string name="dock_non_resizeble_failed_to_dock_text" msgid="7284915968096153808">"Aplikacja nie obsługuje dzielonego ekranu."</string> - <string name="forced_resizable_secondary_display" msgid="522558907654394940">"Aplikacja może nie działać na dodatkowym ekranie."</string> - <string name="activity_launch_on_secondary_display_failed_text" msgid="8446727617187998208">"Aplikacja nie obsługuje uruchamiania na dodatkowych ekranach."</string> <string name="accessibility_quick_settings_settings" msgid="7098489591715844713">"Otwórz ustawienia."</string> <string name="accessibility_quick_settings_expand" msgid="2609275052412521467">"Otwórz szybkie ustawienia."</string> <string name="accessibility_quick_settings_collapse" msgid="4674876336725041982">"Zamknij szybkie ustawienia."</string> @@ -1016,7 +1001,7 @@ <string name="bubble_accessibility_action_move_bottom_left" msgid="6339015902495504715">"Przenieś w lewy dolny róg"</string> <string name="bubble_accessibility_action_move_bottom_right" msgid="7471571700628346212">"Przenieś w prawy dolny róg"</string> <string name="bubble_dismiss_text" msgid="1314082410868930066">"Zamknij dymek"</string> - <string name="bubbles_dont_bubble_conversation" msgid="1033040343437428822">"Nie wyświetlaj rozmowy jako dymku"</string> + <string name="bubbles_dont_bubble_conversation" msgid="1033040343437428822">"Nie wyświetlaj rozmowy jako dymka"</string> <string name="bubbles_user_education_title" msgid="5547017089271445797">"Czatuj, korzystając z dymków"</string> <string name="bubbles_user_education_description" msgid="1160281719576715211">"Nowe rozmowy będą wyświetlane jako pływające ikony lub dymki. Kliknij, by otworzyć dymek. Przeciągnij, by go przenieść."</string> <string name="bubbles_user_education_manage_title" msgid="2848511858160342320">"Zarządzaj dymkami w dowolnym momencie"</string> diff --git a/packages/SystemUI/res/values-pt-rBR/strings.xml b/packages/SystemUI/res/values-pt-rBR/strings.xml index ef5c9cee6ee4..ff2ecd38547f 100644 --- a/packages/SystemUI/res/values-pt-rBR/strings.xml +++ b/packages/SystemUI/res/values-pt-rBR/strings.xml @@ -879,17 +879,6 @@ </string-array> <string name="tuner_low_priority" msgid="8412666814123009820">"Mostrar ícones de notificações de baixa prioridade"</string> <string name="other" msgid="429768510980739978">"Outros"</string> - <string name="accessibility_divider" msgid="2830785970889237307">"Divisor de tela"</string> - <string name="accessibility_action_divider_left_full" msgid="7598733539422375847">"Lado esquerdo em tela cheia"</string> - <string name="accessibility_action_divider_left_70" msgid="4919312892541727761">"Esquerda a 70%"</string> - <string name="accessibility_action_divider_left_50" msgid="3664701169564893826">"Esquerda a 50%"</string> - <string name="accessibility_action_divider_left_30" msgid="4358145268046362088">"Esquerda a 30%"</string> - <string name="accessibility_action_divider_right_full" msgid="8576057422864896305">"Lado direito em tela cheia"</string> - <string name="accessibility_action_divider_top_full" msgid="4243901660795169777">"Parte superior em tela cheia"</string> - <string name="accessibility_action_divider_top_70" msgid="6941226213260515072">"Parte superior a 70%"</string> - <string name="accessibility_action_divider_top_50" msgid="6275211443706497621">"Parte superior a 50%"</string> - <string name="accessibility_action_divider_top_30" msgid="5780597635887574916">"Parte superior a 30%"</string> - <string name="accessibility_action_divider_bottom_full" msgid="7352434720610115395">"Parte inferior em tela cheia"</string> <string name="accessibility_qs_edit_tile_label" msgid="9079791448815232967">"Posição <xliff:g id="POSITION">%1$d</xliff:g>, <xliff:g id="TILE_NAME">%2$s</xliff:g>. Toque duas vezes para editar."</string> <string name="accessibility_qs_edit_add_tile_label" msgid="8292218072049068613">"<xliff:g id="TILE_NAME">%1$s</xliff:g>. Toque duas vezes para adicionar."</string> <string name="accessibility_qs_edit_move_tile" msgid="6027997446473163426">"Move <xliff:g id="TILE_NAME">%1$s</xliff:g>"</string> @@ -898,10 +887,6 @@ <string name="accessibility_qs_edit_tile_move" msgid="4841770637244326837">"Mover <xliff:g id="TILE_NAME">%1$s</xliff:g> para a posição <xliff:g id="POSITION">%2$d</xliff:g>"</string> <string name="accessibility_desc_quick_settings_edit" msgid="741658939453595297">"Editor de configurações rápidas."</string> <string name="accessibility_desc_notification_icon" msgid="7331265967584178674">"Notificação do <xliff:g id="ID_1">%1$s</xliff:g>: <xliff:g id="ID_2">%2$s</xliff:g>"</string> - <string name="dock_forced_resizable" msgid="4689301323912928801">"É possível que o app não funcione com o recurso de divisão de tela."</string> - <string name="dock_non_resizeble_failed_to_dock_text" msgid="7284915968096153808">"O app não é compatível com a divisão de tela."</string> - <string name="forced_resizable_secondary_display" msgid="522558907654394940">"É possível que o app não funcione em uma tela secundária."</string> - <string name="activity_launch_on_secondary_display_failed_text" msgid="8446727617187998208">"O app não é compatível com a inicialização em telas secundárias."</string> <string name="accessibility_quick_settings_settings" msgid="7098489591715844713">"Abrir configurações."</string> <string name="accessibility_quick_settings_expand" msgid="2609275052412521467">"Abrir as configurações rápidas."</string> <string name="accessibility_quick_settings_collapse" msgid="4674876336725041982">"Fechar as configurações rápidas."</string> diff --git a/packages/SystemUI/res/values-pt-rPT/strings.xml b/packages/SystemUI/res/values-pt-rPT/strings.xml index 541f12c32e02..c39a5eb54868 100644 --- a/packages/SystemUI/res/values-pt-rPT/strings.xml +++ b/packages/SystemUI/res/values-pt-rPT/strings.xml @@ -879,17 +879,6 @@ </string-array> <string name="tuner_low_priority" msgid="8412666814123009820">"Mostrar ícones de notificações de prioridade baixa"</string> <string name="other" msgid="429768510980739978">"Outro"</string> - <string name="accessibility_divider" msgid="2830785970889237307">"Divisor do ecrã dividido"</string> - <string name="accessibility_action_divider_left_full" msgid="7598733539422375847">"Ecrã esquerdo inteiro"</string> - <string name="accessibility_action_divider_left_70" msgid="4919312892541727761">"70% no ecrã esquerdo"</string> - <string name="accessibility_action_divider_left_50" msgid="3664701169564893826">"50% no ecrã esquerdo"</string> - <string name="accessibility_action_divider_left_30" msgid="4358145268046362088">"30% no ecrã esquerdo"</string> - <string name="accessibility_action_divider_right_full" msgid="8576057422864896305">"Ecrã direito inteiro"</string> - <string name="accessibility_action_divider_top_full" msgid="4243901660795169777">"Ecrã superior inteiro"</string> - <string name="accessibility_action_divider_top_70" msgid="6941226213260515072">"70% no ecrã superior"</string> - <string name="accessibility_action_divider_top_50" msgid="6275211443706497621">"50% no ecrã superior"</string> - <string name="accessibility_action_divider_top_30" msgid="5780597635887574916">"30% no ecrã superior"</string> - <string name="accessibility_action_divider_bottom_full" msgid="7352434720610115395">"Ecrã inferior inteiro"</string> <string name="accessibility_qs_edit_tile_label" msgid="9079791448815232967">"Posição <xliff:g id="POSITION">%1$d</xliff:g>, <xliff:g id="TILE_NAME">%2$s</xliff:g>. Toque duas vezes para editar."</string> <string name="accessibility_qs_edit_add_tile_label" msgid="8292218072049068613">"<xliff:g id="TILE_NAME">%1$s</xliff:g>. Toque duas vezes para adicionar."</string> <string name="accessibility_qs_edit_move_tile" msgid="6027997446473163426">"Mover <xliff:g id="TILE_NAME">%1$s</xliff:g>"</string> @@ -898,10 +887,6 @@ <string name="accessibility_qs_edit_tile_move" msgid="4841770637244326837">"Mover <xliff:g id="TILE_NAME">%1$s</xliff:g> para a posição <xliff:g id="POSITION">%2$d</xliff:g>"</string> <string name="accessibility_desc_quick_settings_edit" msgid="741658939453595297">"Editor de definições rápidas."</string> <string name="accessibility_desc_notification_icon" msgid="7331265967584178674">"Notificação do <xliff:g id="ID_1">%1$s</xliff:g>: <xliff:g id="ID_2">%2$s</xliff:g>"</string> - <string name="dock_forced_resizable" msgid="4689301323912928801">"A app pode não funcionar com o ecrã dividido."</string> - <string name="dock_non_resizeble_failed_to_dock_text" msgid="7284915968096153808">"A app não é compatível com o ecrã dividido."</string> - <string name="forced_resizable_secondary_display" msgid="522558907654394940">"A app pode não funcionar num ecrã secundário."</string> - <string name="activity_launch_on_secondary_display_failed_text" msgid="8446727617187998208">"A app não é compatível com o início em ecrãs secundários."</string> <string name="accessibility_quick_settings_settings" msgid="7098489591715844713">"Abrir as definições."</string> <string name="accessibility_quick_settings_expand" msgid="2609275052412521467">"Abrir as definições rápidas."</string> <string name="accessibility_quick_settings_collapse" msgid="4674876336725041982">"Fechar as definições rápidas."</string> diff --git a/packages/SystemUI/res/values-pt/strings.xml b/packages/SystemUI/res/values-pt/strings.xml index ef5c9cee6ee4..ff2ecd38547f 100644 --- a/packages/SystemUI/res/values-pt/strings.xml +++ b/packages/SystemUI/res/values-pt/strings.xml @@ -879,17 +879,6 @@ </string-array> <string name="tuner_low_priority" msgid="8412666814123009820">"Mostrar ícones de notificações de baixa prioridade"</string> <string name="other" msgid="429768510980739978">"Outros"</string> - <string name="accessibility_divider" msgid="2830785970889237307">"Divisor de tela"</string> - <string name="accessibility_action_divider_left_full" msgid="7598733539422375847">"Lado esquerdo em tela cheia"</string> - <string name="accessibility_action_divider_left_70" msgid="4919312892541727761">"Esquerda a 70%"</string> - <string name="accessibility_action_divider_left_50" msgid="3664701169564893826">"Esquerda a 50%"</string> - <string name="accessibility_action_divider_left_30" msgid="4358145268046362088">"Esquerda a 30%"</string> - <string name="accessibility_action_divider_right_full" msgid="8576057422864896305">"Lado direito em tela cheia"</string> - <string name="accessibility_action_divider_top_full" msgid="4243901660795169777">"Parte superior em tela cheia"</string> - <string name="accessibility_action_divider_top_70" msgid="6941226213260515072">"Parte superior a 70%"</string> - <string name="accessibility_action_divider_top_50" msgid="6275211443706497621">"Parte superior a 50%"</string> - <string name="accessibility_action_divider_top_30" msgid="5780597635887574916">"Parte superior a 30%"</string> - <string name="accessibility_action_divider_bottom_full" msgid="7352434720610115395">"Parte inferior em tela cheia"</string> <string name="accessibility_qs_edit_tile_label" msgid="9079791448815232967">"Posição <xliff:g id="POSITION">%1$d</xliff:g>, <xliff:g id="TILE_NAME">%2$s</xliff:g>. Toque duas vezes para editar."</string> <string name="accessibility_qs_edit_add_tile_label" msgid="8292218072049068613">"<xliff:g id="TILE_NAME">%1$s</xliff:g>. Toque duas vezes para adicionar."</string> <string name="accessibility_qs_edit_move_tile" msgid="6027997446473163426">"Move <xliff:g id="TILE_NAME">%1$s</xliff:g>"</string> @@ -898,10 +887,6 @@ <string name="accessibility_qs_edit_tile_move" msgid="4841770637244326837">"Mover <xliff:g id="TILE_NAME">%1$s</xliff:g> para a posição <xliff:g id="POSITION">%2$d</xliff:g>"</string> <string name="accessibility_desc_quick_settings_edit" msgid="741658939453595297">"Editor de configurações rápidas."</string> <string name="accessibility_desc_notification_icon" msgid="7331265967584178674">"Notificação do <xliff:g id="ID_1">%1$s</xliff:g>: <xliff:g id="ID_2">%2$s</xliff:g>"</string> - <string name="dock_forced_resizable" msgid="4689301323912928801">"É possível que o app não funcione com o recurso de divisão de tela."</string> - <string name="dock_non_resizeble_failed_to_dock_text" msgid="7284915968096153808">"O app não é compatível com a divisão de tela."</string> - <string name="forced_resizable_secondary_display" msgid="522558907654394940">"É possível que o app não funcione em uma tela secundária."</string> - <string name="activity_launch_on_secondary_display_failed_text" msgid="8446727617187998208">"O app não é compatível com a inicialização em telas secundárias."</string> <string name="accessibility_quick_settings_settings" msgid="7098489591715844713">"Abrir configurações."</string> <string name="accessibility_quick_settings_expand" msgid="2609275052412521467">"Abrir as configurações rápidas."</string> <string name="accessibility_quick_settings_collapse" msgid="4674876336725041982">"Fechar as configurações rápidas."</string> diff --git a/packages/SystemUI/res/values-ro/strings.xml b/packages/SystemUI/res/values-ro/strings.xml index 3e2373deb67d..b793bcd33e4c 100644 --- a/packages/SystemUI/res/values-ro/strings.xml +++ b/packages/SystemUI/res/values-ro/strings.xml @@ -884,17 +884,6 @@ </string-array> <string name="tuner_low_priority" msgid="8412666814123009820">"Afișați pictogramele de notificare cu prioritate redusă"</string> <string name="other" msgid="429768510980739978">"Altele"</string> - <string name="accessibility_divider" msgid="2830785970889237307">"Separator pentru ecranul împărțit"</string> - <string name="accessibility_action_divider_left_full" msgid="7598733539422375847">"Partea stângă pe ecran complet"</string> - <string name="accessibility_action_divider_left_70" msgid="4919312892541727761">"Partea stângă: 70%"</string> - <string name="accessibility_action_divider_left_50" msgid="3664701169564893826">"Partea stângă: 50%"</string> - <string name="accessibility_action_divider_left_30" msgid="4358145268046362088">"Partea stângă: 30%"</string> - <string name="accessibility_action_divider_right_full" msgid="8576057422864896305">"Partea dreaptă pe ecran complet"</string> - <string name="accessibility_action_divider_top_full" msgid="4243901660795169777">"Partea de sus pe ecran complet"</string> - <string name="accessibility_action_divider_top_70" msgid="6941226213260515072">"Partea de sus: 70%"</string> - <string name="accessibility_action_divider_top_50" msgid="6275211443706497621">"Partea de sus: 50%"</string> - <string name="accessibility_action_divider_top_30" msgid="5780597635887574916">"Partea de sus: 30%"</string> - <string name="accessibility_action_divider_bottom_full" msgid="7352434720610115395">"Partea de jos pe ecran complet"</string> <string name="accessibility_qs_edit_tile_label" msgid="9079791448815232967">"Poziția <xliff:g id="POSITION">%1$d</xliff:g>, <xliff:g id="TILE_NAME">%2$s</xliff:g>. Atingeți de două ori pentru a edita."</string> <string name="accessibility_qs_edit_add_tile_label" msgid="8292218072049068613">"<xliff:g id="TILE_NAME">%1$s</xliff:g>. Atingeți de două ori pentru a adăuga."</string> <string name="accessibility_qs_edit_move_tile" msgid="6027997446473163426">"Mutați <xliff:g id="TILE_NAME">%1$s</xliff:g>"</string> @@ -903,10 +892,6 @@ <string name="accessibility_qs_edit_tile_move" msgid="4841770637244326837">"Mutați <xliff:g id="TILE_NAME">%1$s</xliff:g> pe poziția <xliff:g id="POSITION">%2$d</xliff:g>"</string> <string name="accessibility_desc_quick_settings_edit" msgid="741658939453595297">"Editorul pentru setări rapide."</string> <string name="accessibility_desc_notification_icon" msgid="7331265967584178674">"Notificare <xliff:g id="ID_1">%1$s</xliff:g>: <xliff:g id="ID_2">%2$s</xliff:g>"</string> - <string name="dock_forced_resizable" msgid="4689301323912928801">"Este posibil ca aplicația să nu funcționeze cu ecranul împărțit."</string> - <string name="dock_non_resizeble_failed_to_dock_text" msgid="7284915968096153808">"Aplicația nu acceptă ecranul împărțit."</string> - <string name="forced_resizable_secondary_display" msgid="522558907654394940">"Este posibil ca aplicația să nu funcționeze pe un ecran secundar."</string> - <string name="activity_launch_on_secondary_display_failed_text" msgid="8446727617187998208">"Aplicația nu acceptă lansare pe ecrane secundare."</string> <string name="accessibility_quick_settings_settings" msgid="7098489591715844713">"Deschideți setările."</string> <string name="accessibility_quick_settings_expand" msgid="2609275052412521467">"Deschideți setările rapide."</string> <string name="accessibility_quick_settings_collapse" msgid="4674876336725041982">"Închideți setările rapide."</string> diff --git a/packages/SystemUI/res/values-ru/strings.xml b/packages/SystemUI/res/values-ru/strings.xml index 7747724eab80..7560f5309824 100644 --- a/packages/SystemUI/res/values-ru/strings.xml +++ b/packages/SystemUI/res/values-ru/strings.xml @@ -889,17 +889,6 @@ </string-array> <string name="tuner_low_priority" msgid="8412666814123009820">"Показывать значки уведомлений с низким приоритетом"</string> <string name="other" msgid="429768510980739978">"Другое"</string> - <string name="accessibility_divider" msgid="2830785970889237307">"Разделитель экрана"</string> - <string name="accessibility_action_divider_left_full" msgid="7598733539422375847">"Левый во весь экран"</string> - <string name="accessibility_action_divider_left_70" msgid="4919312892541727761">"Левый на 70%"</string> - <string name="accessibility_action_divider_left_50" msgid="3664701169564893826">"Левый на 50%"</string> - <string name="accessibility_action_divider_left_30" msgid="4358145268046362088">"Левый на 30%"</string> - <string name="accessibility_action_divider_right_full" msgid="8576057422864896305">"Правый во весь экран"</string> - <string name="accessibility_action_divider_top_full" msgid="4243901660795169777">"Верхний во весь экран"</string> - <string name="accessibility_action_divider_top_70" msgid="6941226213260515072">"Верхний на 70%"</string> - <string name="accessibility_action_divider_top_50" msgid="6275211443706497621">"Верхний на 50%"</string> - <string name="accessibility_action_divider_top_30" msgid="5780597635887574916">"Верхний на 30%"</string> - <string name="accessibility_action_divider_bottom_full" msgid="7352434720610115395">"Нижний во весь экран"</string> <string name="accessibility_qs_edit_tile_label" msgid="9079791448815232967">"Позиция <xliff:g id="POSITION">%1$d</xliff:g>, кнопка \"<xliff:g id="TILE_NAME">%2$s</xliff:g>\". Чтобы изменить, нажмите дважды."</string> <string name="accessibility_qs_edit_add_tile_label" msgid="8292218072049068613">"Кнопка \"<xliff:g id="TILE_NAME">%1$s</xliff:g>\". Чтобы добавить, нажмите дважды."</string> <string name="accessibility_qs_edit_move_tile" msgid="6027997446473163426">"Переместить кнопку \"<xliff:g id="TILE_NAME">%1$s</xliff:g>\""</string> @@ -908,10 +897,6 @@ <string name="accessibility_qs_edit_tile_move" msgid="4841770637244326837">"Переместить значок <xliff:g id="TILE_NAME">%1$s</xliff:g> на позицию <xliff:g id="POSITION">%2$d</xliff:g>"</string> <string name="accessibility_desc_quick_settings_edit" msgid="741658939453595297">"Редактор быстрых настроек."</string> <string name="accessibility_desc_notification_icon" msgid="7331265967584178674">"Уведомление <xliff:g id="ID_1">%1$s</xliff:g>: <xliff:g id="ID_2">%2$s</xliff:g>"</string> - <string name="dock_forced_resizable" msgid="4689301323912928801">"Приложение не поддерживает разделение экрана."</string> - <string name="dock_non_resizeble_failed_to_dock_text" msgid="7284915968096153808">"Приложение не поддерживает разделение экрана."</string> - <string name="forced_resizable_secondary_display" msgid="522558907654394940">"Приложение может не работать на дополнительном экране"</string> - <string name="activity_launch_on_secondary_display_failed_text" msgid="8446727617187998208">"Приложение не поддерживает запуск на дополнительных экранах"</string> <string name="accessibility_quick_settings_settings" msgid="7098489591715844713">"Открыть настройки."</string> <string name="accessibility_quick_settings_expand" msgid="2609275052412521467">"Развернуть быстрые настройки."</string> <string name="accessibility_quick_settings_collapse" msgid="4674876336725041982">"Скрыть быстрые настройки."</string> diff --git a/packages/SystemUI/res/values-si/strings.xml b/packages/SystemUI/res/values-si/strings.xml index b8813f2ef53c..02f9c23cecf9 100644 --- a/packages/SystemUI/res/values-si/strings.xml +++ b/packages/SystemUI/res/values-si/strings.xml @@ -879,17 +879,6 @@ </string-array> <string name="tuner_low_priority" msgid="8412666814123009820">"අඩු ප්රමුඛතා දැනුම්දීම් අයිකන පෙන්වන්න"</string> <string name="other" msgid="429768510980739978">"වෙනත්"</string> - <string name="accessibility_divider" msgid="2830785970889237307">"බෙදුම්-තිර වෙන්කරණය"</string> - <string name="accessibility_action_divider_left_full" msgid="7598733539422375847">"වම් පූර්ණ තිරය"</string> - <string name="accessibility_action_divider_left_70" msgid="4919312892541727761">"වම් 70%"</string> - <string name="accessibility_action_divider_left_50" msgid="3664701169564893826">"වම් 50%"</string> - <string name="accessibility_action_divider_left_30" msgid="4358145268046362088">"වම් 30%"</string> - <string name="accessibility_action_divider_right_full" msgid="8576057422864896305">"දකුණු පූර්ණ තිරය"</string> - <string name="accessibility_action_divider_top_full" msgid="4243901660795169777">"ඉහළම පූර්ණ තිරය"</string> - <string name="accessibility_action_divider_top_70" msgid="6941226213260515072">"ඉහළම 70%"</string> - <string name="accessibility_action_divider_top_50" msgid="6275211443706497621">"ඉහළම 50%"</string> - <string name="accessibility_action_divider_top_30" msgid="5780597635887574916">"ඉහළම 30%"</string> - <string name="accessibility_action_divider_bottom_full" msgid="7352434720610115395">"පහළ පූර්ණ තිරය"</string> <string name="accessibility_qs_edit_tile_label" msgid="9079791448815232967">"ස්ථානය <xliff:g id="POSITION">%1$d</xliff:g>, <xliff:g id="TILE_NAME">%2$s</xliff:g>. වෙනස් කිරීමට දෙවරක් තට්ටු කරන්න."</string> <string name="accessibility_qs_edit_add_tile_label" msgid="8292218072049068613">"<xliff:g id="TILE_NAME">%1$s</xliff:g>. එක් කිරීමට දෙවරක් තට්ටු කරන්න."</string> <string name="accessibility_qs_edit_move_tile" msgid="6027997446473163426">"<xliff:g id="TILE_NAME">%1$s</xliff:g> ගෙන යන්න"</string> @@ -898,10 +887,6 @@ <string name="accessibility_qs_edit_tile_move" msgid="4841770637244326837">"<xliff:g id="TILE_NAME">%1$s</xliff:g> තත්ත්වයට <xliff:g id="POSITION">%2$d</xliff:g> ගෙන යන්න"</string> <string name="accessibility_desc_quick_settings_edit" msgid="741658939453595297">"ඉක්මන් සැකසුම් සංස්කාරකය."</string> <string name="accessibility_desc_notification_icon" msgid="7331265967584178674">"<xliff:g id="ID_1">%1$s</xliff:g> දැනුම්දීම: <xliff:g id="ID_2">%2$s</xliff:g>"</string> - <string name="dock_forced_resizable" msgid="4689301323912928801">"යෙදුම බෙදුම්-තිරය සමග ක්රියා නොකළ හැකිය."</string> - <string name="dock_non_resizeble_failed_to_dock_text" msgid="7284915968096153808">"යෙදුම බෙදුණු-තිරය සඳහා සහාය නොදක්වයි."</string> - <string name="forced_resizable_secondary_display" msgid="522558907654394940">"යෙදුම ද්විතියික සංදර්ශකයක ක්රියා නොකළ හැකිය."</string> - <string name="activity_launch_on_secondary_display_failed_text" msgid="8446727617187998208">"යෙදුම ද්විතීයික සංදර්ශක මත දියත් කිරීම සඳහා සහාය නොදක්වයි."</string> <string name="accessibility_quick_settings_settings" msgid="7098489591715844713">"සැකසීම් විවෘත කරන්න."</string> <string name="accessibility_quick_settings_expand" msgid="2609275052412521467">"ඉක්මන් සැකසීම් විවෘත කරන්න."</string> <string name="accessibility_quick_settings_collapse" msgid="4674876336725041982">"ඉක්මන් සැකසීම් වසන්න."</string> diff --git a/packages/SystemUI/res/values-sk/strings.xml b/packages/SystemUI/res/values-sk/strings.xml index 0f9cb5f4616c..54a32ddd1cbf 100644 --- a/packages/SystemUI/res/values-sk/strings.xml +++ b/packages/SystemUI/res/values-sk/strings.xml @@ -889,17 +889,6 @@ </string-array> <string name="tuner_low_priority" msgid="8412666814123009820">"Zobraziť ikony upozornení s nízkou prioritou"</string> <string name="other" msgid="429768510980739978">"Ďalšie"</string> - <string name="accessibility_divider" msgid="2830785970889237307">"Rozdeľovač obrazovky"</string> - <string name="accessibility_action_divider_left_full" msgid="7598733539422375847">"Ľavá – na celú obrazovku"</string> - <string name="accessibility_action_divider_left_70" msgid="4919312892541727761">"Ľavá – 70 %"</string> - <string name="accessibility_action_divider_left_50" msgid="3664701169564893826">"Ľavá – 50 %"</string> - <string name="accessibility_action_divider_left_30" msgid="4358145268046362088">"Ľavá – 30 %"</string> - <string name="accessibility_action_divider_right_full" msgid="8576057422864896305">"Pravá– na celú obrazovku"</string> - <string name="accessibility_action_divider_top_full" msgid="4243901660795169777">"Horná – na celú obrazovku"</string> - <string name="accessibility_action_divider_top_70" msgid="6941226213260515072">"Horná – 70 %"</string> - <string name="accessibility_action_divider_top_50" msgid="6275211443706497621">"Horná – 50 %"</string> - <string name="accessibility_action_divider_top_30" msgid="5780597635887574916">"Horná – 30 %"</string> - <string name="accessibility_action_divider_bottom_full" msgid="7352434720610115395">"Dolná – na celú obrazovku"</string> <string name="accessibility_qs_edit_tile_label" msgid="9079791448815232967">"Pozícia <xliff:g id="POSITION">%1$d</xliff:g>, <xliff:g id="TILE_NAME">%2$s</xliff:g>. Upravíte ju dvojitým klepnutím."</string> <string name="accessibility_qs_edit_add_tile_label" msgid="8292218072049068613">"<xliff:g id="TILE_NAME">%1$s</xliff:g>. Pridáte ju dvojitým klepnutím."</string> <string name="accessibility_qs_edit_move_tile" msgid="6027997446473163426">"Presunúť dlaždicu <xliff:g id="TILE_NAME">%1$s</xliff:g>"</string> @@ -908,10 +897,6 @@ <string name="accessibility_qs_edit_tile_move" msgid="4841770637244326837">"Presunúť <xliff:g id="TILE_NAME">%1$s</xliff:g> na pozíciu <xliff:g id="POSITION">%2$d</xliff:g>"</string> <string name="accessibility_desc_quick_settings_edit" msgid="741658939453595297">"Editor rýchlych nastavení"</string> <string name="accessibility_desc_notification_icon" msgid="7331265967584178674">"Upozornenie <xliff:g id="ID_1">%1$s</xliff:g>: <xliff:g id="ID_2">%2$s</xliff:g>"</string> - <string name="dock_forced_resizable" msgid="4689301323912928801">"Aplikácia nemusí fungovať so zapnutou rozdelenou obrazovkou."</string> - <string name="dock_non_resizeble_failed_to_dock_text" msgid="7284915968096153808">"Aplikácia nepodporuje rozdelenú obrazovku."</string> - <string name="forced_resizable_secondary_display" msgid="522558907654394940">"Aplikácia nemusí fungovať na sekundárnej obrazovke."</string> - <string name="activity_launch_on_secondary_display_failed_text" msgid="8446727617187998208">"Aplikácia nepodporuje spúšťanie na sekundárnych obrazovkách."</string> <string name="accessibility_quick_settings_settings" msgid="7098489591715844713">"Otvoriť nastavenia"</string> <string name="accessibility_quick_settings_expand" msgid="2609275052412521467">"Otvoriť rýchle nastavenia"</string> <string name="accessibility_quick_settings_collapse" msgid="4674876336725041982">"Zavrieť rýchle nastavenia"</string> diff --git a/packages/SystemUI/res/values-sl/strings.xml b/packages/SystemUI/res/values-sl/strings.xml index 18db332b63ec..32fce7d58c9c 100644 --- a/packages/SystemUI/res/values-sl/strings.xml +++ b/packages/SystemUI/res/values-sl/strings.xml @@ -889,17 +889,6 @@ </string-array> <string name="tuner_low_priority" msgid="8412666814123009820">"Pokaži ikone obvestil z nizko stopnjo prednosti"</string> <string name="other" msgid="429768510980739978">"Drugo"</string> - <string name="accessibility_divider" msgid="2830785970889237307">"Razdelilnik zaslonov"</string> - <string name="accessibility_action_divider_left_full" msgid="7598733539422375847">"Levi v celozaslonski način"</string> - <string name="accessibility_action_divider_left_70" msgid="4919312892541727761">"Levi 70 %"</string> - <string name="accessibility_action_divider_left_50" msgid="3664701169564893826">"Levi 50 %"</string> - <string name="accessibility_action_divider_left_30" msgid="4358145268046362088">"Levi 30 %"</string> - <string name="accessibility_action_divider_right_full" msgid="8576057422864896305">"Desni v celozaslonski način"</string> - <string name="accessibility_action_divider_top_full" msgid="4243901660795169777">"Zgornji v celozaslonski način"</string> - <string name="accessibility_action_divider_top_70" msgid="6941226213260515072">"Zgornji 70 %"</string> - <string name="accessibility_action_divider_top_50" msgid="6275211443706497621">"Zgornji 50 %"</string> - <string name="accessibility_action_divider_top_30" msgid="5780597635887574916">"Zgornji 30 %"</string> - <string name="accessibility_action_divider_bottom_full" msgid="7352434720610115395">"Spodnji v celozaslonski način"</string> <string name="accessibility_qs_edit_tile_label" msgid="9079791448815232967">"Položaj <xliff:g id="POSITION">%1$d</xliff:g>, <xliff:g id="TILE_NAME">%2$s</xliff:g>. Če želite urediti, se dvakrat dotaknite."</string> <string name="accessibility_qs_edit_add_tile_label" msgid="8292218072049068613">"<xliff:g id="TILE_NAME">%1$s</xliff:g>. Če želite dodati, se dvakrat dotaknite."</string> <string name="accessibility_qs_edit_move_tile" msgid="6027997446473163426">"Premik tega: <xliff:g id="TILE_NAME">%1$s</xliff:g>"</string> @@ -908,10 +897,6 @@ <string name="accessibility_qs_edit_tile_move" msgid="4841770637244326837">"Premakni ploščico <xliff:g id="TILE_NAME">%1$s</xliff:g> na položaj <xliff:g id="POSITION">%2$d</xliff:g>"</string> <string name="accessibility_desc_quick_settings_edit" msgid="741658939453595297">"Urejevalnik hitrih nastavitev."</string> <string name="accessibility_desc_notification_icon" msgid="7331265967584178674">"Obvestilo za <xliff:g id="ID_1">%1$s</xliff:g>: <xliff:g id="ID_2">%2$s</xliff:g>"</string> - <string name="dock_forced_resizable" msgid="4689301323912928801">"Aplikacija morda ne deluje v načinu razdeljenega zaslona."</string> - <string name="dock_non_resizeble_failed_to_dock_text" msgid="7284915968096153808">"Aplikacija ne podpira načina razdeljenega zaslona."</string> - <string name="forced_resizable_secondary_display" msgid="522558907654394940">"Aplikacija morda ne bo delovala na sekundarnem zaslonu."</string> - <string name="activity_launch_on_secondary_display_failed_text" msgid="8446727617187998208">"Aplikacija ne podpira zagona na sekundarnih zaslonih."</string> <string name="accessibility_quick_settings_settings" msgid="7098489591715844713">"Odpri nastavitve."</string> <string name="accessibility_quick_settings_expand" msgid="2609275052412521467">"Odpri hitre nastavitve."</string> <string name="accessibility_quick_settings_collapse" msgid="4674876336725041982">"Zapri hitre nastavitve."</string> diff --git a/packages/SystemUI/res/values-sq/strings.xml b/packages/SystemUI/res/values-sq/strings.xml index 57ab1c384ca9..c907bc23cf32 100644 --- a/packages/SystemUI/res/values-sq/strings.xml +++ b/packages/SystemUI/res/values-sq/strings.xml @@ -480,7 +480,7 @@ <string name="guest_wipe_session_title" msgid="7147965814683990944">"Mirë se erdhe, i ftuar!"</string> <string name="guest_wipe_session_message" msgid="3393823610257065457">"Dëshiron ta vazhdosh sesionin tënd?"</string> <string name="guest_wipe_session_wipe" msgid="8056836584445473309">"Fillo nga e para"</string> - <string name="guest_wipe_session_dontwipe" msgid="3211052048269304205">"Po, vazhdo!"</string> + <string name="guest_wipe_session_dontwipe" msgid="3211052048269304205">"Po, vazhdo"</string> <string name="guest_notification_title" msgid="4434456703930764167">"Përdorues vizitor"</string> <string name="guest_notification_text" msgid="4202692942089571351">"Për të fshirë aplikacionet dhe të dhënat, hiqe përdoruesin vizitor"</string> <string name="guest_notification_remove_action" msgid="4153019027696868099">"HIQ VIZITORIN"</string> @@ -879,17 +879,6 @@ </string-array> <string name="tuner_low_priority" msgid="8412666814123009820">"Shfaq ikonat e njoftimeve me përparësi të ulët"</string> <string name="other" msgid="429768510980739978">"Të tjera"</string> - <string name="accessibility_divider" msgid="2830785970889237307">"Ndarësi i ekranit të ndarë"</string> - <string name="accessibility_action_divider_left_full" msgid="7598733539422375847">"Ekrani i plotë majtas"</string> - <string name="accessibility_action_divider_left_70" msgid="4919312892541727761">"Majtas 70%"</string> - <string name="accessibility_action_divider_left_50" msgid="3664701169564893826">"Majtas 50%"</string> - <string name="accessibility_action_divider_left_30" msgid="4358145268046362088">"Majtas 30%"</string> - <string name="accessibility_action_divider_right_full" msgid="8576057422864896305">"Ekrani i plotë djathtas"</string> - <string name="accessibility_action_divider_top_full" msgid="4243901660795169777">"Ekrani i plotë lart"</string> - <string name="accessibility_action_divider_top_70" msgid="6941226213260515072">"Lart 70%"</string> - <string name="accessibility_action_divider_top_50" msgid="6275211443706497621">"Lart 50%"</string> - <string name="accessibility_action_divider_top_30" msgid="5780597635887574916">"Lart 30%"</string> - <string name="accessibility_action_divider_bottom_full" msgid="7352434720610115395">"Ekrani i plotë poshtë"</string> <string name="accessibility_qs_edit_tile_label" msgid="9079791448815232967">"Pozicioni <xliff:g id="POSITION">%1$d</xliff:g>, <xliff:g id="TILE_NAME">%2$s</xliff:g>. Trokit dy herë për ta redaktuar."</string> <string name="accessibility_qs_edit_add_tile_label" msgid="8292218072049068613">"<xliff:g id="TILE_NAME">%1$s</xliff:g>. Trokit dy herë për ta shtuar."</string> <string name="accessibility_qs_edit_move_tile" msgid="6027997446473163426">"Zhvendose <xliff:g id="TILE_NAME">%1$s</xliff:g>"</string> @@ -898,10 +887,6 @@ <string name="accessibility_qs_edit_tile_move" msgid="4841770637244326837">"Zhvendos <xliff:g id="TILE_NAME">%1$s</xliff:g> te pozicioni <xliff:g id="POSITION">%2$d</xliff:g>"</string> <string name="accessibility_desc_quick_settings_edit" msgid="741658939453595297">"Redaktori i cilësimeve të shpejta."</string> <string name="accessibility_desc_notification_icon" msgid="7331265967584178674">"Njoftim nga <xliff:g id="ID_1">%1$s</xliff:g>: <xliff:g id="ID_2">%2$s</xliff:g>"</string> - <string name="dock_forced_resizable" msgid="4689301323912928801">"Aplikacioni mund të mos funksionojë me ekranin e ndarë."</string> - <string name="dock_non_resizeble_failed_to_dock_text" msgid="7284915968096153808">"Aplikacioni nuk mbështet ekranin e ndarë."</string> - <string name="forced_resizable_secondary_display" msgid="522558907654394940">"Aplikacioni mund të mos funksionojë në një ekran dytësor."</string> - <string name="activity_launch_on_secondary_display_failed_text" msgid="8446727617187998208">"Aplikacioni nuk mbështet nisjen në ekrane dytësore."</string> <string name="accessibility_quick_settings_settings" msgid="7098489591715844713">"Hap cilësimet."</string> <string name="accessibility_quick_settings_expand" msgid="2609275052412521467">"Hap cilësimet e shpejta."</string> <string name="accessibility_quick_settings_collapse" msgid="4674876336725041982">"Mbyll cilësimet e shpejta."</string> diff --git a/packages/SystemUI/res/values-sr/strings.xml b/packages/SystemUI/res/values-sr/strings.xml index ec763f675d4c..8b7ce1f35cb3 100644 --- a/packages/SystemUI/res/values-sr/strings.xml +++ b/packages/SystemUI/res/values-sr/strings.xml @@ -884,17 +884,6 @@ </string-array> <string name="tuner_low_priority" msgid="8412666814123009820">"Прикажи иконе обавештења ниског приоритета"</string> <string name="other" msgid="429768510980739978">"Друго"</string> - <string name="accessibility_divider" msgid="2830785970889237307">"Разделник подељеног екрана"</string> - <string name="accessibility_action_divider_left_full" msgid="7598733539422375847">"Режим целог екрана за леви екран"</string> - <string name="accessibility_action_divider_left_70" msgid="4919312892541727761">"Леви екран 70%"</string> - <string name="accessibility_action_divider_left_50" msgid="3664701169564893826">"Леви екран 50%"</string> - <string name="accessibility_action_divider_left_30" msgid="4358145268046362088">"Леви екран 30%"</string> - <string name="accessibility_action_divider_right_full" msgid="8576057422864896305">"Режим целог екрана за доњи екран"</string> - <string name="accessibility_action_divider_top_full" msgid="4243901660795169777">"Режим целог екрана за горњи екран"</string> - <string name="accessibility_action_divider_top_70" msgid="6941226213260515072">"Горњи екран 70%"</string> - <string name="accessibility_action_divider_top_50" msgid="6275211443706497621">"Горњи екран 50%"</string> - <string name="accessibility_action_divider_top_30" msgid="5780597635887574916">"Горњи екран 30%"</string> - <string name="accessibility_action_divider_bottom_full" msgid="7352434720610115395">"Режим целог екрана за доњи екран"</string> <string name="accessibility_qs_edit_tile_label" msgid="9079791448815232967">"<xliff:g id="POSITION">%1$d</xliff:g>. позиција, <xliff:g id="TILE_NAME">%2$s</xliff:g>. Двапут додирните да бисте изменили."</string> <string name="accessibility_qs_edit_add_tile_label" msgid="8292218072049068613">"<xliff:g id="TILE_NAME">%1$s</xliff:g>. Двапут додирните да бисте додали."</string> <string name="accessibility_qs_edit_move_tile" msgid="6027997446473163426">"Премести плочицу <xliff:g id="TILE_NAME">%1$s</xliff:g>"</string> @@ -903,10 +892,6 @@ <string name="accessibility_qs_edit_tile_move" msgid="4841770637244326837">"Преместите „<xliff:g id="TILE_NAME">%1$s</xliff:g>“ на позицију <xliff:g id="POSITION">%2$d</xliff:g>"</string> <string name="accessibility_desc_quick_settings_edit" msgid="741658939453595297">"Уређивач за Брза подешавања."</string> <string name="accessibility_desc_notification_icon" msgid="7331265967584178674">"Обавештења за <xliff:g id="ID_1">%1$s</xliff:g>: <xliff:g id="ID_2">%2$s</xliff:g>"</string> - <string name="dock_forced_resizable" msgid="4689301323912928801">"Апликација можда неће функционисати са подељеним екраном."</string> - <string name="dock_non_resizeble_failed_to_dock_text" msgid="7284915968096153808">"Апликација не подржава подељени екран."</string> - <string name="forced_resizable_secondary_display" msgid="522558907654394940">"Апликација можда неће функционисати на секундарном екрану."</string> - <string name="activity_launch_on_secondary_display_failed_text" msgid="8446727617187998208">"Апликација не подржава покретање на секундарним екранима."</string> <string name="accessibility_quick_settings_settings" msgid="7098489591715844713">"Отвори Подешавања."</string> <string name="accessibility_quick_settings_expand" msgid="2609275052412521467">"Отвори Брза подешавања."</string> <string name="accessibility_quick_settings_collapse" msgid="4674876336725041982">"Затвори Брза подешавања."</string> diff --git a/packages/SystemUI/res/values-sv/strings.xml b/packages/SystemUI/res/values-sv/strings.xml index a0a563d81d46..c4b7977ae5a6 100644 --- a/packages/SystemUI/res/values-sv/strings.xml +++ b/packages/SystemUI/res/values-sv/strings.xml @@ -879,17 +879,6 @@ </string-array> <string name="tuner_low_priority" msgid="8412666814123009820">"Visa ikoner för aviseringar med låg prioritet"</string> <string name="other" msgid="429768510980739978">"Annat"</string> - <string name="accessibility_divider" msgid="2830785970889237307">"Avdelare för delad skärm"</string> - <string name="accessibility_action_divider_left_full" msgid="7598733539422375847">"Helskärm på vänster skärm"</string> - <string name="accessibility_action_divider_left_70" msgid="4919312892541727761">"Vänster 70 %"</string> - <string name="accessibility_action_divider_left_50" msgid="3664701169564893826">"Vänster 50 %"</string> - <string name="accessibility_action_divider_left_30" msgid="4358145268046362088">"Vänster 30 %"</string> - <string name="accessibility_action_divider_right_full" msgid="8576057422864896305">"Helskärm på höger skärm"</string> - <string name="accessibility_action_divider_top_full" msgid="4243901660795169777">"Helskärm på övre skärm"</string> - <string name="accessibility_action_divider_top_70" msgid="6941226213260515072">"Övre 70 %"</string> - <string name="accessibility_action_divider_top_50" msgid="6275211443706497621">"Övre 50 %"</string> - <string name="accessibility_action_divider_top_30" msgid="5780597635887574916">"Övre 30 %"</string> - <string name="accessibility_action_divider_bottom_full" msgid="7352434720610115395">"Helskärm på nedre skärm"</string> <string name="accessibility_qs_edit_tile_label" msgid="9079791448815232967">"Position <xliff:g id="POSITION">%1$d</xliff:g>, <xliff:g id="TILE_NAME">%2$s</xliff:g>. Tryck snabbt två gånger för att redigera positionen."</string> <string name="accessibility_qs_edit_add_tile_label" msgid="8292218072049068613">"<xliff:g id="TILE_NAME">%1$s</xliff:g>. Lägg till genom att trycka snabbt två gånger."</string> <string name="accessibility_qs_edit_move_tile" msgid="6027997446473163426">"Flytta <xliff:g id="TILE_NAME">%1$s</xliff:g>"</string> @@ -898,10 +887,6 @@ <string name="accessibility_qs_edit_tile_move" msgid="4841770637244326837">"Flytta <xliff:g id="TILE_NAME">%1$s</xliff:g> till position <xliff:g id="POSITION">%2$d</xliff:g>"</string> <string name="accessibility_desc_quick_settings_edit" msgid="741658939453595297">"Redigerare för snabbinställningar."</string> <string name="accessibility_desc_notification_icon" msgid="7331265967584178674">"<xliff:g id="ID_1">%1$s</xliff:g>-avisering: <xliff:g id="ID_2">%2$s</xliff:g>"</string> - <string name="dock_forced_resizable" msgid="4689301323912928801">"Appen kanske inte fungerar med delad skärm."</string> - <string name="dock_non_resizeble_failed_to_dock_text" msgid="7284915968096153808">"Appen har inte stöd för delad skärm."</string> - <string name="forced_resizable_secondary_display" msgid="522558907654394940">"Appen kanske inte fungerar på en sekundär skärm."</string> - <string name="activity_launch_on_secondary_display_failed_text" msgid="8446727617187998208">"Appen kan inte köras på en sekundär skärm."</string> <string name="accessibility_quick_settings_settings" msgid="7098489591715844713">"Öppna inställningarna."</string> <string name="accessibility_quick_settings_expand" msgid="2609275052412521467">"Öppna snabbinställningarna."</string> <string name="accessibility_quick_settings_collapse" msgid="4674876336725041982">"Stäng snabbinställningarna"</string> diff --git a/packages/SystemUI/res/values-sw/strings.xml b/packages/SystemUI/res/values-sw/strings.xml index 7e264a4a312a..b483fa8f0791 100644 --- a/packages/SystemUI/res/values-sw/strings.xml +++ b/packages/SystemUI/res/values-sw/strings.xml @@ -879,17 +879,6 @@ </string-array> <string name="tuner_low_priority" msgid="8412666814123009820">"Onyesha aikoni za arifa zisizo muhimu"</string> <string name="other" msgid="429768510980739978">"Nyingine"</string> - <string name="accessibility_divider" msgid="2830785970889237307">"Kitenganishi cha skrini inayogawanywa"</string> - <string name="accessibility_action_divider_left_full" msgid="7598733539422375847">"Skrini nzima ya kushoto"</string> - <string name="accessibility_action_divider_left_70" msgid="4919312892541727761">"Kushoto 70%"</string> - <string name="accessibility_action_divider_left_50" msgid="3664701169564893826">"Kushoto 50%"</string> - <string name="accessibility_action_divider_left_30" msgid="4358145268046362088">"Kushoto 30%"</string> - <string name="accessibility_action_divider_right_full" msgid="8576057422864896305">"Skrini nzima ya kulia"</string> - <string name="accessibility_action_divider_top_full" msgid="4243901660795169777">"Skrini nzima ya juu"</string> - <string name="accessibility_action_divider_top_70" msgid="6941226213260515072">"Juu 70%"</string> - <string name="accessibility_action_divider_top_50" msgid="6275211443706497621">"Juu 50%"</string> - <string name="accessibility_action_divider_top_30" msgid="5780597635887574916">"Juu 30%"</string> - <string name="accessibility_action_divider_bottom_full" msgid="7352434720610115395">"Skrini nzima ya chini"</string> <string name="accessibility_qs_edit_tile_label" msgid="9079791448815232967">"Nafasi ya <xliff:g id="POSITION">%1$d</xliff:g>, <xliff:g id="TILE_NAME">%2$s</xliff:g>. Gusa mara mbili ili ubadilishe."</string> <string name="accessibility_qs_edit_add_tile_label" msgid="8292218072049068613">"<xliff:g id="TILE_NAME">%1$s</xliff:g>. Gusa mara mbili ili uongeze."</string> <string name="accessibility_qs_edit_move_tile" msgid="6027997446473163426">"Hamisha <xliff:g id="TILE_NAME">%1$s</xliff:g>"</string> @@ -898,10 +887,6 @@ <string name="accessibility_qs_edit_tile_move" msgid="4841770637244326837">"Sogeza <xliff:g id="TILE_NAME">%1$s</xliff:g> kwenye nafasi ya <xliff:g id="POSITION">%2$d</xliff:g>"</string> <string name="accessibility_desc_quick_settings_edit" msgid="741658939453595297">"Kihariri cha Mipangilio ya haraka."</string> <string name="accessibility_desc_notification_icon" msgid="7331265967584178674">"Arifa kutoka <xliff:g id="ID_1">%1$s</xliff:g>: <xliff:g id="ID_2">%2$s</xliff:g>"</string> - <string name="dock_forced_resizable" msgid="4689301323912928801">"Huenda programu isifanye kazi kwenye skrini inayogawanywa."</string> - <string name="dock_non_resizeble_failed_to_dock_text" msgid="7284915968096153808">"Programu haiwezi kutumia skrini iliyogawanywa."</string> - <string name="forced_resizable_secondary_display" msgid="522558907654394940">"Huenda programu isifanye kazi kwenye dirisha lingine."</string> - <string name="activity_launch_on_secondary_display_failed_text" msgid="8446727617187998208">"Programu hii haiwezi kufunguliwa kwenye madirisha mengine."</string> <string name="accessibility_quick_settings_settings" msgid="7098489591715844713">"Fungua mipangilio."</string> <string name="accessibility_quick_settings_expand" msgid="2609275052412521467">"Fungua mipangilio ya haraka."</string> <string name="accessibility_quick_settings_collapse" msgid="4674876336725041982">"Funga mipangilio ya haraka."</string> diff --git a/packages/SystemUI/res/values-ta/strings.xml b/packages/SystemUI/res/values-ta/strings.xml index e0f20ceea353..2c025e72cdf4 100644 --- a/packages/SystemUI/res/values-ta/strings.xml +++ b/packages/SystemUI/res/values-ta/strings.xml @@ -879,17 +879,6 @@ </string-array> <string name="tuner_low_priority" msgid="8412666814123009820">"குறைந்த முன்னுரிமை உள்ள அறிவிப்பு ஐகான்களைக் காட்டு"</string> <string name="other" msgid="429768510980739978">"மற்றவை"</string> - <string name="accessibility_divider" msgid="2830785970889237307">"திரையைப் பிரிக்கும் பிரிப்பான்"</string> - <string name="accessibility_action_divider_left_full" msgid="7598733539422375847">"இடது புறம் முழுத் திரை"</string> - <string name="accessibility_action_divider_left_70" msgid="4919312892541727761">"இடது புறம் 70%"</string> - <string name="accessibility_action_divider_left_50" msgid="3664701169564893826">"இடது புறம் 50%"</string> - <string name="accessibility_action_divider_left_30" msgid="4358145268046362088">"இடது புறம் 30%"</string> - <string name="accessibility_action_divider_right_full" msgid="8576057422864896305">"வலது புறம் முழுத் திரை"</string> - <string name="accessibility_action_divider_top_full" msgid="4243901660795169777">"மேற்புறம் முழுத் திரை"</string> - <string name="accessibility_action_divider_top_70" msgid="6941226213260515072">"மேலே 70%"</string> - <string name="accessibility_action_divider_top_50" msgid="6275211443706497621">"மேலே 50%"</string> - <string name="accessibility_action_divider_top_30" msgid="5780597635887574916">"மேலே 30%"</string> - <string name="accessibility_action_divider_bottom_full" msgid="7352434720610115395">"கீழ்ப்புறம் முழுத் திரை"</string> <string name="accessibility_qs_edit_tile_label" msgid="9079791448815232967">"நிலை <xliff:g id="POSITION">%1$d</xliff:g>, <xliff:g id="TILE_NAME">%2$s</xliff:g>. திருத்த, இருமுறை தட்டவும்."</string> <string name="accessibility_qs_edit_add_tile_label" msgid="8292218072049068613">"<xliff:g id="TILE_NAME">%1$s</xliff:g>. சேர்க்க, இருமுறை தட்டவும்."</string> <string name="accessibility_qs_edit_move_tile" msgid="6027997446473163426">"<xliff:g id="TILE_NAME">%1$s</xliff:g>ஐ நகர்த்தவும்"</string> @@ -898,10 +887,6 @@ <string name="accessibility_qs_edit_tile_move" msgid="4841770637244326837">"நிலைப்பாடு <xliff:g id="POSITION">%2$d</xliff:g>க்கு <xliff:g id="TILE_NAME">%1$s</xliff:g>ஐ நகர்த்தும்"</string> <string name="accessibility_desc_quick_settings_edit" msgid="741658939453595297">"விரைவு அமைப்புகள் திருத்தி."</string> <string name="accessibility_desc_notification_icon" msgid="7331265967584178674">"<xliff:g id="ID_1">%1$s</xliff:g> அறிவிப்பு: <xliff:g id="ID_2">%2$s</xliff:g>"</string> - <string name="dock_forced_resizable" msgid="4689301323912928801">"திரைப் பிரிப்பில் ஆப்ஸ் வேலைசெய்யாமல் போகக்கூடும்."</string> - <string name="dock_non_resizeble_failed_to_dock_text" msgid="7284915968096153808">"திரையைப் பிரிப்பதைப் ஆப்ஸ் ஆதரிக்கவில்லை."</string> - <string name="forced_resizable_secondary_display" msgid="522558907654394940">"இரண்டாம்நிலைத் திரையில் ஆப்ஸ் வேலை செய்யாமல் போகக்கூடும்."</string> - <string name="activity_launch_on_secondary_display_failed_text" msgid="8446727617187998208">"இரண்டாம்நிலைத் திரைகளில் பயன்பாட்டைத் தொடங்க முடியாது."</string> <string name="accessibility_quick_settings_settings" msgid="7098489591715844713">"அமைப்புகளைத் திற."</string> <string name="accessibility_quick_settings_expand" msgid="2609275052412521467">"விரைவு அமைப்புகளைத் திற."</string> <string name="accessibility_quick_settings_collapse" msgid="4674876336725041982">"விரைவு அமைப்புகளை மூடு."</string> diff --git a/packages/SystemUI/res/values-te/strings.xml b/packages/SystemUI/res/values-te/strings.xml index 3e94b72b02fe..a49bb9b46512 100644 --- a/packages/SystemUI/res/values-te/strings.xml +++ b/packages/SystemUI/res/values-te/strings.xml @@ -879,17 +879,6 @@ </string-array> <string name="tuner_low_priority" msgid="8412666814123009820">"తక్కువ ప్రాధాన్యత నోటిఫికేషన్ చిహ్నాలను చూపించు"</string> <string name="other" msgid="429768510980739978">"ఇతరం"</string> - <string name="accessibility_divider" msgid="2830785970889237307">"విభజన స్క్రీన్ విభాగిని"</string> - <string name="accessibility_action_divider_left_full" msgid="7598733539422375847">"ఎడమవైపు పూర్తి స్క్రీన్"</string> - <string name="accessibility_action_divider_left_70" msgid="4919312892541727761">"ఎడమవైపు 70%"</string> - <string name="accessibility_action_divider_left_50" msgid="3664701169564893826">"ఎడమవైపు 50%"</string> - <string name="accessibility_action_divider_left_30" msgid="4358145268046362088">"ఎడమవైపు 30%"</string> - <string name="accessibility_action_divider_right_full" msgid="8576057422864896305">"కుడివైపు పూర్తి స్క్రీన్"</string> - <string name="accessibility_action_divider_top_full" msgid="4243901660795169777">"ఎగువ పూర్తి స్క్రీన్"</string> - <string name="accessibility_action_divider_top_70" msgid="6941226213260515072">"ఎగువ 70%"</string> - <string name="accessibility_action_divider_top_50" msgid="6275211443706497621">"ఎగువ 50%"</string> - <string name="accessibility_action_divider_top_30" msgid="5780597635887574916">"ఎగువ 30%"</string> - <string name="accessibility_action_divider_bottom_full" msgid="7352434720610115395">"దిగువ పూర్తి స్క్రీన్"</string> <string name="accessibility_qs_edit_tile_label" msgid="9079791448815232967">"స్థానం <xliff:g id="POSITION">%1$d</xliff:g>, <xliff:g id="TILE_NAME">%2$s</xliff:g>. సవరించడానికి రెండుసార్లు నొక్కండి."</string> <string name="accessibility_qs_edit_add_tile_label" msgid="8292218072049068613">"<xliff:g id="TILE_NAME">%1$s</xliff:g>. జోడించడానికి రెండుసార్లు నొక్కండి."</string> <string name="accessibility_qs_edit_move_tile" msgid="6027997446473163426">"<xliff:g id="TILE_NAME">%1$s</xliff:g>ని తరలిస్తుంది"</string> @@ -898,10 +887,6 @@ <string name="accessibility_qs_edit_tile_move" msgid="4841770637244326837">"స్థానం <xliff:g id="POSITION">%2$d</xliff:g>కి <xliff:g id="TILE_NAME">%1$s</xliff:g>ని తరలించండి"</string> <string name="accessibility_desc_quick_settings_edit" msgid="741658939453595297">"శీఘ్ర సెట్టింగ్ల ఎడిటర్."</string> <string name="accessibility_desc_notification_icon" msgid="7331265967584178674">"<xliff:g id="ID_1">%1$s</xliff:g> నోటిఫికేషన్: <xliff:g id="ID_2">%2$s</xliff:g>"</string> - <string name="dock_forced_resizable" msgid="4689301323912928801">"స్క్రీన్ విభజనతో యాప్ పని చేయకపోవచ్చు."</string> - <string name="dock_non_resizeble_failed_to_dock_text" msgid="7284915968096153808">"అనువర్తనంలో స్క్రీన్ విభజనకు మద్దతు లేదు."</string> - <string name="forced_resizable_secondary_display" msgid="522558907654394940">"ప్రత్యామ్నాయ డిస్ప్లేలో యాప్ పని చేయకపోవచ్చు."</string> - <string name="activity_launch_on_secondary_display_failed_text" msgid="8446727617187998208">"ప్రత్యామ్నాయ డిస్ప్లేల్లో ప్రారంభానికి యాప్ మద్దతు లేదు."</string> <string name="accessibility_quick_settings_settings" msgid="7098489591715844713">"సెట్టింగ్లను తెరవండి."</string> <string name="accessibility_quick_settings_expand" msgid="2609275052412521467">"శీఘ్ర సెట్టింగ్లను తెరవండి."</string> <string name="accessibility_quick_settings_collapse" msgid="4674876336725041982">"శీఘ్ర సెట్టింగ్లను మూసివేయండి."</string> diff --git a/packages/SystemUI/res/values-th/strings.xml b/packages/SystemUI/res/values-th/strings.xml index 088b62421b92..8fd844203d9f 100644 --- a/packages/SystemUI/res/values-th/strings.xml +++ b/packages/SystemUI/res/values-th/strings.xml @@ -879,17 +879,6 @@ </string-array> <string name="tuner_low_priority" msgid="8412666814123009820">"แสดงไอคอนการแจ้งเตือนลำดับความสำคัญต่ำ"</string> <string name="other" msgid="429768510980739978">"อื่นๆ"</string> - <string name="accessibility_divider" msgid="2830785970889237307">"เส้นแบ่งหน้าจอ"</string> - <string name="accessibility_action_divider_left_full" msgid="7598733539422375847">"เต็มหน้าจอทางซ้าย"</string> - <string name="accessibility_action_divider_left_70" msgid="4919312892541727761">"ซ้าย 70%"</string> - <string name="accessibility_action_divider_left_50" msgid="3664701169564893826">"ซ้าย 50%"</string> - <string name="accessibility_action_divider_left_30" msgid="4358145268046362088">"ซ้าย 30%"</string> - <string name="accessibility_action_divider_right_full" msgid="8576057422864896305">"เต็มหน้าจอทางขวา"</string> - <string name="accessibility_action_divider_top_full" msgid="4243901660795169777">"เต็มหน้าจอด้านบน"</string> - <string name="accessibility_action_divider_top_70" msgid="6941226213260515072">"ด้านบน 70%"</string> - <string name="accessibility_action_divider_top_50" msgid="6275211443706497621">"ด้านบน 50%"</string> - <string name="accessibility_action_divider_top_30" msgid="5780597635887574916">"ด้านบน 30%"</string> - <string name="accessibility_action_divider_bottom_full" msgid="7352434720610115395">"เต็มหน้าจอด้านล่าง"</string> <string name="accessibility_qs_edit_tile_label" msgid="9079791448815232967">"ตำแหน่ง <xliff:g id="POSITION">%1$d</xliff:g> <xliff:g id="TILE_NAME">%2$s</xliff:g> แตะ 2 ครั้งเพื่อแก้ไข"</string> <string name="accessibility_qs_edit_add_tile_label" msgid="8292218072049068613">"<xliff:g id="TILE_NAME">%1$s</xliff:g> แตะ 2 ครั้งเพื่อเพิ่ม"</string> <string name="accessibility_qs_edit_move_tile" msgid="6027997446473163426">"ย้าย <xliff:g id="TILE_NAME">%1$s</xliff:g>"</string> @@ -898,10 +887,6 @@ <string name="accessibility_qs_edit_tile_move" msgid="4841770637244326837">"ย้าย <xliff:g id="TILE_NAME">%1$s</xliff:g> ไปยังตำแหน่ง <xliff:g id="POSITION">%2$d</xliff:g>"</string> <string name="accessibility_desc_quick_settings_edit" msgid="741658939453595297">"ตัวแก้ไขการตั้งค่าด่วน"</string> <string name="accessibility_desc_notification_icon" msgid="7331265967584178674">"<xliff:g id="ID_1">%1$s</xliff:g> การแจ้งเตือน: <xliff:g id="ID_2">%2$s</xliff:g>"</string> - <string name="dock_forced_resizable" msgid="4689301323912928801">"แอปอาจใช้ไม่ได้กับโหมดแยกหน้าจอ"</string> - <string name="dock_non_resizeble_failed_to_dock_text" msgid="7284915968096153808">"แอปไม่สนับสนุนการแยกหน้าจอ"</string> - <string name="forced_resizable_secondary_display" msgid="522558907654394940">"แอปอาจไม่ทำงานในจอแสดงผลรอง"</string> - <string name="activity_launch_on_secondary_display_failed_text" msgid="8446727617187998208">"แอปไม่รองรับการเรียกใช้ในจอแสดงผลรอง"</string> <string name="accessibility_quick_settings_settings" msgid="7098489591715844713">"เปิดการตั้งค่า"</string> <string name="accessibility_quick_settings_expand" msgid="2609275052412521467">"เปิดการตั้งค่าด่วน"</string> <string name="accessibility_quick_settings_collapse" msgid="4674876336725041982">"ปิดการตั้งค่าด่วน"</string> diff --git a/packages/SystemUI/res/values-tl/strings.xml b/packages/SystemUI/res/values-tl/strings.xml index e787b17417bb..5951ba223c5d 100644 --- a/packages/SystemUI/res/values-tl/strings.xml +++ b/packages/SystemUI/res/values-tl/strings.xml @@ -879,17 +879,6 @@ </string-array> <string name="tuner_low_priority" msgid="8412666814123009820">"Ipakita ang mga icon ng notification na may mababang priority"</string> <string name="other" msgid="429768510980739978">"Iba pa"</string> - <string name="accessibility_divider" msgid="2830785970889237307">"Divider ng split-screen"</string> - <string name="accessibility_action_divider_left_full" msgid="7598733539422375847">"I-full screen ang nasa kaliwa"</string> - <string name="accessibility_action_divider_left_70" msgid="4919312892541727761">"Gawing 70% ang nasa kaliwa"</string> - <string name="accessibility_action_divider_left_50" msgid="3664701169564893826">"Gawing 50% ang nasa kaliwa"</string> - <string name="accessibility_action_divider_left_30" msgid="4358145268046362088">"Gawing 30% ang nasa kaliwa"</string> - <string name="accessibility_action_divider_right_full" msgid="8576057422864896305">"I-full screen ang nasa kanan"</string> - <string name="accessibility_action_divider_top_full" msgid="4243901660795169777">"I-full screen ang nasa itaas"</string> - <string name="accessibility_action_divider_top_70" msgid="6941226213260515072">"Gawing 70% ang nasa itaas"</string> - <string name="accessibility_action_divider_top_50" msgid="6275211443706497621">"Gawing 50% ang nasa itaas"</string> - <string name="accessibility_action_divider_top_30" msgid="5780597635887574916">"Gawing 30% ang nasa itaas"</string> - <string name="accessibility_action_divider_bottom_full" msgid="7352434720610115395">"I-full screen ang nasa ibaba"</string> <string name="accessibility_qs_edit_tile_label" msgid="9079791448815232967">"Posisyon <xliff:g id="POSITION">%1$d</xliff:g>, <xliff:g id="TILE_NAME">%2$s</xliff:g>. I-double tap upang i-edit."</string> <string name="accessibility_qs_edit_add_tile_label" msgid="8292218072049068613">"<xliff:g id="TILE_NAME">%1$s</xliff:g>. I-double tap upang idagdag."</string> <string name="accessibility_qs_edit_move_tile" msgid="6027997446473163426">"Ilipat ang <xliff:g id="TILE_NAME">%1$s</xliff:g>"</string> @@ -898,10 +887,6 @@ <string name="accessibility_qs_edit_tile_move" msgid="4841770637244326837">"Ilipat ang <xliff:g id="TILE_NAME">%1$s</xliff:g> sa posisyong <xliff:g id="POSITION">%2$d</xliff:g>"</string> <string name="accessibility_desc_quick_settings_edit" msgid="741658939453595297">"Editor ng Mga mabilisang setting."</string> <string name="accessibility_desc_notification_icon" msgid="7331265967584178674">"Notification sa <xliff:g id="ID_1">%1$s</xliff:g>: <xliff:g id="ID_2">%2$s</xliff:g>"</string> - <string name="dock_forced_resizable" msgid="4689301323912928801">"Maaaring hindi gumana ang app sa split-screen."</string> - <string name="dock_non_resizeble_failed_to_dock_text" msgid="7284915968096153808">"Hindi sinusuportahan ng app ang split-screen."</string> - <string name="forced_resizable_secondary_display" msgid="522558907654394940">"Maaaring hindi gumana ang app sa pangalawang display."</string> - <string name="activity_launch_on_secondary_display_failed_text" msgid="8446727617187998208">"Hindi sinusuportahan ng app ang paglulunsad sa mga pangalawang display."</string> <string name="accessibility_quick_settings_settings" msgid="7098489591715844713">"Buksan ang mga setting."</string> <string name="accessibility_quick_settings_expand" msgid="2609275052412521467">"Buksan ang mga mabilisang setting."</string> <string name="accessibility_quick_settings_collapse" msgid="4674876336725041982">"Isara ang mga mabilisang setting."</string> diff --git a/packages/SystemUI/res/values-tr/strings.xml b/packages/SystemUI/res/values-tr/strings.xml index e33944517393..2d2ccadd65d8 100644 --- a/packages/SystemUI/res/values-tr/strings.xml +++ b/packages/SystemUI/res/values-tr/strings.xml @@ -879,17 +879,6 @@ </string-array> <string name="tuner_low_priority" msgid="8412666814123009820">"Düşük öncelikli bildirim simgelerini göster"</string> <string name="other" msgid="429768510980739978">"Diğer"</string> - <string name="accessibility_divider" msgid="2830785970889237307">"Bölünmüş ekran ayırıcı"</string> - <string name="accessibility_action_divider_left_full" msgid="7598733539422375847">"Solda tam ekran"</string> - <string name="accessibility_action_divider_left_70" msgid="4919312892541727761">"Solda %70"</string> - <string name="accessibility_action_divider_left_50" msgid="3664701169564893826">"Solda %50"</string> - <string name="accessibility_action_divider_left_30" msgid="4358145268046362088">"Solda %30"</string> - <string name="accessibility_action_divider_right_full" msgid="8576057422864896305">"Sağda tam ekran"</string> - <string name="accessibility_action_divider_top_full" msgid="4243901660795169777">"Üstte tam ekran"</string> - <string name="accessibility_action_divider_top_70" msgid="6941226213260515072">"Üstte %70"</string> - <string name="accessibility_action_divider_top_50" msgid="6275211443706497621">"Üstte %50"</string> - <string name="accessibility_action_divider_top_30" msgid="5780597635887574916">"Üstte %30"</string> - <string name="accessibility_action_divider_bottom_full" msgid="7352434720610115395">"Altta tam ekran"</string> <string name="accessibility_qs_edit_tile_label" msgid="9079791448815232967">"<xliff:g id="POSITION">%1$d</xliff:g>. konum, <xliff:g id="TILE_NAME">%2$s</xliff:g>. Düzenlemek için iki kez dokunun."</string> <string name="accessibility_qs_edit_add_tile_label" msgid="8292218072049068613">"<xliff:g id="TILE_NAME">%1$s</xliff:g>. Eklemek için iki kez dokunun."</string> <string name="accessibility_qs_edit_move_tile" msgid="6027997446473163426">"<xliff:g id="TILE_NAME">%1$s</xliff:g> kutusunu taşı"</string> @@ -898,10 +887,6 @@ <string name="accessibility_qs_edit_tile_move" msgid="4841770637244326837">"<xliff:g id="TILE_NAME">%1$s</xliff:g> öğesini <xliff:g id="POSITION">%2$d</xliff:g> konumuna taşı"</string> <string name="accessibility_desc_quick_settings_edit" msgid="741658939453595297">"Hızlı ayar düzenleyicisi."</string> <string name="accessibility_desc_notification_icon" msgid="7331265967584178674">"<xliff:g id="ID_1">%1$s</xliff:g> bildirimi: <xliff:g id="ID_2">%2$s</xliff:g>"</string> - <string name="dock_forced_resizable" msgid="4689301323912928801">"Uygulama bölünmüş ekranda çalışmayabilir."</string> - <string name="dock_non_resizeble_failed_to_dock_text" msgid="7284915968096153808">"Uygulama bölünmüş ekranı desteklemiyor."</string> - <string name="forced_resizable_secondary_display" msgid="522558907654394940">"Uygulama ikincil ekranda çalışmayabilir."</string> - <string name="activity_launch_on_secondary_display_failed_text" msgid="8446727617187998208">"Uygulama ikincil ekranlarda başlatılmayı desteklemiyor."</string> <string name="accessibility_quick_settings_settings" msgid="7098489591715844713">"Ayarları aç."</string> <string name="accessibility_quick_settings_expand" msgid="2609275052412521467">"Hızlı ayarları aç."</string> <string name="accessibility_quick_settings_collapse" msgid="4674876336725041982">"Hızlı ayarları kapat."</string> diff --git a/packages/SystemUI/res/values-uk/strings.xml b/packages/SystemUI/res/values-uk/strings.xml index f5419f1d1290..1a8ce7b6ad76 100644 --- a/packages/SystemUI/res/values-uk/strings.xml +++ b/packages/SystemUI/res/values-uk/strings.xml @@ -889,17 +889,6 @@ </string-array> <string name="tuner_low_priority" msgid="8412666814123009820">"Показувати значки сповіщень із низьким пріоритетом"</string> <string name="other" msgid="429768510980739978">"Інше"</string> - <string name="accessibility_divider" msgid="2830785970889237307">"Розділювач екрана"</string> - <string name="accessibility_action_divider_left_full" msgid="7598733539422375847">"Ліве вікно на весь екран"</string> - <string name="accessibility_action_divider_left_70" msgid="4919312892541727761">"Ліве вікно на 70%"</string> - <string name="accessibility_action_divider_left_50" msgid="3664701169564893826">"Ліве вікно на 50%"</string> - <string name="accessibility_action_divider_left_30" msgid="4358145268046362088">"Ліве вікно на 30%"</string> - <string name="accessibility_action_divider_right_full" msgid="8576057422864896305">"Праве вікно на весь екран"</string> - <string name="accessibility_action_divider_top_full" msgid="4243901660795169777">"Верхнє вікно на весь екран"</string> - <string name="accessibility_action_divider_top_70" msgid="6941226213260515072">"Верхнє вікно на 70%"</string> - <string name="accessibility_action_divider_top_50" msgid="6275211443706497621">"Верхнє вікно на 50%"</string> - <string name="accessibility_action_divider_top_30" msgid="5780597635887574916">"Верхнє вікно на 30%"</string> - <string name="accessibility_action_divider_bottom_full" msgid="7352434720610115395">"Нижнє вікно на весь екран"</string> <string name="accessibility_qs_edit_tile_label" msgid="9079791448815232967">"Позиція <xliff:g id="POSITION">%1$d</xliff:g>, <xliff:g id="TILE_NAME">%2$s</xliff:g>. Двічі торкніться, щоб змінити."</string> <string name="accessibility_qs_edit_add_tile_label" msgid="8292218072049068613">"<xliff:g id="TILE_NAME">%1$s</xliff:g>. Двічі торкніться, щоб додати."</string> <string name="accessibility_qs_edit_move_tile" msgid="6027997446473163426">"Перемістити <xliff:g id="TILE_NAME">%1$s</xliff:g>"</string> @@ -908,10 +897,6 @@ <string name="accessibility_qs_edit_tile_move" msgid="4841770637244326837">"Перемістити <xliff:g id="TILE_NAME">%1$s</xliff:g> на позицію <xliff:g id="POSITION">%2$d</xliff:g>"</string> <string name="accessibility_desc_quick_settings_edit" msgid="741658939453595297">"Редактор швидких налаштувань."</string> <string name="accessibility_desc_notification_icon" msgid="7331265967584178674">"Сповіщення <xliff:g id="ID_1">%1$s</xliff:g>: <xliff:g id="ID_2">%2$s</xliff:g>"</string> - <string name="dock_forced_resizable" msgid="4689301323912928801">"Додаток може не працювати в режимі розділеного екрана."</string> - <string name="dock_non_resizeble_failed_to_dock_text" msgid="7284915968096153808">"Додаток не підтримує розділення екрана."</string> - <string name="forced_resizable_secondary_display" msgid="522558907654394940">"Додаток може не працювати на додатковому екрані."</string> - <string name="activity_launch_on_secondary_display_failed_text" msgid="8446727617187998208">"Додаток не підтримує запуск на додаткових екранах."</string> <string name="accessibility_quick_settings_settings" msgid="7098489591715844713">"Відкрити налаштування."</string> <string name="accessibility_quick_settings_expand" msgid="2609275052412521467">"Відкрити швидкі налаштування."</string> <string name="accessibility_quick_settings_collapse" msgid="4674876336725041982">"Закрити швидкі налаштування."</string> diff --git a/packages/SystemUI/res/values-ur/strings.xml b/packages/SystemUI/res/values-ur/strings.xml index 2abf3500ff4a..4f091d6bde09 100644 --- a/packages/SystemUI/res/values-ur/strings.xml +++ b/packages/SystemUI/res/values-ur/strings.xml @@ -879,17 +879,6 @@ </string-array> <string name="tuner_low_priority" msgid="8412666814123009820">"کم ترجیحی اطلاع کے آئیکنز دکھائیں"</string> <string name="other" msgid="429768510980739978">"دیگر"</string> - <string name="accessibility_divider" msgid="2830785970889237307">"سپلٹ اسکرین تقسیم کار"</string> - <string name="accessibility_action_divider_left_full" msgid="7598733539422375847">"بائیں فل اسکرین"</string> - <string name="accessibility_action_divider_left_70" msgid="4919312892541727761">"بائیں %70"</string> - <string name="accessibility_action_divider_left_50" msgid="3664701169564893826">"بائیں %50"</string> - <string name="accessibility_action_divider_left_30" msgid="4358145268046362088">"بائیں %30"</string> - <string name="accessibility_action_divider_right_full" msgid="8576057422864896305">"دائیں فل اسکرین"</string> - <string name="accessibility_action_divider_top_full" msgid="4243901660795169777">"بالائی فل اسکرین"</string> - <string name="accessibility_action_divider_top_70" msgid="6941226213260515072">"اوپر %70"</string> - <string name="accessibility_action_divider_top_50" msgid="6275211443706497621">"اوپر %50"</string> - <string name="accessibility_action_divider_top_30" msgid="5780597635887574916">"اوپر %30"</string> - <string name="accessibility_action_divider_bottom_full" msgid="7352434720610115395">"نچلی فل اسکرین"</string> <string name="accessibility_qs_edit_tile_label" msgid="9079791448815232967">"پوزیشن <xliff:g id="POSITION">%1$d</xliff:g>، <xliff:g id="TILE_NAME">%2$s</xliff:g>۔ ترمیم کرنے کیلئے دو بار تھپتھپائیں۔"</string> <string name="accessibility_qs_edit_add_tile_label" msgid="8292218072049068613">"<xliff:g id="TILE_NAME">%1$s</xliff:g>۔ شامل کرنے کیلئے دو بار تھپتھپائیں۔"</string> <string name="accessibility_qs_edit_move_tile" msgid="6027997446473163426">"<xliff:g id="TILE_NAME">%1$s</xliff:g> کو منتقل کریں"</string> @@ -898,10 +887,6 @@ <string name="accessibility_qs_edit_tile_move" msgid="4841770637244326837">"<xliff:g id="TILE_NAME">%1$s</xliff:g> کو پوزیشن <xliff:g id="POSITION">%2$d</xliff:g> میں منتقل کریں"</string> <string name="accessibility_desc_quick_settings_edit" msgid="741658939453595297">"فوری ترتیبات کا ایڈیٹر۔"</string> <string name="accessibility_desc_notification_icon" msgid="7331265967584178674">"<xliff:g id="ID_1">%1$s</xliff:g> اطلاع: <xliff:g id="ID_2">%2$s</xliff:g>"</string> - <string name="dock_forced_resizable" msgid="4689301323912928801">"ممکن ہے کہ ایپ سپلٹ اسکرین کے ساتھ کام نہ کرے۔"</string> - <string name="dock_non_resizeble_failed_to_dock_text" msgid="7284915968096153808">"ایپ سپلٹ اسکرین کو سپورٹ نہیں کرتی۔"</string> - <string name="forced_resizable_secondary_display" msgid="522558907654394940">"ممکن ہے ایپ ثانوی ڈسپلے پر کام نہ کرے۔"</string> - <string name="activity_launch_on_secondary_display_failed_text" msgid="8446727617187998208">"ایپ ثانوی ڈسپلیز پر شروعات کا تعاون نہیں کرتی۔"</string> <string name="accessibility_quick_settings_settings" msgid="7098489591715844713">"ترتیبات کھولیں۔"</string> <string name="accessibility_quick_settings_expand" msgid="2609275052412521467">"فوری ترتیبات کھولیں۔"</string> <string name="accessibility_quick_settings_collapse" msgid="4674876336725041982">"فوری ترتیبات بند کریں۔"</string> diff --git a/packages/SystemUI/res/values-uz/strings.xml b/packages/SystemUI/res/values-uz/strings.xml index 61b10a4ed24c..26a691a147ce 100644 --- a/packages/SystemUI/res/values-uz/strings.xml +++ b/packages/SystemUI/res/values-uz/strings.xml @@ -879,17 +879,6 @@ </string-array> <string name="tuner_low_priority" msgid="8412666814123009820">"Muhim boʻlmagan bildirishnoma ikonkalarini koʻrsatish"</string> <string name="other" msgid="429768510980739978">"Boshqa"</string> - <string name="accessibility_divider" msgid="2830785970889237307">"Ekranni ikkiga bo‘lish chizig‘i"</string> - <string name="accessibility_action_divider_left_full" msgid="7598733539422375847">"Chapda to‘liq ekran"</string> - <string name="accessibility_action_divider_left_70" msgid="4919312892541727761">"Chapda 70%"</string> - <string name="accessibility_action_divider_left_50" msgid="3664701169564893826">"Chapda 50%"</string> - <string name="accessibility_action_divider_left_30" msgid="4358145268046362088">"Chapda 30%"</string> - <string name="accessibility_action_divider_right_full" msgid="8576057422864896305">"O‘ngda to‘liq ekran"</string> - <string name="accessibility_action_divider_top_full" msgid="4243901660795169777">"Tepada to‘liq ekran"</string> - <string name="accessibility_action_divider_top_70" msgid="6941226213260515072">"Tepada 70%"</string> - <string name="accessibility_action_divider_top_50" msgid="6275211443706497621">"Tepada 50%"</string> - <string name="accessibility_action_divider_top_30" msgid="5780597635887574916">"Tepada 30%"</string> - <string name="accessibility_action_divider_bottom_full" msgid="7352434720610115395">"Pastda to‘liq ekran"</string> <string name="accessibility_qs_edit_tile_label" msgid="9079791448815232967">"<xliff:g id="POSITION">%1$d</xliff:g>-joy, “<xliff:g id="TILE_NAME">%2$s</xliff:g>” tugmasi. Tahrirlash uchun ustiga ikki marta bosing."</string> <string name="accessibility_qs_edit_add_tile_label" msgid="8292218072049068613">"“<xliff:g id="TILE_NAME">%1$s</xliff:g>” tugmasi. Qo‘shish uchun ustiga ikki marta bosing."</string> <string name="accessibility_qs_edit_move_tile" msgid="6027997446473163426">"“<xliff:g id="TILE_NAME">%1$s</xliff:g>” tugmasini ko‘chirish"</string> @@ -898,10 +887,6 @@ <string name="accessibility_qs_edit_tile_move" msgid="4841770637244326837">"<xliff:g id="POSITION">%2$d</xliff:g>-joyga buni ko‘chirish: <xliff:g id="TILE_NAME">%1$s</xliff:g>"</string> <string name="accessibility_desc_quick_settings_edit" msgid="741658939453595297">"Tezkor sozlamalar muharriri"</string> <string name="accessibility_desc_notification_icon" msgid="7331265967584178674">"<xliff:g id="ID_1">%1$s</xliff:g> bildirishnomasi: <xliff:g id="ID_2">%2$s</xliff:g>"</string> - <string name="dock_forced_resizable" msgid="4689301323912928801">"Ilova ekranni ikkiga bo‘lish rejimini qo‘llab-quvvatlamaydi."</string> - <string name="dock_non_resizeble_failed_to_dock_text" msgid="7284915968096153808">"Bu ilova ekranni bo‘lish xususiyatini qo‘llab-quvvatlamaydi."</string> - <string name="forced_resizable_secondary_display" msgid="522558907654394940">"Bu ilova qo‘shimcha ekranda ishlamasligi mumkin."</string> - <string name="activity_launch_on_secondary_display_failed_text" msgid="8446727617187998208">"Bu ilova qo‘shimcha ekranlarda ishga tushmaydi."</string> <string name="accessibility_quick_settings_settings" msgid="7098489591715844713">"Sozlamalarni ochish."</string> <string name="accessibility_quick_settings_expand" msgid="2609275052412521467">"Tezkor sozlamalarni ochish."</string> <string name="accessibility_quick_settings_collapse" msgid="4674876336725041982">"Tezkor sozlamalarni yopish."</string> diff --git a/packages/SystemUI/res/values-vi/strings.xml b/packages/SystemUI/res/values-vi/strings.xml index 6107270f10c5..bea99a9aa82e 100644 --- a/packages/SystemUI/res/values-vi/strings.xml +++ b/packages/SystemUI/res/values-vi/strings.xml @@ -879,17 +879,6 @@ </string-array> <string name="tuner_low_priority" msgid="8412666814123009820">"Hiển thị biểu tượng thông báo có mức ưu tiên thấp"</string> <string name="other" msgid="429768510980739978">"Khác"</string> - <string name="accessibility_divider" msgid="2830785970889237307">"Bộ chia chia đôi màn hình"</string> - <string name="accessibility_action_divider_left_full" msgid="7598733539422375847">"Toàn màn hình bên trái"</string> - <string name="accessibility_action_divider_left_70" msgid="4919312892541727761">"Trái 70%"</string> - <string name="accessibility_action_divider_left_50" msgid="3664701169564893826">"Trái 50%"</string> - <string name="accessibility_action_divider_left_30" msgid="4358145268046362088">"Trái 30%"</string> - <string name="accessibility_action_divider_right_full" msgid="8576057422864896305">"Toàn màn hình bên phải"</string> - <string name="accessibility_action_divider_top_full" msgid="4243901660795169777">"Toàn màn hình phía trên"</string> - <string name="accessibility_action_divider_top_70" msgid="6941226213260515072">"Trên 70%"</string> - <string name="accessibility_action_divider_top_50" msgid="6275211443706497621">"Trên 50%"</string> - <string name="accessibility_action_divider_top_30" msgid="5780597635887574916">"Trên 30%"</string> - <string name="accessibility_action_divider_bottom_full" msgid="7352434720610115395">"Toàn màn hình phía dưới"</string> <string name="accessibility_qs_edit_tile_label" msgid="9079791448815232967">"Vị trí <xliff:g id="POSITION">%1$d</xliff:g>, <xliff:g id="TILE_NAME">%2$s</xliff:g>. Nhấn đúp để chỉnh sửa."</string> <string name="accessibility_qs_edit_add_tile_label" msgid="8292218072049068613">"<xliff:g id="TILE_NAME">%1$s</xliff:g>. Nhấn đúp để thêm."</string> <string name="accessibility_qs_edit_move_tile" msgid="6027997446473163426">"Di chuyển <xliff:g id="TILE_NAME">%1$s</xliff:g>"</string> @@ -898,10 +887,6 @@ <string name="accessibility_qs_edit_tile_move" msgid="4841770637244326837">"Di chuyển <xliff:g id="TILE_NAME">%1$s</xliff:g> đến vị trí <xliff:g id="POSITION">%2$d</xliff:g>"</string> <string name="accessibility_desc_quick_settings_edit" msgid="741658939453595297">"Trình chỉnh sửa cài đặt nhanh."</string> <string name="accessibility_desc_notification_icon" msgid="7331265967584178674">"Thông báo của <xliff:g id="ID_1">%1$s</xliff:g>: <xliff:g id="ID_2">%2$s</xliff:g>"</string> - <string name="dock_forced_resizable" msgid="4689301323912928801">"Ứng dụng có thể không hoạt động với tính năng chia đôi màn hình."</string> - <string name="dock_non_resizeble_failed_to_dock_text" msgid="7284915968096153808">"Ứng dụng không hỗ trợ chia đôi màn hình."</string> - <string name="forced_resizable_secondary_display" msgid="522558907654394940">"Ứng dụng có thể không hoạt động trên màn hình phụ."</string> - <string name="activity_launch_on_secondary_display_failed_text" msgid="8446727617187998208">"Ứng dụng không hỗ trợ khởi chạy trên màn hình phụ."</string> <string name="accessibility_quick_settings_settings" msgid="7098489591715844713">"Mở phần cài đặt."</string> <string name="accessibility_quick_settings_expand" msgid="2609275052412521467">"Mở cài đặt nhanh."</string> <string name="accessibility_quick_settings_collapse" msgid="4674876336725041982">"Đóng cài đặt nhanh."</string> diff --git a/packages/SystemUI/res/values-zh-rCN/strings.xml b/packages/SystemUI/res/values-zh-rCN/strings.xml index ffd19956f471..8e73f36a74d3 100644 --- a/packages/SystemUI/res/values-zh-rCN/strings.xml +++ b/packages/SystemUI/res/values-zh-rCN/strings.xml @@ -879,17 +879,6 @@ </string-array> <string name="tuner_low_priority" msgid="8412666814123009820">"显示低优先级的通知图标"</string> <string name="other" msgid="429768510980739978">"其他"</string> - <string name="accessibility_divider" msgid="2830785970889237307">"分屏分隔线"</string> - <string name="accessibility_action_divider_left_full" msgid="7598733539422375847">"左侧全屏"</string> - <string name="accessibility_action_divider_left_70" msgid="4919312892541727761">"左侧 70%"</string> - <string name="accessibility_action_divider_left_50" msgid="3664701169564893826">"左侧 50%"</string> - <string name="accessibility_action_divider_left_30" msgid="4358145268046362088">"左侧 30%"</string> - <string name="accessibility_action_divider_right_full" msgid="8576057422864896305">"右侧全屏"</string> - <string name="accessibility_action_divider_top_full" msgid="4243901660795169777">"顶部全屏"</string> - <string name="accessibility_action_divider_top_70" msgid="6941226213260515072">"顶部 70%"</string> - <string name="accessibility_action_divider_top_50" msgid="6275211443706497621">"顶部 50%"</string> - <string name="accessibility_action_divider_top_30" msgid="5780597635887574916">"顶部 30%"</string> - <string name="accessibility_action_divider_bottom_full" msgid="7352434720610115395">"底部全屏"</string> <string name="accessibility_qs_edit_tile_label" msgid="9079791448815232967">"位置 <xliff:g id="POSITION">%1$d</xliff:g>,<xliff:g id="TILE_NAME">%2$s</xliff:g>。点按两次即可修改。"</string> <string name="accessibility_qs_edit_add_tile_label" msgid="8292218072049068613">"<xliff:g id="TILE_NAME">%1$s</xliff:g>。点按两次即可添加。"</string> <string name="accessibility_qs_edit_move_tile" msgid="6027997446473163426">"移动<xliff:g id="TILE_NAME">%1$s</xliff:g>"</string> @@ -898,10 +887,6 @@ <string name="accessibility_qs_edit_tile_move" msgid="4841770637244326837">"将“<xliff:g id="TILE_NAME">%1$s</xliff:g>”移动到位置 <xliff:g id="POSITION">%2$d</xliff:g>"</string> <string name="accessibility_desc_quick_settings_edit" msgid="741658939453595297">"快捷设置编辑器。"</string> <string name="accessibility_desc_notification_icon" msgid="7331265967584178674">"<xliff:g id="ID_1">%1$s</xliff:g>通知:<xliff:g id="ID_2">%2$s</xliff:g>"</string> - <string name="dock_forced_resizable" msgid="4689301323912928801">"应用可能无法在分屏模式下正常运行。"</string> - <string name="dock_non_resizeble_failed_to_dock_text" msgid="7284915968096153808">"应用不支持分屏。"</string> - <string name="forced_resizable_secondary_display" msgid="522558907654394940">"应用可能无法在辅显示屏上正常运行。"</string> - <string name="activity_launch_on_secondary_display_failed_text" msgid="8446727617187998208">"应用不支持在辅显示屏上启动。"</string> <string name="accessibility_quick_settings_settings" msgid="7098489591715844713">"打开设置。"</string> <string name="accessibility_quick_settings_expand" msgid="2609275052412521467">"开启快捷设置。"</string> <string name="accessibility_quick_settings_collapse" msgid="4674876336725041982">"关闭快捷设置。"</string> diff --git a/packages/SystemUI/res/values-zh-rHK/strings.xml b/packages/SystemUI/res/values-zh-rHK/strings.xml index 1575427f155b..08bf63b116cc 100644 --- a/packages/SystemUI/res/values-zh-rHK/strings.xml +++ b/packages/SystemUI/res/values-zh-rHK/strings.xml @@ -879,17 +879,6 @@ </string-array> <string name="tuner_low_priority" msgid="8412666814123009820">"顯示低優先順序通知圖示"</string> <string name="other" msgid="429768510980739978">"其他"</string> - <string name="accessibility_divider" msgid="2830785970889237307">"分割畫面分隔線"</string> - <string name="accessibility_action_divider_left_full" msgid="7598733539422375847">"左邊全螢幕"</string> - <string name="accessibility_action_divider_left_70" msgid="4919312892541727761">"左邊 70%"</string> - <string name="accessibility_action_divider_left_50" msgid="3664701169564893826">"左邊 50%"</string> - <string name="accessibility_action_divider_left_30" msgid="4358145268046362088">"左邊 30%"</string> - <string name="accessibility_action_divider_right_full" msgid="8576057422864896305">"右邊全螢幕"</string> - <string name="accessibility_action_divider_top_full" msgid="4243901660795169777">"頂部全螢幕"</string> - <string name="accessibility_action_divider_top_70" msgid="6941226213260515072">"頂部 70%"</string> - <string name="accessibility_action_divider_top_50" msgid="6275211443706497621">"頂部 50%"</string> - <string name="accessibility_action_divider_top_30" msgid="5780597635887574916">"頂部 30%"</string> - <string name="accessibility_action_divider_bottom_full" msgid="7352434720610115395">"底部全螢幕"</string> <string name="accessibility_qs_edit_tile_label" msgid="9079791448815232967">"位置 <xliff:g id="POSITION">%1$d</xliff:g>,<xliff:g id="TILE_NAME">%2$s</xliff:g>。輕按兩下即可編輯。"</string> <string name="accessibility_qs_edit_add_tile_label" msgid="8292218072049068613">"<xliff:g id="TILE_NAME">%1$s</xliff:g>。輕按兩下即可新增。"</string> <string name="accessibility_qs_edit_move_tile" msgid="6027997446473163426">"移動 <xliff:g id="TILE_NAME">%1$s</xliff:g>"</string> @@ -898,10 +887,6 @@ <string name="accessibility_qs_edit_tile_move" msgid="4841770637244326837">"將「<xliff:g id="TILE_NAME">%1$s</xliff:g>」移去位置 <xliff:g id="POSITION">%2$d</xliff:g>"</string> <string name="accessibility_desc_quick_settings_edit" msgid="741658939453595297">"快速設定編輯工具。"</string> <string name="accessibility_desc_notification_icon" msgid="7331265967584178674">"<xliff:g id="ID_1">%1$s</xliff:g> 通知:<xliff:g id="ID_2">%2$s</xliff:g>"</string> - <string name="dock_forced_resizable" msgid="4689301323912928801">"應用程式可能無法在分割畫面中運作。"</string> - <string name="dock_non_resizeble_failed_to_dock_text" msgid="7284915968096153808">"應用程式不支援分割畫面。"</string> - <string name="forced_resizable_secondary_display" msgid="522558907654394940">"應用程式可能無法在次要顯示屏上運作。"</string> - <string name="activity_launch_on_secondary_display_failed_text" msgid="8446727617187998208">"應用程式無法在次要顯示屏上啟動。"</string> <string name="accessibility_quick_settings_settings" msgid="7098489591715844713">"開啟設定。"</string> <string name="accessibility_quick_settings_expand" msgid="2609275052412521467">"開啟快速設定。"</string> <string name="accessibility_quick_settings_collapse" msgid="4674876336725041982">"關閉快速設定。"</string> diff --git a/packages/SystemUI/res/values-zh-rTW/strings.xml b/packages/SystemUI/res/values-zh-rTW/strings.xml index bbd83551c0f9..3e7d2e481630 100644 --- a/packages/SystemUI/res/values-zh-rTW/strings.xml +++ b/packages/SystemUI/res/values-zh-rTW/strings.xml @@ -879,17 +879,6 @@ </string-array> <string name="tuner_low_priority" msgid="8412666814123009820">"顯示低優先順序通知圖示"</string> <string name="other" msgid="429768510980739978">"其他"</string> - <string name="accessibility_divider" msgid="2830785970889237307">"分割畫面分隔線"</string> - <string name="accessibility_action_divider_left_full" msgid="7598733539422375847">"以全螢幕顯示左側畫面"</string> - <string name="accessibility_action_divider_left_70" msgid="4919312892541727761">"以 70% 的螢幕空間顯示左側畫面"</string> - <string name="accessibility_action_divider_left_50" msgid="3664701169564893826">"以 50% 的螢幕空間顯示左側畫面"</string> - <string name="accessibility_action_divider_left_30" msgid="4358145268046362088">"以 30% 的螢幕空間顯示左側畫面"</string> - <string name="accessibility_action_divider_right_full" msgid="8576057422864896305">"以全螢幕顯示右側畫面"</string> - <string name="accessibility_action_divider_top_full" msgid="4243901660795169777">"以全螢幕顯示頂端畫面"</string> - <string name="accessibility_action_divider_top_70" msgid="6941226213260515072">"以 70% 的螢幕空間顯示頂端畫面"</string> - <string name="accessibility_action_divider_top_50" msgid="6275211443706497621">"以 50% 的螢幕空間顯示頂端畫面"</string> - <string name="accessibility_action_divider_top_30" msgid="5780597635887574916">"以 30% 的螢幕空間顯示頂端畫面"</string> - <string name="accessibility_action_divider_bottom_full" msgid="7352434720610115395">"以全螢幕顯示底部畫面"</string> <string name="accessibility_qs_edit_tile_label" msgid="9079791448815232967">"位置 <xliff:g id="POSITION">%1$d</xliff:g>,<xliff:g id="TILE_NAME">%2$s</xliff:g>。輕觸兩下即可編輯。"</string> <string name="accessibility_qs_edit_add_tile_label" msgid="8292218072049068613">"<xliff:g id="TILE_NAME">%1$s</xliff:g>。輕觸兩下即可新增。"</string> <string name="accessibility_qs_edit_move_tile" msgid="6027997446473163426">"移動 <xliff:g id="TILE_NAME">%1$s</xliff:g>"</string> @@ -898,10 +887,6 @@ <string name="accessibility_qs_edit_tile_move" msgid="4841770637244326837">"將 <xliff:g id="TILE_NAME">%1$s</xliff:g> 移到位置 <xliff:g id="POSITION">%2$d</xliff:g>"</string> <string name="accessibility_desc_quick_settings_edit" msgid="741658939453595297">"快速設定編輯器。"</string> <string name="accessibility_desc_notification_icon" msgid="7331265967584178674">"<xliff:g id="ID_1">%1$s</xliff:g> 通知:<xliff:g id="ID_2">%2$s</xliff:g>"</string> - <string name="dock_forced_resizable" msgid="4689301323912928801">"應用程式可能無法在分割畫面中運作。"</string> - <string name="dock_non_resizeble_failed_to_dock_text" msgid="7284915968096153808">"這個應用程式不支援分割畫面。"</string> - <string name="forced_resizable_secondary_display" msgid="522558907654394940">"應用程式可能無法在次要顯示器上運作。"</string> - <string name="activity_launch_on_secondary_display_failed_text" msgid="8446727617187998208">"應用程式無法在次要顯示器上啟動。"</string> <string name="accessibility_quick_settings_settings" msgid="7098489591715844713">"開啟設定。"</string> <string name="accessibility_quick_settings_expand" msgid="2609275052412521467">"開啟快速設定。"</string> <string name="accessibility_quick_settings_collapse" msgid="4674876336725041982">"關閉快速設定。"</string> diff --git a/packages/SystemUI/res/values-zu/strings.xml b/packages/SystemUI/res/values-zu/strings.xml index 63b4c613a06a..f93ff1d85db8 100644 --- a/packages/SystemUI/res/values-zu/strings.xml +++ b/packages/SystemUI/res/values-zu/strings.xml @@ -879,17 +879,6 @@ </string-array> <string name="tuner_low_priority" msgid="8412666814123009820">"Bonisa izithonjana zesaziso zokubaluleka okuncane"</string> <string name="other" msgid="429768510980739978">"Okunye"</string> - <string name="accessibility_divider" msgid="2830785970889237307">"Isihlukanisi sokuhlukanisa isikrini"</string> - <string name="accessibility_action_divider_left_full" msgid="7598733539422375847">"Isikrini esigcwele esingakwesokunxele"</string> - <string name="accessibility_action_divider_left_70" msgid="4919312892541727761">"Kwesokunxele ngo-70%"</string> - <string name="accessibility_action_divider_left_50" msgid="3664701169564893826">"Kwesokunxele ngo-50%"</string> - <string name="accessibility_action_divider_left_30" msgid="4358145268046362088">"Kwesokunxele ngo-30%"</string> - <string name="accessibility_action_divider_right_full" msgid="8576057422864896305">"Isikrini esigcwele esingakwesokudla"</string> - <string name="accessibility_action_divider_top_full" msgid="4243901660795169777">"Isikrini esigcwele esiphezulu"</string> - <string name="accessibility_action_divider_top_70" msgid="6941226213260515072">"Okuphezulu okungu-70%"</string> - <string name="accessibility_action_divider_top_50" msgid="6275211443706497621">"Okuphezulu okungu-50%"</string> - <string name="accessibility_action_divider_top_30" msgid="5780597635887574916">"Okuphezulu okungu-30%"</string> - <string name="accessibility_action_divider_bottom_full" msgid="7352434720610115395">"Ngaphansi kwesikrini esigcwele"</string> <string name="accessibility_qs_edit_tile_label" msgid="9079791448815232967">"Isimo esingu-<xliff:g id="POSITION">%1$d</xliff:g>, <xliff:g id="TILE_NAME">%2$s</xliff:g>. Thepha kabili ukuze uhlele."</string> <string name="accessibility_qs_edit_add_tile_label" msgid="8292218072049068613">"<xliff:g id="TILE_NAME">%1$s</xliff:g>. Thepha kabili ukuze ungeze."</string> <string name="accessibility_qs_edit_move_tile" msgid="6027997446473163426">"Hambisa i-<xliff:g id="TILE_NAME">%1$s</xliff:g>"</string> @@ -898,10 +887,6 @@ <string name="accessibility_qs_edit_tile_move" msgid="4841770637244326837">"Hambisa i-<xliff:g id="TILE_NAME">%1$s</xliff:g> ukuze ubeke i-<xliff:g id="POSITION">%2$d</xliff:g>"</string> <string name="accessibility_desc_quick_settings_edit" msgid="741658939453595297">"Isihleli sezilungiselelo ezisheshayo."</string> <string name="accessibility_desc_notification_icon" msgid="7331265967584178674">"<xliff:g id="ID_1">%1$s</xliff:g> isaziso: <xliff:g id="ID_2">%2$s</xliff:g>"</string> - <string name="dock_forced_resizable" msgid="4689301323912928801">"Izinhlelo zokusebenza kungenzeka zingasebenzi ngesikrini esihlukanisiwe."</string> - <string name="dock_non_resizeble_failed_to_dock_text" msgid="7284915968096153808">"Uhlelo lokusebenza alusekeli isikrini esihlukanisiwe."</string> - <string name="forced_resizable_secondary_display" msgid="522558907654394940">"Uhlelo lokusebenza kungenzeka lungasebenzi kusibonisi sesibili."</string> - <string name="activity_launch_on_secondary_display_failed_text" msgid="8446727617187998208">"Uhlelo lokusebenza alusekeli ukuqalisa kuzibonisi zesibili."</string> <string name="accessibility_quick_settings_settings" msgid="7098489591715844713">"Vula izilungiselelo."</string> <string name="accessibility_quick_settings_expand" msgid="2609275052412521467">"Vula izilungiselelo ezisheshayo."</string> <string name="accessibility_quick_settings_collapse" msgid="4674876336725041982">"Vala izilungiselelo ezisheshayo."</string> diff --git a/packages/SystemUI/res/values/config.xml b/packages/SystemUI/res/values/config.xml index 1c3fba2abacd..ab09a967bc26 100644 --- a/packages/SystemUI/res/values/config.xml +++ b/packages/SystemUI/res/values/config.xml @@ -560,9 +560,6 @@ <!-- If the config font scale is >= this value, potentially adjust the number of columns--> <item name="controls_max_columns_adjust_above_font_scale" translatable="false" format="float" type="dimen">1.25</item> - <!-- Allow one handed to enable round corner --> - <bool name="config_one_handed_enable_round_corner">true</bool> - <!-- Show a separate icon for low and high volume on the volume dialog --> <bool name="config_showLowMediaVolumeIcon">false</bool> </resources> diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml index 76c61fb6e1e5..875fe1471b1c 100644 --- a/packages/SystemUI/res/values/dimens.xml +++ b/packages/SystemUI/res/values/dimens.xml @@ -1366,8 +1366,4 @@ <dimen name="config_rounded_mask_size">@*android:dimen/rounded_corner_radius</dimen> <dimen name="config_rounded_mask_size_top">@*android:dimen/rounded_corner_radius_top</dimen> <dimen name="config_rounded_mask_size_bottom">@*android:dimen/rounded_corner_radius_bottom</dimen> - - <!-- One-Handed Mode --> - <!-- Threshold for dragging distance to enable one-handed mode --> - <dimen name="gestures_onehanded_drag_threshold">20dp</dimen> </resources> diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml index e58bf3bad795..cca70f9aa518 100644 --- a/packages/SystemUI/res/values/strings.xml +++ b/packages/SystemUI/res/values/strings.xml @@ -2799,9 +2799,4 @@ <string name="udfps_hbm_enable_command" translatable="false"></string> <!-- Device-specific payload for disabling the high-brightness mode --> <string name="udfps_hbm_disable_command" translatable="false"></string> - - <!-- One-Handed Tutorial title [CHAR LIMIT=60] --> - <string name="one_handed_tutorial_title">Using one-handed mode</string> - <!-- One-Handed Tutorial description [CHAR LIMIT=NONE] --> - <string name="one_handed_tutorial_description">To exit, swipe up from the bottom of the screen or tap anywhere above the app</string> </resources> diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/InputChannelCompat.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/InputChannelCompat.java index 2b1fce8a4cf5..ffde84128549 100644 --- a/packages/SystemUI/shared/src/com/android/systemui/shared/system/InputChannelCompat.java +++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/InputChannelCompat.java @@ -41,16 +41,6 @@ public class InputChannelCompat { } /** - * Creates a dispatcher from the extras received as part on onInitialize - */ - public static InputEventReceiver fromBundle(Bundle params, String key, - Looper looper, Choreographer choreographer, InputEventListener listener) { - - InputChannel channel = params.getParcelable(key); - return new InputEventReceiver(channel, looper, choreographer, listener); - } - - /** * Version of addBatch method which preserves time accuracy in nanoseconds instead of * converting the time to milliseconds. * @param src old MotionEvent where the target should be appended @@ -69,11 +59,9 @@ public class InputChannelCompat { public static class InputEventReceiver { private final BatchedInputEventReceiver mReceiver; - private final InputChannel mInputChannel; public InputEventReceiver(InputChannel inputChannel, Looper looper, Choreographer choreographer, final InputEventListener listener) { - mInputChannel = inputChannel; mReceiver = new BatchedInputEventReceiver(inputChannel, looper, choreographer) { @Override @@ -85,40 +73,17 @@ public class InputChannelCompat { } /** - * @see BatchedInputEventReceiver#dispose() + * @see BatchedInputEventReceiver#setBatchingEnabled() */ - public void dispose() { - mReceiver.dispose(); - mInputChannel.dispose(); - } - } - - /** - * @see InputEventSender - */ - public static class InputEventDispatcher { - - private final InputChannel mInputChannel; - private final InputEventSender mSender; - - public InputEventDispatcher(InputChannel inputChannel, Looper looper) { - mInputChannel = inputChannel; - mSender = new InputEventSender(inputChannel, looper) { }; - } - - /** - * @see InputEventSender#sendInputEvent(int, InputEvent) - */ - public void dispatch(InputEvent ev) { - mSender.sendInputEvent(ev.getSequenceNumber(), ev); + public void setBatchingEnabled(boolean batchingEnabled) { + mReceiver.setBatchingEnabled(batchingEnabled); } /** - * @see InputEventSender#dispose() + * @see BatchedInputEventReceiver#dispose() */ public void dispose() { - mSender.dispose(); - mInputChannel.dispose(); + mReceiver.dispose(); } } } diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/WindowManagerWrapper.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/WindowManagerWrapper.java index d64bf77ad9d5..067ac9ec7b1e 100644 --- a/packages/SystemUI/shared/src/com/android/systemui/shared/system/WindowManagerWrapper.java +++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/WindowManagerWrapper.java @@ -153,12 +153,9 @@ public class WindowManagerWrapper { } } + @Deprecated public void setPipVisibility(final boolean visible) { - try { - WindowManagerGlobal.getWindowManagerService().setPipVisibility(visible); - } catch (RemoteException e) { - Log.e(TAG, "Unable to reach window manager", e); - } + // To be removed } /** diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardHostView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardHostView.java index 57b3761c294f..08e9cf60a65a 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardHostView.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardHostView.java @@ -16,32 +16,11 @@ package com.android.keyguard; -import android.app.ActivityManager; import android.content.Context; -import android.content.res.ColorStateList; -import android.content.res.Resources; import android.graphics.Canvas; -import android.media.AudioManager; -import android.os.SystemClock; -import android.service.trust.TrustAgentService; -import android.telephony.TelephonyManager; import android.util.AttributeSet; -import android.util.Log; -import android.view.KeyEvent; import android.widget.FrameLayout; -import androidx.annotation.VisibleForTesting; - -import com.android.internal.widget.LockPatternUtils; -import com.android.keyguard.KeyguardSecurityContainer.SecurityCallback; -import com.android.keyguard.KeyguardSecurityModel.SecurityMode; -import com.android.settingslib.Utils; -import com.android.systemui.Dependency; -import com.android.systemui.R; -import com.android.systemui.plugins.ActivityStarter.OnDismissAction; - -import java.io.File; - /** * Base class for keyguard view. {@link #reset} is where you should * reset the state of your view. Use the {@link KeyguardViewCallback} via @@ -51,59 +30,10 @@ import java.io.File; * Handles intercepting of media keys that still work when the keyguard is * showing. */ -public class KeyguardHostView extends FrameLayout implements SecurityCallback { +public class KeyguardHostView extends FrameLayout { - private AudioManager mAudioManager; - private TelephonyManager mTelephonyManager = null; protected ViewMediatorCallback mViewMediatorCallback; - protected LockPatternUtils mLockPatternUtils; - private OnDismissAction mDismissAction; - private Runnable mCancelAction; - private final KeyguardUpdateMonitorCallback mUpdateCallback = - new KeyguardUpdateMonitorCallback() { - - @Override - public void onUserSwitchComplete(int userId) { - getSecurityContainer().showPrimarySecurityScreen(false /* turning off */); - } - - @Override - public void onTrustGrantedWithFlags(int flags, int userId) { - if (userId != KeyguardUpdateMonitor.getCurrentUser()) return; - if (!isAttachedToWindow()) return; - boolean bouncerVisible = isVisibleToUser(); - boolean initiatedByUser = - (flags & TrustAgentService.FLAG_GRANT_TRUST_INITIATED_BY_USER) != 0; - boolean dismissKeyguard = - (flags & TrustAgentService.FLAG_GRANT_TRUST_DISMISS_KEYGUARD) != 0; - - if (initiatedByUser || dismissKeyguard) { - if (mViewMediatorCallback.isScreenOn() && (bouncerVisible || dismissKeyguard)) { - if (!bouncerVisible) { - // The trust agent dismissed the keyguard without the user proving - // that they are present (by swiping up to show the bouncer). That's fine if - // the user proved presence via some other way to the trust agent. - Log.i(TAG, "TrustAgent dismissed Keyguard."); - } - dismiss(false /* authenticated */, userId, - /* bypassSecondaryLockScreen */ false); - } else { - mViewMediatorCallback.playTrustedSound(); - } - } - } - }; - - // Whether the volume keys should be handled by keyguard. If true, then - // they will be handled here for specific media types such as music, otherwise - // the audio service will bring up the volume dialog. - private static final boolean KEYGUARD_MANAGES_VOLUME = false; - public static final boolean DEBUG = KeyguardConstants.DEBUG; - private static final String TAG = "KeyguardViewBase"; - - @VisibleForTesting - protected KeyguardSecurityContainer mSecurityContainer; public KeyguardHostView(Context context) { this(context, null); @@ -111,7 +41,6 @@ public class KeyguardHostView extends FrameLayout implements SecurityCallback { public KeyguardHostView(Context context, AttributeSet attrs) { super(context, attrs); - Dependency.get(KeyguardUpdateMonitor.class).registerCallback(mUpdateCallback); } @Override @@ -122,337 +51,7 @@ public class KeyguardHostView extends FrameLayout implements SecurityCallback { } } - /** - * Sets an action to run when keyguard finishes. - * - * @param action - */ - public void setOnDismissAction(OnDismissAction action, Runnable cancelAction) { - if (mCancelAction != null) { - mCancelAction.run(); - mCancelAction = null; - } - mDismissAction = action; - mCancelAction = cancelAction; - } - - public boolean hasDismissActions() { - return mDismissAction != null || mCancelAction != null; - } - - public void cancelDismissAction() { - setOnDismissAction(null, null); - } - - @Override - protected void onFinishInflate() { - mSecurityContainer = - findViewById(R.id.keyguard_security_container); - mLockPatternUtils = new LockPatternUtils(mContext); - mSecurityContainer.setLockPatternUtils(mLockPatternUtils); - mSecurityContainer.setSecurityCallback(this); - mSecurityContainer.showPrimarySecurityScreen(false); - } - - /** - * Called when the view needs to be shown. - */ - public void showPrimarySecurityScreen() { - if (DEBUG) Log.d(TAG, "show()"); - mSecurityContainer.showPrimarySecurityScreen(false); - } - - public KeyguardSecurityView getCurrentSecurityView() { - return mSecurityContainer != null ? mSecurityContainer.getCurrentSecurityView() : null; - } - - /** - * Show a string explaining why the security view needs to be solved. - * - * @param reason a flag indicating which string should be shown, see - * {@link KeyguardSecurityView#PROMPT_REASON_NONE}, - * {@link KeyguardSecurityView#PROMPT_REASON_RESTART}, - * {@link KeyguardSecurityView#PROMPT_REASON_TIMEOUT}, and - * {@link KeyguardSecurityView#PROMPT_REASON_PREPARE_FOR_UPDATE}. - */ - public void showPromptReason(int reason) { - mSecurityContainer.showPromptReason(reason); - } - - public void showMessage(CharSequence message, ColorStateList colorState) { - mSecurityContainer.showMessage(message, colorState); - } - - public void showErrorMessage(CharSequence message) { - showMessage(message, Utils.getColorError(mContext)); - } - - /** - * Dismisses the keyguard by going to the next screen or making it gone. - * @param targetUserId a user that needs to be the foreground user at the dismissal completion. - * @return True if the keyguard is done. - */ - public boolean dismiss(int targetUserId) { - return dismiss(false, targetUserId, false); - } - - public boolean handleBackKey() { - if (mSecurityContainer.getCurrentSecuritySelection() != SecurityMode.None) { - mSecurityContainer.dismiss(false, KeyguardUpdateMonitor.getCurrentUser()); - return true; - } - return false; - } - - protected KeyguardSecurityContainer getSecurityContainer() { - return mSecurityContainer; - } - - @Override - public boolean dismiss(boolean authenticated, int targetUserId, - boolean bypassSecondaryLockScreen) { - return mSecurityContainer.showNextSecurityScreenOrFinish(authenticated, targetUserId, - bypassSecondaryLockScreen); - } - - /** - * Authentication has happened and it's time to dismiss keyguard. This function - * should clean up and inform KeyguardViewMediator. - * - * @param strongAuth whether the user has authenticated with strong authentication like - * pattern, password or PIN but not by trust agents or fingerprint - * @param targetUserId a user that needs to be the foreground user at the dismissal completion. - */ - @Override - public void finish(boolean strongAuth, int targetUserId) { - // If there's a pending runnable because the user interacted with a widget - // and we're leaving keyguard, then run it. - boolean deferKeyguardDone = false; - if (mDismissAction != null) { - deferKeyguardDone = mDismissAction.onDismiss(); - mDismissAction = null; - mCancelAction = null; - } - if (mViewMediatorCallback != null) { - if (deferKeyguardDone) { - mViewMediatorCallback.keyguardDonePending(strongAuth, targetUserId); - } else { - mViewMediatorCallback.keyguardDone(strongAuth, targetUserId); - } - } - } - - @Override - public void reset() { - mViewMediatorCallback.resetKeyguard(); - } - - @Override - public void onCancelClicked() { - mViewMediatorCallback.onCancelClicked(); - } - - public void resetSecurityContainer() { - mSecurityContainer.reset(); - } - - @Override - public void onSecurityModeChanged(SecurityMode securityMode, boolean needsInput) { - if (mViewMediatorCallback != null) { - mViewMediatorCallback.setNeedsInput(needsInput); - } - } - - public CharSequence getAccessibilityTitleForCurrentMode() { - return mSecurityContainer.getTitle(); - } - - public void userActivity() { - if (mViewMediatorCallback != null) { - mViewMediatorCallback.userActivity(); - } - } - - /** - * Called when the Keyguard is not actively shown anymore on the screen. - */ - public void onPause() { - if (DEBUG) Log.d(TAG, String.format("screen off, instance %s at %s", - Integer.toHexString(hashCode()), SystemClock.uptimeMillis())); - mSecurityContainer.showPrimarySecurityScreen(true); - mSecurityContainer.onPause(); - clearFocus(); - } - - /** - * Called when the Keyguard is actively shown on the screen. - */ - public void onResume() { - if (DEBUG) Log.d(TAG, "screen on, instance " + Integer.toHexString(hashCode())); - mSecurityContainer.onResume(KeyguardSecurityView.SCREEN_ON); - requestFocus(); - } - - /** - * Starts the animation when the Keyguard gets shown. - */ - public void startAppearAnimation() { - mSecurityContainer.startAppearAnimation(); - } - - public void startDisappearAnimation(Runnable finishRunnable) { - if (!mSecurityContainer.startDisappearAnimation(finishRunnable) && finishRunnable != null) { - finishRunnable.run(); - } - } - - /** - * Called before this view is being removed. - */ - public void cleanUp() { - getSecurityContainer().onPause(); - } - - @Override - public boolean dispatchKeyEvent(KeyEvent event) { - if (interceptMediaKey(event)) { - return true; - } - return super.dispatchKeyEvent(event); - } - - /** - * Allows the media keys to work when the keyguard is showing. - * The media keys should be of no interest to the actual keyguard view(s), - * so intercepting them here should not be of any harm. - * @param event The key event - * @return whether the event was consumed as a media key. - */ - public boolean interceptMediaKey(KeyEvent event) { - final int keyCode = event.getKeyCode(); - if (event.getAction() == KeyEvent.ACTION_DOWN) { - switch (keyCode) { - case KeyEvent.KEYCODE_MEDIA_PLAY: - case KeyEvent.KEYCODE_MEDIA_PAUSE: - case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE: - /* Suppress PLAY/PAUSE toggle when phone is ringing or - * in-call to avoid music playback */ - if (mTelephonyManager == null) { - mTelephonyManager = (TelephonyManager) getContext().getSystemService( - Context.TELEPHONY_SERVICE); - } - if (mTelephonyManager != null && - mTelephonyManager.getCallState() != TelephonyManager.CALL_STATE_IDLE) { - return true; // suppress key event - } - case KeyEvent.KEYCODE_MUTE: - case KeyEvent.KEYCODE_HEADSETHOOK: - case KeyEvent.KEYCODE_MEDIA_STOP: - case KeyEvent.KEYCODE_MEDIA_NEXT: - case KeyEvent.KEYCODE_MEDIA_PREVIOUS: - case KeyEvent.KEYCODE_MEDIA_REWIND: - case KeyEvent.KEYCODE_MEDIA_RECORD: - case KeyEvent.KEYCODE_MEDIA_FAST_FORWARD: - case KeyEvent.KEYCODE_MEDIA_AUDIO_TRACK: { - handleMediaKeyEvent(event); - return true; - } - - case KeyEvent.KEYCODE_VOLUME_UP: - case KeyEvent.KEYCODE_VOLUME_DOWN: - case KeyEvent.KEYCODE_VOLUME_MUTE: { - if (KEYGUARD_MANAGES_VOLUME) { - synchronized (this) { - if (mAudioManager == null) { - mAudioManager = (AudioManager) getContext().getSystemService( - Context.AUDIO_SERVICE); - } - } - // Volume buttons should only function for music (local or remote). - // TODO: Actually handle MUTE. - mAudioManager.adjustSuggestedStreamVolume( - keyCode == KeyEvent.KEYCODE_VOLUME_UP - ? AudioManager.ADJUST_RAISE - : AudioManager.ADJUST_LOWER /* direction */, - AudioManager.STREAM_MUSIC /* stream */, 0 /* flags */); - // Don't execute default volume behavior - return true; - } else { - return false; - } - } - } - } else if (event.getAction() == KeyEvent.ACTION_UP) { - switch (keyCode) { - case KeyEvent.KEYCODE_MUTE: - case KeyEvent.KEYCODE_HEADSETHOOK: - case KeyEvent.KEYCODE_MEDIA_PLAY: - case KeyEvent.KEYCODE_MEDIA_PAUSE: - case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE: - case KeyEvent.KEYCODE_MEDIA_STOP: - case KeyEvent.KEYCODE_MEDIA_NEXT: - case KeyEvent.KEYCODE_MEDIA_PREVIOUS: - case KeyEvent.KEYCODE_MEDIA_REWIND: - case KeyEvent.KEYCODE_MEDIA_RECORD: - case KeyEvent.KEYCODE_MEDIA_FAST_FORWARD: - case KeyEvent.KEYCODE_MEDIA_AUDIO_TRACK: { - handleMediaKeyEvent(event); - return true; - } - } - } - return false; - } - - private void handleMediaKeyEvent(KeyEvent keyEvent) { - synchronized (this) { - if (mAudioManager == null) { - mAudioManager = (AudioManager) getContext().getSystemService( - Context.AUDIO_SERVICE); - } - } - mAudioManager.dispatchMediaKeyEvent(keyEvent); - } - - /** - * In general, we enable unlocking the insecure keyguard with the menu key. However, there are - * some cases where we wish to disable it, notably when the menu button placement or technology - * is prone to false positives. - * - * @return true if the menu key should be enabled - */ - private static final String ENABLE_MENU_KEY_FILE = "/data/local/enable_menu_key"; - public boolean shouldEnableMenuKey() { - final Resources res = getResources(); - final boolean configDisabled = res.getBoolean(R.bool.config_disableMenuKeyInLockScreen); - final boolean isTestHarness = ActivityManager.isRunningInTestHarness(); - final boolean fileOverride = (new File(ENABLE_MENU_KEY_FILE)).exists(); - return !configDisabled || isTestHarness || fileOverride; - } - public void setViewMediatorCallback(ViewMediatorCallback viewMediatorCallback) { mViewMediatorCallback = viewMediatorCallback; - // Update ViewMediator with the current input method requirements - mViewMediatorCallback.setNeedsInput(mSecurityContainer.needsInput()); - } - - public void setLockPatternUtils(LockPatternUtils utils) { - mLockPatternUtils = utils; - mSecurityContainer.setLockPatternUtils(utils); - } - - public SecurityMode getSecurityMode() { - return mSecurityContainer.getSecurityMode(); - } - - public SecurityMode getCurrentSecurityMode() { - return mSecurityContainer.getCurrentSecurityMode(); - } - - /** - * When bouncer was visible and is starting to become hidden. - */ - public void onStartingToHide() { - mSecurityContainer.onStartingToHide(); } } diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardHostViewController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardHostViewController.java new file mode 100644 index 000000000000..7aabb17de90c --- /dev/null +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardHostViewController.java @@ -0,0 +1,460 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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; + +import android.app.ActivityManager; +import android.content.res.ColorStateList; +import android.content.res.Resources; +import android.media.AudioManager; +import android.os.SystemClock; +import android.service.trust.TrustAgentService; +import android.telephony.TelephonyManager; +import android.util.Log; +import android.util.MathUtils; +import android.view.KeyEvent; +import android.view.View; +import android.view.View.OnKeyListener; +import android.view.ViewTreeObserver; + +import com.android.keyguard.KeyguardSecurityContainer.SecurityCallback; +import com.android.keyguard.KeyguardSecurityModel.SecurityMode; +import com.android.keyguard.dagger.KeyguardBouncerScope; +import com.android.settingslib.Utils; +import com.android.systemui.R; +import com.android.systemui.plugins.ActivityStarter; +import com.android.systemui.statusbar.phone.KeyguardBouncer; +import com.android.systemui.util.ViewController; + +import java.io.File; + +import javax.inject.Inject; + +/** Controller for a {@link KeyguardHostView}. */ +@KeyguardBouncerScope +public class KeyguardHostViewController extends ViewController<KeyguardHostView> { + private static final String TAG = "KeyguardViewBase"; + public static final boolean DEBUG = KeyguardConstants.DEBUG; + // Whether the volume keys should be handled by keyguard. If true, then + // they will be handled here for specific media types such as music, otherwise + // the audio service will bring up the volume dialog. + private static final boolean KEYGUARD_MANAGES_VOLUME = false; + + private static final String ENABLE_MENU_KEY_FILE = "/data/local/enable_menu_key"; + + private final KeyguardUpdateMonitor mKeyguardUpdateMonitor; + private final KeyguardSecurityContainerController mKeyguardSecurityContainerController; + private final TelephonyManager mTelephonyManager; + private final ViewMediatorCallback mViewMediatorCallback; + private final AudioManager mAudioManager; + + private ActivityStarter.OnDismissAction mDismissAction; + private Runnable mCancelAction; + + private final KeyguardUpdateMonitorCallback mUpdateCallback = + new KeyguardUpdateMonitorCallback() { + @Override + public void onUserSwitchComplete(int userId) { + mKeyguardSecurityContainerController.showPrimarySecurityScreen( + false /* turning off */); + } + + @Override + public void onTrustGrantedWithFlags(int flags, int userId) { + if (userId != KeyguardUpdateMonitor.getCurrentUser()) return; + boolean bouncerVisible = mView.isVisibleToUser(); + boolean initiatedByUser = + (flags & TrustAgentService.FLAG_GRANT_TRUST_INITIATED_BY_USER) != 0; + boolean dismissKeyguard = + (flags & TrustAgentService.FLAG_GRANT_TRUST_DISMISS_KEYGUARD) != 0; + + if (initiatedByUser || dismissKeyguard) { + if (mViewMediatorCallback.isScreenOn() + && (bouncerVisible || dismissKeyguard)) { + if (!bouncerVisible) { + // The trust agent dismissed the keyguard without the user proving + // that they are present (by swiping up to show the bouncer). That's + // fine if the user proved presence via some other way to the trust + //agent. + Log.i(TAG, "TrustAgent dismissed Keyguard."); + } + mSecurityCallback.dismiss(false /* authenticated */, userId, + /* bypassSecondaryLockScreen */ false); + } else { + mViewMediatorCallback.playTrustedSound(); + } + } + } + }; + + private final SecurityCallback mSecurityCallback = new SecurityCallback() { + + @Override + public boolean dismiss(boolean authenticated, int targetUserId, + boolean bypassSecondaryLockScreen) { + return mKeyguardSecurityContainerController.showNextSecurityScreenOrFinish( + authenticated, targetUserId, bypassSecondaryLockScreen); + } + + @Override + public void userActivity() { + mViewMediatorCallback.userActivity(); + } + + @Override + public void onSecurityModeChanged(SecurityMode securityMode, boolean needsInput) { + mViewMediatorCallback.setNeedsInput(needsInput); + } + + /** + * Authentication has happened and it's time to dismiss keyguard. This function + * should clean up and inform KeyguardViewMediator. + * + * @param strongAuth whether the user has authenticated with strong authentication like + * pattern, password or PIN but not by trust agents or fingerprint + * @param targetUserId a user that needs to be the foreground user at the dismissal + * completion. + */ + @Override + public void finish(boolean strongAuth, int targetUserId) { + // If there's a pending runnable because the user interacted with a widget + // and we're leaving keyguard, then run it. + boolean deferKeyguardDone = false; + if (mDismissAction != null) { + deferKeyguardDone = mDismissAction.onDismiss(); + mDismissAction = null; + mCancelAction = null; + } + if (mViewMediatorCallback != null) { + if (deferKeyguardDone) { + mViewMediatorCallback.keyguardDonePending(strongAuth, targetUserId); + } else { + mViewMediatorCallback.keyguardDone(strongAuth, targetUserId); + } + } + } + + @Override + public void reset() { + mViewMediatorCallback.resetKeyguard(); + } + + @Override + public void onCancelClicked() { + mViewMediatorCallback.onCancelClicked(); + } + }; + + private OnKeyListener mOnKeyListener = (v, keyCode, event) -> interceptMediaKey(event); + + @Inject + public KeyguardHostViewController(KeyguardHostView view, + KeyguardUpdateMonitor keyguardUpdateMonitor, + KeyguardSecurityContainerController keyguardSecurityContainerController, + AudioManager audioManager, + TelephonyManager telephonyManager, + ViewMediatorCallback viewMediatorCallback) { + super(view); + mKeyguardUpdateMonitor = keyguardUpdateMonitor; + mKeyguardSecurityContainerController = keyguardSecurityContainerController; + mAudioManager = audioManager; + mTelephonyManager = telephonyManager; + mViewMediatorCallback = viewMediatorCallback; + } + + /** Initialize the Controller. */ + public void init() { + super.init(); + mView.setViewMediatorCallback(mViewMediatorCallback); + // Update ViewMediator with the current input method requirements + mViewMediatorCallback.setNeedsInput(mKeyguardSecurityContainerController.needsInput()); + mKeyguardSecurityContainerController.init(); + mKeyguardSecurityContainerController.setSecurityCallback(mSecurityCallback); + mKeyguardSecurityContainerController.showPrimarySecurityScreen(false); + } + + @Override + protected void onViewAttached() { + mKeyguardUpdateMonitor.registerCallback(mUpdateCallback); + mView.setOnKeyListener(mOnKeyListener); + } + + @Override + protected void onViewDetached() { + mKeyguardUpdateMonitor.removeCallback(mUpdateCallback); + mView.setOnKeyListener(null); + } + + /** Called before this view is being removed. */ + public void cleanUp() { + mKeyguardSecurityContainerController.onPause(); + } + + public void resetSecurityContainer() { + mKeyguardSecurityContainerController.reset(); + } + + /** + * Dismisses the keyguard by going to the next screen or making it gone. + * @param targetUserId a user that needs to be the foreground user at the dismissal completion. + * @return True if the keyguard is done. + */ + public boolean dismiss(int targetUserId) { + return mSecurityCallback.dismiss(false, targetUserId, false); + } + + /** + * Called when the Keyguard is actively shown on the screen. + */ + public void onResume() { + if (DEBUG) Log.d(TAG, "screen on, instance " + Integer.toHexString(hashCode())); + mKeyguardSecurityContainerController.onResume(KeyguardSecurityView.SCREEN_ON); + mView.requestFocus(); + } + + public CharSequence getAccessibilityTitleForCurrentMode() { + return mKeyguardSecurityContainerController.getTitle(); + } + + /** + * Starts the animation when the Keyguard gets shown. + */ + public void appear(int statusBarHeight) { + // We might still be collapsed and the view didn't have time to layout yet or still + // be small, let's wait on the predraw to do the animation in that case. + if (mView.getHeight() != 0 && mView.getHeight() != statusBarHeight) { + mKeyguardSecurityContainerController.startAppearAnimation(); + } else { + mView.getViewTreeObserver().addOnPreDrawListener( + new ViewTreeObserver.OnPreDrawListener() { + @Override + public boolean onPreDraw() { + mView.getViewTreeObserver().removeOnPreDrawListener(this); + mKeyguardSecurityContainerController.startAppearAnimation(); + return true; + } + }); + mView.requestLayout(); + } + } + + /** + * Show a string explaining why the security view needs to be solved. + * + * @param reason a flag indicating which string should be shown, see + * {@link KeyguardSecurityView#PROMPT_REASON_NONE}, + * {@link KeyguardSecurityView#PROMPT_REASON_RESTART}, + * {@link KeyguardSecurityView#PROMPT_REASON_TIMEOUT}, and + * {@link KeyguardSecurityView#PROMPT_REASON_PREPARE_FOR_UPDATE}. + */ + public void showPromptReason(int reason) { + mKeyguardSecurityContainerController.showPromptReason(reason); + } + + public void showMessage(CharSequence message, ColorStateList colorState) { + mKeyguardSecurityContainerController.showMessage(message, colorState); + } + + public void showErrorMessage(CharSequence customMessage) { + showMessage(customMessage, Utils.getColorError(mView.getContext())); + } + + /** + * Sets an action to run when keyguard finishes. + * + * @param action + */ + public void setOnDismissAction(ActivityStarter.OnDismissAction action, Runnable cancelAction) { + if (mCancelAction != null) { + mCancelAction.run(); + mCancelAction = null; + } + mDismissAction = action; + mCancelAction = cancelAction; + } + + public void cancelDismissAction() { + setOnDismissAction(null, null); + } + + public void startDisappearAnimation(Runnable finishRunnable) { + if (!mKeyguardSecurityContainerController.startDisappearAnimation(finishRunnable) + && finishRunnable != null) { + finishRunnable.run(); + } + } + + /** + * Called when the Keyguard is not actively shown anymore on the screen. + */ + public void onPause() { + if (DEBUG) { + Log.d(TAG, String.format("screen off, instance %s at %s", + Integer.toHexString(hashCode()), SystemClock.uptimeMillis())); + } + mKeyguardSecurityContainerController.showPrimarySecurityScreen(true); + mKeyguardSecurityContainerController.onPause(); + mView.clearFocus(); + } + + /** + * Called when the view needs to be shown. + */ + public void showPrimarySecurityScreen() { + if (DEBUG) Log.d(TAG, "show()"); + mKeyguardSecurityContainerController.showPrimarySecurityScreen(false); + } + + public void setExpansion(float fraction) { + float alpha = MathUtils.map(KeyguardBouncer.ALPHA_EXPANSION_THRESHOLD, 1, 1, 0, fraction); + mView.setAlpha(MathUtils.constrain(alpha, 0f, 1f)); + mView.setTranslationY(fraction * mView.getHeight()); + } + + /** + * When bouncer was visible and is starting to become hidden. + */ + public void onStartingToHide() { + mKeyguardSecurityContainerController.onStartingToHide(); + } + + public boolean hasDismissActions() { + return mDismissAction != null || mCancelAction != null; + } + + public SecurityMode getCurrentSecurityMode() { + return mKeyguardSecurityContainerController.getCurrentSecurityMode(); + } + + public int getTop() { + int top = mView.getTop(); + // The password view has an extra top padding that should be ignored. + if (getCurrentSecurityMode() == SecurityMode.Password) { + View messageArea = mView.findViewById(R.id.keyguard_message_area); + top += messageArea.getTop(); + } + return top; + } + + public boolean handleBackKey() { + if (mKeyguardSecurityContainerController.getCurrentSecuritySelection() + != SecurityMode.None) { + mKeyguardSecurityContainerController.dismiss( + false, KeyguardUpdateMonitor.getCurrentUser()); + return true; + } + return false; + } + + /** + * In general, we enable unlocking the insecure keyguard with the menu key. However, there are + * some cases where we wish to disable it, notably when the menu button placement or technology + * is prone to false positives. + * + * @return true if the menu key should be enabled + */ + public boolean shouldEnableMenuKey() { + final Resources res = mView.getResources(); + final boolean configDisabled = res.getBoolean(R.bool.config_disableMenuKeyInLockScreen); + final boolean isTestHarness = ActivityManager.isRunningInTestHarness(); + final boolean fileOverride = (new File(ENABLE_MENU_KEY_FILE)).exists(); + return !configDisabled || isTestHarness || fileOverride; + } + + /** + * Allows the media keys to work when the keyguard is showing. + * The media keys should be of no interest to the actual keyguard view(s), + * so intercepting them here should not be of any harm. + * @param event The key event + * @return whether the event was consumed as a media key. + */ + public boolean interceptMediaKey(KeyEvent event) { + int keyCode = event.getKeyCode(); + if (event.getAction() == KeyEvent.ACTION_DOWN) { + switch (keyCode) { + case KeyEvent.KEYCODE_MEDIA_PLAY: + case KeyEvent.KEYCODE_MEDIA_PAUSE: + case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE: + /* Suppress PLAY/PAUSE toggle when phone is ringing or + * in-call to avoid music playback */ + if (mTelephonyManager != null && + mTelephonyManager.getCallState() != TelephonyManager.CALL_STATE_IDLE) { + return true; // suppress key event + } + case KeyEvent.KEYCODE_MUTE: + case KeyEvent.KEYCODE_HEADSETHOOK: + case KeyEvent.KEYCODE_MEDIA_STOP: + case KeyEvent.KEYCODE_MEDIA_NEXT: + case KeyEvent.KEYCODE_MEDIA_PREVIOUS: + case KeyEvent.KEYCODE_MEDIA_REWIND: + case KeyEvent.KEYCODE_MEDIA_RECORD: + case KeyEvent.KEYCODE_MEDIA_FAST_FORWARD: + case KeyEvent.KEYCODE_MEDIA_AUDIO_TRACK: { + handleMediaKeyEvent(event); + return true; + } + + case KeyEvent.KEYCODE_VOLUME_UP: + case KeyEvent.KEYCODE_VOLUME_DOWN: + case KeyEvent.KEYCODE_VOLUME_MUTE: { + if (KEYGUARD_MANAGES_VOLUME) { + // Volume buttons should only function for music (local or remote). + // TODO: Actually handle MUTE. + mAudioManager.adjustSuggestedStreamVolume( + keyCode == KeyEvent.KEYCODE_VOLUME_UP + ? AudioManager.ADJUST_RAISE + : AudioManager.ADJUST_LOWER /* direction */, + AudioManager.STREAM_MUSIC /* stream */, 0 /* flags */); + // Don't execute default volume behavior + return true; + } else { + return false; + } + } + } + } else if (event.getAction() == KeyEvent.ACTION_UP) { + switch (keyCode) { + case KeyEvent.KEYCODE_MUTE: + case KeyEvent.KEYCODE_HEADSETHOOK: + case KeyEvent.KEYCODE_MEDIA_PLAY: + case KeyEvent.KEYCODE_MEDIA_PAUSE: + case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE: + case KeyEvent.KEYCODE_MEDIA_STOP: + case KeyEvent.KEYCODE_MEDIA_NEXT: + case KeyEvent.KEYCODE_MEDIA_PREVIOUS: + case KeyEvent.KEYCODE_MEDIA_REWIND: + case KeyEvent.KEYCODE_MEDIA_RECORD: + case KeyEvent.KEYCODE_MEDIA_FAST_FORWARD: + case KeyEvent.KEYCODE_MEDIA_AUDIO_TRACK: { + handleMediaKeyEvent(event); + return true; + } + } + } + return false; + } + + + private void handleMediaKeyEvent(KeyEvent keyEvent) { + mAudioManager.dispatchMediaKeyEvent(keyEvent); + } + + public void finish(boolean strongAuth, int currentUser) { + mSecurityCallback.finish(strongAuth, currentUser); + } + + +} diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardMessageAreaController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardMessageAreaController.java new file mode 100644 index 000000000000..f056bdbb9706 --- /dev/null +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardMessageAreaController.java @@ -0,0 +1,68 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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; + +import com.android.systemui.statusbar.policy.ConfigurationController; +import com.android.systemui.util.ViewController; + +import javax.inject.Inject; + +/** Controller for a {@link KeyguardMessageAreaController}. */ +public class KeyguardMessageAreaController extends ViewController<KeyguardMessageArea> { + private final KeyguardUpdateMonitor mKeyguardUpdateMonitor; + private final ConfigurationController mConfigurationController; + + private KeyguardMessageAreaController(KeyguardMessageArea view, + KeyguardUpdateMonitor keyguardUpdateMonitor, + ConfigurationController configurationController) { + super(view); + + mKeyguardUpdateMonitor = keyguardUpdateMonitor; + mConfigurationController = configurationController; + } + + @Override + protected void onViewAttached() { + //mConfigurationController.addCallback(); + //mKeyguardUpdateMonitor.registerCallback(); + } + + @Override + protected void onViewDetached() { + //mConfigurationController.removeCallback(); + //mKeyguardUpdateMonitor.removeCallback(); + } + + /** Factory for createing {@link com.android.keyguard.KeyguardMessageAreaController}. */ + public static class Factory { + private final KeyguardUpdateMonitor mKeyguardUpdateMonitor; + private final ConfigurationController mConfigurationController; + + @Inject + public Factory(KeyguardUpdateMonitor keyguardUpdateMonitor, + ConfigurationController configurationController) { + mKeyguardUpdateMonitor = keyguardUpdateMonitor; + mConfigurationController = configurationController; + } + + /** Build a new {@link KeyguardMessageAreaController}. */ + public KeyguardMessageAreaController create(KeyguardMessageArea view) { + return new KeyguardMessageAreaController( + view, mKeyguardUpdateMonitor, mConfigurationController); + } + } +} diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardRootViewController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardRootViewController.java new file mode 100644 index 000000000000..5c125fcc95cb --- /dev/null +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardRootViewController.java @@ -0,0 +1,48 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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; + +import android.view.ViewGroup; + +import com.android.keyguard.dagger.KeyguardBouncerScope; +import com.android.keyguard.dagger.RootView; +import com.android.systemui.statusbar.phone.KeyguardBouncer; +import com.android.systemui.util.ViewController; + +import javax.inject.Inject; +/** Controller for a {@link KeyguardBouncer}'s Root view. */ +@KeyguardBouncerScope +public class KeyguardRootViewController extends ViewController<ViewGroup> { + @Inject + public KeyguardRootViewController(@RootView ViewGroup view) { + super(view); + } + + public ViewGroup getView() { + return mView; + } + + @Override + protected void onViewAttached() { + + } + + @Override + protected void onViewDetached() { + + } +} diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainerController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainerController.java new file mode 100644 index 000000000000..17f25bd08ef4 --- /dev/null +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainerController.java @@ -0,0 +1,118 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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; + +import android.content.res.ColorStateList; + +import com.android.internal.widget.LockPatternUtils; +import com.android.keyguard.KeyguardSecurityContainer.SecurityCallback; +import com.android.keyguard.KeyguardSecurityModel.SecurityMode; +import com.android.systemui.util.ViewController; + +import javax.inject.Inject; + +/** Controller for {@link KeyguardSecurityContainer} */ +public class KeyguardSecurityContainerController extends ViewController<KeyguardSecurityContainer> { + + private final LockPatternUtils mLockPatternUtils; + private final KeyguardSecurityViewController.Factory mKeyguardSecurityViewControllerFactory; + + @Inject + KeyguardSecurityContainerController(KeyguardSecurityContainer view, + LockPatternUtils lockPatternUtils, + KeyguardSecurityViewController.Factory keyguardSecurityViewControllerFactory) { + super(view); + mLockPatternUtils = lockPatternUtils; + view.setLockPatternUtils(mLockPatternUtils); + mKeyguardSecurityViewControllerFactory = keyguardSecurityViewControllerFactory; + } + + @Override + protected void onViewAttached() { + } + + @Override + protected void onViewDetached() { + } + + /** */ + public void onPause() { + mView.onPause(); + } + + public void showPrimarySecurityScreen(boolean turningOff) { + mView.showPrimarySecurityScreen(turningOff); + } + + public void showPromptReason(int reason) { + mView.showPromptReason(reason); + } + + public void showMessage(CharSequence message, ColorStateList colorState) { + mView.showMessage(message, colorState); + } + + public SecurityMode getCurrentSecuritySelection() { + return mView.getCurrentSecuritySelection(); + } + + public void dismiss(boolean authenticated, int targetUserId) { + mView.dismiss(authenticated, targetUserId); + } + + public void reset() { + mView.reset(); + } + + public CharSequence getTitle() { + return mView.getTitle(); + } + + public void onResume(int screenOn) { + mView.onResume(screenOn); + } + + public void startAppearAnimation() { + mView.startAppearAnimation(); + } + + public boolean startDisappearAnimation(Runnable onFinishRunnable) { + return mView.startDisappearAnimation(onFinishRunnable); + } + + public void onStartingToHide() { + mView.onStartingToHide(); + } + + public void setSecurityCallback(SecurityCallback securityCallback) { + mView.setSecurityCallback(securityCallback); + } + + public boolean showNextSecurityScreenOrFinish(boolean authenticated, int targetUserId, + boolean bypassSecondaryLockScreen) { + return mView.showNextSecurityScreenOrFinish( + authenticated, targetUserId, bypassSecondaryLockScreen); + } + + public boolean needsInput() { + return mView.needsInput(); + } + + public SecurityMode getCurrentSecurityMode() { + return mView.getCurrentSecurityMode(); + } +} diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityViewController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityViewController.java new file mode 100644 index 000000000000..ef9ba19fbb43 --- /dev/null +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityViewController.java @@ -0,0 +1,58 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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; + +import android.view.View; + +import com.android.systemui.util.ViewController; + +import javax.inject.Inject; + + +/** Controller for a {@link KeyguardSecurityView}. */ +public class KeyguardSecurityViewController extends ViewController<View> { + + private final KeyguardSecurityView mView; + + private KeyguardSecurityViewController(KeyguardSecurityView view) { + super((View) view); + // KeyguardSecurityView isn't actually a View, so we need to track it ourselves. + mView = view; + } + + @Override + protected void onViewAttached() { + + } + + @Override + protected void onViewDetached() { + + } + + /** Factory for a {@link KeyguardSecurityViewController}. */ + public static class Factory { + @Inject + public Factory() { + } + + /** Create a new {@link KeyguardSecurityViewController}. */ + public KeyguardSecurityViewController create(KeyguardSecurityView view) { + return new KeyguardSecurityViewController(view); + } + } +} diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java index 1027329b8d3c..76090f87223e 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java @@ -36,6 +36,7 @@ import android.annotation.MainThread; import android.annotation.NonNull; import android.app.ActivityManager; import android.app.ActivityTaskManager; +import android.app.ActivityTaskManager.RootTaskInfo; import android.app.AlarmManager; import android.app.PendingIntent; import android.app.UserSwitchObserver; @@ -2783,7 +2784,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab @Override public void onTaskStackChangedBackground() { try { - ActivityManager.StackInfo info = ActivityTaskManager.getService().getStackInfo( + RootTaskInfo info = ActivityTaskManager.getService().getRootTaskInfo( WINDOWING_MODE_UNDEFINED, ACTIVITY_TYPE_ASSISTANT); if (info == null) { return; diff --git a/packages/SystemUI/src/com/android/keyguard/dagger/KeyguardBouncerComponent.java b/packages/SystemUI/src/com/android/keyguard/dagger/KeyguardBouncerComponent.java index 84deaca096aa..5160b7e01e89 100644 --- a/packages/SystemUI/src/com/android/keyguard/dagger/KeyguardBouncerComponent.java +++ b/packages/SystemUI/src/com/android/keyguard/dagger/KeyguardBouncerComponent.java @@ -16,27 +16,27 @@ package com.android.keyguard.dagger; -import android.view.ViewGroup; - +import com.android.keyguard.KeyguardHostViewController; +import com.android.keyguard.KeyguardRootViewController; import com.android.systemui.statusbar.phone.KeyguardBouncer; -import dagger.BindsInstance; import dagger.Subcomponent; /** * Dagger Subcomponent for the {@link KeyguardBouncer}. */ -@Subcomponent +@Subcomponent(modules = {KeyguardBouncerModule.class}) @KeyguardBouncerScope public interface KeyguardBouncerComponent { /** Simple factory for {@link KeyguardBouncerComponent}. */ @Subcomponent.Factory interface Factory { - KeyguardBouncerComponent build( - @BindsInstance @ContainerView ViewGroup container, - @BindsInstance KeyguardBouncer.BouncerExpansionCallback bouncerExpansionCallback); + KeyguardBouncerComponent create(); } - /** */ - KeyguardBouncer createKeyguardBouncer(); + /** Returns a {@link KeyguardRootViewController}. */ + KeyguardRootViewController getKeyguardRootViewController(); + + /** Returns a {@link KeyguardHostViewController}. */ + KeyguardHostViewController getKeyguardHostViewController(); } diff --git a/packages/SystemUI/src/com/android/keyguard/dagger/KeyguardBouncerModule.java b/packages/SystemUI/src/com/android/keyguard/dagger/KeyguardBouncerModule.java new file mode 100644 index 000000000000..b6010c8915e7 --- /dev/null +++ b/packages/SystemUI/src/com/android/keyguard/dagger/KeyguardBouncerModule.java @@ -0,0 +1,64 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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.dagger; + +import android.view.LayoutInflater; +import android.view.ViewGroup; + +import com.android.keyguard.KeyguardHostView; +import com.android.keyguard.KeyguardMessageArea; +import com.android.keyguard.KeyguardSecurityContainer; +import com.android.systemui.R; +import com.android.systemui.statusbar.phone.KeyguardBouncer; + +import dagger.Module; +import dagger.Provides; + +/** + * Module to create and access view related to the {@link KeyguardBouncer}. + */ +@Module +public interface KeyguardBouncerModule { + /** */ + @Provides + @KeyguardBouncerScope + @RootView + static ViewGroup providesRootView(LayoutInflater layoutInflater) { + return (ViewGroup) layoutInflater.inflate(R.layout.keyguard_bouncer, null); + } + + /** */ + @Provides + @KeyguardBouncerScope + static KeyguardMessageArea providesKeyguardMessageArea(@RootView ViewGroup viewGroup) { + return viewGroup.findViewById(R.id.keyguard_message_area); + } + + /** */ + @Provides + @KeyguardBouncerScope + static KeyguardHostView providesKeyguardHostView(@RootView ViewGroup rootView) { + return rootView.findViewById(R.id.keyguard_host_view); + } + + /** */ + @Provides + @KeyguardBouncerScope + static KeyguardSecurityContainer preovidesKeyguardSecurityContainer(KeyguardHostView hostView) { + return hostView.findViewById(R.id.keyguard_security_container); + } +} diff --git a/packages/SystemUI/src/com/android/keyguard/dagger/ContainerView.java b/packages/SystemUI/src/com/android/keyguard/dagger/RootView.java index e65f19db5ac2..5ebff097604b 100644 --- a/packages/SystemUI/src/com/android/keyguard/dagger/ContainerView.java +++ b/packages/SystemUI/src/com/android/keyguard/dagger/RootView.java @@ -26,5 +26,5 @@ import javax.inject.Qualifier; @Qualifier @Documented @Retention(RUNTIME) -public @interface ContainerView { +public @interface RootView { } diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/MagnificationModeSwitch.java b/packages/SystemUI/src/com/android/systemui/accessibility/MagnificationModeSwitch.java index 128af3702c49..68e404e36bba 100644 --- a/packages/SystemUI/src/com/android/systemui/accessibility/MagnificationModeSwitch.java +++ b/packages/SystemUI/src/com/android/systemui/accessibility/MagnificationModeSwitch.java @@ -43,6 +43,7 @@ class MagnificationModeSwitch { private static final int DURATION_MS = 5000; private static final int START_DELAY_MS = 3000; + private final Runnable mAnimationTask; private final Context mContext; private final WindowManager mWindowManager; @@ -70,6 +71,14 @@ class MagnificationModeSwitch { applyResourcesValues(); mImageView.setImageResource(getIconResId(mMagnificationMode)); mImageView.setOnTouchListener(this::onTouch); + + mAnimationTask = () -> { + mImageView.animate() + .alpha(0f) + .setDuration(DURATION_MS) + .withEndAction(() -> removeButton()) + .start(); + }; } private void applyResourcesValues() { @@ -147,13 +156,8 @@ class MagnificationModeSwitch { // Dismiss the magnification switch button after the button is displayed for a period of // time. mImageView.animate().cancel(); - mImageView.animate() - .alpha(0f) - .setStartDelay(START_DELAY_MS) - .setDuration(DURATION_MS) - .withEndAction( - () -> removeButton()) - .start(); + mImageView.removeCallbacks(mAnimationTask); + mImageView.postDelayed(mAnimationTask, START_DELAY_MS); } void onConfigurationChanged(int configDiff) { diff --git a/packages/SystemUI/src/com/android/systemui/broadcast/BroadcastDispatcher.kt b/packages/SystemUI/src/com/android/systemui/broadcast/BroadcastDispatcher.kt index b9b849b8488e..83de3243602b 100644 --- a/packages/SystemUI/src/com/android/systemui/broadcast/BroadcastDispatcher.kt +++ b/packages/SystemUI/src/com/android/systemui/broadcast/BroadcastDispatcher.kt @@ -16,7 +16,6 @@ package com.android.systemui.broadcast -import android.app.ActivityManager import android.content.BroadcastReceiver import android.content.Context import android.content.Intent @@ -33,6 +32,7 @@ import com.android.internal.util.IndentingPrintWriter import com.android.systemui.Dumpable import com.android.systemui.broadcast.logging.BroadcastDispatcherLogger import com.android.systemui.dump.DumpManager +import com.android.systemui.settings.UserTracker import java.io.FileDescriptor import java.io.PrintWriter import java.util.concurrent.Executor @@ -47,8 +47,6 @@ data class ReceiverData( private const val MSG_ADD_RECEIVER = 0 private const val MSG_REMOVE_RECEIVER = 1 private const val MSG_REMOVE_RECEIVER_FOR_USER = 2 -private const val MSG_USER_SWITCH = 3 -private const val MSG_SET_STARTING_USER = 99 private const val TAG = "BroadcastDispatcher" private const val DEBUG = true @@ -68,23 +66,15 @@ open class BroadcastDispatcher constructor ( private val bgLooper: Looper, private val bgExecutor: Executor, private val dumpManager: DumpManager, - private val logger: BroadcastDispatcherLogger -) : Dumpable, BroadcastReceiver() { + private val logger: BroadcastDispatcherLogger, + private val userTracker: UserTracker +) : Dumpable { // Only modify in BG thread private val receiversByUser = SparseArray<UserBroadcastDispatcher>(20) fun initialize() { dumpManager.registerDumpable(javaClass.name, this) - handler.sendEmptyMessage(MSG_SET_STARTING_USER) - registerReceiver(this, IntentFilter(Intent.ACTION_USER_SWITCHED), null, UserHandle.ALL) - } - - override fun onReceive(context: Context, intent: Intent) { - if (intent.action == Intent.ACTION_USER_SWITCHED) { - val user = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, UserHandle.USER_NULL) - handler.obtainMessage(MSG_USER_SWITCH, user, 0).sendToTarget() - } } /** @@ -181,7 +171,6 @@ open class BroadcastDispatcher constructor ( pw.println("Broadcast dispatcher:") val ipw = IndentingPrintWriter(pw, " ") ipw.increaseIndent() - ipw.println("Current user: ${handler.currentUser}") for (index in 0 until receiversByUser.size()) { ipw.println("User ${receiversByUser.keyAt(index)}") receiversByUser.valueAt(index).dump(fd, ipw, args) @@ -190,7 +179,6 @@ open class BroadcastDispatcher constructor ( } private val handler = object : Handler(bgLooper) { - var currentUser = UserHandle.USER_SYSTEM override fun handleMessage(msg: Message) { when (msg.what) { @@ -199,7 +187,7 @@ open class BroadcastDispatcher constructor ( // If the receiver asked to be registered under the current user, we register // under the actual current user. val userId = if (data.user.identifier == UserHandle.USER_CURRENT) { - currentUser + userTracker.userId } else { data.user.identifier } @@ -221,14 +209,6 @@ open class BroadcastDispatcher constructor ( MSG_REMOVE_RECEIVER_FOR_USER -> { receiversByUser.get(msg.arg1)?.unregisterReceiver(msg.obj as BroadcastReceiver) } - - MSG_USER_SWITCH -> { - currentUser = msg.arg1 - } - MSG_SET_STARTING_USER -> { - currentUser = ActivityManager.getCurrentUser() - } - else -> super.handleMessage(msg) } } diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/Bubble.java b/packages/SystemUI/src/com/android/systemui/bubbles/Bubble.java index 27863ba6c857..62bc425b2bd2 100644 --- a/packages/SystemUI/src/com/android/systemui/bubbles/Bubble.java +++ b/packages/SystemUI/src/com/android/systemui/bubbles/Bubble.java @@ -694,6 +694,7 @@ class Bubble implements BubbleViewProvider { pw.print(" showInShade: "); pw.println(showInShade()); pw.print(" showDot: "); pw.println(showDot()); pw.print(" showFlyout: "); pw.println(showFlyout()); + pw.print(" lastActivity: "); pw.println(getLastActivity()); pw.print(" desiredHeight: "); pw.println(getDesiredHeightString()); pw.print(" suppressNotif: "); pw.println(shouldSuppressNotification()); pw.print(" autoExpand: "); pw.println(shouldAutoExpand()); diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java index c81b7cefbbd7..4b4e275e5cbd 100644 --- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java +++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java @@ -196,7 +196,7 @@ public class BubbleController implements ConfigurationController.ConfigurationLi private INotificationManager mINotificationManager; // Callback that updates BubbleOverflowActivity on data change. - @Nullable private Runnable mOverflowCallback = null; + @Nullable private BubbleData.Listener mOverflowListener = null; // Only load overflow data from disk once private boolean mOverflowDataLoaded = false; @@ -722,8 +722,8 @@ public class BubbleController implements ConfigurationController.ConfigurationLi mInflateSynchronously = inflateSynchronously; } - void setOverflowCallback(Runnable updateOverflow) { - mOverflowCallback = updateOverflow; + void setOverflowListener(BubbleData.Listener listener) { + mOverflowListener = listener; } /** @@ -1327,9 +1327,10 @@ public class BubbleController implements ConfigurationController.ConfigurationLi // Lazy load overflow bubbles from disk loadOverflowBubblesFromDisk(); + // Update bubbles in overflow. - if (mOverflowCallback != null) { - mOverflowCallback.run(); + if (mOverflowListener != null) { + mOverflowListener.applyUpdate(update); } // Collapsing? Do this first before remaining steps. @@ -1438,21 +1439,6 @@ public class BubbleController implements ConfigurationController.ConfigurationLi cb.invalidateNotifications("BubbleData.Listener.applyUpdate"); } updateStack(); - - if (DEBUG_BUBBLE_CONTROLLER) { - Log.d(TAG, "\n[BubbleData] bubbles:"); - Log.d(TAG, BubbleDebugConfig.formatBubblesString(mBubbleData.getBubbles(), - mBubbleData.getSelectedBubble())); - - if (mStackView != null) { - Log.d(TAG, "\n[BubbleStackView]"); - Log.d(TAG, BubbleDebugConfig.formatBubblesString(mStackView.getBubblesOnScreen(), - mStackView.getExpandedBubble())); - } - Log.d(TAG, "\n[BubbleData] overflow:"); - Log.d(TAG, BubbleDebugConfig.formatBubblesString(mBubbleData.getOverflowBubbles(), - null) + "\n"); - } } }; diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleData.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleData.java index 5c6d16d4bbee..a747db680b2e 100644 --- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleData.java +++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleData.java @@ -75,6 +75,8 @@ public class BubbleData { @Nullable Bubble selectedBubble; @Nullable Bubble addedBubble; @Nullable Bubble updatedBubble; + @Nullable Bubble addedOverflowBubble; + @Nullable Bubble removedOverflowBubble; // Pair with Bubble and @DismissReason Integer final List<Pair<Bubble, Integer>> removedBubbles = new ArrayList<>(); @@ -93,10 +95,12 @@ public class BubbleData { || addedBubble != null || updatedBubble != null || !removedBubbles.isEmpty() + || addedOverflowBubble != null + || removedOverflowBubble != null || orderChanged; } - void bubbleRemoved(Bubble bubbleToRemove, @DismissReason int reason) { + void bubbleRemoved(Bubble bubbleToRemove, @DismissReason int reason) { removedBubbles.add(new Pair<>(bubbleToRemove, reason)); } } @@ -486,8 +490,9 @@ public class BubbleData { b.stopInflation(); } mLogger.logOverflowRemove(b, reason); - mStateChange.bubbleRemoved(b, reason); mOverflowBubbles.remove(b); + mStateChange.bubbleRemoved(b, reason); + mStateChange.removedOverflowBubble = b; } return; } @@ -532,6 +537,7 @@ public class BubbleData { } mLogger.logOverflowAdd(bubble, reason); mOverflowBubbles.add(0, bubble); + mStateChange.addedOverflowBubble = bubble; bubble.stopInflation(); if (mOverflowBubbles.size() == mMaxOverflowBubbles + 1) { // Remove oldest bubble. @@ -542,6 +548,7 @@ public class BubbleData { mStateChange.bubbleRemoved(oldest, BubbleController.DISMISS_OVERFLOW_MAX_REACHED); mLogger.log(bubble, BubbleLogger.Event.BUBBLE_OVERFLOW_REMOVE_MAX_REACHED); mOverflowBubbles.remove(oldest); + mStateChange.removedOverflowBubble = oldest; } } @@ -821,11 +828,19 @@ public class BubbleData { : "null"); pw.print("expanded: "); pw.println(mExpanded); - pw.print("count: "); + + pw.print("stack bubble count: "); pw.println(mBubbles.size()); for (Bubble bubble : mBubbles) { bubble.dump(fd, pw, args); } + + pw.print("overflow bubble count: "); + pw.println(mOverflowBubbles.size()); + for (Bubble bubble : mOverflowBubbles) { + bubble.dump(fd, pw, args); + } + pw.print("summaryKeys: "); pw.println(mSuppressedGroupKeys.size()); for (String key : mSuppressedGroupKeys.keySet()) { diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleExpandedView.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleExpandedView.java index 80150c9b7e32..33310962a6f2 100644 --- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleExpandedView.java +++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleExpandedView.java @@ -164,7 +164,7 @@ public class BubbleExpandedView extends LinearLayout { ActivityOptions options = ActivityOptions.makeCustomAnimation(getContext(), 0 /* enterResId */, 0 /* exitResId */); options.setTaskAlwaysOnTop(true); - options.setLaunchWindowingMode(WINDOWING_MODE_MULTI_WINDOW); + // Soptions.setLaunchWindowingMode(WINDOWING_MODE_MULTI_WINDOW); // Post to keep the lifecycle normal post(() -> { if (DEBUG_BUBBLE_EXPANDED_VIEW) { diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleOverflowActivity.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleOverflowActivity.java index 9926f2ef9b64..160addc405fa 100644 --- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleOverflowActivity.java +++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleOverflowActivity.java @@ -108,14 +108,10 @@ public class BubbleOverflowActivity extends Activity { mEmptyStateSubtitle = findViewById(R.id.bubble_overflow_empty_subtitle); mEmptyStateImage = findViewById(R.id.bubble_overflow_empty_state_image); - updateDimensions(); - onDataChanged(mBubbleController.getOverflowBubbles()); - mBubbleController.setOverflowCallback(() -> { - onDataChanged(mBubbleController.getOverflowBubbles()); - }); + updateOverflow(); } - void updateDimensions() { + void updateOverflow() { Resources res = getResources(); final int columns = res.getInteger(R.integer.bubbles_overflow_columns); mRecyclerView.setLayoutManager( @@ -137,6 +133,22 @@ public class BubbleOverflowActivity extends Activity { mAdapter = new BubbleOverflowAdapter(getApplicationContext(), mOverflowBubbles, mBubbleController::promoteBubbleFromOverflow, viewWidth, viewHeight); mRecyclerView.setAdapter(mAdapter); + + mOverflowBubbles.clear(); + mOverflowBubbles.addAll(mBubbleController.getOverflowBubbles()); + mAdapter.notifyDataSetChanged(); + updateEmptyStateVisibility(); + + mBubbleController.setOverflowListener(mDataListener); + updateTheme(); + } + + void updateEmptyStateVisibility() { + if (mOverflowBubbles.isEmpty()) { + mEmptyState.setVisibility(View.VISIBLE); + } else { + mEmptyState.setVisibility(View.GONE); + } } /** @@ -168,22 +180,40 @@ public class BubbleOverflowActivity extends Activity { mEmptyStateSubtitle.setTextColor(textColor); } - void onDataChanged(List<Bubble> bubbles) { - mOverflowBubbles.clear(); - mOverflowBubbles.addAll(bubbles); - mAdapter.notifyDataSetChanged(); + private final BubbleData.Listener mDataListener = new BubbleData.Listener() { - if (mOverflowBubbles.isEmpty()) { - mEmptyState.setVisibility(View.VISIBLE); - } else { - mEmptyState.setVisibility(View.GONE); - } + @Override + public void applyUpdate(BubbleData.Update update) { + + Bubble toRemove = update.removedOverflowBubble; + if (toRemove != null) { + if (DEBUG_OVERFLOW) { + Log.d(TAG, "remove: " + toRemove); + } + toRemove.cleanupViews(); + final int i = mOverflowBubbles.indexOf(toRemove); + mOverflowBubbles.remove(toRemove); + mAdapter.notifyItemRemoved(i); + } + + Bubble toAdd = update.addedOverflowBubble; + if (toAdd != null) { + if (DEBUG_OVERFLOW) { + Log.d(TAG, "add: " + toAdd); + } + mOverflowBubbles.add(0, toAdd); + mAdapter.notifyItemInserted(0); + } + + updateEmptyStateVisibility(); - if (DEBUG_OVERFLOW) { - Log.d(TAG, "Updated overflow bubbles:\n" + BubbleDebugConfig.formatBubblesString( - mOverflowBubbles, /*selected*/ null)); + if (DEBUG_OVERFLOW) { + Log.d(TAG, BubbleDebugConfig.formatBubblesString( + mBubbleController.getOverflowBubbles(), + null)); + } } - } + }; @Override public void onStart() { @@ -198,8 +228,7 @@ public class BubbleOverflowActivity extends Activity { @Override public void onResume() { super.onResume(); - updateDimensions(); - updateTheme(); + updateOverflow(); } @Override diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java index 64df2b99ee22..c1b68824d20f 100644 --- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java +++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java @@ -276,6 +276,10 @@ public class BubbleStackView extends FrameLayout /** Description of current animation controller state. */ public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { pw.println("Stack view state:"); + + String bubblesOnScreen = BubbleDebugConfig.formatBubblesString( + getBubblesOnScreen(), getExpandedBubble()); + pw.print(" bubbles on screen: "); pw.println(bubblesOnScreen); pw.print(" gestureInProgress: "); pw.println(mIsGestureInProgress); pw.print(" showingDismiss: "); pw.println(mDismissView.isShowing()); pw.print(" isExpansionAnimating: "); pw.println(mIsExpansionAnimating); diff --git a/packages/SystemUI/src/com/android/systemui/controls/management/ControlAdapter.kt b/packages/SystemUI/src/com/android/systemui/controls/management/ControlAdapter.kt index 31830b94e8e4..40662536e57e 100644 --- a/packages/SystemUI/src/com/android/systemui/controls/management/ControlAdapter.kt +++ b/packages/SystemUI/src/com/android/systemui/controls/management/ControlAdapter.kt @@ -263,6 +263,7 @@ internal class ControlHolder( val context = itemView.context val fg = context.getResources().getColorStateList(ri.foreground, context.getTheme()) + icon.imageTintList = null ci.customIcon?.let { icon.setImageIcon(it) } ?: run { diff --git a/packages/SystemUI/src/com/android/systemui/controls/ui/ControlsUiControllerImpl.kt b/packages/SystemUI/src/com/android/systemui/controls/ui/ControlsUiControllerImpl.kt index 371031020b14..2b529f9a6cde 100644 --- a/packages/SystemUI/src/com/android/systemui/controls/ui/ControlsUiControllerImpl.kt +++ b/packages/SystemUI/src/com/android/systemui/controls/ui/ControlsUiControllerImpl.kt @@ -104,6 +104,7 @@ class ControlsUiControllerImpl @Inject constructor ( private var hidden = true private lateinit var dismissGlobalActions: Runnable private val popupThemedContext = ContextThemeWrapper(context, R.style.Control_ListPopupWindow) + private var retainCache = false private val collator = Collator.getInstance(context.resources.configuration.locales[0]) private val localeComparator = compareBy<SelectionItem, CharSequence>(collator) { @@ -149,6 +150,7 @@ class ControlsUiControllerImpl @Inject constructor ( this.parent = parent this.dismissGlobalActions = dismissGlobalActions hidden = false + retainCache = false allStructures = controlsController.get().getFavorites() selectedStructure = loadPreference(allStructures) @@ -235,6 +237,8 @@ class ControlsUiControllerImpl @Inject constructor ( } putIntentExtras(i, si) startActivity(context, i) + + retainCache = true } private fun putIntentExtras(intent: Intent, si: StructureInfo) { @@ -497,7 +501,7 @@ class ControlsUiControllerImpl @Inject constructor ( controlsListingController.get().removeCallback(listingCallback) - RenderInfo.clearCache() + if (!retainCache) RenderInfo.clearCache() } override fun onRefreshState(componentName: ComponentName, controls: List<Control>) { diff --git a/packages/SystemUI/src/com/android/systemui/dagger/DependencyProvider.java b/packages/SystemUI/src/com/android/systemui/dagger/DependencyProvider.java index ac01ba1539b3..38e12a6ed5f8 100644 --- a/packages/SystemUI/src/com/android/systemui/dagger/DependencyProvider.java +++ b/packages/SystemUI/src/com/android/systemui/dagger/DependencyProvider.java @@ -61,6 +61,7 @@ import com.android.systemui.plugins.PluginInitializerImpl; import com.android.systemui.plugins.statusbar.StatusBarStateController; import com.android.systemui.recents.OverviewProxyService; import com.android.systemui.recents.Recents; +import com.android.systemui.settings.UserTracker; import com.android.systemui.shared.plugins.PluginManager; import com.android.systemui.shared.plugins.PluginManagerImpl; import com.android.systemui.shared.system.ActivityManagerWrapper; @@ -269,10 +270,11 @@ public class DependencyProvider { @Background Looper backgroundLooper, @Background Executor backgroundExecutor, DumpManager dumpManager, - BroadcastDispatcherLogger logger + BroadcastDispatcherLogger logger, + UserTracker userTracker ) { BroadcastDispatcher bD = new BroadcastDispatcher(context, backgroundLooper, - backgroundExecutor, dumpManager, logger); + backgroundExecutor, dumpManager, logger, userTracker); bD.initialize(); return bD; } diff --git a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java index 3e64749c0dce..9c90510099a2 100644 --- a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java +++ b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java @@ -19,6 +19,7 @@ import static android.view.WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM; import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS; import static android.view.WindowManager.ScreenshotSource.SCREENSHOT_GLOBAL_ACTIONS; import static android.view.WindowManager.TAKE_SCREENSHOT_FULLSCREEN; +import static android.view.WindowManagerPolicyConstants.NAV_BAR_MODE_2BUTTON; import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.SOME_AUTH_REQUIRED_AFTER_USER_REQUEST; import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_NOT_REQUIRED; @@ -548,7 +549,7 @@ public class GlobalActionsDialog implements DialogInterface.OnDismissListener, if (!mDeviceProvisioned && !action.showBeforeProvisioning()) { return false; } - return true; + return action.shouldShow(); } /** @@ -961,6 +962,8 @@ public class GlobalActionsDialog implements DialogInterface.OnDismissListener, @VisibleForTesting class ScreenshotAction extends SinglePressAction implements LongPressAction { + final String KEY_SYSTEM_NAV_2BUTTONS = "system_nav_2buttons"; + public ScreenshotAction() { super(R.drawable.ic_screenshot, R.string.global_action_screenshot); } @@ -993,6 +996,19 @@ public class GlobalActionsDialog implements DialogInterface.OnDismissListener, } @Override + public boolean shouldShow() { + // Include screenshot in power menu for legacy nav because it is not accessible + // through Recents in that mode + return is2ButtonNavigationEnabled(); + } + + boolean is2ButtonNavigationEnabled() { + return NAV_BAR_MODE_2BUTTON == mContext.getResources().getInteger( + com.android.internal.R.integer.config_navBarInteractionMode); + } + + + @Override public boolean onLongPress() { if (FeatureFlagUtils.isEnabled(mContext, FeatureFlagUtils.SCREENRECORD_LONG_PRESS)) { mUiEventLogger.log(GlobalActionsEvent.GA_SCREENSHOT_LONG_PRESS); @@ -1615,6 +1631,10 @@ public class GlobalActionsDialog implements DialogInterface.OnDismissListener, * @return */ CharSequence getMessage(); + + default boolean shouldShow() { + return true; + } } /** diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaCarouselController.kt b/packages/SystemUI/src/com/android/systemui/media/MediaCarouselController.kt index e5a9ac10389f..f150381f4070 100644 --- a/packages/SystemUI/src/com/android/systemui/media/MediaCarouselController.kt +++ b/packages/SystemUI/src/com/android/systemui/media/MediaCarouselController.kt @@ -42,7 +42,7 @@ class MediaCarouselController @Inject constructor( private val mediaHostStatesManager: MediaHostStatesManager, private val activityStarter: ActivityStarter, @Main executor: DelayableExecutor, - mediaManager: MediaDataManager, + private val mediaManager: MediaDataManager, configurationController: ConfigurationController, falsingManager: FalsingManager ) { @@ -109,6 +109,7 @@ class MediaCarouselController @Inject constructor( private val pageIndicator: PageIndicator private val visualStabilityCallback: VisualStabilityManager.Callback private var needsReordering: Boolean = false + private var keysNeedRemoval = mutableSetOf<String>() private var isRtl: Boolean = false set(value) { if (value != field) { @@ -161,6 +162,10 @@ class MediaCarouselController @Inject constructor( needsReordering = false reorderAllPlayers() } + + keysNeedRemoval.forEach { removePlayer(it) } + keysNeedRemoval.clear() + // Let's reset our scroll position mediaCarouselScrollHandler.scrollToStart() } @@ -168,13 +173,19 @@ class MediaCarouselController @Inject constructor( true /* persistent */) mediaManager.addListener(object : MediaDataManager.Listener { override fun onMediaDataLoaded(key: String, oldKey: String?, data: MediaData) { - if (!data.active && !Utils.useMediaResumption(context)) { - // This view is inactive, let's remove this! This happens e.g when dismissing / - // timing out a view. We still have the data around because resumption could - // be on, but we should save the resources and release this. - onMediaDataRemoved(key) + addOrUpdatePlayer(key, oldKey, data) + val canRemove = data.isPlaying?.let { !it } ?: data.isClearable + if (canRemove && !Utils.useMediaResumption(context)) { + // This view isn't playing, let's remove this! This happens e.g when + // dismissing/timing out a view. We still have the data around because + // resumption could be on, but we should save the resources and release this. + if (visualStabilityManager.isReorderingAllowed) { + onMediaDataRemoved(key) + } else { + keysNeedRemoval.add(key) + } } else { - addOrUpdatePlayer(key, oldKey, data) + keysNeedRemoval.remove(key) } } @@ -236,12 +247,12 @@ class MediaCarouselController @Inject constructor( var newPlayer = mediaControlPanelFactory.get() newPlayer.attach(PlayerViewHolder.create(LayoutInflater.from(context), mediaContent)) newPlayer.mediaViewController.sizeChangedListener = this::updateCarouselDimensions - MediaPlayerData.addMediaPlayer(key, data, newPlayer) val lp = LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT) newPlayer.view?.player?.setLayoutParams(lp) newPlayer.bind(data) newPlayer.setListening(currentlyExpanded) + MediaPlayerData.addMediaPlayer(key, data, newPlayer) updatePlayerToState(newPlayer, noAnimation = true) reorderAllPlayers() } else { @@ -271,6 +282,9 @@ class MediaCarouselController @Inject constructor( removed.onDestroy() mediaCarouselScrollHandler.onPlayersChanged() updatePageIndicator() + + // Inform the media manager of a potentially late dismissal + mediaManager.dismissMediaData(key, 0L) } } @@ -478,12 +492,11 @@ class MediaCarouselController @Inject constructor( internal object MediaPlayerData { private data class MediaSortKey( val data: MediaData, - val updateTime: Long = 0, - val isPlaying: Boolean = false + val updateTime: Long = 0 ) private val comparator = - compareByDescending<MediaSortKey> { it.isPlaying } + compareByDescending<MediaSortKey> { it.data.isPlaying } .thenByDescending { it.data.isLocalSession } .thenByDescending { !it.data.resumption } .thenByDescending { it.updateTime } @@ -493,7 +506,7 @@ internal object MediaPlayerData { fun addMediaPlayer(key: String, data: MediaData, player: MediaControlPanel) { removeMediaPlayer(key) - val sortKey = MediaSortKey(data, System.currentTimeMillis(), player.isPlaying()) + val sortKey = MediaSortKey(data, System.currentTimeMillis()) mediaData.put(key, sortKey) mediaPlayers.put(sortKey, player) } diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaData.kt b/packages/SystemUI/src/com/android/systemui/media/MediaData.kt index d6a02687c905..40a879abde34 100644 --- a/packages/SystemUI/src/com/android/systemui/media/MediaData.kt +++ b/packages/SystemUI/src/com/android/systemui/media/MediaData.kt @@ -94,7 +94,17 @@ data class MediaData( * Notification key for cancelling a media player after a timeout (when not using resumption.) */ val notificationKey: String? = null, - var hasCheckedForResume: Boolean = false + var hasCheckedForResume: Boolean = false, + + /** + * If apps do not report PlaybackState, set as null to imply 'undetermined' + */ + val isPlaying: Boolean? = null, + + /** + * Set from the notification and used as fallback when PlaybackState cannot be determined + */ + val isClearable: Boolean = true ) /** State of a media action. */ diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaDataFilter.kt b/packages/SystemUI/src/com/android/systemui/media/MediaDataFilter.kt index 0664a41f841d..1f580a953d09 100644 --- a/packages/SystemUI/src/com/android/systemui/media/MediaDataFilter.kt +++ b/packages/SystemUI/src/com/android/systemui/media/MediaDataFilter.kt @@ -136,14 +136,8 @@ class MediaDataFilter @Inject constructor( /** * Are there any media entries we should display? - * If resumption is enabled, this will include inactive players - * If resumption is disabled, we only want to show active players */ - fun hasAnyMedia() = if (mediaResumeListener.isResumptionEnabled()) { - userEntries.isNotEmpty() - } else { - hasActiveMedia() - } + fun hasAnyMedia() = userEntries.isNotEmpty() /** * Add a listener for filtered [MediaData] changes diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaDataManager.kt b/packages/SystemUI/src/com/android/systemui/media/MediaDataManager.kt index b2ad19b5f42f..cb6b22c2321f 100644 --- a/packages/SystemUI/src/com/android/systemui/media/MediaDataManager.kt +++ b/packages/SystemUI/src/com/android/systemui/media/MediaDataManager.kt @@ -47,6 +47,7 @@ import com.android.systemui.dagger.qualifiers.Background import com.android.systemui.dagger.qualifiers.Main import com.android.systemui.dump.DumpManager import com.android.systemui.plugins.ActivityStarter +import com.android.systemui.statusbar.NotificationMediaManager.isPlayingState import com.android.systemui.statusbar.notification.MediaNotificationProcessor import com.android.systemui.statusbar.notification.row.HybridGroupManager import com.android.systemui.util.Assert @@ -350,6 +351,16 @@ class MediaDataManager( } fun dismissMediaData(key: String, delay: Long) { + backgroundExecutor.execute { + mediaEntries[key]?.let { mediaData -> + if (mediaData.isLocalSession) { + mediaData.token?.let { + val mediaController = mediaControllerFactory.create(it) + mediaController.transportControls.stop() + } + } + } + } foregroundExecutor.executeDelayed({ removeEntry(key) }, delay) } @@ -500,6 +511,7 @@ class MediaDataManager( val isLocalSession = mediaController.playbackInfo?.playbackType == MediaController.PlaybackInfo.PLAYBACK_TYPE_LOCAL ?: true + val isPlaying = mediaController.playbackState?.let { isPlayingState(it.state) } ?: null foregroundExecutor.execute { val resumeAction: Runnable? = mediaEntries[key]?.resumeAction @@ -509,7 +521,8 @@ class MediaDataManager( smallIconDrawable, artist, song, artWorkIcon, actionIcons, actionsToShowCollapsed, sbn.packageName, token, notif.contentIntent, null, active, resumeAction = resumeAction, isLocalSession = isLocalSession, - notificationKey = key, hasCheckedForResume = hasCheckedForResume)) + notificationKey = key, hasCheckedForResume = hasCheckedForResume, + isPlaying = isPlaying, isClearable = sbn.isClearable())) } } diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaResumeListener.kt b/packages/SystemUI/src/com/android/systemui/media/MediaResumeListener.kt index c00b5e92f93d..5b59214afdc9 100644 --- a/packages/SystemUI/src/com/android/systemui/media/MediaResumeListener.kt +++ b/packages/SystemUI/src/com/android/systemui/media/MediaResumeListener.kt @@ -125,8 +125,6 @@ class MediaResumeListener @Inject constructor( }, Settings.Secure.MEDIA_CONTROLS_RESUME_BLOCKED) } - fun isResumptionEnabled() = useMediaResumption - private fun loadSavedComponents() { // Make sure list is empty (if we switched users) resumeComponents.clear() diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgeBackGestureHandler.java b/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgeBackGestureHandler.java index 92d2f421d6ee..dfc82f120c90 100644 --- a/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgeBackGestureHandler.java +++ b/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgeBackGestureHandler.java @@ -38,11 +38,11 @@ import android.provider.DeviceConfig; import android.util.DisplayMetrics; import android.util.Log; import android.util.TypedValue; +import android.view.Choreographer; import android.view.ISystemGestureExclusionListener; import android.view.InputChannel; import android.view.InputDevice; import android.view.InputEvent; -import android.view.InputEventReceiver; import android.view.InputMonitor; import android.view.KeyCharacterMap; import android.view.KeyEvent; @@ -67,6 +67,7 @@ import com.android.systemui.recents.OverviewProxyService; import com.android.systemui.settings.CurrentUserTracker; import com.android.systemui.shared.plugins.PluginManager; import com.android.systemui.shared.system.ActivityManagerWrapper; +import com.android.systemui.shared.system.InputChannelCompat; import com.android.systemui.shared.system.QuickStepContract; import com.android.systemui.shared.system.SysUiStatsLog; import com.android.systemui.shared.system.TaskStackChangeListener; @@ -169,7 +170,7 @@ public class EdgeBackGestureHandler extends CurrentUserTracker implements Displa private boolean mGestureBlockingActivityRunning; private InputMonitor mInputMonitor; - private InputEventReceiver mInputEventReceiver; + private InputChannelCompat.InputEventReceiver mInputEventReceiver; private NavigationEdgeBackPlugin mEdgeBackPlugin; private int mLeftInset; @@ -383,8 +384,9 @@ public class EdgeBackGestureHandler extends CurrentUserTracker implements Displa // Register input event receiver mInputMonitor = InputManager.getInstance().monitorGestureInput( "edge-swipe", mDisplayId); - mInputEventReceiver = new SysUiInputEventReceiver( - mInputMonitor.getInputChannel(), Looper.getMainLooper()); + mInputEventReceiver = new InputChannelCompat.InputEventReceiver( + mInputMonitor.getInputChannel(), Looper.getMainLooper(), + Choreographer.getInstance(), this::onInputEvent); // Add a nav bar panel window setEdgeBackPlugin(new NavigationBarEdgePanel(mContext)); @@ -520,6 +522,7 @@ public class EdgeBackGestureHandler extends CurrentUserTracker implements Displa if (action == MotionEvent.ACTION_DOWN) { // Verify if this is in within the touch region and we aren't in immersive mode, and // either the bouncer is showing or the notification panel is hidden + mInputEventReceiver.setBatchingEnabled(false); mIsOnLeftEdge = ev.getX() <= mEdgeWidthLeft + mLeftInset; mLogGesture = false; mInRejectedExclusion = false; @@ -571,6 +574,7 @@ public class EdgeBackGestureHandler extends CurrentUserTracker implements Displa mThresholdCrossed = true; // Capture inputs mInputMonitor.pilferPointers(); + mInputEventReceiver.setBatchingEnabled(true); } else { logGesture(SysUiStatsLog.BACK_GESTURE__TYPE__INCOMPLETE_FAR_FROM_EDGE); } @@ -672,15 +676,4 @@ public class EdgeBackGestureHandler extends CurrentUserTracker implements Displa } proto.edgeBackGestureHandler.allowGesture = mAllowGesture; } - - class SysUiInputEventReceiver extends InputEventReceiver { - SysUiInputEventReceiver(InputChannel channel, Looper looper) { - super(channel, looper); - } - - public void onInputEvent(InputEvent event) { - EdgeBackGestureHandler.this.onInputEvent(event); - finishInputEvent(event, true); - } - } } diff --git a/packages/SystemUI/src/com/android/systemui/pip/PipBoundsHandler.java b/packages/SystemUI/src/com/android/systemui/pip/PipBoundsHandler.java index b464e8adea59..89b5c38d94a7 100644 --- a/packages/SystemUI/src/com/android/systemui/pip/PipBoundsHandler.java +++ b/packages/SystemUI/src/com/android/systemui/pip/PipBoundsHandler.java @@ -22,8 +22,8 @@ import static android.util.TypedValue.COMPLEX_UNIT_DIP; import static android.view.Surface.ROTATION_0; import static android.view.Surface.ROTATION_180; -import android.app.ActivityManager; import android.app.ActivityTaskManager; +import android.app.ActivityTaskManager.RootTaskInfo; import android.content.ComponentName; import android.content.Context; import android.content.res.Resources; @@ -328,14 +328,14 @@ public class PipBoundsHandler { return false; } - // Bail early if the pinned stack is staled. - final ActivityManager.StackInfo pinnedStackInfo; + // Bail early if the pinned task is staled. + final RootTaskInfo pinnedTaskInfo; try { - pinnedStackInfo = ActivityTaskManager.getService() - .getStackInfo(WINDOWING_MODE_PINNED, ACTIVITY_TYPE_UNDEFINED); - if (pinnedStackInfo == null) return false; + pinnedTaskInfo = ActivityTaskManager.getService() + .getRootTaskInfo(WINDOWING_MODE_PINNED, ACTIVITY_TYPE_UNDEFINED); + if (pinnedTaskInfo == null) return false; } catch (RemoteException e) { - Log.e(TAG, "Failed to get StackInfo for pinned stack", e); + Log.e(TAG, "Failed to get RootTaskInfo for pinned task", e); return false; } @@ -362,7 +362,7 @@ public class PipBoundsHandler { getInsetBounds(outInsetBounds); outBounds.set(postChangeStackBounds); - t.setBounds(pinnedStackInfo.stackToken, outBounds); + t.setBounds(pinnedTaskInfo.token, outBounds); return true; } diff --git a/packages/SystemUI/src/com/android/systemui/pip/PipTaskOrganizer.java b/packages/SystemUI/src/com/android/systemui/pip/PipTaskOrganizer.java index 862405609de8..a5ee3a0cd4e0 100644 --- a/packages/SystemUI/src/com/android/systemui/pip/PipTaskOrganizer.java +++ b/packages/SystemUI/src/com/android/systemui/pip/PipTaskOrganizer.java @@ -57,7 +57,6 @@ import android.window.TaskOrganizer; import android.window.WindowContainerToken; import android.window.WindowContainerTransaction; import android.window.WindowContainerTransactionCallback; -import android.window.WindowOrganizer; import com.android.internal.os.SomeArgs; import com.android.systemui.dagger.SysUISingleton; @@ -100,6 +99,36 @@ public class PipTaskOrganizer extends TaskOrganizer implements ShellTaskOrganize private static final int MSG_FINISH_RESIZE = 4; private static final int MSG_RESIZE_USER = 5; + // Not a complete set of states but serves what we want right now. + private enum State { + UNDEFINED(0), + TASK_APPEARED(1), + ENTERING_PIP(2), + EXITING_PIP(3); + + private final int mStateValue; + + State(int value) { + mStateValue = value; + } + + private boolean isInPip() { + return mStateValue >= TASK_APPEARED.mStateValue + && mStateValue != EXITING_PIP.mStateValue; + } + + /** + * Resize request can be initiated in other component, ignore if we are no longer in PIP, + * still waiting for animation or we're exiting from it. + * + * @return {@code true} if the resize request should be blocked/ignored. + */ + private boolean shouldBlockResizeRequest() { + return mStateValue < ENTERING_PIP.mStateValue + || mStateValue == EXITING_PIP.mStateValue; + } + } + private final Context mContext; private final Handler mMainHandler; private final Handler mUpdateHandler; @@ -201,8 +230,7 @@ public class PipTaskOrganizer extends TaskOrganizer implements ShellTaskOrganize private ActivityManager.RunningTaskInfo mTaskInfo; private WindowContainerToken mToken; private SurfaceControl mLeash; - private boolean mInPip; - private boolean mExitingPip; + private State mState = State.UNDEFINED; private @PipAnimationController.AnimationType int mOneShotAnimationType = ANIM_TYPE_BOUNDS; private PipSurfaceTransactionHelper.SurfaceControlTransactionFactory mSurfaceControlTransactionFactory; @@ -254,11 +282,11 @@ public class PipTaskOrganizer extends TaskOrganizer implements ShellTaskOrganize } public boolean isInPip() { - return mInPip; + return mState.isInPip(); } public boolean isDeferringEnterPipAnimation() { - return mInPip && mShouldDeferEnteringPip; + return mState.isInPip() && mShouldDeferEnteringPip; } /** @@ -287,9 +315,9 @@ public class PipTaskOrganizer extends TaskOrganizer implements ShellTaskOrganize * @param animationDurationMs duration in millisecond for the exiting PiP transition */ public void exitPip(int animationDurationMs) { - if (!mInPip || mExitingPip || mToken == null) { + if (!mState.isInPip() || mState == State.EXITING_PIP || mToken == null) { Log.wtf(TAG, "Not allowed to exitPip in current state" - + " mInPip=" + mInPip + " mExitingPip=" + mExitingPip + " mToken=" + mToken); + + " mState=" + mState + " mToken=" + mToken); return; } @@ -304,15 +332,15 @@ public class PipTaskOrganizer extends TaskOrganizer implements ShellTaskOrganize ? TRANSITION_DIRECTION_LEAVE_PIP_TO_SPLIT_SCREEN : TRANSITION_DIRECTION_LEAVE_PIP; if (orientationDiffers) { + mState = State.EXITING_PIP; // Send started callback though animation is ignored. sendOnPipTransitionStarted(direction); // Don't bother doing an animation if the display rotation differs or if it's in // a non-supported windowing mode applyWindowingModeChangeOnExit(wct, direction); - WindowOrganizer.applyTransaction(wct); + mTaskOrganizer.applyTransaction(wct); // Send finished callback though animation is ignored. sendOnPipTransitionFinished(direction); - mInPip = false; } else { final SurfaceControl.Transaction tx = mSurfaceControlTransactionFactory.getTransaction(); @@ -334,11 +362,10 @@ public class PipTaskOrganizer extends TaskOrganizer implements ShellTaskOrganize scheduleAnimateResizePip(mLastReportedBounds, destinationBounds, null /* sourceHintRect */, direction, animationDurationMs, null /* updateBoundsCallback */); - mInPip = false; + mState = State.EXITING_PIP; } }); } - mExitingPip = true; } private void applyWindowingModeChangeOnExit(WindowContainerTransaction wct, int direction) { @@ -357,9 +384,9 @@ public class PipTaskOrganizer extends TaskOrganizer implements ShellTaskOrganize * Removes PiP immediately. */ public void removePip() { - if (!mInPip || mExitingPip || mToken == null) { + if (!mState.isInPip() || mToken == null) { Log.wtf(TAG, "Not allowed to removePip in current state" - + " mInPip=" + mInPip + " mExitingPip=" + mExitingPip + " mToken=" + mToken); + + " mState=" + mState + " mToken=" + mToken); return; } @@ -371,7 +398,7 @@ public class PipTaskOrganizer extends TaskOrganizer implements ShellTaskOrganize .setDuration(mEnterExitAnimationDuration) .start()); mInitialState.remove(mToken.asBinder()); - mExitingPip = true; + mState = State.EXITING_PIP; } private void removePipImmediately() { @@ -379,7 +406,7 @@ public class PipTaskOrganizer extends TaskOrganizer implements ShellTaskOrganize // Reset the task bounds first to ensure the activity configuration is reset as well final WindowContainerTransaction wct = new WindowContainerTransaction(); wct.setBounds(mToken, null); - WindowOrganizer.applyTransaction(wct); + mTaskOrganizer.applyTransaction(wct); ActivityTaskManager.getService().removeStacksInWindowingModes( new int[]{ WINDOWING_MODE_PINNED }); @@ -393,8 +420,7 @@ public class PipTaskOrganizer extends TaskOrganizer implements ShellTaskOrganize Objects.requireNonNull(info, "Requires RunningTaskInfo"); mTaskInfo = info; mToken = mTaskInfo.token; - mInPip = true; - mExitingPip = false; + mState = State.TASK_APPEARED; mLeash = leash; mInitialState.put(mToken.asBinder(), new Configuration(mTaskInfo.configuration)); mPictureInPictureParams = mTaskInfo.pictureInPictureParams; @@ -424,6 +450,7 @@ public class PipTaskOrganizer extends TaskOrganizer implements ShellTaskOrganize scheduleAnimateResizePip(currentBounds, destinationBounds, sourceHintRect, TRANSITION_DIRECTION_TO_PIP, mEnterExitAnimationDuration, null /* updateBoundsCallback */); + mState = State.ENTERING_PIP; } else if (mOneShotAnimationType == ANIM_TYPE_ALPHA) { enterPipWithAlphaAnimation(destinationBounds, mEnterExitAnimationDuration); mOneShotAnimationType = ANIM_TYPE_BOUNDS; @@ -469,6 +496,9 @@ public class PipTaskOrganizer extends TaskOrganizer implements ShellTaskOrganize .setPipAnimationCallback(mPipAnimationCallback) .setDuration(durationMs) .start()); + // mState is set right after the animation is kicked off to block any resize + // requests such as offsetPip that may have been called prior to the transition. + mState = State.ENTERING_PIP; } }); } @@ -561,7 +591,7 @@ public class PipTaskOrganizer extends TaskOrganizer implements ShellTaskOrganize */ @Override public void onTaskVanished(ActivityManager.RunningTaskInfo info) { - if (!mInPip) { + if (!mState.isInPip()) { return; } final WindowContainerToken token = info.token; @@ -572,8 +602,7 @@ public class PipTaskOrganizer extends TaskOrganizer implements ShellTaskOrganize } mShouldDeferEnteringPip = false; mPictureInPictureParams = null; - mInPip = false; - mExitingPip = false; + mState = State.UNDEFINED; mPipUiEventLoggerLogger.setTaskInfo(null); } @@ -601,7 +630,7 @@ public class PipTaskOrganizer extends TaskOrganizer implements ShellTaskOrganize @Override public void onFixedRotationFinished(int displayId) { - if (mShouldDeferEnteringPip && mInPip) { + if (mShouldDeferEnteringPip && mState.isInPip()) { final Rect destinationBounds = mPipBoundsHandler.getDestinationBounds( mTaskInfo.topActivity, getAspectRatioOrDefault(mPictureInPictureParams), null /* bounds */, getMinimalSize(mTaskInfo.topActivityInfo)); @@ -624,7 +653,7 @@ public class PipTaskOrganizer extends TaskOrganizer implements ShellTaskOrganize mPipAnimationController.getCurrentAnimator(); if (animator == null || !animator.isRunning() || animator.getTransitionDirection() != TRANSITION_DIRECTION_TO_PIP) { - if (mInPip && fromRotation) { + if (mState.isInPip() && fromRotation) { // If we are rotating while there is a current animation, immediately cancel the // animation (remove the listeners so we don't trigger the normal finish resize // call that should only happen on the update thread) @@ -713,10 +742,10 @@ public class PipTaskOrganizer extends TaskOrganizer implements ShellTaskOrganize private void scheduleAnimateResizePip(Rect currentBounds, Rect destinationBounds, Rect sourceHintRect, @PipAnimationController.TransitionDirection int direction, int durationMs, Consumer<Rect> updateBoundsCallback) { - if (!mInPip) { + if (!mState.isInPip()) { // TODO: tend to use shouldBlockResizeRequest here as well but need to consider // the fact that when in exitPip, scheduleAnimateResizePip is executed in the window - // container transaction callback and we want to set the mExitingPip immediately. + // container transaction callback and we want to set the mState immediately. return; } @@ -773,7 +802,7 @@ public class PipTaskOrganizer extends TaskOrganizer implements ShellTaskOrganize private void scheduleFinishResizePip(Rect destinationBounds, @PipAnimationController.TransitionDirection int direction, Consumer<Rect> updateBoundsCallback) { - if (shouldBlockResizeRequest()) { + if (mState.shouldBlockResizeRequest()) { return; } @@ -792,7 +821,7 @@ public class PipTaskOrganizer extends TaskOrganizer implements ShellTaskOrganize mSurfaceTransactionHelper .crop(tx, mLeash, destinationBounds) .resetScale(tx, mLeash, destinationBounds) - .round(tx, mLeash, mInPip); + .round(tx, mLeash, mState.isInPip()); return tx; } @@ -801,7 +830,7 @@ public class PipTaskOrganizer extends TaskOrganizer implements ShellTaskOrganize */ public void scheduleOffsetPip(Rect originalBounds, int offset, int duration, Consumer<Rect> updateBoundsCallback) { - if (shouldBlockResizeRequest()) { + if (mState.shouldBlockResizeRequest()) { return; } if (mShouldDeferEnteringPip) { @@ -846,7 +875,7 @@ public class PipTaskOrganizer extends TaskOrganizer implements ShellTaskOrganize final SurfaceControl.Transaction tx = mSurfaceControlTransactionFactory.getTransaction(); mSurfaceTransactionHelper .crop(tx, mLeash, destinationBounds) - .round(tx, mLeash, mInPip); + .round(tx, mLeash, mState.isInPip()); tx.apply(); } @@ -932,7 +961,7 @@ public class PipTaskOrganizer extends TaskOrganizer implements ShellTaskOrganize */ public void applyFinishBoundsResize(@NonNull WindowContainerTransaction wct, @PipAnimationController.TransitionDirection int direction) { - WindowOrganizer.applyTransaction(wct); + mTaskOrganizer.applyTransaction(wct); } /** @@ -984,16 +1013,6 @@ public class PipTaskOrganizer extends TaskOrganizer implements ShellTaskOrganize } /** - * Resize request can be initiated in other component, ignore if we are no longer in PIP - * or we're exiting from it. - * - * @return {@code true} if the resize request should be blocked/ignored. - */ - private boolean shouldBlockResizeRequest() { - return !mInPip || mExitingPip; - } - - /** * Sync with {@link SplitScreen} on destination bounds if PiP is going to split screen. * * @param destinationBoundsOut contain the updated destination bounds if applicable @@ -1027,7 +1046,7 @@ public class PipTaskOrganizer extends TaskOrganizer implements ShellTaskOrganize pw.println(innerPrefix + "mToken=" + mToken + " binder=" + (mToken != null ? mToken.asBinder() : null)); pw.println(innerPrefix + "mLeash=" + mLeash); - pw.println(innerPrefix + "mInPip=" + mInPip); + pw.println(innerPrefix + "mState=" + mState); pw.println(innerPrefix + "mOneShotAnimationType=" + mOneShotAnimationType); pw.println(innerPrefix + "mPictureInPictureParams=" + mPictureInPictureParams); pw.println(innerPrefix + "mLastReportedBounds=" + mLastReportedBounds); diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipController.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipController.java index 6998e90b3a7c..4f225e2f9590 100644 --- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipController.java +++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipController.java @@ -25,6 +25,7 @@ import static com.android.systemui.pip.PipAnimationController.isOutPipDirection; import android.annotation.Nullable; import android.app.ActivityManager; import android.app.ActivityTaskManager; +import android.app.ActivityTaskManager.RootTaskInfo; import android.app.IActivityManager; import android.app.RemoteAction; import android.content.ComponentName; @@ -324,9 +325,9 @@ public class PipController implements Pip, PipTaskOrganizer.PipTransitionCallbac configController.addCallback(mOverlayChangedListener); try { - ActivityManager.StackInfo stackInfo = ActivityTaskManager.getService().getStackInfo( + RootTaskInfo taskInfo = ActivityTaskManager.getService().getRootTaskInfo( WINDOWING_MODE_PINNED, ACTIVITY_TYPE_UNDEFINED); - if (stackInfo != null) { + if (taskInfo != null) { // If SystemUI restart, and it already existed a pinned stack, // register the pip input consumer to ensure touch can send to it. mInputConsumerController.registerInputConsumer(true /* withSfVsync */); diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivityController.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivityController.java index 873ba26b39ab..d308172689db 100644 --- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivityController.java +++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivityController.java @@ -19,8 +19,8 @@ package com.android.systemui.pip.phone; import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED; import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED; -import android.app.ActivityManager.StackInfo; import android.app.ActivityTaskManager; +import android.app.ActivityTaskManager.RootTaskInfo; import android.app.RemoteAction; import android.content.Context; import android.content.pm.ParceledListSlice; @@ -312,10 +312,10 @@ public class PipMenuActivityController { // Fetch the pinned stack bounds Rect stackBounds = null; try { - StackInfo pinnedStackInfo = ActivityTaskManager.getService().getStackInfo( + RootTaskInfo pinnedTaskInfo = ActivityTaskManager.getService().getRootTaskInfo( WINDOWING_MODE_PINNED, ACTIVITY_TYPE_UNDEFINED); - if (pinnedStackInfo != null) { - stackBounds = pinnedStackInfo.bounds; + if (pinnedTaskInfo != null) { + stackBounds = pinnedTaskInfo.bounds; } } catch (RemoteException e) { Log.e(TAG, "Error showing PIP menu", e); diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuView.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuView.java index 993bfe04f9a3..c66f442c4c0d 100644 --- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuView.java +++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuView.java @@ -475,12 +475,10 @@ public class PipMenuView extends FrameLayout { final Pair<ComponentName, Integer> topPipActivityInfo = PipUtils.getTopPipActivity(mContext, ActivityManager.getService()); if (topPipActivityInfo.first != null) { - final UserHandle user = UserHandle.of(topPipActivityInfo.second); final Intent settingsIntent = new Intent(ACTION_PICTURE_IN_PICTURE_SETTINGS, Uri.fromParts("package", topPipActivityInfo.first.getPackageName(), null)); - settingsIntent.putExtra(Intent.EXTRA_USER_HANDLE, user); settingsIntent.setFlags(FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK); - mContext.startActivity(settingsIntent); + mContext.startActivityAsUser(settingsIntent, UserHandle.CURRENT); } } diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipResizeGestureHandler.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipResizeGestureHandler.java index 50d20d3572d1..08d9b2ae21b0 100644 --- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipResizeGestureHandler.java +++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipResizeGestureHandler.java @@ -15,7 +15,7 @@ */ package com.android.systemui.pip.phone; -import static com.android.internal.config.sysui.SystemUiDeviceConfigFlags.PIP_USER_RESIZE; +import static com.android.internal.config.sysui.SystemUiDeviceConfigFlags.PIP_PINCH_RESIZE; import static com.android.internal.policy.TaskResizingAlgorithm.CTRL_BOTTOM; import static com.android.internal.policy.TaskResizingAlgorithm.CTRL_LEFT; import static com.android.internal.policy.TaskResizingAlgorithm.CTRL_NONE; @@ -46,6 +46,7 @@ import android.view.InputEvent; import android.view.InputEventReceiver; import android.view.InputMonitor; import android.view.MotionEvent; +import android.view.ScaleGestureDetector; import android.view.ViewConfiguration; import com.android.internal.policy.TaskResizingAlgorithm; @@ -67,6 +68,8 @@ import java.util.function.Function; public class PipResizeGestureHandler { private static final String TAG = "PipResizeGestureHandler"; + private static final float PINCH_THRESHOLD = 0.05f; + private static final float STARTING_SCALE_FACTOR = 1.0f; private static final int INVALID_SYSUI_STATE_MASK = SYSUI_STATE_GLOBAL_ACTIONS_SHOWING @@ -83,6 +86,7 @@ public class PipResizeGestureHandler { private final int mDisplayId; private final Executor mMainExecutor; private final SysUiState mSysUiState; + private final ScaleGestureDetector mScaleGestureDetector; private final Region mTmpRegion = new Region(); private final PointF mDownPoint = new PointF(); @@ -105,8 +109,10 @@ public class PipResizeGestureHandler { private boolean mAllowGesture; private boolean mIsAttached; private boolean mIsEnabled; - private boolean mEnableUserResize; + private boolean mEnablePinchResize; private boolean mThresholdCrossed; + private boolean mUsingPinchToZoom = false; + private float mScaleFactor = STARTING_SCALE_FACTOR; private InputMonitor mInputMonitor; private InputEventReceiver mInputEventReceiver; @@ -136,17 +142,73 @@ public class PipResizeGestureHandler { context.getDisplay().getRealSize(mMaxSize); reloadResources(); - mEnableUserResize = DeviceConfig.getBoolean( + mScaleGestureDetector = new ScaleGestureDetector(context, + new ScaleGestureDetector.OnScaleGestureListener() { + @Override + public boolean onScale(ScaleGestureDetector detector) { + mScaleFactor *= detector.getScaleFactor(); + + if (!mThresholdCrossed + && (mScaleFactor > (STARTING_SCALE_FACTOR + PINCH_THRESHOLD) + || mScaleFactor < (STARTING_SCALE_FACTOR - PINCH_THRESHOLD))) { + mThresholdCrossed = true; + mInputMonitor.pilferPointers(); + } + if (mThresholdCrossed) { + int height = Math.min(mMaxSize.y, Math.max(mMinSize.y, + (int) (mScaleFactor * mLastDownBounds.height()))); + int width = Math.min(mMaxSize.x, Math.max(mMinSize.x, + (int) (mScaleFactor * mLastDownBounds.width()))); + int top, bottom, left, right; + + if ((mCtrlType & CTRL_TOP) != 0) { + top = mLastDownBounds.bottom - height; + bottom = mLastDownBounds.bottom; + } else { + top = mLastDownBounds.top; + bottom = mLastDownBounds.top + height; + } + + if ((mCtrlType & CTRL_LEFT) != 0) { + left = mLastDownBounds.right - width; + right = mLastDownBounds.right; + } else { + left = mLastDownBounds.left; + right = mLastDownBounds.left + width; + } + + mLastResizeBounds.set(left, top, right, bottom); + mPipTaskOrganizer.scheduleUserResizePip(mLastDownBounds, + mLastResizeBounds, + null); + } + return true; + } + + @Override + public boolean onScaleBegin(ScaleGestureDetector detector) { + setCtrlTypeForPinchToZoom(); + return true; + } + + @Override + public void onScaleEnd(ScaleGestureDetector detector) { + mScaleFactor = STARTING_SCALE_FACTOR; + finishResize(); + } + }); + + mEnablePinchResize = DeviceConfig.getBoolean( DeviceConfig.NAMESPACE_SYSTEMUI, - PIP_USER_RESIZE, - /* defaultValue = */ true); + PIP_PINCH_RESIZE, + /* defaultValue = */ false); deviceConfig.addOnPropertiesChangedListener(DeviceConfig.NAMESPACE_SYSTEMUI, mMainExecutor, new DeviceConfig.OnPropertiesChangedListener() { @Override public void onPropertiesChanged(DeviceConfig.Properties properties) { - if (properties.getKeyset().contains(PIP_USER_RESIZE)) { - mEnableUserResize = properties.getBoolean( - PIP_USER_RESIZE, /* defaultValue = */ true); + if (properties.getKeyset().contains(PIP_PINCH_RESIZE)) { + mEnablePinchResize = properties.getBoolean( + PIP_PINCH_RESIZE, /* defaultValue = */ false); } } }); @@ -193,7 +255,7 @@ public class PipResizeGestureHandler { } private void updateIsEnabled() { - boolean isEnabled = mIsAttached && mEnableUserResize; + boolean isEnabled = mIsAttached; if (isEnabled == mIsEnabled) { return; } @@ -211,7 +273,11 @@ public class PipResizeGestureHandler { private void onInputEvent(InputEvent ev) { if (ev instanceof MotionEvent) { - onMotionEvent((MotionEvent) ev); + if (mUsingPinchToZoom) { + mScaleGestureDetector.onTouchEvent((MotionEvent) ev); + } else { + onDragCornerResize((MotionEvent) ev); + } } } @@ -254,8 +320,51 @@ public class PipResizeGestureHandler { } public boolean willStartResizeGesture(MotionEvent ev) { - return mEnableUserResize && isInValidSysUiState() - && isWithinTouchRegion((int) ev.getRawX(), (int) ev.getRawY()); + if (isInValidSysUiState()) { + switch (ev.getActionMasked()) { + case MotionEvent.ACTION_DOWN: + // Always pass the DOWN event to the ScaleGestureDetector + mScaleGestureDetector.onTouchEvent(ev); + if (isWithinTouchRegion((int) ev.getRawX(), (int) ev.getRawY())) { + return true; + } + break; + + case MotionEvent.ACTION_POINTER_DOWN: + if (mEnablePinchResize && ev.getPointerCount() == 2) { + mUsingPinchToZoom = true; + return true; + } + break; + + default: + break; + } + } + return false; + } + + private void setCtrlTypeForPinchToZoom() { + final Rect currentPipBounds = mMotionHelper.getBounds(); + mLastDownBounds.set(mMotionHelper.getBounds()); + + Rect movementBounds = mMovementBoundsSupplier.apply(currentPipBounds); + mDisplayBounds.set(movementBounds.left, + movementBounds.top, + movementBounds.right + currentPipBounds.width(), + movementBounds.bottom + currentPipBounds.height()); + + if (currentPipBounds.left == mDisplayBounds.left) { + mCtrlType |= CTRL_RIGHT; + } else { + mCtrlType |= CTRL_LEFT; + } + + if (currentPipBounds.top > mDisplayBounds.top + mDisplayBounds.height()) { + mCtrlType |= CTRL_TOP; + } else { + mCtrlType |= CTRL_BOTTOM; + } } private void setCtrlType(int x, int y) { @@ -295,7 +404,7 @@ public class PipResizeGestureHandler { return (mSysUiState.getFlags() & INVALID_SYSUI_STATE_MASK) == 0; } - private void onMotionEvent(MotionEvent ev) { + private void onDragCornerResize(MotionEvent ev) { int action = ev.getActionMasked(); float x = ev.getX(); float y = ev.getY(); @@ -345,28 +454,33 @@ public class PipResizeGestureHandler { break; case MotionEvent.ACTION_UP: case MotionEvent.ACTION_CANCEL: - if (!mLastResizeBounds.isEmpty()) { - mUserResizeBounds.set(mLastResizeBounds); - mPipTaskOrganizer.scheduleFinishResizePip(mLastResizeBounds, - (Rect bounds) -> { - new Handler(Looper.getMainLooper()).post(() -> { - mMotionHelper.synchronizePinnedStackBounds(); - mUpdateMovementBoundsRunnable.run(); - resetState(); - }); - }); - mPipUiEventLogger.log( - PipUiEventLogger.PipUiEventEnum.PICTURE_IN_PICTURE_RESIZE); - } else { - resetState(); - } + finishResize(); break; } } } + private void finishResize() { + if (!mLastResizeBounds.isEmpty()) { + mUserResizeBounds.set(mLastResizeBounds); + mPipTaskOrganizer.scheduleFinishResizePip(mLastResizeBounds, + (Rect bounds) -> { + new Handler(Looper.getMainLooper()).post(() -> { + mMotionHelper.synchronizePinnedStackBounds(); + mUpdateMovementBoundsRunnable.run(); + resetState(); + }); + }); + mPipUiEventLogger.log( + PipUiEventLogger.PipUiEventEnum.PICTURE_IN_PICTURE_RESIZE); + } else { + resetState(); + } + } + private void resetState() { mCtrlType = CTRL_NONE; + mUsingPinchToZoom = false; mAllowGesture = false; mThresholdCrossed = false; } @@ -397,7 +511,7 @@ public class PipResizeGestureHandler { pw.println(innerPrefix + "mAllowGesture=" + mAllowGesture); pw.println(innerPrefix + "mIsAttached=" + mIsAttached); pw.println(innerPrefix + "mIsEnabled=" + mIsEnabled); - pw.println(innerPrefix + "mEnableUserResize=" + mEnableUserResize); + pw.println(innerPrefix + "mEnablePinchResize=" + mEnablePinchResize); pw.println(innerPrefix + "mThresholdCrossed=" + mThresholdCrossed); } diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchHandler.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchHandler.java index 9693f235a4ff..97b3484292c6 100644 --- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchHandler.java +++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchHandler.java @@ -650,8 +650,7 @@ public class PipTouchHandler { } MotionEvent ev = (MotionEvent) inputEvent; - if (ev.getActionMasked() == MotionEvent.ACTION_DOWN - && mPipResizeGestureHandler.willStartResizeGesture(ev)) { + if (mPipResizeGestureHandler.willStartResizeGesture(ev)) { // Initialize the touch state for the gesture, but immediately reset to invalidate the // gesture mTouchState.onTouchEvent(ev); diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipUtils.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipUtils.java index 4cfec0193b54..baa8f118f362 100644 --- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipUtils.java +++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipUtils.java @@ -19,8 +19,8 @@ package com.android.systemui.pip.phone; import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED; import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED; -import android.app.ActivityManager.StackInfo; import android.app.ActivityTaskManager; +import android.app.ActivityTaskManager.RootTaskInfo; import android.app.IActivityManager; import android.content.ComponentName; import android.content.Context; @@ -40,15 +40,15 @@ public class PipUtils { IActivityManager activityManager) { try { final String sysUiPackageName = context.getPackageName(); - final StackInfo pinnedStackInfo = ActivityTaskManager.getService().getStackInfo( + final RootTaskInfo pinnedTaskInfo = ActivityTaskManager.getService().getRootTaskInfo( WINDOWING_MODE_PINNED, ACTIVITY_TYPE_UNDEFINED); - if (pinnedStackInfo != null && pinnedStackInfo.taskIds != null && - pinnedStackInfo.taskIds.length > 0) { - for (int i = pinnedStackInfo.taskNames.length - 1; i >= 0; i--) { + if (pinnedTaskInfo != null && pinnedTaskInfo.childTaskIds != null + && pinnedTaskInfo.childTaskIds.length > 0) { + for (int i = pinnedTaskInfo.childTaskNames.length - 1; i >= 0; i--) { ComponentName cn = ComponentName.unflattenFromString( - pinnedStackInfo.taskNames[i]); + pinnedTaskInfo.childTaskNames[i]); if (cn != null && !cn.getPackageName().equals(sysUiPackageName)) { - return new Pair<>(cn, pinnedStackInfo.taskUserIds[i]); + return new Pair<>(cn, pinnedTaskInfo.childTaskUserIds[i]); } } } diff --git a/packages/SystemUI/src/com/android/systemui/pip/tv/PipController.java b/packages/SystemUI/src/com/android/systemui/pip/tv/PipController.java index 3b3235f1e63c..12a545aa4b02 100644 --- a/packages/SystemUI/src/com/android/systemui/pip/tv/PipController.java +++ b/packages/SystemUI/src/com/android/systemui/pip/tv/PipController.java @@ -21,8 +21,8 @@ import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED; import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED; import android.app.ActivityManager.RunningTaskInfo; -import android.app.ActivityManager.StackInfo; import android.app.ActivityTaskManager; +import android.app.ActivityTaskManager.RootTaskInfo; import android.app.IActivityTaskManager; import android.app.RemoteAction; import android.content.BroadcastReceiver; @@ -289,7 +289,7 @@ public class PipController implements Pip, PipTaskOrganizer.PipTransitionCallbac // 1. Configuration changed due to the language change (RTL <-> RTL) // 2. SystemUI restarts after the crash mPipBounds = mDefaultPipBounds; - resizePinnedStack(getPinnedStackInfo() == null ? STATE_NO_PIP : STATE_PIP); + resizePinnedStack(getPinnedTaskInfo() == null ? STATE_NO_PIP : STATE_PIP); } /** @@ -505,15 +505,15 @@ public class PipController implements Pip, PipTaskOrganizer.PipTransitionCallbac return mState != STATE_NO_PIP; } - private StackInfo getPinnedStackInfo() { - StackInfo stackInfo = null; + private RootTaskInfo getPinnedTaskInfo() { + RootTaskInfo taskInfo = null; try { - stackInfo = ActivityTaskManager.getService().getStackInfo( + taskInfo = ActivityTaskManager.getService().getRootTaskInfo( WINDOWING_MODE_PINNED, ACTIVITY_TYPE_UNDEFINED); } catch (RemoteException e) { - Log.e(TAG, "getStackInfo failed", e); + Log.e(TAG, "getRootTaskInfo failed", e); } - return stackInfo; + return taskInfo; } private void handleMediaResourceGranted(String[] packageNames) { @@ -611,14 +611,14 @@ public class PipController implements Pip, PipTaskOrganizer.PipTransitionCallbac if (getState() != STATE_NO_PIP) { boolean hasPip = false; - StackInfo stackInfo = getPinnedStackInfo(); - if (stackInfo == null || stackInfo.taskIds == null) { + RootTaskInfo taskInfo = getPinnedTaskInfo(); + if (taskInfo == null || taskInfo.childTaskIds == null) { Log.w(TAG, "There is nothing in pinned stack"); closePipInternal(false); return; } - for (int i = stackInfo.taskIds.length - 1; i >= 0; --i) { - if (stackInfo.taskIds[i] == mPipTaskId) { + for (int i = taskInfo.childTaskIds.length - 1; i >= 0; --i) { + if (taskInfo.childTaskIds[i] == mPipTaskId) { // PIP task is still alive. hasPip = true; break; @@ -642,16 +642,16 @@ public class PipController implements Pip, PipTaskOrganizer.PipTransitionCallbac public void onActivityPinned(String packageName, int userId, int taskId, int stackId) { if (DEBUG) Log.d(TAG, "onActivityPinned()"); - StackInfo stackInfo = getPinnedStackInfo(); - if (stackInfo == null) { + RootTaskInfo taskInfo = getPinnedTaskInfo(); + if (taskInfo == null) { Log.w(TAG, "Cannot find pinned stack"); return; } - if (DEBUG) Log.d(TAG, "PINNED_STACK:" + stackInfo); - mPinnedStackId = stackInfo.stackId; - mPipTaskId = stackInfo.taskIds[stackInfo.taskIds.length - 1]; + if (DEBUG) Log.d(TAG, "PINNED_STACK:" + taskInfo); + mPinnedStackId = taskInfo.taskId; + mPipTaskId = taskInfo.childTaskIds[taskInfo.childTaskIds.length - 1]; mPipComponentName = ComponentName.unflattenFromString( - stackInfo.taskNames[stackInfo.taskNames.length - 1]); + taskInfo.childTaskNames[taskInfo.childTaskNames.length - 1]); // Set state to STATE_PIP so we show it when the pinned stack animation ends. mState = STATE_PIP; mMediaSessionManager.addOnActiveSessionsChangedListener( diff --git a/packages/SystemUI/src/com/android/systemui/privacy/PrivacyItemController.kt b/packages/SystemUI/src/com/android/systemui/privacy/PrivacyItemController.kt index e57478eb0988..4d6d71c06085 100644 --- a/packages/SystemUI/src/com/android/systemui/privacy/PrivacyItemController.kt +++ b/packages/SystemUI/src/com/android/systemui/privacy/PrivacyItemController.kt @@ -72,6 +72,8 @@ class PrivacyItemController @Inject constructor( private const val ALL_INDICATORS = SystemUiDeviceConfigFlags.PROPERTY_PERMISSIONS_HUB_ENABLED private const val MIC_CAMERA = SystemUiDeviceConfigFlags.PROPERTY_MIC_CAMERA_ENABLED + private const val DEFAULT_ALL_INDICATORS = false + private const val DEFAULT_MIC_CAMERA = true } @VisibleForTesting @@ -81,12 +83,12 @@ class PrivacyItemController @Inject constructor( private fun isAllIndicatorsEnabled(): Boolean { return deviceConfigProxy.getBoolean(DeviceConfig.NAMESPACE_PRIVACY, - ALL_INDICATORS, false) + ALL_INDICATORS, DEFAULT_ALL_INDICATORS) } private fun isMicCameraEnabled(): Boolean { return deviceConfigProxy.getBoolean(DeviceConfig.NAMESPACE_PRIVACY, - MIC_CAMERA, false) + MIC_CAMERA, DEFAULT_MIC_CAMERA) } private var currentUserIds = emptyList<Int>() @@ -118,12 +120,13 @@ class PrivacyItemController @Inject constructor( // Running on the ui executor so can iterate on callbacks if (properties.keyset.contains(ALL_INDICATORS)) { - allIndicatorsAvailable = properties.getBoolean(ALL_INDICATORS, false) + allIndicatorsAvailable = properties.getBoolean(ALL_INDICATORS, + DEFAULT_ALL_INDICATORS) callbacks.forEach { it.get()?.onFlagAllChanged(allIndicatorsAvailable) } } if (properties.keyset.contains(MIC_CAMERA)) { - micCameraAvailable = properties.getBoolean(MIC_CAMERA, false) + micCameraAvailable = properties.getBoolean(MIC_CAMERA, DEFAULT_MIC_CAMERA) callbacks.forEach { it.get()?.onFlagMicCameraChanged(micCameraAvailable) } } internalUiExecutor.updateListeningState() diff --git a/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java b/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java index cba938f5e1a6..2a976f546ba4 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java +++ b/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java @@ -75,8 +75,6 @@ import com.android.systemui.navigationbar.NavigationBar; import com.android.systemui.navigationbar.NavigationBarController; import com.android.systemui.navigationbar.NavigationBarView; import com.android.systemui.navigationbar.NavigationModeController; -import com.android.systemui.onehanded.OneHanded; -import com.android.systemui.onehanded.OneHandedEvents; import com.android.systemui.pip.Pip; import com.android.systemui.pip.PipAnimationController; import com.android.systemui.recents.OverviewProxyService.OverviewProxyListener; @@ -93,6 +91,8 @@ import com.android.systemui.statusbar.NotificationShadeWindowController; import com.android.systemui.statusbar.phone.StatusBar; import com.android.systemui.statusbar.phone.StatusBarWindowCallback; import com.android.systemui.statusbar.policy.CallbackController; +import com.android.wm.shell.onehanded.OneHanded; +import com.android.wm.shell.onehanded.OneHandedEvents; import com.android.wm.shell.splitscreen.SplitScreen; import java.io.FileDescriptor; diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java b/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java index 7dd4edd233bd..2b4fa2a23a07 100644 --- a/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java +++ b/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java @@ -574,7 +574,8 @@ public class GlobalScreenshot implements ViewTreeObserver.OnComputeInternalInset private void saveScreenshot(Bitmap screenshot, Consumer<Uri> finisher, Rect screenRect, Insets screenInsets, boolean showFlash) { if (mScreenshotLayout.isAttachedToWindow()) { - if (!mDismissAnimation.isRunning()) { // if we didn't already dismiss for another reason + // if we didn't already dismiss for another reason + if (mDismissAnimation == null || !mDismissAnimation.isRunning()) { mUiEventLogger.log(ScreenshotEvent.SCREENSHOT_REENTERED); } dismissScreenshot("new screenshot requested", true); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMediaManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMediaManager.java index c01bdc4c2f28..8bf134d9c5b9 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMediaManager.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMediaManager.java @@ -21,6 +21,7 @@ import static com.android.systemui.statusbar.phone.StatusBar.ENABLE_LOCKSCREEN_W import static com.android.systemui.statusbar.phone.StatusBar.SHOW_LOCKSCREEN_MEDIA_ARTWORK; import android.annotation.MainThread; +import android.annotation.NonNull; import android.annotation.Nullable; import android.app.Notification; import android.content.Context; @@ -57,6 +58,7 @@ import com.android.systemui.statusbar.dagger.StatusBarModule; import com.android.systemui.statusbar.notification.NotificationEntryListener; import com.android.systemui.statusbar.notification.NotificationEntryManager; import com.android.systemui.statusbar.notification.collection.NotificationEntry; +import com.android.systemui.statusbar.notification.collection.notifcollection.NotifCollectionListener; import com.android.systemui.statusbar.phone.BiometricUnlockController; import com.android.systemui.statusbar.phone.KeyguardBypassController; import com.android.systemui.statusbar.phone.LockscreenWallpaper; @@ -233,8 +235,17 @@ public class NotificationMediaManager implements Dumpable { NotificationVisibility visibility, boolean removedByUser, int reason) { - onNotificationRemoved(entry.getKey()); - mediaDataManager.onNotificationRemoved(entry.getKey()); + removeEntry(entry); + } + }); + + // Pending entries are never inflated, and will never generate a call to onEntryRemoved(). + // This can happen when notifications are added and canceled before inflation. Add this + // separate listener for cleanup, since media inflation occurs onPendingEntryAdded(). + notificationEntryManager.addCollectionListener(new NotifCollectionListener() { + @Override + public void onEntryCleanUp(@NonNull NotificationEntry entry) { + removeEntry(entry); } }); @@ -247,6 +258,11 @@ public class NotificationMediaManager implements Dumpable { mPropertiesChangedListener); } + private void removeEntry(NotificationEntry entry) { + onNotificationRemoved(entry.getKey()); + mMediaDataManager.onNotificationRemoved(entry.getKey()); + } + /** * Check if a state should be considered actively playing * @param state a PlaybackState diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java index 8f3033edecbb..7bac007ae478 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java @@ -188,7 +188,7 @@ public class NotificationShelf extends ActivatableNotificationView implements viewState.openedAmount = openedAmount; viewState.clipTopAmount = 0; viewState.alpha = 1; - viewState.belowSpeedBump = mAmbientState.getSpeedBumpIndex() == 0; + viewState.belowSpeedBump = mHostLayoutController.getSpeedBumpIndex() == 0; viewState.hideSensitive = false; viewState.xTranslation = getTranslationX(); if (mNotGoneIndex != -1) { @@ -352,7 +352,7 @@ public class NotificationShelf extends ActivatableNotificationView implements } setBackgroundTop(backgroundTop); setFirstElementRoundness(firstElementRoundness); - mShelfIcons.setSpeedBumpIndex(mAmbientState.getSpeedBumpIndex()); + mShelfIcons.setSpeedBumpIndex(mHostLayoutController.getSpeedBumpIndex()); mShelfIcons.calculateIconTranslations(); mShelfIcons.applyIconStates(); for (int i = 0; i < mHostLayoutController.getChildCount(); i++) { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java index 8cf8a2299922..01d31039a749 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java @@ -390,17 +390,21 @@ public class StatusBarIconView extends AnimatedImageView implements StatusIconDi } private Drawable getIcon(StatusBarIcon icon) { - return getIcon(getContext(), icon); + Context notifContext = mNotification != null ? + mNotification.getPackageContext(getContext()) : getContext(); + return getIcon(getContext(), notifContext, icon); } /** * Returns the right icon to use for this item * - * @param context Context to use to get resources + * @param sysuiContext Context to use to get scale factor + * @param context Context to use to get resources of notification icon * @return Drawable for this item, or null if the package or item could not * be found */ - public static Drawable getIcon(Context context, StatusBarIcon statusBarIcon) { + public static Drawable getIcon(Context sysuiContext, + Context context, StatusBarIcon statusBarIcon) { int userId = statusBarIcon.user.getIdentifier(); if (userId == UserHandle.USER_ALL) { userId = UserHandle.USER_SYSTEM; @@ -409,7 +413,8 @@ public class StatusBarIconView extends AnimatedImageView implements StatusIconDi Drawable icon = statusBarIcon.icon.loadDrawableAsUser(context, userId); TypedValue typedValue = new TypedValue(); - context.getResources().getValue(R.dimen.status_bar_icon_scale_factor, typedValue, true); + sysuiContext.getResources().getValue(R.dimen.status_bar_icon_scale_factor, + typedValue, true); float scaleFactor = typedValue.getFloat(); // No need to scale the icon, so return it as is. diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/InstantAppNotifier.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/InstantAppNotifier.java index 6f7b32b3ac74..363a08566fd3 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/InstantAppNotifier.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/InstantAppNotifier.java @@ -26,6 +26,7 @@ import android.annotation.NonNull; import android.annotation.Nullable; import android.app.ActivityManager; import android.app.ActivityTaskManager; +import android.app.ActivityTaskManager.RootTaskInfo; import android.app.AppGlobals; import android.app.Notification; import android.app.NotificationManager; @@ -161,16 +162,16 @@ public class InstantAppNotifier extends SystemUI () -> { ArraySet<Pair<String, Integer>> notifs = new ArraySet<>(mCurrentNotifs); try { - final ActivityManager.StackInfo focusedStack = - ActivityTaskManager.getService().getFocusedStackInfo(); - if (focusedStack != null) { + final RootTaskInfo focusedTask = + ActivityTaskManager.getService().getFocusedRootTaskInfo(); + if (focusedTask != null) { final int windowingMode = - focusedStack.configuration.windowConfiguration + focusedTask.configuration.windowConfiguration .getWindowingMode(); if (windowingMode == WINDOWING_MODE_FULLSCREEN || windowingMode == WINDOWING_MODE_SPLIT_SCREEN_SECONDARY || windowingMode == WINDOWING_MODE_FREEFORM) { - checkAndPostForStack(focusedStack, notifs, noMan, pm); + checkAndPostForStack(focusedTask, notifs, noMan, pm); } } if (mDockedStackExists) { @@ -205,10 +206,8 @@ public class InstantAppNotifier extends SystemUI @NonNull NotificationManager noMan, @NonNull IPackageManager pm) { try { - final ActivityManager.StackInfo info = - ActivityTaskManager.getService() - .getStackInfo( - WINDOWING_MODE_SPLIT_SCREEN_PRIMARY, ACTIVITY_TYPE_UNDEFINED); + final RootTaskInfo info = ActivityTaskManager.getService().getRootTaskInfo( + WINDOWING_MODE_SPLIT_SCREEN_PRIMARY, ACTIVITY_TYPE_UNDEFINED); checkAndPostForStack(info, notifs, noMan, pm); } catch (RemoteException e) { e.rethrowFromSystemServer(); @@ -221,7 +220,7 @@ public class InstantAppNotifier extends SystemUI * exists, this method removes it from {@code notifs} in the arguments. */ private void checkAndPostForStack( - @Nullable ActivityManager.StackInfo info, + @Nullable RootTaskInfo info, @NonNull ArraySet<Pair<String, Integer>> notifs, @NonNull NotificationManager noMan, @NonNull IPackageManager pm) { @@ -241,7 +240,7 @@ public class InstantAppNotifier extends SystemUI info.userId, appInfo, noMan, - info.taskIds[info.taskIds.length - 1]); + info.childTaskIds[info.childTaskIds.length - 1]); } } } catch (RemoteException e) { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifCollection.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifCollection.java index 90492b5d606d..fdfd72489e93 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifCollection.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifCollection.java @@ -18,6 +18,7 @@ package com.android.systemui.statusbar.notification.collection; import static android.service.notification.NotificationListenerService.REASON_APP_CANCEL; import static android.service.notification.NotificationListenerService.REASON_APP_CANCEL_ALL; +import static android.service.notification.NotificationListenerService.REASON_CANCEL; import static android.service.notification.NotificationListenerService.REASON_CANCEL_ALL; import static android.service.notification.NotificationListenerService.REASON_CHANNEL_BANNED; import static android.service.notification.NotificationListenerService.REASON_CLICK; @@ -459,8 +460,7 @@ public class NotifCollection implements Dumpable { + ": has not been marked for removal")); } - if (isDismissedByUser(entry)) { - // User-dismissed notifications cannot be lifetime-extended + if (cannotBeLifetimeExtended(entry)) { cancelLifetimeExtension(entry); } else { updateLifetimeExtension(entry); @@ -583,7 +583,7 @@ public class NotifCollection implements Dumpable { } private void cancelLocalDismissal(NotificationEntry entry) { - if (isDismissedByUser(entry)) { + if (entry.getDismissState() != NOT_DISMISSED) { entry.setDismissState(NOT_DISMISSED); if (entry.getSbn().getNotification().isGroupSummary()) { for (NotificationEntry otherEntry : mNotificationSet.values()) { @@ -669,12 +669,16 @@ public class NotifCollection implements Dumpable { * immediately removed from the collection, but can sometimes stick around due to lifetime * extenders. */ - private static boolean isCanceled(NotificationEntry entry) { + private boolean isCanceled(NotificationEntry entry) { return entry.mCancellationReason != REASON_NOT_CANCELED; } - private static boolean isDismissedByUser(NotificationEntry entry) { - return entry.getDismissState() != NOT_DISMISSED; + private boolean cannotBeLifetimeExtended(NotificationEntry entry) { + final boolean locallyDismissedByUser = entry.getDismissState() != NOT_DISMISSED; + final boolean systemServerReportedUserCancel = + entry.mCancellationReason == REASON_CLICK + || entry.mCancellationReason == REASON_CANCEL; + return locallyDismissedByUser || systemServerReportedUserCancel; } /** diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/ShadeListBuilder.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/ShadeListBuilder.java index 2b545c56c8bf..df63fec62e4e 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/ShadeListBuilder.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/ShadeListBuilder.java @@ -673,7 +673,6 @@ public class ShadeListBuilder implements Dumpable { GroupEntry parent = (GroupEntry) entry; for (NotificationEntry child : parent.getChildren()) { child.getAttachState().setSection(section); - child.getAttachState().setSection(section); } parent.sortChildren(sChildComparator); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/ConversationCoordinator.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/ConversationCoordinator.kt index 3aaa9acdb897..f0eb084ea8ef 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/ConversationCoordinator.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/ConversationCoordinator.kt @@ -22,6 +22,8 @@ import com.android.systemui.statusbar.notification.collection.NotifPipeline import com.android.systemui.statusbar.notification.collection.NotificationEntry import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifPromoter import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifSectioner +import com.android.systemui.statusbar.notification.collection.render.NodeController +import com.android.systemui.statusbar.notification.dagger.PeopleHeader import com.android.systemui.statusbar.notification.people.PeopleNotificationIdentifier import com.android.systemui.statusbar.notification.people.PeopleNotificationIdentifier.Companion.TYPE_NON_PERSON import javax.inject.Inject @@ -33,7 +35,8 @@ import javax.inject.Inject */ @SysUISingleton class ConversationCoordinator @Inject constructor( - private val peopleNotificationIdentifier: PeopleNotificationIdentifier + private val peopleNotificationIdentifier: PeopleNotificationIdentifier, + @PeopleHeader peopleHeaderController: NodeController ) : Coordinator { private val notificationPromoter = object : NotifPromoter(TAG) { @@ -43,9 +46,9 @@ class ConversationCoordinator @Inject constructor( } val sectioner = object : NotifSectioner("People") { - override fun isInSection(entry: ListEntry): Boolean { - return isConversation(entry.representativeEntry!!) - } + override fun isInSection(entry: ListEntry): Boolean = + isConversation(entry.representativeEntry!!) + override fun getHeaderNodeController() = peopleHeaderController } override fun attach(pipeline: NotifPipeline) { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/HeadsUpCoordinator.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/HeadsUpCoordinator.java index 24e912ed0cc3..be1383fb6b8a 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/HeadsUpCoordinator.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/HeadsUpCoordinator.java @@ -30,6 +30,8 @@ import com.android.systemui.statusbar.notification.collection.listbuilder.plugga import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifSectioner; import com.android.systemui.statusbar.notification.collection.notifcollection.NotifCollectionListener; import com.android.systemui.statusbar.notification.collection.notifcollection.NotifLifetimeExtender; +import com.android.systemui.statusbar.notification.collection.render.NodeController; +import com.android.systemui.statusbar.notification.dagger.IncomingHeader; import com.android.systemui.statusbar.notification.interruption.HeadsUpViewBinder; import com.android.systemui.statusbar.notification.interruption.NotificationInterruptStateProvider; import com.android.systemui.statusbar.policy.HeadsUpManager; @@ -61,6 +63,7 @@ public class HeadsUpCoordinator implements Coordinator { private final HeadsUpViewBinder mHeadsUpViewBinder; private final NotificationInterruptStateProvider mNotificationInterruptStateProvider; private final NotificationRemoteInputManager mRemoteInputManager; + private final NodeController mIncomingHeaderController; // tracks the current HeadUpNotification reported by HeadsUpManager private @Nullable NotificationEntry mCurrentHun; @@ -73,11 +76,13 @@ public class HeadsUpCoordinator implements Coordinator { HeadsUpManager headsUpManager, HeadsUpViewBinder headsUpViewBinder, NotificationInterruptStateProvider notificationInterruptStateProvider, - NotificationRemoteInputManager remoteInputManager) { + NotificationRemoteInputManager remoteInputManager, + @IncomingHeader NodeController incomingHeaderController) { mHeadsUpManager = headsUpManager; mHeadsUpViewBinder = headsUpViewBinder; mNotificationInterruptStateProvider = notificationInterruptStateProvider; mRemoteInputManager = remoteInputManager; + mIncomingHeaderController = incomingHeaderController; } @Override @@ -196,6 +201,12 @@ public class HeadsUpCoordinator implements Coordinator { public boolean isInSection(ListEntry entry) { return isCurrentlyShowingHun(entry); } + + @Nullable + @Override + public NodeController getHeaderNodeController() { + return mIncomingHeaderController; + } }; private final OnHeadsUpChangedListener mOnHeadsUpChangedListener = diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/RankingCoordinator.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/RankingCoordinator.java index 0f08e0ff491c..133ddfebe84f 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/RankingCoordinator.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/RankingCoordinator.java @@ -16,6 +16,8 @@ package com.android.systemui.statusbar.notification.collection.coordinator; +import android.annotation.Nullable; + import com.android.systemui.dagger.SysUISingleton; import com.android.systemui.plugins.statusbar.StatusBarStateController; import com.android.systemui.statusbar.notification.collection.ListEntry; @@ -24,6 +26,9 @@ import com.android.systemui.statusbar.notification.collection.NotificationEntry; import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifFilter; import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifSectioner; import com.android.systemui.statusbar.notification.collection.provider.HighPriorityProvider; +import com.android.systemui.statusbar.notification.collection.render.NodeController; +import com.android.systemui.statusbar.notification.dagger.AlertingHeader; +import com.android.systemui.statusbar.notification.dagger.SilentHeader; import javax.inject.Inject; @@ -40,13 +45,19 @@ public class RankingCoordinator implements Coordinator { private final StatusBarStateController mStatusBarStateController; private final HighPriorityProvider mHighPriorityProvider; + private final NodeController mSilentHeaderController; + private final NodeController mAlertingHeaderController; @Inject public RankingCoordinator( StatusBarStateController statusBarStateController, - HighPriorityProvider highPriorityProvider) { + HighPriorityProvider highPriorityProvider, + @AlertingHeader NodeController alertingHeaderController, + @SilentHeader NodeController silentHeaderController) { mStatusBarStateController = statusBarStateController; mHighPriorityProvider = highPriorityProvider; + mAlertingHeaderController = alertingHeaderController; + mSilentHeaderController = silentHeaderController; } @Override @@ -70,6 +81,12 @@ public class RankingCoordinator implements Coordinator { public boolean isInSection(ListEntry entry) { return mHighPriorityProvider.isHighPriority(entry); } + + @Nullable + @Override + public NodeController getHeaderNodeController() { + return mAlertingHeaderController; + } }; private final NotifSectioner mSilentNotifSectioner = new NotifSectioner("Silent") { @@ -77,6 +94,12 @@ public class RankingCoordinator implements Coordinator { public boolean isInSection(ListEntry entry) { return !mHighPriorityProvider.isHighPriority(entry); } + + @Nullable + @Override + public NodeController getHeaderNodeController() { + return mSilentHeaderController; + } }; /** diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/legacy/OnUserInteractionCallbackImplLegacy.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/legacy/OnUserInteractionCallbackImplLegacy.java index cce8cdc64d30..610cd33383e9 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/legacy/OnUserInteractionCallbackImplLegacy.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/legacy/OnUserInteractionCallbackImplLegacy.java @@ -26,6 +26,7 @@ import com.android.systemui.plugins.statusbar.StatusBarStateController; import com.android.systemui.statusbar.notification.NotificationEntryManager; import com.android.systemui.statusbar.notification.collection.NotificationEntry; import com.android.systemui.statusbar.notification.collection.notifcollection.DismissedByUserStats; +import com.android.systemui.statusbar.notification.collection.render.GroupMembershipManager; import com.android.systemui.statusbar.notification.logging.NotificationLogger; import com.android.systemui.statusbar.notification.row.OnUserInteractionCallback; import com.android.systemui.statusbar.policy.HeadsUpManager; @@ -38,17 +39,20 @@ public class OnUserInteractionCallbackImplLegacy implements OnUserInteractionCal private final HeadsUpManager mHeadsUpManager; private final StatusBarStateController mStatusBarStateController; private final VisualStabilityManager mVisualStabilityManager; + private final GroupMembershipManager mGroupMembershipManager; public OnUserInteractionCallbackImplLegacy( NotificationEntryManager notificationEntryManager, HeadsUpManager headsUpManager, StatusBarStateController statusBarStateController, - VisualStabilityManager visualStabilityManager + VisualStabilityManager visualStabilityManager, + GroupMembershipManager groupMembershipManager ) { mNotificationEntryManager = notificationEntryManager; mHeadsUpManager = headsUpManager; mStatusBarStateController = statusBarStateController; mVisualStabilityManager = visualStabilityManager; + mGroupMembershipManager = groupMembershipManager; } /** @@ -69,6 +73,13 @@ public class OnUserInteractionCallbackImplLegacy implements OnUserInteractionCal dismissalSurface = NotificationStats.DISMISSAL_AOD; } + if (mGroupMembershipManager.isOnlyChildInGroup(entry)) { + NotificationEntry groupSummary = mGroupMembershipManager.getLogicalGroupSummary(entry); + if (groupSummary.isClearable()) { + onDismiss(groupSummary, cancellationReason); + } + } + mNotificationEntryManager.performRemoveNotification( entry.getSbn(), new DismissedByUserStats( @@ -82,6 +93,7 @@ public class OnUserInteractionCallbackImplLegacy implements OnUserInteractionCal NotificationLogger.getNotificationLocation(entry))), cancellationReason ); + } @Override diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/NotifSection.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/NotifSection.kt index c09122ea3c26..c9fc9929f0d3 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/NotifSection.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/NotifSection.kt @@ -17,6 +17,7 @@ package com.android.systemui.statusbar.notification.collection.listbuilder import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifSectioner +import com.android.systemui.statusbar.notification.collection.render.NodeController data class NotifSection( val sectioner: NotifSectioner, @@ -24,4 +25,7 @@ data class NotifSection( ) { val label: String get() = "Section($index, \"${sectioner.name}\")" + + val headerController: NodeController? + get() = sectioner.headerNodeController } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/pluggable/NotifSectioner.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/pluggable/NotifSectioner.java index b57f504189f1..c8982d35c4a0 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/pluggable/NotifSectioner.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/pluggable/NotifSectioner.java @@ -16,8 +16,12 @@ package com.android.systemui.statusbar.notification.collection.listbuilder.pluggable; +import android.annotation.Nullable; + import com.android.systemui.statusbar.notification.collection.ListEntry; import com.android.systemui.statusbar.notification.collection.ShadeListBuilder; +import com.android.systemui.statusbar.notification.collection.render.NodeController; +import com.android.systemui.statusbar.notification.collection.render.NodeSpec; /** * Pluggable for participating in notif sectioning. See {@link ShadeListBuilder#setSections}. @@ -34,4 +38,12 @@ public abstract class NotifSectioner extends Pluggable<NotifSectioner> { * notification. The first section to return true determines the section of the notification. */ public abstract boolean isInSection(ListEntry entry); + + /** + * Returns an optional {@link NodeSpec} for the section header. If {@code null}, no header will + * be used for the section. + */ + public @Nullable NodeController getHeaderNodeController() { + return null; + } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/NodeController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/NodeController.kt index 67f7b1c09df3..727ce20cd72c 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/NodeController.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/NodeController.kt @@ -39,9 +39,7 @@ interface NodeController { throw RuntimeException("Not supported") } - fun getChildCount(): Int { - throw RuntimeException("Not supported") - } + fun getChildCount(): Int = 0 fun addChildAt(child: NodeController, index: Int) { throw RuntimeException("Not supported") diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/SectionHeaderController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/SectionHeaderController.kt new file mode 100644 index 000000000000..498b8e884b17 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/SectionHeaderController.kt @@ -0,0 +1,81 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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.collection.render + +import android.annotation.StringRes +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import com.android.systemui.R +import com.android.systemui.statusbar.notification.dagger.HeaderClick +import com.android.systemui.statusbar.notification.dagger.HeaderText +import com.android.systemui.statusbar.notification.dagger.NodeLabel +import com.android.systemui.statusbar.notification.dagger.SectionHeaderScope +import com.android.systemui.statusbar.notification.stack.SectionHeaderView +import javax.inject.Inject + +interface SectionHeaderController { + fun reinflateView(parent: ViewGroup) + val headerView: SectionHeaderView? + fun setOnClearAllClickListener(listener: View.OnClickListener) +} + +@SectionHeaderScope +internal class SectionHeaderNodeControllerImpl @Inject constructor( + @NodeLabel override val nodeLabel: String, + private val layoutInflater: LayoutInflater, + @HeaderText @StringRes private val headerTextResId: Int, + @HeaderClick private val onHeaderClickListener: View.OnClickListener +) : NodeController, SectionHeaderController { + + private var _view: SectionHeaderView? = null + private var clearAllClickListener: View.OnClickListener? = null + + override fun reinflateView(parent: ViewGroup) { + var oldPos = -1 + _view?.let { _view -> + _view.transientContainer?.removeView(_view) + if (_view.parent === parent) { + oldPos = parent.indexOfChild(_view) + parent.removeView(_view) + } + } + val inflated = layoutInflater.inflate( + R.layout.status_bar_notification_section_header, + parent, + false /* attachToRoot */) + as SectionHeaderView + inflated.setHeaderText(headerTextResId) + inflated.setOnHeaderClickListener(onHeaderClickListener) + clearAllClickListener?.let { inflated.setOnClearAllClickListener(it) } + if (oldPos != -1) { + parent.addView(inflated, oldPos) + } + _view = inflated + } + + override val headerView: SectionHeaderView? + get() = _view + + override fun setOnClearAllClickListener(listener: View.OnClickListener) { + clearAllClickListener = listener + _view?.setOnClearAllClickListener(listener) + } + + override val view: View + get() = _view!! +}
\ No newline at end of file diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/ShadeViewDiffer.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/ShadeViewDiffer.kt index 019520f18982..22ca4961320c 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/ShadeViewDiffer.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/ShadeViewDiffer.kt @@ -65,9 +65,7 @@ class ShadeViewDiffer( * * For debugging purposes. */ - fun getViewLabel(view: View): String { - return views[view]?.label ?: view.toString() - } + fun getViewLabel(view: View): String = views[view]?.label ?: view.toString() private fun detachChildren( parentNode: ShadeNode, diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/ShadeViewManager.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/ShadeViewManager.kt index 5243854ea412..44a5c958c408 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/ShadeViewManager.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/ShadeViewManager.kt @@ -42,45 +42,35 @@ class ShadeViewManager constructor( private val rootController = RootNodeController(listContainer, View(context)) private val viewDiffer = ShadeViewDiffer(rootController, logger) - fun attach(listBuilder: ShadeListBuilder) { - listBuilder.setOnRenderListListener(::onNewNotifTree) - } + fun attach(listBuilder: ShadeListBuilder) = + listBuilder.setOnRenderListListener(::onNewNotifTree) - private fun onNewNotifTree(tree: List<ListEntry>) { - viewDiffer.applySpec(buildTree(tree)) - } + private fun onNewNotifTree(tree: List<ListEntry>) = viewDiffer.applySpec(buildTree(tree)) private fun buildTree(notifList: List<ListEntry>): NodeSpec { - val root = NodeSpecImpl(null, rootController) - - for (entry in notifList) { - // TODO: Add section header logic here - root.children.add(buildNotifNode(entry, root)) + val root = NodeSpecImpl(null, rootController).apply { + // Insert first section header, if present + notifList.firstOrNull()?.section?.headerController?.let { + children.add(NodeSpecImpl(this, it)) + } + notifList.asSequence().zipWithNext().forEach { (prev, entry) -> + // Insert new header if the section has changed between two entries + entry.section.takeIf { it != prev.section }?.headerController?.let { + children.add(NodeSpecImpl(this, it)) + } + children.add(buildNotifNode(entry, this)) + } } - notificationIconAreaController.updateNotificationIcons(notifList) return root } private fun buildNotifNode(entry: ListEntry, parent: NodeSpec): NodeSpec { return when (entry) { - is NotificationEntry -> { - NodeSpecImpl(parent, viewBarn.requireView(entry)) - } - is GroupEntry -> { - val groupNode = NodeSpecImpl( - parent, - viewBarn.requireView(checkNotNull(entry.summary))) - - for (childEntry in entry.children) { - groupNode.children.add(buildNotifNode(childEntry, groupNode)) - } - - groupNode - } - else -> { - throw RuntimeException("Unexpected entry: $entry") - } + is NotificationEntry -> NodeSpecImpl(parent, viewBarn.requireView(entry)) + is GroupEntry -> NodeSpecImpl(parent, viewBarn.requireView(checkNotNull(entry.summary))) + .apply { entry.children.forEach { children.add(buildNotifNode(it, this)) } } + else -> throw RuntimeException("Unexpected entry: $entry") } } } @@ -91,12 +81,11 @@ class ShadeViewManagerFactory @Inject constructor( private val viewBarn: NotifViewBarn, private val notificationIconAreaController: NotificationIconAreaController ) { - fun create(listContainer: NotificationListContainer): ShadeViewManager { - return ShadeViewManager( - context, - listContainer, - logger, - viewBarn, - notificationIconAreaController) - } + fun create(listContainer: NotificationListContainer) = + ShadeViewManager( + context, + listContainer, + logger, + viewBarn, + notificationIconAreaController) } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/dagger/NotificationSectionHeadersModule.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/dagger/NotificationSectionHeadersModule.kt new file mode 100644 index 000000000000..179d49cb55a1 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/dagger/NotificationSectionHeadersModule.kt @@ -0,0 +1,195 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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.dagger + +import android.annotation.StringRes +import android.content.Intent +import android.provider.Settings +import android.view.View +import com.android.systemui.R +import com.android.systemui.dagger.SysUISingleton +import com.android.systemui.plugins.ActivityStarter +import com.android.systemui.statusbar.notification.collection.render.NodeController +import com.android.systemui.statusbar.notification.collection.render.SectionHeaderController +import com.android.systemui.statusbar.notification.collection.render.SectionHeaderNodeControllerImpl +import dagger.Binds +import dagger.BindsInstance +import dagger.Module +import dagger.Provides +import dagger.Subcomponent +import javax.inject.Provider +import javax.inject.Qualifier +import javax.inject.Scope + +@Module(subcomponents = [SectionHeaderControllerSubcomponent::class]) +object NotificationSectionHeadersModule { + + @Provides + @HeaderClick + @JvmStatic fun providesOnHeaderClickListener( + activityStarter: ActivityStarter + ) = View.OnClickListener { + activityStarter.startActivity( + Intent(Settings.ACTION_NOTIFICATION_SETTINGS), + true /* onlyProvisioned */, + true /* dismissShade */, + Intent.FLAG_ACTIVITY_SINGLE_TOP) + } + + @Provides + @IncomingHeader + @SysUISingleton + @JvmStatic fun providesIncomingHeaderSubcomponent( + builder: Provider<SectionHeaderControllerSubcomponent.Builder> + ) = builder.get() + .nodeLabel("incoming header") + .headerText(R.string.notification_section_header_incoming) + .build() + + @Provides + @AlertingHeader + @SysUISingleton + @JvmStatic fun providesAlertingHeaderSubcomponent( + builder: Provider<SectionHeaderControllerSubcomponent.Builder> + ) = builder.get() + .nodeLabel("alerting header") + .headerText(R.string.notification_section_header_alerting) + .build() + + @Provides + @PeopleHeader + @SysUISingleton + @JvmStatic fun providesPeopleHeaderSubcomponent( + builder: Provider<SectionHeaderControllerSubcomponent.Builder> + ) = builder.get() + .nodeLabel("people header") + .headerText(R.string.notification_section_header_conversations) + .build() + + @Provides + @SilentHeader + @SysUISingleton + @JvmStatic fun providesSilentHeaderSubcomponent( + builder: Provider<SectionHeaderControllerSubcomponent.Builder> + ) = builder.get() + .nodeLabel("silent header") + .headerText(R.string.notification_section_header_gentle) + .build() + + @Provides + @SilentHeader + @JvmStatic fun providesSilentHeaderNodeController( + @SilentHeader subcomponent: SectionHeaderControllerSubcomponent + ) = subcomponent.nodeController + + @Provides + @SilentHeader + @JvmStatic fun providesSilentHeaderController( + @SilentHeader subcomponent: SectionHeaderControllerSubcomponent + ) = subcomponent.headerController + + @Provides + @AlertingHeader + @JvmStatic fun providesAlertingHeaderNodeController( + @AlertingHeader subcomponent: SectionHeaderControllerSubcomponent + ) = subcomponent.nodeController + + @Provides + @AlertingHeader + @JvmStatic fun providesAlertingHeaderController( + @AlertingHeader subcomponent: SectionHeaderControllerSubcomponent + ) = subcomponent.headerController + + @Provides + @PeopleHeader + @JvmStatic fun providesPeopleHeaderNodeController( + @PeopleHeader subcomponent: SectionHeaderControllerSubcomponent + ) = subcomponent.nodeController + + @Provides + @PeopleHeader + @JvmStatic fun providesPeopleHeaderController( + @PeopleHeader subcomponent: SectionHeaderControllerSubcomponent + ) = subcomponent.headerController + + @Provides + @IncomingHeader + @JvmStatic fun providesIncomingHeaderNodeController( + @IncomingHeader subcomponent: SectionHeaderControllerSubcomponent + ) = subcomponent.nodeController + + @Provides + @IncomingHeader + @JvmStatic fun providesIncomingHeaderController( + @IncomingHeader subcomponent: SectionHeaderControllerSubcomponent + ) = subcomponent.headerController +} + +@Subcomponent(modules = [ SectionHeaderBindingModule::class ]) +@SectionHeaderScope +interface SectionHeaderControllerSubcomponent { + + val nodeController: NodeController + val headerController: SectionHeaderController + + @Subcomponent.Builder + interface Builder { + fun build(): SectionHeaderControllerSubcomponent + @BindsInstance fun nodeLabel(@NodeLabel nodeLabel: String): Builder + @BindsInstance fun headerText(@HeaderText @StringRes headerText: Int): Builder + } +} + +@Module +private abstract class SectionHeaderBindingModule { + @Binds abstract fun bindsNodeController(impl: SectionHeaderNodeControllerImpl): NodeController + @Binds abstract fun bindsSectionHeaderController( + impl: SectionHeaderNodeControllerImpl + ): SectionHeaderController +} + +@Qualifier +@Retention(AnnotationRetention.BINARY) +annotation class HeaderText + +@Qualifier +@Retention(AnnotationRetention.BINARY) +annotation class IncomingHeader + +@Qualifier +@Retention(AnnotationRetention.BINARY) +annotation class AlertingHeader + +@Qualifier +@Retention(AnnotationRetention.BINARY) +annotation class SilentHeader + +@Qualifier +@Retention(AnnotationRetention.BINARY) +annotation class PeopleHeader + +@Qualifier +@Retention(AnnotationRetention.BINARY) +annotation class NodeLabel + +@Qualifier +@Retention(AnnotationRetention.BINARY) +annotation class HeaderClick + +@Scope +@Retention(AnnotationRetention.BINARY) +annotation class SectionHeaderScope
\ No newline at end of file diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/dagger/NotificationsModule.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/dagger/NotificationsModule.java index e2aae64ce220..23270630c7da 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/dagger/NotificationsModule.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/dagger/NotificationsModule.java @@ -88,7 +88,7 @@ import dagger.Provides; /** * Dagger Module for classes found within the com.android.systemui.statusbar.notification package. */ -@Module +@Module(includes = { NotificationSectionHeadersModule.class }) public interface NotificationsModule { /** Provides an instance of {@link NotificationEntryManager} */ @SysUISingleton @@ -205,9 +205,11 @@ public interface NotificationsModule { Context context, NotificationGutsManager notificationGutsManager, NotificationEntryManager notificationEntryManager, - MetricsLogger metricsLogger) { + MetricsLogger metricsLogger, + GroupMembershipManager groupMembershipManager) { return new NotificationBlockingHelperManager( - context, notificationGutsManager, notificationEntryManager, metricsLogger); + context, notificationGutsManager, notificationEntryManager, metricsLogger, + groupMembershipManager); } /** Provides an instance of {@link GroupMembershipManager} */ @@ -273,7 +275,8 @@ public interface NotificationsModule { Lazy<NotifCollection> notifCollection, Lazy<VisualStabilityCoordinator> visualStabilityCoordinator, NotificationEntryManager entryManager, - VisualStabilityManager visualStabilityManager) { + VisualStabilityManager visualStabilityManager, + Lazy<GroupMembershipManager> groupMembershipManagerLazy) { return featureFlags.isNewNotifPipelineRenderingEnabled() ? new OnUserInteractionCallbackImpl( pipeline.get(), @@ -285,7 +288,8 @@ public interface NotificationsModule { entryManager, headsUpManager, statusBarStateController, - visualStabilityManager); + visualStabilityManager, + groupMembershipManagerLazy.get()); } /** */ 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 89f720535402..adda049951ac 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 @@ -817,13 +817,6 @@ public class ExpandableNotificationRow extends ActivatableNotificationView return mNotificationParent != null; } - /** - * @return whether this notification is the only child in the group summary - */ - public boolean isOnlyChildInGroup() { - return mGroupMembershipManager.isOnlyChildInGroup(mEntry); - } - public ExpandableNotificationRow getNotificationParent() { return mNotificationParent; } @@ -1425,14 +1418,6 @@ public class ExpandableNotificationRow extends ActivatableNotificationView } public void performDismiss(boolean fromAccessibility) { - if (isOnlyChildInGroup()) { - NotificationEntry groupSummary = mGroupMembershipManager.getLogicalGroupSummary(mEntry); - if (groupSummary.isClearable()) { - // If this is the only child in the group, dismiss the group, but don't try to show - // the blocking helper affordance! - groupSummary.getRow().performDismiss(fromAccessibility); - } - } dismiss(fromAccessibility); if (mEntry.isClearable()) { if (mOnUserInteractionCallback != null) { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationBlockingHelperManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationBlockingHelperManager.java index 921232568755..ab78d197da0b 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationBlockingHelperManager.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationBlockingHelperManager.java @@ -28,6 +28,8 @@ import com.android.internal.logging.MetricsLogger; import com.android.internal.logging.nano.MetricsProto.MetricsEvent; import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin; import com.android.systemui.statusbar.notification.NotificationEntryManager; +import com.android.systemui.statusbar.notification.collection.NotificationEntry; +import com.android.systemui.statusbar.notification.collection.render.GroupMembershipManager; import com.android.systemui.statusbar.notification.dagger.NotificationsModule; import com.android.systemui.statusbar.notification.logging.NotificationCounters; @@ -48,6 +50,7 @@ public class NotificationBlockingHelperManager { private final NotificationGutsManager mNotificationGutsManager; private final NotificationEntryManager mNotificationEntryManager; private final MetricsLogger mMetricsLogger; + private final GroupMembershipManager mGroupMembershipManager; /** Row that the blocking helper will be shown in (via {@link NotificationGuts}. */ private ExpandableNotificationRow mBlockingHelperRow; private Set<String> mNonBlockablePkgs; @@ -65,7 +68,8 @@ public class NotificationBlockingHelperManager { Context context, NotificationGutsManager notificationGutsManager, NotificationEntryManager notificationEntryManager, - MetricsLogger metricsLogger) { + MetricsLogger metricsLogger, + GroupMembershipManager groupMembershipManager) { mContext = context; mNotificationGutsManager = notificationGutsManager; mNotificationEntryManager = notificationEntryManager; @@ -73,6 +77,7 @@ public class NotificationBlockingHelperManager { mNonBlockablePkgs = new HashSet<>(); Collections.addAll(mNonBlockablePkgs, mContext.getResources().getStringArray( com.android.internal.R.array.config_nonBlockableNotificationPackages)); + mGroupMembershipManager = groupMembershipManager; } /** @@ -92,11 +97,12 @@ public class NotificationBlockingHelperManager { // - The row is blockable (i.e. not non-blockable) // - The dismissed row is a valid group (>1 or 0 children from the same channel) // or the only child in the group - if ((row.getEntry().getUserSentiment() == USER_SENTIMENT_NEGATIVE || DEBUG) + final NotificationEntry entry = row.getEntry(); + if ((entry.getUserSentiment() == USER_SENTIMENT_NEGATIVE || DEBUG) && mIsShadeExpanded && !row.getIsNonblockable() - && ((!row.isChildInGroup() || row.isOnlyChildInGroup()) - && row.getNumUniqueChannels() <= 1)) { + && ((!row.isChildInGroup() || mGroupMembershipManager.isOnlyChildInGroup(entry)) + && row.getNumUniqueChannels() <= 1)) { // Dismiss any current blocking helper before continuing forward (only one can be shown // at a given time). dismissCurrentBlockingHelper(); 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 0302b2b450e2..8050fea562a7 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 @@ -30,7 +30,6 @@ import com.android.systemui.statusbar.notification.row.ActivatableNotificationVi import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow; import com.android.systemui.statusbar.notification.row.ExpandableView; import com.android.systemui.statusbar.notification.stack.StackScrollAlgorithm.SectionProvider; -import com.android.systemui.statusbar.policy.HeadsUpManager; import java.util.ArrayList; @@ -50,7 +49,6 @@ public class AmbientState { private ActivatableNotificationView mActivatedChild; private float mOverScrollTopAmount; private float mOverScrollBottomAmount; - private int mSpeedBumpIndex = -1; private boolean mDozing; private boolean mHideSensitive; private float mStackTranslation; @@ -245,14 +243,6 @@ public class AmbientState { return top ? mOverScrollTopAmount : mOverScrollBottomAmount; } - public int getSpeedBumpIndex() { - return mSpeedBumpIndex; - } - - public void setSpeedBumpIndex(int shelfIndex) { - mSpeedBumpIndex = shelfIndex; - } - public SectionProvider getSectionProvider() { return mSectionProvider; } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationSectionsManager.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationSectionsManager.kt index ff7793d506fd..4f7e14ba4a4c 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationSectionsManager.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationSectionsManager.kt @@ -18,23 +18,21 @@ package com.android.systemui.statusbar.notification.stack import android.annotation.ColorInt import android.annotation.IntDef import android.annotation.LayoutRes -import android.content.Intent -import android.provider.Settings import android.util.Log import android.view.LayoutInflater import android.view.View import com.android.internal.annotations.VisibleForTesting import com.android.systemui.R import com.android.systemui.media.KeyguardMediaController -import com.android.systemui.plugins.ActivityStarter import com.android.systemui.plugins.statusbar.StatusBarStateController import com.android.systemui.statusbar.StatusBarState import com.android.systemui.statusbar.notification.NotificationSectionsFeatureManager -import com.android.systemui.statusbar.notification.people.DataListener -import com.android.systemui.statusbar.notification.people.PeopleHubViewAdapter -import com.android.systemui.statusbar.notification.people.PeopleHubViewBoundary -import com.android.systemui.statusbar.notification.people.PersonViewModel -import com.android.systemui.statusbar.notification.people.Subscription +import com.android.systemui.statusbar.notification.collection.render.SectionHeaderController +import com.android.systemui.statusbar.notification.collection.render.ShadeViewManager +import com.android.systemui.statusbar.notification.dagger.AlertingHeader +import com.android.systemui.statusbar.notification.dagger.IncomingHeader +import com.android.systemui.statusbar.notification.dagger.PeopleHeader +import com.android.systemui.statusbar.notification.dagger.SilentHeader import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow import com.android.systemui.statusbar.notification.row.ExpandableView import com.android.systemui.statusbar.notification.row.StackScrollerDecorView @@ -46,19 +44,25 @@ import com.android.systemui.util.takeUntil import javax.inject.Inject /** - * Manages the boundaries of the two notification sections (high priority and low priority). Also - * shows/hides the headers for those sections where appropriate. + * Manages the boundaries of the notification sections (incoming, conversations, high priority, and + * low priority). + * + * In the legacy notification pipeline, this is responsible for correctly positioning all section + * headers after the [NotificationStackScrollLayout] has had notifications added/removed/changed. In + * the new pipeline, this is handled as part of the [ShadeViewManager]. * * TODO: Move remaining sections logic from NSSL into this class. */ class NotificationSectionsManager @Inject internal constructor( - private val activityStarter: ActivityStarter, private val statusBarStateController: StatusBarStateController, private val configurationController: ConfigurationController, - private val peopleHubViewAdapter: PeopleHubViewAdapter, private val keyguardMediaController: KeyguardMediaController, private val sectionsFeatureManager: NotificationSectionsFeatureManager, - private val logger: NotificationSectionsLogger + private val logger: NotificationSectionsLogger, + @IncomingHeader private val incomingHeaderController: SectionHeaderController, + @PeopleHeader private val peopleHeaderController: SectionHeaderController, + @AlertingHeader private val alertingHeaderController: SectionHeaderController, + @SilentHeader private val silentHeaderController: SectionHeaderController ) : SectionProvider { private val configurationListener = object : ConfigurationController.ConfigurationListener { @@ -67,46 +71,25 @@ class NotificationSectionsManager @Inject internal constructor( } } - private val peopleHubViewBoundary: PeopleHubViewBoundary = object : PeopleHubViewBoundary { - override fun setVisible(isVisible: Boolean) { - if (peopleHubVisible != isVisible) { - peopleHubVisible = isVisible - if (initialized) { - updateSectionBoundaries("PeopleHub visibility changed") - } - } - } - - override val associatedViewForClickAnimation: View - get() = peopleHeaderView!! - - override val personViewAdapters: Sequence<DataListener<PersonViewModel?>> - get() = peopleHeaderView!!.personViewAdapters - } - private lateinit var parent: NotificationStackScrollLayout private var initialized = false private var onClearSilentNotifsClickListener: View.OnClickListener? = null - @get:VisibleForTesting - var silentHeaderView: SectionHeaderView? = null - private set - - @get:VisibleForTesting - var alertingHeaderView: SectionHeaderView? = null - private set + @VisibleForTesting + val silentHeaderView: SectionHeaderView? + get() = silentHeaderController.headerView - @get:VisibleForTesting - var incomingHeaderView: SectionHeaderView? = null - private set + @VisibleForTesting + val alertingHeaderView: SectionHeaderView? + get() = alertingHeaderController.headerView - @get:VisibleForTesting - var peopleHeaderView: PeopleHubView? = null - private set + @VisibleForTesting + val incomingHeaderView: SectionHeaderView? + get() = incomingHeaderController.headerView - @set:VisibleForTesting - var peopleHubVisible = false - private var peopleHubSubscription: Subscription? = null + @VisibleForTesting + val peopleHeaderView: SectionHeaderView? + get() = peopleHeaderController.headerView @get:VisibleForTesting var mediaControlsView: MediaHeaderView? = null @@ -150,34 +133,10 @@ class NotificationSectionsManager @Inject internal constructor( * Reinflates the entire notification header, including all decoration views. */ fun reinflateViews(layoutInflater: LayoutInflater) { - silentHeaderView = reinflateView( - silentHeaderView, layoutInflater, R.layout.status_bar_notification_section_header - ).apply { - setHeaderText(R.string.notification_section_header_gentle) - setOnHeaderClickListener { onGentleHeaderClick() } - setOnClearAllClickListener { onClearGentleNotifsClick(it) } - } - alertingHeaderView = reinflateView( - alertingHeaderView, layoutInflater, R.layout.status_bar_notification_section_header - ).apply { - setHeaderText(R.string.notification_section_header_alerting) - setOnHeaderClickListener { onGentleHeaderClick() } - } - peopleHubSubscription?.unsubscribe() - peopleHubSubscription = null - peopleHeaderView = reinflateView(peopleHeaderView, layoutInflater, R.layout.people_strip) - .apply { - setOnHeaderClickListener(View.OnClickListener { onGentleHeaderClick() }) - } - if (ENABLE_SNOOZED_CONVERSATION_HUB) { - peopleHubSubscription = peopleHubViewAdapter.bindView(peopleHubViewBoundary) - } - incomingHeaderView = reinflateView( - incomingHeaderView, layoutInflater, R.layout.status_bar_notification_section_header - ).apply { - setHeaderText(R.string.notification_section_header_incoming) - setOnHeaderClickListener { onGentleHeaderClick() } - } + silentHeaderController.reinflateView(parent) + alertingHeaderController.reinflateView(parent) + peopleHeaderController.reinflateView(parent) + incomingHeaderController.reinflateView(parent) mediaControlsView = reinflateView(mediaControlsView, layoutInflater, R.layout.keyguard_media_header) .also(keyguardMediaController::attach) @@ -296,7 +255,6 @@ class NotificationSectionsManager @Inject internal constructor( // target, but won't be once they are moved / removed after the pass has completed. val showHeaders = statusBarStateController.state != StatusBarState.KEYGUARD - val usingPeopleFiltering = sectionsFeatureManager.isFilteringEnabled() val usingMediaControls = sectionsFeatureManager.isMediaControlsEnabled() val mediaState = mediaControlsView?.let(::expandableViewHeaderState) @@ -319,7 +277,6 @@ class NotificationSectionsManager @Inject internal constructor( ).filterNotNull() var peopleNotifsPresent = false - var lastNotifIndex = 0 var nextBucket: Int? = null var inIncomingSection = false @@ -373,30 +330,9 @@ class NotificationSectionsManager @Inject internal constructor( // Check if there are any people notifications peopleNotifsPresent = peopleNotifsPresent || row.entry.bucket == BUCKET_PEOPLE - - if (nextBucket == null) { - lastNotifIndex = i - } nextBucket = row.entry.bucket } - if (showHeaders && usingPeopleFiltering && peopleHubVisible) { - peopleState?.targetPosition = peopleState?.targetPosition - // Insert the people header even if there are no people visible, in order to - // show the hub. Put it directly above the next header. - ?: alertingState?.targetPosition - ?: gentleState?.targetPosition - // Put it at the end of the list. - ?: lastNotifIndex - - // Offset the target to account for the current position of the people header. - peopleState?.targetPosition = peopleState?.currentPosition?.let { current -> - peopleState.targetPosition?.let { target -> - if (current < target) target - 1 else target - } - } - } - mediaState?.targetPosition = if (usingMediaControls) 0 else null logger.logStr("New header target positions:") @@ -420,14 +356,6 @@ class NotificationSectionsManager @Inject internal constructor( .hasActiveClearableNotifications(NotificationStackScrollLayout.ROWS_GENTLE) setAreThereDismissableGentleNotifs(hasActiveClearableNotifications) } - peopleHeaderView?.run { - canSwipe = showHeaders && peopleHubVisible && !peopleNotifsPresent - peopleState?.targetPosition?.let { targetPosition -> - if (targetPosition != peopleState.currentPosition) { - resetTranslation() - } - } - } } private sealed class SectionBounds { @@ -513,31 +441,13 @@ class NotificationSectionsManager @Inject internal constructor( } } - private fun onGentleHeaderClick() { - val intent = Intent(Settings.ACTION_NOTIFICATION_SETTINGS) - activityStarter.startActivity( - intent, - true, - true, - Intent.FLAG_ACTIVITY_SINGLE_TOP) - } - - private fun onClearGentleNotifsClick(v: View) { - onClearSilentNotifsClickListener?.onClick(v) - } - /** Listener for when the "clear all" button is clicked on the gentle notification header. */ fun setOnClearSilentNotifsClickListener(listener: View.OnClickListener) { onClearSilentNotifsClickListener = listener } - fun hidePeopleRow() { - peopleHubVisible = false - updateSectionBoundaries("PeopleHub dismissed") - } - fun setHeaderForegroundColor(@ColorInt color: Int) { - peopleHeaderView?.setTextColor(color) + peopleHeaderView?.setForegroundColor(color) silentHeaderView?.setForegroundColor(color) alertingHeaderView?.setForegroundColor(color) } @@ -545,7 +455,6 @@ class NotificationSectionsManager @Inject internal constructor( companion object { private const val TAG = "NotifSectionsManager" private const val DEBUG = false - private const val ENABLE_SNOOZED_CONVERSATION_HUB = false } } 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 c24d3fcadbf9..b33aa5739273 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 @@ -248,6 +248,9 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable private boolean mChangePositionInProgress; private boolean mChildTransferInProgress; + private int mSpeedBumpIndex = -1; + private boolean mSpeedBumpIndexDirty = true; + /** * The raw amount of the overScroll on the top, which is not rubber-banded. */ @@ -444,7 +447,6 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable private int mMaxDisplayedNotifications = -1; private int mStatusBarHeight; private int mMinInteractionHeight; - private boolean mNoAmbient; private final Rect mClipRect = new Rect(); private boolean mIsClipped; private Rect mRequestedClipBounds; @@ -1010,7 +1012,33 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable } public int getSpeedBumpIndex() { - return mAmbientState.getSpeedBumpIndex(); + if (mSpeedBumpIndexDirty) { + mSpeedBumpIndexDirty = false; + int speedBumpIndex = 0; + int currentIndex = 0; + final int n = getChildCount(); + for (int i = 0; i < n; i++) { + View view = getChildAt(i); + if (view.getVisibility() == View.GONE + || !(view instanceof ExpandableNotificationRow)) { + continue; + } + ExpandableNotificationRow row = (ExpandableNotificationRow) view; + currentIndex++; + boolean beforeSpeedBump; + if (mHighPriorityBeforeSpeedBump) { + beforeSpeedBump = row.getEntry().getBucket() < BUCKET_SILENT; + } else { + beforeSpeedBump = !row.getEntry().isAmbient(); + } + if (beforeSpeedBump) { + speedBumpIndex = currentIndex; + } + } + + mSpeedBumpIndex = speedBumpIndex; + } + return mSpeedBumpIndex; } @Override @@ -1066,12 +1094,6 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable } } - @ShadeViewRefactor(RefactorComponent.ADAPTER) - private void setSpeedBumpIndex(int newIndex, boolean noAmbient) { - mAmbientState.setSpeedBumpIndex(newIndex); - mNoAmbient = noAmbient; - } - @ShadeViewRefactor(RefactorComponent.STATE_RESOLVER) public void setChildLocationsChangedListener( NotificationLogger.OnChildLocationsChangedListener listener) { @@ -1135,7 +1157,7 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable } else { mAmbientState.setScrollY(mOwnScrollY); } - mStackScrollAlgorithm.resetViewStates(mAmbientState); + mStackScrollAlgorithm.resetViewStates(mAmbientState, getSpeedBumpIndex()); if (!isCurrentlyAnimating() && !mNeedsAnimation) { applyCurrentState(); } else { @@ -5785,32 +5807,11 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable * @param open Should the fling open or close the overscroll view. */ void flingTopOverscroll(float velocity, boolean open); - } + } @ShadeViewRefactor(RefactorComponent.SHADE_VIEW) private void updateSpeedBumpIndex() { - int speedBumpIndex = 0; - int currentIndex = 0; - final int N = getChildCount(); - for (int i = 0; i < N; i++) { - View view = getChildAt(i); - if (view.getVisibility() == View.GONE || !(view instanceof ExpandableNotificationRow)) { - continue; - } - ExpandableNotificationRow row = (ExpandableNotificationRow) view; - currentIndex++; - boolean beforeSpeedBump; - if (mHighPriorityBeforeSpeedBump) { - beforeSpeedBump = row.getEntry().getBucket() < BUCKET_SILENT; - } else { - beforeSpeedBump = !row.getEntry().isAmbient(); - } - if (beforeSpeedBump) { - speedBumpIndex = currentIndex; - } - } - boolean noAmbient = speedBumpIndex == N; - setSpeedBumpIndex(speedBumpIndex, noAmbient); + mSpeedBumpIndexDirty = true; } /** Updates the indices of the boundaries between sections. */ diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java index 8d792ab6aa58..c10362d00a13 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java @@ -18,6 +18,8 @@ package com.android.systemui.statusbar.notification.stack; import static com.android.systemui.Dependency.ALLOW_NOTIFICATION_LONG_PRESS_NAME; import static com.android.systemui.statusbar.StatusBarState.KEYGUARD; +import static com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout.ROWS_GENTLE; +import static com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout.ROWS_HIGH_PRIORITY; import android.content.res.Resources; import android.graphics.Point; @@ -61,6 +63,8 @@ import com.android.systemui.statusbar.notification.collection.legacy.Notificatio import com.android.systemui.statusbar.notification.collection.legacy.NotificationGroupManagerLegacy.NotificationGroup; import com.android.systemui.statusbar.notification.collection.legacy.NotificationGroupManagerLegacy.OnGroupChangeListener; import com.android.systemui.statusbar.notification.collection.render.GroupExpansionManager; +import com.android.systemui.statusbar.notification.collection.render.SectionHeaderController; +import com.android.systemui.statusbar.notification.dagger.SilentHeader; import com.android.systemui.statusbar.notification.logging.NotificationLogger; import com.android.systemui.statusbar.notification.row.ActivatableNotificationView; import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow; @@ -117,6 +121,7 @@ public class NotificationStackScrollLayoutController { private final NotificationLockscreenUserManager mLockscreenUserManager; // TODO: StatusBar should be encapsulated behind a Controller private final StatusBar mStatusBar; + private final SectionHeaderController mSilentHeaderController; private NotificationStackScrollLayout mView; private boolean mFadeNotificationsOnDismiss; @@ -359,10 +364,6 @@ public class NotificationStackScrollLayoutController { row.performDismissWithBlockingHelper(false /* fromAccessibility */); } - if (view instanceof PeopleHubView) { - mNotificationSectionsManager.hidePeopleRow(); - } - if (!isBlockingHelperShown) { mView.addSwipedOutView(view); } @@ -523,7 +524,8 @@ public class NotificationStackScrollLayoutController { StatusBar statusBar, ScrimController scrimController, NotificationGroupManagerLegacy legacyGroupManager, - GroupExpansionManager groupManager) { + GroupExpansionManager groupManager, + @SilentHeader SectionHeaderController silentHeaderController) { mAllowLongPress = allowLongPress; mNotificationGutsManager = notificationGutsManager; mHeadsUpManager = headsUpManager; @@ -559,6 +561,7 @@ public class NotificationStackScrollLayoutController { mStatusBar.requestNotificationUpdate("onGroupsChanged"); } }); + mSilentHeaderController = silentHeaderController; } public void attach(NotificationStackScrollLayout view) { @@ -624,6 +627,7 @@ public class NotificationStackScrollLayoutController { mOnAttachStateChangeListener.onViewAttachedToWindow(mView); } mView.addOnAttachStateChangeListener(mOnAttachStateChangeListener); + mSilentHeaderController.setOnClearAllClickListener(v -> clearSilentNotifications()); } public void addOnExpandedHeightChangedListener(BiConsumer<Float, Float> listener) { @@ -713,6 +717,10 @@ public class NotificationStackScrollLayoutController { return mView.getWakeUpHeight(); } + public int getSpeedBumpIndex() { + return mView.getSpeedBumpIndex(); + } + public void setHideAmount(float linearAmount, float amount) { mView.setHideAmount(linearAmount, amount); } @@ -1134,6 +1142,12 @@ public class NotificationStackScrollLayoutController { } } + public void clearSilentNotifications() { + // Leave the shade open if there will be other notifs left over to clear + final boolean closeShade = !hasActiveClearableNotifications(ROWS_HIGH_PRIORITY); + mView.clearNotifications(ROWS_GENTLE, closeShade); + } + private class NotificationListContainerImpl implements NotificationListContainer { @Override diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/SectionHeaderView.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/SectionHeaderView.java index 5777ba120ef0..99ec7548fb9d 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/SectionHeaderView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/SectionHeaderView.java @@ -97,7 +97,7 @@ public class SectionHeaderView extends StackScrollerDecorView { /** * Fired whenever the user clicks on the body of the header (e.g. no sub-buttons or anything). */ - void setOnHeaderClickListener(View.OnClickListener listener) { + public void setOnHeaderClickListener(View.OnClickListener listener) { mLabelClickListener = listener; mLabelView.setOnClickListener(listener); } @@ -112,7 +112,7 @@ public class SectionHeaderView extends StackScrollerDecorView { } /** Fired when the user clicks on the "X" button on the far right of the header. */ - void setOnClearAllClickListener(View.OnClickListener listener) { + public void setOnClearAllClickListener(View.OnClickListener listener) { mOnClearClickListener = listener; mClearAllButton.setOnClickListener(listener); } @@ -122,7 +122,8 @@ public class SectionHeaderView extends StackScrollerDecorView { return true; } - void setHeaderText(@StringRes int resId) { + /** Sets text to be displayed in the header */ + public void setHeaderText(@StringRes int resId) { mLabelTextId = resId; mLabelView.setText(resId); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithm.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithm.java index 541c7845a5d3..95edfe37fee7 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithm.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithm.java @@ -91,7 +91,7 @@ public class StackScrollAlgorithm { /** * Updates the state of all children in the hostview based on this algorithm. */ - public void resetViewStates(AmbientState ambientState) { + public void resetViewStates(AmbientState ambientState, int speedBumpIndex) { // The state of the local variables are saved in an algorithmState to easily subdivide it // into multiple phases. StackScrollAlgorithmState algorithmState = mTempAlgorithmState; @@ -110,7 +110,7 @@ public class StackScrollAlgorithm { updateDimmedActivatedHideSensitive(ambientState, algorithmState); updateClipping(algorithmState, ambientState); - updateSpeedBumpState(algorithmState, ambientState); + updateSpeedBumpState(algorithmState, speedBumpIndex); updateShelfState(ambientState); getNotificationChildrenStates(algorithmState, ambientState); } @@ -136,9 +136,9 @@ public class StackScrollAlgorithm { } private void updateSpeedBumpState(StackScrollAlgorithmState algorithmState, - AmbientState ambientState) { + int speedBumpIndex) { int childCount = algorithmState.visibleChildren.size(); - int belowSpeedBump = ambientState.getSpeedBumpIndex(); + int belowSpeedBump = speedBumpIndex; for (int i = 0; i < childCount; i++) { ExpandableView child = algorithmState.visibleChildren.get(i); ExpandableViewState childViewState = child.getViewState(); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java index 09034c0899f5..3665c39bd9ea 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java @@ -25,26 +25,21 @@ import android.os.Handler; import android.os.UserHandle; import android.os.UserManager; import android.util.Log; -import android.util.MathUtils; import android.view.KeyEvent; -import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; -import android.view.ViewTreeObserver; import android.view.WindowInsets; -import com.android.internal.widget.LockPatternUtils; -import com.android.keyguard.KeyguardHostView; +import com.android.keyguard.KeyguardHostViewController; +import com.android.keyguard.KeyguardRootViewController; import com.android.keyguard.KeyguardSecurityModel; import com.android.keyguard.KeyguardSecurityView; import com.android.keyguard.KeyguardUpdateMonitor; import com.android.keyguard.KeyguardUpdateMonitorCallback; import com.android.keyguard.ViewMediatorCallback; -import com.android.keyguard.dagger.ContainerView; -import com.android.keyguard.dagger.KeyguardBouncerScope; +import com.android.keyguard.dagger.KeyguardBouncerComponent; +import com.android.keyguard.dagger.RootView; import com.android.systemui.DejankUtils; -import com.android.systemui.Dependency; -import com.android.systemui.R; import com.android.systemui.keyguard.DismissCallbackRegistry; import com.android.systemui.plugins.FalsingManager; import com.android.systemui.shared.system.SysUiStatsLog; @@ -57,18 +52,16 @@ import javax.inject.Inject; /** * A class which manages the bouncer on the lockscreen. */ -@KeyguardBouncerScope public class KeyguardBouncer { private static final String TAG = "KeyguardBouncer"; static final long BOUNCER_FACE_DELAY = 1200; - static final float ALPHA_EXPANSION_THRESHOLD = 0.95f; + public static final float ALPHA_EXPANSION_THRESHOLD = 0.95f; static final float EXPANSION_HIDDEN = 1f; static final float EXPANSION_VISIBLE = 0f; protected final Context mContext; protected final ViewMediatorCallback mCallback; - protected final LockPatternUtils mLockPatternUtils; protected final ViewGroup mContainer; private final FalsingManager mFalsingManager; private final DismissCallbackRegistry mDismissCallbackRegistry; @@ -76,6 +69,8 @@ public class KeyguardBouncer { private final BouncerExpansionCallback mExpansionCallback; private final KeyguardUpdateMonitor mKeyguardUpdateMonitor; private final KeyguardStateController mKeyguardStateController; + private final KeyguardSecurityModel mKeyguardSecurityModel; + private final KeyguardBouncerComponent.Factory mKeyguardBouncerComponentFactory; private final KeyguardUpdateMonitorCallback mUpdateMonitorCallback = new KeyguardUpdateMonitorCallback() { @Override @@ -85,32 +80,33 @@ public class KeyguardBouncer { }; private final Runnable mRemoveViewRunnable = this::removeView; private final KeyguardBypassController mKeyguardBypassController; - protected KeyguardHostView mKeyguardView; + private KeyguardHostViewController mKeyguardViewController; private final Runnable mResetRunnable = ()-> { - if (mKeyguardView != null) { - mKeyguardView.resetSecurityContainer(); + if (mKeyguardViewController != null) { + mKeyguardViewController.resetSecurityContainer(); } }; private int mStatusBarHeight; private float mExpansion = EXPANSION_HIDDEN; protected ViewGroup mRoot; + private KeyguardRootViewController mRootViewController; private boolean mShowingSoon; private int mBouncerPromptReason; private boolean mIsAnimatingAway; private boolean mIsScrimmed; - @Inject - public KeyguardBouncer(Context context, ViewMediatorCallback callback, - LockPatternUtils lockPatternUtils, @ContainerView ViewGroup container, + private KeyguardBouncer(Context context, ViewMediatorCallback callback, + ViewGroup container, DismissCallbackRegistry dismissCallbackRegistry, FalsingManager falsingManager, BouncerExpansionCallback expansionCallback, KeyguardStateController keyguardStateController, KeyguardUpdateMonitor keyguardUpdateMonitor, - KeyguardBypassController keyguardBypassController, Handler handler) { + KeyguardBypassController keyguardBypassController, Handler handler, + KeyguardSecurityModel keyguardSecurityModel, + KeyguardBouncerComponent.Factory keyguardBouncerComponentFactory) { mContext = context; mCallback = callback; - mLockPatternUtils = lockPatternUtils; mContainer = container; mKeyguardUpdateMonitor = keyguardUpdateMonitor; mFalsingManager = falsingManager; @@ -118,6 +114,8 @@ public class KeyguardBouncer { mExpansionCallback = expansionCallback; mHandler = handler; mKeyguardStateController = keyguardStateController; + mKeyguardSecurityModel = keyguardSecurityModel; + mKeyguardBouncerComponentFactory = keyguardBouncerComponentFactory; mKeyguardUpdateMonitor.registerCallback(mUpdateMonitorCallback); mKeyguardBypassController = keyguardBypassController; } @@ -168,7 +166,7 @@ public class KeyguardBouncer { // If allowed, try to dismiss the Keyguard. If no security auth (password/pin/pattern) is // set, this will dismiss the whole Keyguard. Otherwise, show the bouncer. - if (allowDismissKeyguard && mKeyguardView.dismiss(activeUserId)) { + if (allowDismissKeyguard && mKeyguardViewController.dismiss(activeUserId)) { return; } @@ -204,12 +202,13 @@ public class KeyguardBouncer { */ private void onFullyShown() { mFalsingManager.onBouncerShown(); - if (mKeyguardView == null) { + if (mKeyguardViewController == null) { Log.wtf(TAG, "onFullyShown when view was null"); } else { - mKeyguardView.onResume(); + mKeyguardViewController.onResume(); if (mRoot != null) { - mRoot.announceForAccessibility(mKeyguardView.getAccessibilityTitleForCurrentMode()); + mRoot.announceForAccessibility( + mKeyguardViewController.getAccessibilityTitleForCurrentMode()); } } } @@ -233,28 +232,13 @@ public class KeyguardBouncer { showPromptReason(mBouncerPromptReason); final CharSequence customMessage = mCallback.consumeCustomMessage(); if (customMessage != null) { - mKeyguardView.showErrorMessage(customMessage); - } - // We might still be collapsed and the view didn't have time to layout yet or still - // be small, let's wait on the predraw to do the animation in that case. - if (mKeyguardView.getHeight() != 0 && mKeyguardView.getHeight() != mStatusBarHeight) { - mKeyguardView.startAppearAnimation(); - } else { - mKeyguardView.getViewTreeObserver().addOnPreDrawListener( - new ViewTreeObserver.OnPreDrawListener() { - @Override - public boolean onPreDraw() { - mKeyguardView.getViewTreeObserver().removeOnPreDrawListener(this); - mKeyguardView.startAppearAnimation(); - return true; - } - }); - mKeyguardView.requestLayout(); + mKeyguardViewController.showErrorMessage(customMessage); } + mKeyguardViewController.appear(mStatusBarHeight); mShowingSoon = false; if (mExpansion == EXPANSION_VISIBLE) { - mKeyguardView.onResume(); - mKeyguardView.resetSecurityContainer(); + mKeyguardViewController.onResume(); + mKeyguardViewController.resetSecurityContainer(); showPromptReason(mBouncerPromptReason); } SysUiStatsLog.write(SysUiStatsLog.KEYGUARD_BOUNCER_STATE_CHANGED, @@ -270,16 +254,16 @@ public class KeyguardBouncer { * and {@link KeyguardSecurityView#PROMPT_REASON_RESTART} */ public void showPromptReason(int reason) { - if (mKeyguardView != null) { - mKeyguardView.showPromptReason(reason); + if (mKeyguardViewController != null) { + mKeyguardViewController.showPromptReason(reason); } else { Log.w(TAG, "Trying to show prompt reason on empty bouncer"); } } public void showMessage(String message, ColorStateList colorState) { - if (mKeyguardView != null) { - mKeyguardView.showMessage(message, colorState); + if (mKeyguardViewController != null) { + mKeyguardViewController.showMessage(message, colorState); } else { Log.w(TAG, "Trying to show message on empty bouncer"); } @@ -293,7 +277,7 @@ public class KeyguardBouncer { public void showWithDismissAction(OnDismissAction r, Runnable cancelAction) { ensureView(); - mKeyguardView.setOnDismissAction(r, cancelAction); + mKeyguardViewController.setOnDismissAction(r, cancelAction); show(false /* resetSecuritySelection */); } @@ -307,9 +291,9 @@ public class KeyguardBouncer { mFalsingManager.onBouncerHidden(); mCallback.onBouncerVisiblityChanged(false /* shown */); cancelShowRunnable(); - if (mKeyguardView != null) { - mKeyguardView.cancelDismissAction(); - mKeyguardView.cleanUp(); + if (mKeyguardViewController != null) { + mKeyguardViewController.cancelDismissAction(); + mKeyguardViewController.cleanUp(); } mIsAnimatingAway = false; if (mRoot != null) { @@ -328,8 +312,8 @@ public class KeyguardBouncer { */ public void startPreHideAnimation(Runnable runnable) { mIsAnimatingAway = true; - if (mKeyguardView != null) { - mKeyguardView.startDisappearAnimation(runnable); + if (mKeyguardViewController != null) { + mKeyguardViewController.startDisappearAnimation(runnable); } else if (runnable != null) { runnable.run(); } @@ -345,8 +329,9 @@ public class KeyguardBouncer { } public void onScreenTurnedOff() { - if (mKeyguardView != null && mRoot != null && mRoot.getVisibility() == View.VISIBLE) { - mKeyguardView.onPause(); + if (mKeyguardViewController != null + && mRoot != null && mRoot.getVisibility() == View.VISIBLE) { + mKeyguardViewController.onPause(); } } @@ -380,7 +365,7 @@ public class KeyguardBouncer { } private void showPrimarySecurityScreen() { - mKeyguardView.showPrimarySecurityScreen(); + mKeyguardViewController.showPrimarySecurityScreen(); } /** @@ -391,10 +376,8 @@ public class KeyguardBouncer { public void setExpansion(float fraction) { float oldExpansion = mExpansion; mExpansion = fraction; - if (mKeyguardView != null && !mIsAnimatingAway) { - float alpha = MathUtils.map(ALPHA_EXPANSION_THRESHOLD, 1, 1, 0, fraction); - mKeyguardView.setAlpha(MathUtils.constrain(alpha, 0f, 1f)); - mKeyguardView.setTranslationY(fraction * mKeyguardView.getHeight()); + if (mKeyguardViewController != null && !mIsAnimatingAway) { + mKeyguardViewController.setExpansion(fraction); } if (fraction == EXPANSION_VISIBLE && oldExpansion != EXPANSION_VISIBLE) { @@ -405,28 +388,22 @@ public class KeyguardBouncer { mExpansionCallback.onFullyHidden(); } else if (fraction != EXPANSION_VISIBLE && oldExpansion == EXPANSION_VISIBLE) { mExpansionCallback.onStartingToHide(); - if (mKeyguardView != null) { - mKeyguardView.onStartingToHide(); + if (mKeyguardViewController != null) { + mKeyguardViewController.onStartingToHide(); } } } public boolean willDismissWithAction() { - return mKeyguardView != null && mKeyguardView.hasDismissActions(); + return mKeyguardViewController != null && mKeyguardViewController.hasDismissActions(); } public int getTop() { - if (mKeyguardView == null) { + if (mKeyguardViewController == null) { return 0; } - int top = mKeyguardView.getTop(); - // The password view has an extra top padding that should be ignored. - if (mKeyguardView.getCurrentSecurityMode() == SecurityMode.Password) { - View messageArea = mKeyguardView.findViewById(R.id.keyguard_message_area); - top += messageArea.getTop(); - } - return top; + return mKeyguardViewController.getTop(); } protected void ensureView() { @@ -442,10 +419,13 @@ public class KeyguardBouncer { protected void inflateView() { removeView(); mHandler.removeCallbacks(mRemoveViewRunnable); - mRoot = (ViewGroup) LayoutInflater.from(mContext).inflate(R.layout.keyguard_bouncer, null); - mKeyguardView = mRoot.findViewById(R.id.keyguard_host_view); - mKeyguardView.setLockPatternUtils(mLockPatternUtils); - mKeyguardView.setViewMediatorCallback(mCallback); + KeyguardBouncerComponent component = mKeyguardBouncerComponentFactory.create(); + mRootViewController = component.getKeyguardRootViewController(); + mRootViewController.init(); + mRoot = mRootViewController.getView(); // TODO(b/166448040): Don't access root view here. + mKeyguardViewController = component.getKeyguardHostViewController(); + mKeyguardViewController.init(); + mContainer.addView(mRoot, mContainer.getChildCount()); mStatusBarHeight = mRoot.getResources().getDimensionPixelOffset( com.android.systemui.R.dimen.status_bar_height); @@ -465,7 +445,7 @@ public class KeyguardBouncer { } public boolean onBackPressed() { - return mKeyguardView != null && mKeyguardView.handleBackKey(); + return mKeyguardViewController != null && mKeyguardViewController.handleBackKey(); } /** @@ -473,7 +453,7 @@ public class KeyguardBouncer { * notifications on Keyguard, like SIM PIN/PUK. */ public boolean needsFullscreenBouncer() { - SecurityMode mode = Dependency.get(KeyguardSecurityModel.class).getSecurityMode( + SecurityMode mode = mKeyguardSecurityModel.getSecurityMode( KeyguardUpdateMonitor.getCurrentUser()); return mode == SecurityMode.SimPin || mode == SecurityMode.SimPuk; } @@ -483,8 +463,8 @@ public class KeyguardBouncer { * makes this method much faster. */ public boolean isFullscreenBouncer() { - if (mKeyguardView != null) { - SecurityMode mode = mKeyguardView.getCurrentSecurityMode(); + if (mKeyguardViewController != null) { + SecurityMode mode = mKeyguardViewController.getCurrentSecurityMode(); return mode == SecurityMode.SimPin || mode == SecurityMode.SimPuk; } return false; @@ -494,21 +474,22 @@ public class KeyguardBouncer { * WARNING: This method might cause Binder calls. */ public boolean isSecure() { - return mKeyguardView == null || mKeyguardView.getSecurityMode() != SecurityMode.None; + return mKeyguardSecurityModel.getSecurityMode( + KeyguardUpdateMonitor.getCurrentUser()) != SecurityMode.None; } public boolean shouldDismissOnMenuPressed() { - return mKeyguardView.shouldEnableMenuKey(); + return mKeyguardViewController.shouldEnableMenuKey(); } public boolean interceptMediaKey(KeyEvent event) { ensureView(); - return mKeyguardView.interceptMediaKey(event); + return mKeyguardViewController.interceptMediaKey(event); } public void notifyKeyguardAuthenticated(boolean strongAuth) { ensureView(); - mKeyguardView.finish(strongAuth, KeyguardUpdateMonitor.getCurrentUser()); + mKeyguardViewController.finish(strongAuth, KeyguardUpdateMonitor.getCurrentUser()); } public void dump(PrintWriter pw) { @@ -516,8 +497,8 @@ public class KeyguardBouncer { pw.println(" isShowing(): " + isShowing()); pw.println(" mStatusBarHeight: " + mStatusBarHeight); pw.println(" mExpansion: " + mExpansion); - pw.println(" mKeyguardView; " + mKeyguardView); - pw.println(" mShowingSoon: " + mKeyguardView); + pw.println(" mKeyguardViewController; " + mKeyguardViewController); + pw.println(" mShowingSoon: " + mShowingSoon); pw.println(" mBouncerPromptReason: " + mBouncerPromptReason); pw.println(" mIsAnimatingAway: " + mIsAnimatingAway); } @@ -528,4 +509,46 @@ public class KeyguardBouncer { void onStartingToShow(); void onFullyHidden(); } + + /** Create a {@link KeyguardBouncer} once a container and bouncer callback are available. */ + public static class Factory { + private final Context mContext; + private final ViewMediatorCallback mCallback; + private final DismissCallbackRegistry mDismissCallbackRegistry; + private final FalsingManager mFalsingManager; + private final KeyguardStateController mKeyguardStateController; + private final KeyguardUpdateMonitor mKeyguardUpdateMonitor; + private final KeyguardBypassController mKeyguardBypassController; + private final Handler mHandler; + private final KeyguardSecurityModel mKeyguardSecurityModel; + private final KeyguardBouncerComponent.Factory mKeyguardBouncerComponentFactory; + + @Inject + public Factory(Context context, ViewMediatorCallback callback, + DismissCallbackRegistry dismissCallbackRegistry, FalsingManager falsingManager, + KeyguardStateController keyguardStateController, + KeyguardUpdateMonitor keyguardUpdateMonitor, + KeyguardBypassController keyguardBypassController, Handler handler, + KeyguardSecurityModel keyguardSecurityModel, + KeyguardBouncerComponent.Factory keyguardBouncerComponentFactory) { + mContext = context; + mCallback = callback; + mDismissCallbackRegistry = dismissCallbackRegistry; + mFalsingManager = falsingManager; + mKeyguardStateController = keyguardStateController; + mKeyguardUpdateMonitor = keyguardUpdateMonitor; + mKeyguardBypassController = keyguardBypassController; + mHandler = handler; + mKeyguardSecurityModel = keyguardSecurityModel; + mKeyguardBouncerComponentFactory = keyguardBouncerComponentFactory; + } + + public KeyguardBouncer create(@RootView ViewGroup container, + BouncerExpansionCallback expansionCallback) { + return new KeyguardBouncer(mContext, mCallback, container, + mDismissCallbackRegistry, mFalsingManager, expansionCallback, + mKeyguardStateController, mKeyguardUpdateMonitor, mKeyguardBypassController, + mHandler, mKeyguardSecurityModel, mKeyguardBouncerComponentFactory); + } + } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java index b56993b5f439..51209d166eee 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java @@ -44,7 +44,6 @@ import com.android.keyguard.KeyguardUpdateMonitor; import com.android.keyguard.KeyguardUpdateMonitorCallback; import com.android.keyguard.KeyguardViewController; import com.android.keyguard.ViewMediatorCallback; -import com.android.keyguard.dagger.KeyguardBouncerComponent; import com.android.settingslib.animation.AppearAnimationUtils; import com.android.systemui.DejankUtils; import com.android.systemui.dagger.SysUISingleton; @@ -104,7 +103,7 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb private final NavigationModeController mNavigationModeController; private final NotificationShadeWindowController mNotificationShadeWindowController; private final Optional<FaceAuthScreenBrightnessController> mFaceAuthScreenBrightnessController; - private final KeyguardBouncerComponent.Factory mKeyguardBouncerComponentFactory; + private final KeyguardBouncer.Factory mKeyguardBouncerFactory; private final BouncerExpansionCallback mExpansionCallback = new BouncerExpansionCallback() { @Override public void onFullyShown() { @@ -216,7 +215,7 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb KeyguardStateController keyguardStateController, Optional<FaceAuthScreenBrightnessController> faceAuthScreenBrightnessController, NotificationMediaManager notificationMediaManager, - KeyguardBouncerComponent.Factory keyguardBouncerComponentFactory) { + KeyguardBouncer.Factory keyguardBouncerFactory) { mContext = context; mViewMediatorCallback = callback; mLockPatternUtils = lockPatternUtils; @@ -229,7 +228,7 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb mStatusBarStateController = sysuiStatusBarStateController; mDockManager = dockManager; mFaceAuthScreenBrightnessController = faceAuthScreenBrightnessController; - mKeyguardBouncerComponentFactory = keyguardBouncerComponentFactory; + mKeyguardBouncerFactory = keyguardBouncerFactory; } @Override @@ -246,9 +245,7 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb mLastLockVisible = mLockIconContainer.getVisibility() == View.VISIBLE; } mBiometricUnlockController = biometricUnlockController; - mBouncer = mKeyguardBouncerComponentFactory - .build(container, mExpansionCallback) - .createKeyguardBouncer(); + mBouncer = mKeyguardBouncerFactory.create(container, mExpansionCallback); mNotificationPanelViewController = notificationPanelViewController; notificationPanelViewController.addExpansionListener(this); mBypassController = bypassController; 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 f80656706f37..737cdeba797a 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarter.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarter.java @@ -281,17 +281,10 @@ public class StatusBarNotificationActivityStarter implements NotificationActivit // TODO: Some of this code may be able to move to NotificationEntryManager. removeHUN(row); - NotificationEntry parentToCancel = null; - if (shouldAutoCancel(entry.getSbn()) && mGroupMembershipManager.isOnlyChildInGroup(entry)) { - NotificationEntry summarySbn = mGroupMembershipManager.getLogicalGroupSummary(entry); - if (shouldAutoCancel(summarySbn.getSbn())) { - parentToCancel = summarySbn; - } - } - final NotificationEntry parentToCancelFinal = parentToCancel; + final Runnable runnable = () -> handleNotificationClickAfterPanelCollapsed( entry, row, controller, intent, - isActivityIntent, wasOccluded, parentToCancelFinal); + isActivityIntent, wasOccluded); if (showOverLockscreen) { mShadeController.addPostCollapseAction(runnable); @@ -312,8 +305,7 @@ public class StatusBarNotificationActivityStarter implements NotificationActivit RemoteInputController controller, PendingIntent intent, boolean isActivityIntent, - boolean wasOccluded, - NotificationEntry parentToCancelFinal) { + boolean wasOccluded) { String notificationKey = entry.getKey(); mLogger.logHandleClickAfterPanelCollapsed(notificationKey); @@ -373,22 +365,23 @@ public class StatusBarNotificationActivityStarter implements NotificationActivit NotificationLogger.getNotificationLocation(entry); final NotificationVisibility nv = NotificationVisibility.obtain(notificationKey, rank, count, true, location); + + // NMS will officially remove notification if the notification has FLAG_AUTO_CANCEL: mClickNotifier.onNotificationClick(notificationKey, nv); - if (!canBubble) { - if (parentToCancelFinal != null) { - // TODO: (b/145659174) remove - this cancels the parent if the notification clicked - // on will auto-cancel and is the only child in the group. This won't be - // necessary in the new pipeline due to group pruning in ShadeListBuilder. - removeNotification(parentToCancelFinal); - } + // TODO (b/162832756): delete these notification removals when migrating to the new + // pipeline; this is taken care of in {@link NotifCollection#tryRemoveNotification} + // which cancels lifetime extenders if the notification was dismissed by the user (ie: + // clicked or manually dismissed) + if (!canBubble && !mFeatureFlags.isNewNotifPipelineRenderingEnabled()) { if (shouldAutoCancel(entry.getSbn()) || mRemoteInputManager.isNotificationKeptForRemoteInputHistory( notificationKey)) { - // Automatically remove all notifications that we may have kept around longer + // manually call notification removal in order to cancel any lifetime extenders removeNotification(row.getEntry()); } } + mIsCollapsingToShowActivityOverLockscreen = false; } diff --git a/packages/SystemUI/src/com/android/systemui/util/ViewController.java b/packages/SystemUI/src/com/android/systemui/util/ViewController.java new file mode 100644 index 000000000000..64f8dbbb9e34 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/util/ViewController.java @@ -0,0 +1,72 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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.util; + +import android.view.View; +import android.view.View.OnAttachStateChangeListener; + +/** + * Utility class that handles view lifecycle events for View Controllers. + * + * Implementations should handle setup and teardown related activities inside of + * {@link #onViewAttached()} and {@link #onViewDetached()}. + * + * @param <T> View class that this ViewController is for. + */ +public abstract class ViewController<T extends View> { + protected final T mView; + private boolean mInited; + + private OnAttachStateChangeListener mOnAttachStateListener = new OnAttachStateChangeListener() { + @Override + public void onViewAttachedToWindow(View v) { + ViewController.this.onViewAttached(); + } + + @Override + public void onViewDetachedFromWindow(View v) { + ViewController.this.onViewDetached(); + } + }; + + protected ViewController(T view) { + mView = view; + } + + /** Call immediately after constructing Controller in order to handle view lifecycle events. */ + public void init() { + if (mInited) { + return; + } + mInited = true; + + if (mView.isAttachedToWindow()) { + mOnAttachStateListener.onViewAttachedToWindow(mView); + } + mView.addOnAttachStateChangeListener(mOnAttachStateListener); + } + + /** + * Called when the view is attached and a call to {@link #init()} has been made in either order. + */ + protected abstract void onViewAttached(); + + /** + * Called when the view is detached. + */ + protected abstract void onViewDetached(); +} diff --git a/packages/SystemUI/src/com/android/systemui/wmshell/WMShell.java b/packages/SystemUI/src/com/android/systemui/wmshell/WMShell.java index c7a9af3642e5..98c0b1e99fc4 100644 --- a/packages/SystemUI/src/com/android/systemui/wmshell/WMShell.java +++ b/packages/SystemUI/src/com/android/systemui/wmshell/WMShell.java @@ -38,10 +38,6 @@ import com.android.systemui.dagger.SysUISingleton; import com.android.systemui.keyguard.ScreenLifecycle; import com.android.systemui.model.SysUiState; import com.android.systemui.navigationbar.NavigationModeController; -import com.android.systemui.onehanded.OneHanded; -import com.android.systemui.onehanded.OneHandedEvents; -import com.android.systemui.onehanded.OneHandedGestureHandler.OneHandedGestureEventCallback; -import com.android.systemui.onehanded.OneHandedTransitionCallback; import com.android.systemui.pip.Pip; import com.android.systemui.shared.system.ActivityManagerWrapper; import com.android.systemui.shared.system.TaskStackChangeListener; @@ -51,6 +47,10 @@ import com.android.systemui.tracing.ProtoTracer; import com.android.systemui.tracing.nano.SystemUiTraceProto; import com.android.wm.shell.common.DisplayImeController; import com.android.wm.shell.nano.WmShellTraceProto; +import com.android.wm.shell.onehanded.OneHanded; +import com.android.wm.shell.onehanded.OneHandedEvents; +import com.android.wm.shell.onehanded.OneHandedGestureHandler.OneHandedGestureEventCallback; +import com.android.wm.shell.onehanded.OneHandedTransitionCallback; import com.android.wm.shell.protolog.ShellProtoLogImpl; import com.android.wm.shell.splitscreen.SplitScreen; @@ -248,10 +248,9 @@ public final class WMShell extends SystemUI implements ProtoTraceable<SystemUiTr @Override public void setImeWindowStatus(int displayId, IBinder token, int vis, int backDisposition, boolean showImeSwitcher) { - if (displayId != DEFAULT_DISPLAY && (vis & InputMethodService.IME_VISIBLE) == 0) { - return; + if (displayId == DEFAULT_DISPLAY && (vis & InputMethodService.IME_VISIBLE) != 0) { + oneHanded.stopOneHanded(OneHandedEvents.EVENT_ONE_HANDED_TRIGGER_POP_IME_OUT); } - oneHanded.stopOneHanded(OneHandedEvents.EVENT_ONE_HANDED_TRIGGER_POP_IME_OUT); } }); diff --git a/packages/SystemUI/src/com/android/systemui/wmshell/WMShellBaseModule.java b/packages/SystemUI/src/com/android/systemui/wmshell/WMShellBaseModule.java index adb9186d6705..1f8cf95169d8 100644 --- a/packages/SystemUI/src/com/android/systemui/wmshell/WMShellBaseModule.java +++ b/packages/SystemUI/src/com/android/systemui/wmshell/WMShellBaseModule.java @@ -24,7 +24,6 @@ import android.view.IWindowManager; import com.android.internal.logging.UiEventLogger; import com.android.systemui.dagger.SysUISingleton; import com.android.systemui.dagger.qualifiers.Main; -import com.android.systemui.onehanded.OneHanded; import com.android.systemui.pip.Pip; import com.android.systemui.pip.PipSurfaceTransactionHelper; import com.android.systemui.pip.PipUiEventLogger; @@ -36,6 +35,7 @@ import com.android.wm.shell.animation.FlingAnimationUtils; import com.android.wm.shell.common.DisplayController; import com.android.wm.shell.common.SystemWindows; import com.android.wm.shell.common.TransactionPool; +import com.android.wm.shell.onehanded.OneHanded; import com.android.wm.shell.splitscreen.SplitScreen; import dagger.BindsOptionalOf; diff --git a/packages/SystemUI/src/com/android/systemui/wmshell/WMShellModule.java b/packages/SystemUI/src/com/android/systemui/wmshell/WMShellModule.java index 3a249d68d969..16fb2cacc950 100644 --- a/packages/SystemUI/src/com/android/systemui/wmshell/WMShellModule.java +++ b/packages/SystemUI/src/com/android/systemui/wmshell/WMShellModule.java @@ -24,8 +24,6 @@ import com.android.systemui.broadcast.BroadcastDispatcher; import com.android.systemui.dagger.SysUISingleton; import com.android.systemui.dagger.qualifiers.Main; import com.android.systemui.model.SysUiState; -import com.android.systemui.onehanded.OneHanded; -import com.android.systemui.onehanded.OneHandedController; import com.android.systemui.pip.Pip; import com.android.systemui.pip.PipBoundsHandler; import com.android.systemui.pip.PipSurfaceTransactionHelper; @@ -40,6 +38,8 @@ import com.android.wm.shell.common.DisplayController; import com.android.wm.shell.common.DisplayImeController; import com.android.wm.shell.common.SystemWindows; import com.android.wm.shell.common.TransactionPool; +import com.android.wm.shell.onehanded.OneHanded; +import com.android.wm.shell.onehanded.OneHandedController; import com.android.wm.shell.splitscreen.SplitScreen; import com.android.wm.shell.splitscreen.SplitScreenController; diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardHostViewTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardHostViewControllerTest.java index dd5c8335eefa..54e879e2ff38 100644 --- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardHostViewTest.java +++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardHostViewControllerTest.java @@ -11,7 +11,7 @@ * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT 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.keyguard; @@ -19,11 +19,12 @@ package com.android.keyguard; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; +import android.media.AudioManager; +import android.telephony.TelephonyManager; import android.test.suitebuilder.annotation.SmallTest; import android.testing.AndroidTestingRunner; import android.testing.TestableLooper; -import com.android.internal.widget.LockPatternUtils; import com.android.systemui.SysuiTestCase; import com.android.systemui.plugins.ActivityStarter.OnDismissAction; @@ -39,41 +40,44 @@ import org.mockito.junit.MockitoRule; @SmallTest @RunWith(AndroidTestingRunner.class) @TestableLooper.RunWithLooper -public class KeyguardHostViewTest extends SysuiTestCase { +public class KeyguardHostViewControllerTest extends SysuiTestCase { @Mock - private KeyguardSecurityContainer mSecurityContainer; + private KeyguardUpdateMonitor mKeyguardUpdateMonitor; @Mock - private LockPatternUtils mLockPatternUtils; + private KeyguardHostView mKeyguardHostView; + @Mock + private KeyguardSecurityContainerController mKeyguardSecurityContainerController; + @Mock + private AudioManager mAudioManager; + @Mock + private TelephonyManager mTelephonyManager; + @Mock + private ViewMediatorCallback mViewMediatorCallback; + @Rule public MockitoRule mMockitoRule = MockitoJUnit.rule(); - private KeyguardHostView mKeyguardHostView; + private KeyguardHostViewController mKeyguardHostViewController; @Before public void setup() { - mDependency.injectMockDependency(KeyguardUpdateMonitor.class); - mKeyguardHostView = new KeyguardHostView(getContext()) { - @Override - protected void onFinishInflate() { - mSecurityContainer = KeyguardHostViewTest.this.mSecurityContainer; - mLockPatternUtils = KeyguardHostViewTest.this.mLockPatternUtils; - } - }; - mKeyguardHostView.onFinishInflate(); + mKeyguardHostViewController = new KeyguardHostViewController( + mKeyguardHostView, mKeyguardUpdateMonitor, mKeyguardSecurityContainerController, + mAudioManager, mTelephonyManager, mViewMediatorCallback); } @Test public void testHasDismissActions() { - Assert.assertFalse("Action not set yet", mKeyguardHostView.hasDismissActions()); - mKeyguardHostView.setOnDismissAction(mock(OnDismissAction.class), + Assert.assertFalse("Action not set yet", mKeyguardHostViewController.hasDismissActions()); + mKeyguardHostViewController.setOnDismissAction(mock(OnDismissAction.class), null /* cancelAction */); - Assert.assertTrue("Action should exist", mKeyguardHostView.hasDismissActions()); + Assert.assertTrue("Action should exist", mKeyguardHostViewController.hasDismissActions()); } @Test public void testOnStartingToHide() { - mKeyguardHostView.onStartingToHide(); - verify(mSecurityContainer).onStartingToHide(); + mKeyguardHostViewController.onStartingToHide(); + verify(mKeyguardSecurityContainerController).onStartingToHide(); } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/SysuiTestCase.java b/packages/SystemUI/tests/src/com/android/systemui/SysuiTestCase.java index b7175eabab39..0fe381746449 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/SysuiTestCase.java +++ b/packages/SystemUI/tests/src/com/android/systemui/SysuiTestCase.java @@ -39,6 +39,7 @@ import com.android.systemui.broadcast.logging.BroadcastDispatcherLogger; import com.android.systemui.classifier.FalsingManagerFake; import com.android.systemui.dump.DumpManager; import com.android.systemui.plugins.FalsingManager; +import com.android.systemui.settings.UserTracker; import com.android.systemui.statusbar.SmartReplyController; import com.android.systemui.statusbar.notification.row.NotificationBlockingHelperManager; @@ -78,7 +79,7 @@ public abstract class SysuiTestCase { Dependency.setInstance(mDependency); mFakeBroadcastDispatcher = new FakeBroadcastDispatcher(mContext, mock(Looper.class), mock(Executor.class), mock(DumpManager.class), - mock(BroadcastDispatcherLogger.class)); + mock(BroadcastDispatcherLogger.class), mock(UserTracker.class)); mRealInstrumentation = InstrumentationRegistry.getInstrumentation(); Instrumentation inst = spy(mRealInstrumentation); diff --git a/packages/SystemUI/tests/src/com/android/systemui/accessibility/MagnificationModeSwitchTest.java b/packages/SystemUI/tests/src/com/android/systemui/accessibility/MagnificationModeSwitchTest.java index cdbc647f152b..64e067396059 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/accessibility/MagnificationModeSwitchTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/accessibility/MagnificationModeSwitchTest.java @@ -231,7 +231,6 @@ public class MagnificationModeSwitchTest extends SysuiTestCase { private void assertShowButtonAnimation() { verify(mViewPropertyAnimator).cancel(); verify(mViewPropertyAnimator).setDuration(anyLong()); - verify(mViewPropertyAnimator).setStartDelay(anyLong()); verify(mViewPropertyAnimator).alpha(anyFloat()); verify(mViewPropertyAnimator).start(); } @@ -239,11 +238,15 @@ public class MagnificationModeSwitchTest extends SysuiTestCase { private void initMockImageViewAndAnimator() { when(mViewPropertyAnimator.setDuration(anyLong())).thenReturn(mViewPropertyAnimator); when(mViewPropertyAnimator.alpha(anyFloat())).thenReturn(mViewPropertyAnimator); - when(mViewPropertyAnimator.setStartDelay(anyLong())).thenReturn(mViewPropertyAnimator); when(mViewPropertyAnimator.withEndAction(any(Runnable.class))).thenReturn( mViewPropertyAnimator); when(mSpyImageView.animate()).thenReturn(mViewPropertyAnimator); + doAnswer(invocation -> { + Runnable run = invocation.getArgument(0); + run.run(); + return null; + }).when(mSpyImageView).postDelayed(any(), anyLong()); } private void resetMockImageViewAndAnimator() { diff --git a/packages/SystemUI/tests/src/com/android/systemui/broadcast/BroadcastDispatcherTest.kt b/packages/SystemUI/tests/src/com/android/systemui/broadcast/BroadcastDispatcherTest.kt index 22e9594ca420..65301fe6fd3e 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/broadcast/BroadcastDispatcherTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/broadcast/BroadcastDispatcherTest.kt @@ -18,7 +18,6 @@ package com.android.systemui.broadcast import android.content.BroadcastReceiver import android.content.Context -import android.content.Intent import android.content.IntentFilter import android.os.Handler import android.os.Looper @@ -30,6 +29,7 @@ import android.testing.TestableLooper import com.android.systemui.SysuiTestCase import com.android.systemui.broadcast.logging.BroadcastDispatcherLogger import com.android.systemui.dump.DumpManager +import com.android.systemui.settings.UserTracker import com.android.systemui.util.concurrency.FakeExecutor import com.android.systemui.util.time.FakeSystemClock import junit.framework.Assert.assertSame @@ -80,6 +80,8 @@ class BroadcastDispatcherTest : SysuiTestCase() { private lateinit var mockHandler: Handler @Mock private lateinit var logger: BroadcastDispatcherLogger + @Mock + private lateinit var userTracker: UserTracker private lateinit var executor: Executor @@ -101,6 +103,7 @@ class BroadcastDispatcherTest : SysuiTestCase() { mock(Executor::class.java), mock(DumpManager::class.java), logger, + userTracker, mapOf(0 to mockUBRUser0, 1 to mockUBRUser1)) // These should be valid filters @@ -178,11 +181,7 @@ class BroadcastDispatcherTest : SysuiTestCase() { @Test fun testRegisterCurrentAsActualUser() { - val intent = Intent(Intent.ACTION_USER_SWITCHED).apply { - putExtra(Intent.EXTRA_USER_HANDLE, user1.identifier) - } - broadcastDispatcher.onReceive(mockContext, intent) - testableLooper.processAllMessages() + `when`(userTracker.userId).thenReturn(user1.identifier) broadcastDispatcher.registerReceiverWithHandler(broadcastReceiver, intentFilter, mockHandler, UserHandle.CURRENT) @@ -250,8 +249,9 @@ class BroadcastDispatcherTest : SysuiTestCase() { executor: Executor, dumpManager: DumpManager, logger: BroadcastDispatcherLogger, + userTracker: UserTracker, var mockUBRMap: Map<Int, UserBroadcastDispatcher> - ) : BroadcastDispatcher(context, bgLooper, executor, dumpManager, logger) { + ) : BroadcastDispatcher(context, bgLooper, executor, dumpManager, logger, userTracker) { override fun createUBRForUser(userId: Int): UserBroadcastDispatcher { return mockUBRMap.getOrDefault(userId, mock(UserBroadcastDispatcher::class.java)) } diff --git a/packages/SystemUI/tests/src/com/android/systemui/broadcast/FakeBroadcastDispatcher.kt b/packages/SystemUI/tests/src/com/android/systemui/broadcast/FakeBroadcastDispatcher.kt index 949932da4d50..da00e7e9518b 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/broadcast/FakeBroadcastDispatcher.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/broadcast/FakeBroadcastDispatcher.kt @@ -26,6 +26,7 @@ import android.util.Log import com.android.systemui.SysuiTestableContext import com.android.systemui.broadcast.logging.BroadcastDispatcherLogger import com.android.systemui.dump.DumpManager +import com.android.systemui.settings.UserTracker import java.util.concurrent.Executor class FakeBroadcastDispatcher( @@ -33,8 +34,9 @@ class FakeBroadcastDispatcher( looper: Looper, executor: Executor, dumpManager: DumpManager, - logger: BroadcastDispatcherLogger -) : BroadcastDispatcher(context, looper, executor, dumpManager, logger) { + logger: BroadcastDispatcherLogger, + userTracker: UserTracker +) : BroadcastDispatcher(context, looper, executor, dumpManager, logger, userTracker) { private val registeredReceivers = ArraySet<BroadcastReceiver>() diff --git a/packages/SystemUI/tests/src/com/android/systemui/globalactions/GlobalActionsDialogTest.java b/packages/SystemUI/tests/src/com/android/systemui/globalactions/GlobalActionsDialogTest.java index 909acead9553..b4af786c5579 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/globalactions/GlobalActionsDialogTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/globalactions/GlobalActionsDialogTest.java @@ -49,6 +49,7 @@ import android.testing.TestableLooper; import android.util.FeatureFlagUtils; import android.view.IWindowManager; import android.view.View; +import android.view.WindowManagerPolicyConstants; import android.widget.FrameLayout; import androidx.test.filters.SmallTest; @@ -241,6 +242,28 @@ public class GlobalActionsDialogTest extends SysuiTestCase { verifyLogPosted(GlobalActionsDialog.GlobalActionsEvent.GA_SCREENSHOT_LONG_PRESS); } + @Test + public void testShouldShowScreenshot() { + mContext.getOrCreateTestableResources().addOverride( + com.android.internal.R.integer.config_navBarInteractionMode, + WindowManagerPolicyConstants.NAV_BAR_MODE_2BUTTON); + + GlobalActionsDialog.ScreenshotAction screenshotAction = + mGlobalActionsDialog.makeScreenshotActionForTesting(); + assertThat(screenshotAction.shouldShow()).isTrue(); + } + + @Test + public void testShouldNotShowScreenshot() { + mContext.getOrCreateTestableResources().addOverride( + com.android.internal.R.integer.config_navBarInteractionMode, + WindowManagerPolicyConstants.NAV_BAR_MODE_3BUTTON); + + GlobalActionsDialog.ScreenshotAction screenshotAction = + mGlobalActionsDialog.makeScreenshotActionForTesting(); + assertThat(screenshotAction.shouldShow()).isFalse(); + } + private void verifyLogPosted(GlobalActionsDialog.GlobalActionsEvent event) { mTestableLooper.processAllMessages(); verify(mUiEventLogger, times(1)) diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/MediaDataCombineLatestTest.java b/packages/SystemUI/tests/src/com/android/systemui/media/MediaDataCombineLatestTest.java index 89538ac8bc9f..609b8474d134 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/media/MediaDataCombineLatestTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/media/MediaDataCombineLatestTest.java @@ -74,7 +74,7 @@ public class MediaDataCombineLatestTest extends SysuiTestCase { mMediaData = new MediaData(USER_ID, true, BG_COLOR, APP, null, ARTIST, TITLE, null, new ArrayList<>(), new ArrayList<>(), PACKAGE, null, null, null, true, null, true, - false, KEY, false); + false, KEY, false, false, false); mDeviceData = new MediaDeviceData(true, null, DEVICE_NAME); } diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/MediaPlayerDataTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/MediaPlayerDataTest.kt index da1ec9869d87..ef8d322ca2ec 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/media/MediaPlayerDataTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/media/MediaPlayerDataTest.kt @@ -25,7 +25,6 @@ import org.junit.Ignore import org.junit.Test import org.junit.runner.RunWith import org.mockito.Mockito.mock -import org.mockito.Mockito.`when` as whenever @SmallTest @RunWith(AndroidTestingRunner::class) @@ -34,6 +33,8 @@ public class MediaPlayerDataTest : SysuiTestCase() { companion object { val LOCAL = true val RESUMPTION = true + val PLAYING = true + val UNDETERMINED = null } @Before @@ -44,15 +45,13 @@ public class MediaPlayerDataTest : SysuiTestCase() { @Test fun addPlayingThenRemote() { val playerIsPlaying = mock(MediaControlPanel::class.java) - whenever(playerIsPlaying.isPlaying).thenReturn(true) - val dataIsPlaying = createMediaData("app1", LOCAL, !RESUMPTION) + val dataIsPlaying = createMediaData("app1", PLAYING, LOCAL, !RESUMPTION) val playerIsRemote = mock(MediaControlPanel::class.java) - whenever(playerIsRemote.isPlaying).thenReturn(false) - val dataIsRemote = createMediaData("app2", !LOCAL, !RESUMPTION) + val dataIsRemote = createMediaData("app2", PLAYING, !LOCAL, !RESUMPTION) - MediaPlayerData.addMediaPlayer("1", dataIsPlaying, playerIsPlaying) MediaPlayerData.addMediaPlayer("2", dataIsRemote, playerIsRemote) + MediaPlayerData.addMediaPlayer("1", dataIsPlaying, playerIsPlaying) val players = MediaPlayerData.players() assertThat(players).hasSize(2) @@ -63,18 +62,16 @@ public class MediaPlayerDataTest : SysuiTestCase() { @Ignore("Flaky") fun switchPlayersPlaying() { val playerIsPlaying1 = mock(MediaControlPanel::class.java) - whenever(playerIsPlaying1.isPlaying).thenReturn(true) - val dataIsPlaying1 = createMediaData("app1", LOCAL, !RESUMPTION) + var dataIsPlaying1 = createMediaData("app1", PLAYING, LOCAL, !RESUMPTION) val playerIsPlaying2 = mock(MediaControlPanel::class.java) - whenever(playerIsPlaying2.isPlaying).thenReturn(false) - val dataIsPlaying2 = createMediaData("app2", LOCAL, !RESUMPTION) + var dataIsPlaying2 = createMediaData("app2", !PLAYING, LOCAL, !RESUMPTION) MediaPlayerData.addMediaPlayer("1", dataIsPlaying1, playerIsPlaying1) MediaPlayerData.addMediaPlayer("2", dataIsPlaying2, playerIsPlaying2) - whenever(playerIsPlaying1.isPlaying).thenReturn(false) - whenever(playerIsPlaying2.isPlaying).thenReturn(true) + dataIsPlaying1 = createMediaData("app1", !PLAYING, LOCAL, !RESUMPTION) + dataIsPlaying2 = createMediaData("app2", PLAYING, LOCAL, !RESUMPTION) MediaPlayerData.addMediaPlayer("1", dataIsPlaying1, playerIsPlaying1) MediaPlayerData.addMediaPlayer("2", dataIsPlaying2, playerIsPlaying2) @@ -87,38 +84,43 @@ public class MediaPlayerDataTest : SysuiTestCase() { @Test fun fullOrderTest() { val playerIsPlaying = mock(MediaControlPanel::class.java) - whenever(playerIsPlaying.isPlaying).thenReturn(true) - val dataIsPlaying = createMediaData("app1", LOCAL, !RESUMPTION) + val dataIsPlaying = createMediaData("app1", PLAYING, LOCAL, !RESUMPTION) val playerIsPlayingAndRemote = mock(MediaControlPanel::class.java) - whenever(playerIsPlayingAndRemote.isPlaying).thenReturn(true) - val dataIsPlayingAndRemote = createMediaData("app2", !LOCAL, !RESUMPTION) + val dataIsPlayingAndRemote = createMediaData("app2", PLAYING, !LOCAL, !RESUMPTION) val playerIsStoppedAndLocal = mock(MediaControlPanel::class.java) - whenever(playerIsStoppedAndLocal.isPlaying).thenReturn(false) - val dataIsStoppedAndLocal = createMediaData("app3", LOCAL, !RESUMPTION) + val dataIsStoppedAndLocal = createMediaData("app3", !PLAYING, LOCAL, !RESUMPTION) val playerIsStoppedAndRemote = mock(MediaControlPanel::class.java) - whenever(playerIsStoppedAndLocal.isPlaying).thenReturn(false) - val dataIsStoppedAndRemote = createMediaData("app4", !LOCAL, !RESUMPTION) + val dataIsStoppedAndRemote = createMediaData("app4", !PLAYING, !LOCAL, !RESUMPTION) val playerCanResume = mock(MediaControlPanel::class.java) - whenever(playerCanResume.isPlaying).thenReturn(false) - val dataCanResume = createMediaData("app5", LOCAL, RESUMPTION) + val dataCanResume = createMediaData("app5", !PLAYING, LOCAL, RESUMPTION) + + val playerUndetermined = mock(MediaControlPanel::class.java) + val dataUndetermined = createMediaData("app6", UNDETERMINED, LOCAL, RESUMPTION) MediaPlayerData.addMediaPlayer("3", dataIsStoppedAndLocal, playerIsStoppedAndLocal) MediaPlayerData.addMediaPlayer("5", dataIsStoppedAndRemote, playerIsStoppedAndRemote) MediaPlayerData.addMediaPlayer("4", dataCanResume, playerCanResume) MediaPlayerData.addMediaPlayer("1", dataIsPlaying, playerIsPlaying) MediaPlayerData.addMediaPlayer("2", dataIsPlayingAndRemote, playerIsPlayingAndRemote) + MediaPlayerData.addMediaPlayer("6", dataUndetermined, playerUndetermined) val players = MediaPlayerData.players() - assertThat(players).hasSize(5) + assertThat(players).hasSize(6) assertThat(players).containsExactly(playerIsPlaying, playerIsPlayingAndRemote, - playerIsStoppedAndLocal, playerCanResume, playerIsStoppedAndRemote).inOrder() + playerIsStoppedAndLocal, playerCanResume, playerIsStoppedAndRemote, + playerUndetermined).inOrder() } - private fun createMediaData(app: String, isLocalSession: Boolean, resumption: Boolean) = + private fun createMediaData( + app: String, + isPlaying: Boolean?, + isLocalSession: Boolean, + resumption: Boolean + ) = MediaData(0, false, 0, app, null, null, null, null, emptyList(), emptyList<Int>(), "", - null, null, null, true, null, isLocalSession, resumption, null, false) + null, null, null, true, null, isLocalSession, resumption, null, false, isPlaying) } diff --git a/packages/SystemUI/tests/src/com/android/systemui/onehanded/OneHandedGestureHandlerTest.java b/packages/SystemUI/tests/src/com/android/systemui/onehanded/OneHandedGestureHandlerTest.java deleted file mode 100644 index 41af53b1c522..000000000000 --- a/packages/SystemUI/tests/src/com/android/systemui/onehanded/OneHandedGestureHandlerTest.java +++ /dev/null @@ -1,121 +0,0 @@ -/* - * Copyright (C) 2020 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT 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.onehanded; - -import static com.google.common.truth.Truth.assertThat; - -import static org.mockito.Mockito.atLeast; -import static org.mockito.Mockito.atLeastOnce; -import static org.mockito.Mockito.verify; - -import android.testing.AndroidTestingRunner; -import android.testing.TestableLooper; - -import androidx.test.filters.SmallTest; - -import com.android.wm.shell.common.DisplayController; - -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.mockito.Mock; -import org.mockito.Mockito; -import org.mockito.MockitoAnnotations; - -@SmallTest -@RunWith(AndroidTestingRunner.class) -@TestableLooper.RunWithLooper -public class OneHandedGestureHandlerTest extends OneHandedTestCase { - OneHandedTouchHandler mTouchHandler; - OneHandedTutorialHandler mTutorialHandler; - OneHandedGestureHandler mGestureHandler; - OneHandedController mOneHandedController; - @Mock - DisplayController mMockDisplayController; - @Mock - OneHandedDisplayAreaOrganizer mMockDisplayAreaOrganizer; - @Before - public void setUp() throws Exception { - MockitoAnnotations.initMocks(this); - mTouchHandler = new OneHandedTouchHandler(); - mTutorialHandler = new OneHandedTutorialHandler(mContext); - mGestureHandler = Mockito.spy( - new OneHandedGestureHandler(mContext, mMockDisplayController)); - mOneHandedController = new OneHandedController( - getContext(), - mMockDisplayController, - mMockDisplayAreaOrganizer, - mTouchHandler, - mTutorialHandler, - mGestureHandler); - mOneHandedController.setThreeButtonModeEnabled(true); - } - - @Test - public void testOneHandedManager_registerForDisplayAreaOrganizer() { - verify(mMockDisplayAreaOrganizer, atLeastOnce()) - .registerTransitionCallback(mGestureHandler); - } - - @Test - public void testOneHandedManager_setGestureEventListener() { - OneHandedGestureHandler.OneHandedGestureEventCallback callback = - new OneHandedGestureHandler.OneHandedGestureEventCallback() { - @Override - public void onStart() {} - - @Override - public void onStop() {} - }; - mOneHandedController.registerGestureCallback(callback); - - verify(mGestureHandler).setGestureEventListener(callback); - assertThat(mGestureHandler.mGestureEventCallback).isEqualTo(callback); - } - - @Test - public void testReceiveNewConfig_whenSetOneHandedEnabled() { - // 1st called at init - verify(mGestureHandler, atLeastOnce()).onOneHandedEnabled(true); - mOneHandedController.setOneHandedEnabled(true); - // 2nd called by setOneHandedEnabled() - verify(mGestureHandler, atLeast(2)).onOneHandedEnabled(true); - } - - @Test - public void testOneHandedDisabled_shouldDisposeInputChannel() { - mOneHandedController.setOneHandedEnabled(false); - mOneHandedController.setSwipeToNotificationEnabled(false); - - assertThat(mGestureHandler.mInputMonitor).isNull(); - assertThat(mGestureHandler.mInputEventReceiver).isNull(); - } - - @Test - public void testChangeNavBarToNon3Button_shouldDisposeInputChannel() { - // 1st called at init - verify(mGestureHandler, atLeastOnce()).onOneHandedEnabled(true); - mOneHandedController.setOneHandedEnabled(true); - // 2nd called by setOneHandedEnabled() - verify(mGestureHandler, atLeast(2)).onOneHandedEnabled(true); - - mGestureHandler.onThreeButtonModeEnabled(false); - - assertThat(mGestureHandler.mInputMonitor).isNull(); - assertThat(mGestureHandler.mInputEventReceiver).isNull(); - } -} diff --git a/packages/SystemUI/tests/src/com/android/systemui/onehanded/OneHandedTouchHandlerTest.java b/packages/SystemUI/tests/src/com/android/systemui/onehanded/OneHandedTouchHandlerTest.java deleted file mode 100644 index 1e408313a36e..000000000000 --- a/packages/SystemUI/tests/src/com/android/systemui/onehanded/OneHandedTouchHandlerTest.java +++ /dev/null @@ -1,100 +0,0 @@ -/* - * Copyright (C) 2020 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT 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.onehanded; - -import static com.google.common.truth.Truth.assertThat; - -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.Mockito.atLeast; -import static org.mockito.Mockito.atLeastOnce; -import static org.mockito.Mockito.verify; - -import android.testing.AndroidTestingRunner; -import android.testing.TestableLooper; - -import androidx.test.filters.SmallTest; - -import com.android.wm.shell.common.DisplayController; - -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.mockito.Mock; -import org.mockito.Mockito; -import org.mockito.MockitoAnnotations; - -@SmallTest -@RunWith(AndroidTestingRunner.class) -@TestableLooper.RunWithLooper -public class OneHandedTouchHandlerTest extends OneHandedTestCase { - OneHandedTouchHandler mTouchHandler; - OneHandedTutorialHandler mTutorialHandler; - OneHandedGestureHandler mGestureHandler; - OneHandedController mOneHandedController; - @Mock - DisplayController mMockDisplayController; - @Mock - OneHandedDisplayAreaOrganizer mMockDisplayAreaOrganizer; - - @Before - public void setUp() { - MockitoAnnotations.initMocks(this); - mTouchHandler = Mockito.spy(new OneHandedTouchHandler()); - mGestureHandler = new OneHandedGestureHandler(mContext, mMockDisplayController); - mOneHandedController = new OneHandedController( - getContext(), - mMockDisplayController, - mMockDisplayAreaOrganizer, - mTouchHandler, - mTutorialHandler, - mGestureHandler); - } - - @Test - public void testOneHandedManager_registerForDisplayAreaOrganizer() { - verify(mMockDisplayAreaOrganizer).registerTransitionCallback(mTouchHandler); - } - - @Test - public void testOneHandedManager_registerTouchEventListener() { - verify(mTouchHandler).registerTouchEventListener(any()); - assertThat(mTouchHandler.mTouchEventCallback).isNotNull(); - } - - @Test - public void testOneHandedDisabled_shouldDisposeInputChannel() { - mOneHandedController.setOneHandedEnabled(false); - assertThat(mTouchHandler.mInputMonitor).isNull(); - assertThat(mTouchHandler.mInputEventReceiver).isNull(); - } - - @Test - public void testOneHandedEnabled_monitorInputChannel() { - mOneHandedController.setOneHandedEnabled(true); - assertThat(mTouchHandler.mInputMonitor).isNotNull(); - assertThat(mTouchHandler.mInputEventReceiver).isNotNull(); - } - - @Test - public void testReceiveNewConfig_whenSetOneHandedEnabled() { - // Called at init - verify(mTouchHandler, atLeastOnce()).onOneHandedEnabled(true); - mOneHandedController.setOneHandedEnabled(true); - // Called by setOneHandedEnabled() - verify(mTouchHandler, atLeast(2)).onOneHandedEnabled(true); - } -} diff --git a/packages/SystemUI/tests/src/com/android/systemui/privacy/PrivacyItemControllerFlagsTest.kt b/packages/SystemUI/tests/src/com/android/systemui/privacy/PrivacyItemControllerFlagsTest.kt index 4ba29e6e02a6..25fb7d300b8f 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/privacy/PrivacyItemControllerFlagsTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/privacy/PrivacyItemControllerFlagsTest.kt @@ -96,22 +96,24 @@ class PrivacyItemControllerFlagsTest : SysuiTestCase() { } @Test - fun testNotListeningByDefault() { + fun testNotListeningAllByDefault() { assertFalse(privacyItemController.allIndicatorsAvailable) - assertFalse(privacyItemController.micCameraAvailable) + } - verify(appOpsController, never()).addCallback(any(), any()) + @Test + fun testMicCameraListeningByDefault() { + assertTrue(privacyItemController.micCameraAvailable) } @Test fun testMicCameraChanged() { - changeMicCamera(true) + changeMicCamera(false) // default is true executor.runAllReady() - verify(callback).onFlagMicCameraChanged(true) + verify(callback).onFlagMicCameraChanged(false) verify(callback, never()).onFlagAllChanged(anyBoolean()) - assertTrue(privacyItemController.micCameraAvailable) + assertFalse(privacyItemController.micCameraAvailable) assertFalse(privacyItemController.allIndicatorsAvailable) } @@ -124,20 +126,19 @@ class PrivacyItemControllerFlagsTest : SysuiTestCase() { verify(callback, never()).onFlagMicCameraChanged(anyBoolean()) assertTrue(privacyItemController.allIndicatorsAvailable) - assertFalse(privacyItemController.micCameraAvailable) } @Test fun testBothChanged() { changeAll(true) - changeMicCamera(true) + changeMicCamera(false) executor.runAllReady() verify(callback, atLeastOnce()).onFlagAllChanged(true) - verify(callback, atLeastOnce()).onFlagMicCameraChanged(true) + verify(callback, atLeastOnce()).onFlagMicCameraChanged(false) assertTrue(privacyItemController.allIndicatorsAvailable) - assertTrue(privacyItemController.micCameraAvailable) + assertFalse(privacyItemController.micCameraAvailable) } @Test @@ -157,18 +158,11 @@ class PrivacyItemControllerFlagsTest : SysuiTestCase() { } @Test - fun testAll_listening() { - changeAll(true) - executor.runAllReady() - - verify(appOpsController).addCallback(eq(PrivacyItemController.OPS), any()) - } - - @Test fun testAllFalse_notListening() { changeAll(true) executor.runAllReady() changeAll(false) + changeMicCamera(false) executor.runAllReady() verify(appOpsController).removeCallback(any(), any()) @@ -176,8 +170,8 @@ class PrivacyItemControllerFlagsTest : SysuiTestCase() { @Test fun testSomeListening_stillListening() { + // Mic and camera are true by default changeAll(true) - changeMicCamera(true) executor.runAllReady() changeAll(false) executor.runAllReady() @@ -186,7 +180,8 @@ class PrivacyItemControllerFlagsTest : SysuiTestCase() { } @Test - fun testAllDeleted_stopListening() { + fun testAllDeleted_micCameraFalse_stopListening() { + changeMicCamera(false) changeAll(true) executor.runAllReady() changeAll(null) @@ -196,13 +191,13 @@ class PrivacyItemControllerFlagsTest : SysuiTestCase() { } @Test - fun testMicDeleted_stopListening() { + fun testMicDeleted_stillListening() { changeMicCamera(true) executor.runAllReady() changeMicCamera(null) executor.runAllReady() - verify(appOpsController).removeCallback(any(), any()) + verify(appOpsController, never()).removeCallback(any(), any()) } private fun changeMicCamera(value: Boolean?) = changeProperty(MIC_CAMERA, value) diff --git a/packages/SystemUI/tests/src/com/android/systemui/privacy/PrivacyItemControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/privacy/PrivacyItemControllerTest.kt index fb42baaa0cb5..f152a74da0d5 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/privacy/PrivacyItemControllerTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/privacy/PrivacyItemControllerTest.kt @@ -273,6 +273,7 @@ class PrivacyItemControllerTest : SysuiTestCase() { @Test fun testNotListeningWhenIndicatorsDisabled() { changeAll(false) + changeMicCamera(false) privacyItemController.addCallback(callback) executor.runAllReady() verify(appOpsController, never()).addCallback(eq(PrivacyItemController.OPS), diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotifCollectionTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotifCollectionTest.java index 359faba48f08..ce0f1220fc88 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotifCollectionTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotifCollectionTest.java @@ -442,7 +442,7 @@ public class NotifCollectionTest extends SysuiTestCase { } @Test - public void testDismissingLifetimeExtendedSummaryDoesNotDismissChildren() { + public void testRetractingLifetimeExtendedSummaryDoesNotDismissChildren() { // GIVEN A notif group with one summary and two children mCollection.addNotificationLifetimeExtender(mExtender1); CollectionEvent notif1 = postNotif( @@ -460,15 +460,16 @@ public class NotifCollectionTest extends SysuiTestCase { NotificationEntry entry2 = mCollectionListener.getEntry(notif2.key); NotificationEntry entry3 = mCollectionListener.getEntry(notif3.key); - // GIVEN that the summary and one child are retracted, but both are lifetime-extended + // GIVEN that the summary and one child are retracted by the app, but both are + // lifetime-extended mExtender1.shouldExtendLifetime = true; - mNoMan.retractNotif(notif1.sbn, REASON_CANCEL); - mNoMan.retractNotif(notif2.sbn, REASON_CANCEL); + mNoMan.retractNotif(notif1.sbn, REASON_APP_CANCEL); + mNoMan.retractNotif(notif2.sbn, REASON_APP_CANCEL); assertEquals( new ArraySet<>(List.of(entry1, entry2, entry3)), new ArraySet<>(mCollection.getAllNotifs())); - // WHEN the summary is dismissed by the user + // WHEN the summary is retracted by the app mCollection.dismissNotification(entry1, defaultStats(entry1)); // THEN the summary is removed, but both children stick around @@ -480,6 +481,28 @@ public class NotifCollectionTest extends SysuiTestCase { } @Test + public void testNMSReportsUserDismissalAlwaysRemovesNotif() throws RemoteException { + // GIVEN notifications are lifetime extended + mExtender1.shouldExtendLifetime = true; + CollectionEvent notif = postNotif(buildNotif(TEST_PACKAGE, 1, "myTag")); + CollectionEvent notif2 = postNotif(buildNotif(TEST_PACKAGE, 2, "myTag")); + NotificationEntry entry = mCollectionListener.getEntry(notif.key); + NotificationEntry entry2 = mCollectionListener.getEntry(notif2.key); + assertEquals( + new ArraySet<>(List.of(entry, entry2)), + new ArraySet<>(mCollection.getAllNotifs())); + + // WHEN the notifications are reported to be dismissed by the user by NMS + mNoMan.retractNotif(notif.sbn, REASON_CANCEL); + mNoMan.retractNotif(notif2.sbn, REASON_CLICK); + + // THEN the notifications are removed b/c they were dismissed by the user + assertEquals( + new ArraySet<>(List.of()), + new ArraySet<>(mCollection.getAllNotifs())); + } + + @Test public void testDismissNotificationCallsDismissInterceptors() throws RemoteException { // GIVEN a collection with notifications with multiple dismiss interceptors mInterceptor1.shouldInterceptDismissal = true; @@ -833,13 +856,13 @@ public class NotifCollectionTest extends SysuiTestCase { NotifEvent notif2 = mNoMan.postNotif(buildNotif(TEST_PACKAGE2, 88)); NotificationEntry entry2 = mCollectionListener.getEntry(notif2.key); - // WHEN a notification is removed - mNoMan.retractNotif(notif2.sbn, REASON_CLICK); + // WHEN a notification is removed by the app + mNoMan.retractNotif(notif2.sbn, REASON_APP_CANCEL); // THEN each extender is asked whether to extend, even if earlier ones return true - verify(mExtender1).shouldExtendLifetime(entry2, REASON_CLICK); - verify(mExtender2).shouldExtendLifetime(entry2, REASON_CLICK); - verify(mExtender3).shouldExtendLifetime(entry2, REASON_CLICK); + verify(mExtender1).shouldExtendLifetime(entry2, REASON_APP_CANCEL); + verify(mExtender2).shouldExtendLifetime(entry2, REASON_APP_CANCEL); + verify(mExtender3).shouldExtendLifetime(entry2, REASON_APP_CANCEL); // THEN the entry is not removed assertTrue(mCollection.getAllNotifs().contains(entry2)); diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/ConversationCoordinatorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/ConversationCoordinatorTest.kt index 09c9bcd967bd..711f0bab5068 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/ConversationCoordinatorTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/ConversationCoordinatorTest.kt @@ -26,6 +26,7 @@ import com.android.systemui.statusbar.notification.collection.NotificationEntry import com.android.systemui.statusbar.notification.collection.NotificationEntryBuilder import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifPromoter import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifSectioner +import com.android.systemui.statusbar.notification.collection.render.NodeController import com.android.systemui.statusbar.notification.people.PeopleNotificationIdentifier import com.android.systemui.statusbar.notification.people.PeopleNotificationIdentifier.Companion.TYPE_PERSON import org.junit.Assert.assertFalse @@ -47,12 +48,10 @@ class ConversationCoordinatorTest : SysuiTestCase() { private lateinit var promoter: NotifPromoter private lateinit var peopleSectioner: NotifSectioner - @Mock - private lateinit var pipeline: NotifPipeline - @Mock - private lateinit var peopleNotificationIdentifier: PeopleNotificationIdentifier - @Mock - private lateinit var channel: NotificationChannel + @Mock private lateinit var pipeline: NotifPipeline + @Mock private lateinit var peopleNotificationIdentifier: PeopleNotificationIdentifier + @Mock private lateinit var channel: NotificationChannel + @Mock private lateinit var headerController: NodeController private lateinit var entry: NotificationEntry private lateinit var coordinator: ConversationCoordinator @@ -60,7 +59,7 @@ class ConversationCoordinatorTest : SysuiTestCase() { @Before fun setUp() { MockitoAnnotations.initMocks(this) - coordinator = ConversationCoordinator(peopleNotificationIdentifier) + coordinator = ConversationCoordinator(peopleNotificationIdentifier, headerController) whenever(channel.isImportantConversation).thenReturn(true) coordinator.attach(pipeline) diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/HeadsUpCoordinatorTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/HeadsUpCoordinatorTest.java index fa992a5d5dbb..7e771cecaf66 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/HeadsUpCoordinatorTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/HeadsUpCoordinatorTest.java @@ -39,6 +39,7 @@ import com.android.systemui.statusbar.notification.collection.listbuilder.plugga import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifSectioner; import com.android.systemui.statusbar.notification.collection.notifcollection.NotifCollectionListener; import com.android.systemui.statusbar.notification.collection.notifcollection.NotifLifetimeExtender; +import com.android.systemui.statusbar.notification.collection.render.NodeController; import com.android.systemui.statusbar.notification.interruption.HeadsUpViewBinder; import com.android.systemui.statusbar.notification.interruption.NotificationInterruptStateProvider; import com.android.systemui.statusbar.notification.row.NotifBindPipeline.BindCallback; @@ -73,6 +74,7 @@ public class HeadsUpCoordinatorTest extends SysuiTestCase { @Mock private NotificationRemoteInputManager mRemoteInputManager; @Mock private RemoteInputController mRemoteInputController; @Mock private NotifLifetimeExtender.OnEndLifetimeExtensionCallback mEndLifetimeExtension; + @Mock private NodeController mHeaderController; private NotificationEntry mEntry; @@ -85,8 +87,8 @@ public class HeadsUpCoordinatorTest extends SysuiTestCase { mHeadsUpManager, mHeadsUpViewBinder, mNotificationInterruptStateProvider, - mRemoteInputManager - ); + mRemoteInputManager, + mHeaderController); mCoordinator.attach(mNotifPipeline); diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/RankingCoordinatorTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/RankingCoordinatorTest.java index 3a7d28ab56ec..1031d6befc36 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/RankingCoordinatorTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/RankingCoordinatorTest.java @@ -38,6 +38,7 @@ import com.android.systemui.statusbar.notification.collection.NotificationEntryB import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifFilter; import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifSectioner; import com.android.systemui.statusbar.notification.collection.provider.HighPriorityProvider; +import com.android.systemui.statusbar.notification.collection.render.NodeController; import org.junit.Before; import org.junit.Test; @@ -54,6 +55,8 @@ public class RankingCoordinatorTest extends SysuiTestCase { @Mock private StatusBarStateController mStatusBarStateController; @Mock private HighPriorityProvider mHighPriorityProvider; @Mock private NotifPipeline mNotifPipeline; + @Mock private NodeController mAlertingHeaderController; + @Mock private NodeController mSilentHeaderController; @Captor private ArgumentCaptor<NotifFilter> mNotifFilterCaptor; @@ -67,8 +70,9 @@ public class RankingCoordinatorTest extends SysuiTestCase { @Before public void setup() { MockitoAnnotations.initMocks(this); - RankingCoordinator rankingCoordinator = - new RankingCoordinator(mStatusBarStateController, mHighPriorityProvider); + RankingCoordinator rankingCoordinator = new RankingCoordinator( + mStatusBarStateController, mHighPriorityProvider, mAlertingHeaderController, + mSilentHeaderController); mEntry = new NotificationEntryBuilder().build(); rankingCoordinator.attach(mNotifPipeline); diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationBlockingHelperManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationBlockingHelperManagerTest.java index 5aeb43fbd959..edb8776bcb02 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationBlockingHelperManagerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationBlockingHelperManagerTest.java @@ -49,6 +49,7 @@ import com.android.systemui.SysuiTestCase; import com.android.systemui.bubbles.BubbleController; import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin; import com.android.systemui.statusbar.notification.NotificationEntryManager; +import com.android.systemui.statusbar.notification.collection.render.GroupMembershipManager; import org.junit.Before; import org.junit.Test; @@ -71,6 +72,7 @@ public class NotificationBlockingHelperManagerTest extends SysuiTestCase { @Mock private NotificationEntryManager mEntryManager; @Mock private NotificationMenuRow mMenuRow; @Mock private NotificationMenuRowPlugin.MenuItem mMenuItem; + @Mock private GroupMembershipManager mGroupMembershipManager; @Before public void setUp() { @@ -89,7 +91,8 @@ public class NotificationBlockingHelperManagerTest extends SysuiTestCase { mHelper = new NotificationTestHelper(mContext, mDependency, TestableLooper.get(this)); mBlockingHelperManager = new NotificationBlockingHelperManager( - mContext, mGutsManager, mEntryManager, mock(MetricsLogger.class)); + mContext, mGutsManager, mEntryManager, mock(MetricsLogger.class), + mGroupMembershipManager); // By default, have the shade visible/expanded. mBlockingHelperManager.setNotificationShadeExpanded(1f); } @@ -185,6 +188,7 @@ public class NotificationBlockingHelperManagerTest extends SysuiTestCase { .build(); assertFalse(childRow.getIsNonblockable()); + when(mGroupMembershipManager.isOnlyChildInGroup(childRow.getEntry())).thenReturn(true); assertTrue(mBlockingHelperManager.perhapsShowBlockingHelper(childRow, mMenuRow)); verify(mGutsManager).openGuts(childRow, 0, 0, mMenuItem); diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationSectionsManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationSectionsManagerTest.java index 7ca24789a29b..8cd71031a8f8 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationSectionsManagerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationSectionsManagerTest.java @@ -53,6 +53,7 @@ import com.android.systemui.plugins.statusbar.StatusBarStateController; import com.android.systemui.statusbar.StatusBarState; import com.android.systemui.statusbar.notification.NotificationSectionsFeatureManager; import com.android.systemui.statusbar.notification.collection.NotificationEntry; +import com.android.systemui.statusbar.notification.collection.render.SectionHeaderController; import com.android.systemui.statusbar.notification.people.PeopleHubViewAdapter; import com.android.systemui.statusbar.notification.row.ActivatableNotificationViewController; import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow; @@ -63,6 +64,7 @@ import org.junit.Before; import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; +import org.mockito.Answers; import org.mockito.Mock; import org.mockito.junit.MockitoJUnit; import org.mockito.junit.MockitoRule; @@ -87,6 +89,10 @@ public class NotificationSectionsManagerTest extends SysuiTestCase { @Mock private NotificationRowComponent mNotificationRowComponent; @Mock private ActivatableNotificationViewController mActivatableNotificationViewController; @Mock private NotificationSectionsLogger mLogger; + @Mock private SectionHeaderController mIncomingHeaderController; + @Mock private SectionHeaderController mPeopleHeaderController; + @Mock private SectionHeaderController mAlertingHeaderController; + @Mock private SectionHeaderController mSilentHeaderController; private NotificationSectionsManager mSectionsManager; @@ -109,15 +115,21 @@ public class NotificationSectionsManagerTest extends SysuiTestCase { }); when(mNotificationRowComponent.getActivatableNotificationViewController()) .thenReturn(mActivatableNotificationViewController); + when(mIncomingHeaderController.getHeaderView()).thenReturn(mock(SectionHeaderView.class)); + when(mPeopleHeaderController.getHeaderView()).thenReturn(mock(SectionHeaderView.class)); + when(mAlertingHeaderController.getHeaderView()).thenReturn(mock(SectionHeaderView.class)); + when(mSilentHeaderController.getHeaderView()).thenReturn(mock(SectionHeaderView.class)); mSectionsManager = new NotificationSectionsManager( - mActivityStarterDelegate, mStatusBarStateController, mConfigurationController, - mPeopleHubAdapter, mKeyguardMediaController, mSectionsFeatureManager, - mLogger + mLogger, + mIncomingHeaderController, + mPeopleHeaderController, + mAlertingHeaderController, + mSilentHeaderController ); // Required in order for the header inflation to work properly when(mNssl.generateLayoutParams(any(AttributeSet.class))) @@ -241,8 +253,9 @@ public class NotificationSectionsManagerTest extends SysuiTestCase { mSectionsManager.updateSectionBoundaries(); clearInvocations(mNssl); + SectionHeaderView silentHeaderView = mSectionsManager.getSilentHeaderView(); ViewGroup transientParent = mock(ViewGroup.class); - mSectionsManager.getSilentHeaderView().setTransientContainer(transientParent); + when(silentHeaderView.getTransientContainer()).thenReturn(transientParent); // WHEN the LO section reappears setStackState( @@ -252,8 +265,8 @@ public class NotificationSectionsManagerTest extends SysuiTestCase { // THEN the header is first removed from the transient parent before being added to the // NSSL. - verify(transientParent).removeTransientView(mSectionsManager.getSilentHeaderView()); - verify(mNssl).addView(mSectionsManager.getSilentHeaderView(), 1); + verify(transientParent).removeTransientView(silentHeaderView); + verify(mNssl).addView(silentHeaderView, 1); } @Test @@ -358,23 +371,6 @@ public class NotificationSectionsManagerTest extends SysuiTestCase { } @Test - public void testPeopleFiltering_keepPeopleHeaderWhenSectionEmpty() { - mSectionsManager.setPeopleHubVisible(true); - enablePeopleFiltering(); - - setStackState( - PEOPLE_HEADER, - ALERTING_HEADER, - ALERTING, - GENTLE_HEADER, - GENTLE); - mSectionsManager.updateSectionBoundaries(); - - verify(mNssl, never()).removeView(mSectionsManager.getPeopleHeaderView()); - verify(mNssl).changeViewPosition(mSectionsManager.getPeopleHeaderView(), 0); - } - - @Test public void testPeopleFiltering_AlertingHunWhilePeopleVisible() { enablePeopleFiltering(); 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 f48e6ea7941e..de59ac319bd9 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 @@ -451,8 +451,8 @@ public class NotificationStackScrollLayoutTest extends SysuiTestCase { @Test public void testAddNotificationUpdatesSpeedBumpIndex() { - // initial state == -1 - assertEquals(-1, mStackScroller.getSpeedBumpIndex()); + // initial state calculated == 0 + assertEquals(0, mStackScroller.getSpeedBumpIndex()); // add notification that's before the speed bump ExpandableNotificationRow row = mock(ExpandableNotificationRow.class); @@ -467,8 +467,8 @@ public class NotificationStackScrollLayoutTest extends SysuiTestCase { @Test public void testAddAmbientNotificationNoSpeedBumpUpdate() { - // initial state == -1 - assertEquals(-1, mStackScroller.getSpeedBumpIndex()); + // initial state calculated == 0 + assertEquals(0, mStackScroller.getSpeedBumpIndex()); // add notification that's after the speed bump ExpandableNotificationRow row = mock(ExpandableNotificationRow.class); @@ -483,8 +483,8 @@ public class NotificationStackScrollLayoutTest extends SysuiTestCase { @Test public void testRemoveNotificationUpdatesSpeedBump() { - // initial state == -1 - assertEquals(-1, mStackScroller.getSpeedBumpIndex()); + // initial state calculated == 0 + assertEquals(0, mStackScroller.getSpeedBumpIndex()); // add 3 notification that are after the speed bump ExpandableNotificationRow row = mock(ExpandableNotificationRow.class); diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollerControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollerControllerTest.java index 32c682878c28..ef11f81971b3 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollerControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollerControllerTest.java @@ -49,6 +49,7 @@ import com.android.systemui.statusbar.NotificationLockscreenUserManager.UserChan import com.android.systemui.statusbar.SysuiStatusBarStateController; import com.android.systemui.statusbar.notification.DynamicPrivacyController; import com.android.systemui.statusbar.notification.collection.legacy.NotificationGroupManagerLegacy; +import com.android.systemui.statusbar.notification.collection.render.SectionHeaderController; import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow; import com.android.systemui.statusbar.notification.row.NotificationGutsManager; import com.android.systemui.statusbar.phone.HeadsUpManagerPhone; @@ -76,50 +77,30 @@ import org.mockito.MockitoAnnotations; @RunWith(AndroidTestingRunner.class) public class NotificationStackScrollerControllerTest extends SysuiTestCase { - @Mock - private NotificationGutsManager mNotificationGutsManager; - @Mock - private HeadsUpManagerPhone mHeadsUpManager; - @Mock - private NotificationRoundnessManager mNotificationRoundnessManager; - @Mock - private TunerService mTunerService; - @Mock - private DynamicPrivacyController mDynamicPrivacyController; - @Mock - private ConfigurationController mConfigurationController; - @Mock - private NotificationStackScrollLayout mNotificationStackScrollLayout; - @Mock - private ZenModeController mZenModeController; - @Mock - private KeyguardMediaController mKeyguardMediaController; - @Mock - private SysuiStatusBarStateController mSysuiStatusBarStateController; - @Mock - private KeyguardBypassController mKeyguardBypassController; - @Mock - private SysuiColorExtractor mColorExtractor; - @Mock - private NotificationLockscreenUserManager mNotificationLockscreenUserManager; - @Mock - private MetricsLogger mMetricsLogger; - @Mock - private FalsingManager mFalsingManager; - @Mock - private NotificationSectionsManager mNotificationSectionsManager; - @Mock - private Resources mResources; + @Mock private NotificationGutsManager mNotificationGutsManager; + @Mock private HeadsUpManagerPhone mHeadsUpManager; + @Mock private NotificationRoundnessManager mNotificationRoundnessManager; + @Mock private TunerService mTunerService; + @Mock private DynamicPrivacyController mDynamicPrivacyController; + @Mock private ConfigurationController mConfigurationController; + @Mock private NotificationStackScrollLayout mNotificationStackScrollLayout; + @Mock private ZenModeController mZenModeController; + @Mock private KeyguardMediaController mKeyguardMediaController; + @Mock private SysuiStatusBarStateController mSysuiStatusBarStateController; + @Mock private KeyguardBypassController mKeyguardBypassController; + @Mock private SysuiColorExtractor mColorExtractor; + @Mock private NotificationLockscreenUserManager mNotificationLockscreenUserManager; + @Mock private MetricsLogger mMetricsLogger; + @Mock private FalsingManager mFalsingManager; + @Mock private NotificationSectionsManager mNotificationSectionsManager; + @Mock private Resources mResources; @Mock(answer = Answers.RETURNS_SELF) private NotificationSwipeHelper.Builder mNotificationSwipeHelperBuilder; - @Mock - private NotificationSwipeHelper mNotificationSwipeHelper; - @Mock - private StatusBar mStatusBar; - @Mock - private ScrimController mScrimController; - @Mock - private NotificationGroupManagerLegacy mLegacyGroupManager; + @Mock private NotificationSwipeHelper mNotificationSwipeHelper; + @Mock private StatusBar mStatusBar; + @Mock private ScrimController mScrimController; + @Mock private NotificationGroupManagerLegacy mLegacyGroupManager; + @Mock private SectionHeaderController mSilentHeaderController; @Captor ArgumentCaptor<StatusBarStateController.StateListener> mStateListenerArgumentCaptor; @@ -154,7 +135,8 @@ public class NotificationStackScrollerControllerTest extends SysuiTestCase { mStatusBar, mScrimController, mLegacyGroupManager, - mLegacyGroupManager + mLegacyGroupManager, + mSilentHeaderController ); when(mNotificationStackScrollLayout.isAttachedToWindow()).thenReturn(true); diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardBouncerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardBouncerTest.java index 0a041e4a4dc5..1b05ad7f8b5b 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardBouncerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardBouncerTest.java @@ -38,16 +38,16 @@ import android.testing.AndroidTestingRunner; import android.testing.TestableLooper; import android.view.View; import android.view.ViewGroup; -import android.view.ViewTreeObserver; import android.widget.FrameLayout; import androidx.test.filters.SmallTest; -import com.android.internal.widget.LockPatternUtils; -import com.android.keyguard.KeyguardHostView; +import com.android.keyguard.KeyguardHostViewController; +import com.android.keyguard.KeyguardRootViewController; import com.android.keyguard.KeyguardSecurityModel; import com.android.keyguard.KeyguardUpdateMonitor; import com.android.keyguard.ViewMediatorCallback; +import com.android.keyguard.dagger.KeyguardBouncerComponent; import com.android.systemui.DejankUtils; import com.android.systemui.SysuiTestCase; import com.android.systemui.keyguard.DismissCallbackRegistry; @@ -76,13 +76,9 @@ public class KeyguardBouncerTest extends SysuiTestCase { @Mock private ViewMediatorCallback mViewMediatorCallback; @Mock - private LockPatternUtils mLockPatternUtils; - @Mock private DismissCallbackRegistry mDismissCallbackRegistry; @Mock - private KeyguardHostView mKeyguardHostView; - @Mock - private ViewTreeObserver mViewTreeObserver; + private KeyguardHostViewController mKeyguardHostViewController; @Mock private KeyguardBouncer.BouncerExpansionCallback mExpansionCallback; @Mock @@ -96,7 +92,13 @@ public class KeyguardBouncerTest extends SysuiTestCase { @Mock private KeyguardSecurityModel mKeyguardSecurityModel; @Mock + private KeyguardRootViewController mRootViewController; + @Mock private ViewGroup mRootView; + @Mock + private KeyguardBouncerComponent.Factory mKeyguardBouncerComponentFactory; + @Mock + private KeyguardBouncerComponent mKeyguardBouncerComponent; @Rule public MockitoRule mRule = MockitoJUnit.rule(); private Integer mRootVisibility = View.INVISIBLE; @@ -106,7 +108,6 @@ public class KeyguardBouncerTest extends SysuiTestCase { public void setup() { allowTestableLooperAsMainThread(); mDependency.injectTestDependency(KeyguardUpdateMonitor.class, mKeyguardUpdateMonitor); - mDependency.injectTestDependency(KeyguardSecurityModel.class, mKeyguardSecurityModel); mDependency.injectMockDependency(KeyguardStateController.class); when(mRootView.getVisibility()).thenAnswer((Answer<Integer>) invocation -> mRootVisibility); doAnswer(invocation -> { @@ -116,19 +117,22 @@ public class KeyguardBouncerTest extends SysuiTestCase { when(mKeyguardSecurityModel.getSecurityMode(anyInt())) .thenReturn(KeyguardSecurityModel.SecurityMode.None); DejankUtils.setImmediate(true); + when(mKeyguardBouncerComponentFactory.create()).thenReturn(mKeyguardBouncerComponent); + when(mKeyguardBouncerComponent.getKeyguardHostViewController()) + .thenReturn(mKeyguardHostViewController); + when(mKeyguardBouncerComponent.getKeyguardRootViewController()) + .thenReturn(mRootViewController); + + when(mRootViewController.getView()).thenReturn(mRootView); + when(mRootView.getResources()).thenReturn(mContext.getResources()); + final ViewGroup container = new FrameLayout(getContext()); - when(mKeyguardHostView.getViewTreeObserver()).thenReturn(mViewTreeObserver); - when(mKeyguardHostView.getHeight()).thenReturn(500); - mBouncer = new KeyguardBouncer(getContext(), mViewMediatorCallback, - mLockPatternUtils, container, mDismissCallbackRegistry, mFalsingManager, - mExpansionCallback, mKeyguardStateController, mKeyguardUpdateMonitor, - mKeyguardBypassController, mHandler) { - @Override - protected void inflateView() { - mKeyguardView = mKeyguardHostView; - mRoot = mRootView; - } - }; + mBouncer = new KeyguardBouncer.Factory(getContext(), mViewMediatorCallback, + mDismissCallbackRegistry, mFalsingManager, + mKeyguardStateController, mKeyguardUpdateMonitor, + mKeyguardBypassController, mHandler, mKeyguardSecurityModel, + mKeyguardBouncerComponentFactory) + .create(container, mExpansionCallback); } @Test @@ -154,12 +158,10 @@ public class KeyguardBouncerTest extends SysuiTestCase { mBouncer.ensureView(); mBouncer.setExpansion(1); - reset(mKeyguardHostView); - when(mKeyguardHostView.getHeight()).thenReturn(500); + reset(mKeyguardHostViewController); mBouncer.show(true); - verify(mKeyguardHostView).setAlpha(eq(1f)); - verify(mKeyguardHostView).setTranslationY(eq(0f)); + verify(mKeyguardHostViewController).setExpansion(0); } @Test @@ -177,23 +179,23 @@ public class KeyguardBouncerTest extends SysuiTestCase { @Test public void testShow_triesToDismissKeyguard() { mBouncer.show(true); - verify(mKeyguardHostView).dismiss(anyInt()); + verify(mKeyguardHostViewController).dismiss(anyInt()); } @Test public void testShow_resetsSecuritySelection() { mBouncer.show(false); - verify(mKeyguardHostView, never()).showPrimarySecurityScreen(); + verify(mKeyguardHostViewController, never()).showPrimarySecurityScreen(); mBouncer.hide(false); mBouncer.show(true); - verify(mKeyguardHostView).showPrimarySecurityScreen(); + verify(mKeyguardHostViewController).showPrimarySecurityScreen(); } @Test public void testShow_animatesKeyguardView() { mBouncer.show(true); - verify(mKeyguardHostView).startAppearAnimation(); + verify(mKeyguardHostViewController).appear(anyInt()); } @Test @@ -201,7 +203,7 @@ public class KeyguardBouncerTest extends SysuiTestCase { final String errorMessage = "an error message"; when(mViewMediatorCallback.consumeCustomMessage()).thenReturn(errorMessage); mBouncer.show(true); - verify(mKeyguardHostView).showErrorMessage(eq(errorMessage)); + verify(mKeyguardHostViewController).showErrorMessage(eq(errorMessage)); } @Test @@ -218,10 +220,10 @@ public class KeyguardBouncerTest extends SysuiTestCase { verify(mExpansionCallback).onFullyShown(); verify(mExpansionCallback, never()).onStartingToHide(); - verify(mKeyguardHostView, never()).onStartingToHide(); + verify(mKeyguardHostViewController, never()).onStartingToHide(); mBouncer.setExpansion(0.9f); verify(mExpansionCallback).onStartingToHide(); - verify(mKeyguardHostView).onStartingToHide(); + verify(mKeyguardHostViewController).onStartingToHide(); } @Test @@ -230,7 +232,7 @@ public class KeyguardBouncerTest extends SysuiTestCase { mBouncer.setExpansion(0.1f); mBouncer.setExpansion(0); - verify(mKeyguardHostView).onResume(); + verify(mKeyguardHostViewController).onResume(); verify(mRootView).announceForAccessibility(any()); } @@ -267,7 +269,7 @@ public class KeyguardBouncerTest extends SysuiTestCase { public void testShowPromptReason_propagates() { mBouncer.ensureView(); mBouncer.showPromptReason(1); - verify(mKeyguardHostView).showPromptReason(eq(1)); + verify(mKeyguardHostViewController).showPromptReason(eq(1)); } @Test @@ -275,7 +277,8 @@ public class KeyguardBouncerTest extends SysuiTestCase { final String message = "a message"; mBouncer.ensureView(); mBouncer.showMessage(message, ColorStateList.valueOf(Color.GREEN)); - verify(mKeyguardHostView).showMessage(eq(message), eq(ColorStateList.valueOf(Color.GREEN))); + verify(mKeyguardHostViewController).showMessage( + eq(message), eq(ColorStateList.valueOf(Color.GREEN))); } @Test @@ -283,7 +286,7 @@ public class KeyguardBouncerTest extends SysuiTestCase { final OnDismissAction dismissAction = () -> false; final Runnable cancelAction = () -> {}; mBouncer.showWithDismissAction(dismissAction, cancelAction); - verify(mKeyguardHostView).setOnDismissAction(dismissAction, cancelAction); + verify(mKeyguardHostViewController).setOnDismissAction(dismissAction, cancelAction); Assert.assertTrue("Should be showing", mBouncer.isShowing()); } @@ -297,7 +300,7 @@ public class KeyguardBouncerTest extends SysuiTestCase { ran[0] = false; mBouncer.ensureView(); mBouncer.startPreHideAnimation(r); - verify(mKeyguardHostView).startDisappearAnimation(r); + verify(mKeyguardHostViewController).startDisappearAnimation(r); Assert.assertFalse("Callback should have been deferred", ran[0]); } @@ -322,16 +325,14 @@ public class KeyguardBouncerTest extends SysuiTestCase { public void testSetExpansion() { mBouncer.ensureView(); mBouncer.setExpansion(0.5f); - verify(mKeyguardHostView).setAlpha(anyFloat()); - verify(mKeyguardHostView).setTranslationY(anyFloat()); + verify(mKeyguardHostViewController).setExpansion(0.5f); } @Test public void testIsFullscreenBouncer_asksKeyguardView() { mBouncer.ensureView(); mBouncer.isFullscreenBouncer(); - verify(mKeyguardHostView).getCurrentSecurityMode(); - verify(mKeyguardHostView, never()).getSecurityMode(); + verify(mKeyguardHostViewController).getCurrentSecurityMode(); } @Test @@ -346,21 +347,18 @@ public class KeyguardBouncerTest extends SysuiTestCase { @Test public void testIsHiding_skipsTranslation() { mBouncer.show(false /* reset */); - reset(mKeyguardHostView); + reset(mKeyguardHostViewController); mBouncer.startPreHideAnimation(null /* runnable */); mBouncer.setExpansion(0.5f); - verify(mKeyguardHostView, never()).setTranslationY(anyFloat()); - verify(mKeyguardHostView, never()).setAlpha(anyFloat()); + verify(mKeyguardHostViewController, never()).setExpansion(anyFloat()); } @Test public void testIsSecure() { - Assert.assertTrue("Bouncer is secure before inflating views", mBouncer.isSecure()); - mBouncer.ensureView(); for (KeyguardSecurityModel.SecurityMode mode : KeyguardSecurityModel.SecurityMode.values()){ - reset(mKeyguardHostView); - when(mKeyguardHostView.getSecurityMode()).thenReturn(mode); + reset(mKeyguardSecurityModel); + when(mKeyguardSecurityModel.getSecurityMode(anyInt())).thenReturn(mode); Assert.assertEquals("Security doesn't match for mode: " + mode, mBouncer.isSecure(), mode != KeyguardSecurityModel.SecurityMode.None); } @@ -392,7 +390,7 @@ public class KeyguardBouncerTest extends SysuiTestCase { public void testWillDismissWithAction() { mBouncer.ensureView(); Assert.assertFalse("Action not set yet", mBouncer.willDismissWithAction()); - when(mKeyguardHostView.hasDismissActions()).thenReturn(true); + when(mKeyguardHostViewController.hasDismissActions()).thenReturn(true); Assert.assertTrue("Action should exist", mBouncer.willDismissWithAction()); } diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManagerTest.java index 108327341f94..9832d31f7b05 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManagerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManagerTest.java @@ -39,7 +39,6 @@ import androidx.test.filters.SmallTest; import com.android.internal.widget.LockPatternUtils; import com.android.keyguard.KeyguardUpdateMonitor; import com.android.keyguard.ViewMediatorCallback; -import com.android.keyguard.dagger.KeyguardBouncerComponent; import com.android.systemui.SysuiTestCase; import com.android.systemui.dock.DockManager; import com.android.systemui.keyguard.DismissCallbackRegistry; @@ -92,9 +91,7 @@ public class StatusBarKeyguardViewManagerTest extends SysuiTestCase { @Mock private FaceAuthScreenBrightnessController mFaceAuthScreenBrightnessController; @Mock - private KeyguardBouncerComponent.Factory mKeyguardBouncerComponentFactory; - @Mock - private KeyguardBouncerComponent mKeyguardBouncerComponent; + private KeyguardBouncer.Factory mKeyguardBouncerFactory; @Mock private KeyguardBouncer mBouncer; @@ -107,11 +104,10 @@ public class StatusBarKeyguardViewManagerTest extends SysuiTestCase { when(mLockIconContainer.animate()).thenReturn(mock(ViewPropertyAnimator.class, RETURNS_DEEP_STUBS)); - when(mKeyguardBouncerComponentFactory.build( + when(mKeyguardBouncerFactory.create( any(ViewGroup.class), any(KeyguardBouncer.BouncerExpansionCallback.class))) - .thenReturn(mKeyguardBouncerComponent); - when(mKeyguardBouncerComponent.createKeyguardBouncer()).thenReturn(mBouncer); + .thenReturn(mBouncer); mStatusBarKeyguardViewManager = new StatusBarKeyguardViewManager( getContext(), @@ -126,7 +122,7 @@ public class StatusBarKeyguardViewManagerTest extends SysuiTestCase { mKeyguardStateController, Optional.of(mFaceAuthScreenBrightnessController), mock(NotificationMediaManager.class), - mKeyguardBouncerComponentFactory); + mKeyguardBouncerFactory); mStatusBarKeyguardViewManager.registerStatusBar(mStatusBar, mContainer, mNotificationPanelView, mBiometrucUnlockController, mLockIconContainer, mNotificationContainer, mBypassController); diff --git a/packages/SystemUI/tests/src/com/android/systemui/wmshell/WMShellTest.java b/packages/SystemUI/tests/src/com/android/systemui/wmshell/WMShellTest.java index 51cc5f175444..bcc36396e1d8 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/wmshell/WMShellTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/wmshell/WMShellTest.java @@ -30,15 +30,15 @@ import com.android.systemui.SysuiTestCase; import com.android.systemui.keyguard.ScreenLifecycle; import com.android.systemui.model.SysUiState; import com.android.systemui.navigationbar.NavigationModeController; -import com.android.systemui.onehanded.OneHanded; -import com.android.systemui.onehanded.OneHandedGestureHandler; -import com.android.systemui.onehanded.OneHandedTransitionCallback; import com.android.systemui.pip.Pip; import com.android.systemui.shared.system.ActivityManagerWrapper; import com.android.systemui.shared.system.TaskStackChangeListener; import com.android.systemui.statusbar.CommandQueue; import com.android.systemui.tracing.ProtoTracer; import com.android.wm.shell.common.DisplayImeController; +import com.android.wm.shell.onehanded.OneHanded; +import com.android.wm.shell.onehanded.OneHandedGestureHandler; +import com.android.wm.shell.onehanded.OneHandedTransitionCallback; import com.android.wm.shell.splitscreen.SplitScreen; import org.junit.Before; diff --git a/packages/Tethering/common/TetheringLib/Android.bp b/packages/Tethering/common/TetheringLib/Android.bp index c8becce7be82..bf643cdcecc5 100644 --- a/packages/Tethering/common/TetheringLib/Android.bp +++ b/packages/Tethering/common/TetheringLib/Android.bp @@ -16,19 +16,9 @@ java_sdk_library { name: "framework-tethering", defaults: ["framework-module-defaults"], + impl_library_visibility: ["//frameworks/base/packages/Tethering:__subpackages__"], - // Allow access to the stubs from anywhere. - visibility: ["//visibility:public"], - - // Restrict access to implementation library. - impl_library_visibility: [ - "//visibility:override", // Ignore the visibility property. - "//frameworks/base/packages/Tethering:__subpackages__", - ], - - srcs: [ - ":framework-tethering-srcs", - ], + srcs: [":framework-tethering-srcs"], jarjar_rules: "jarjar-rules.txt", installable: true, diff --git a/packages/overlays/IconPackCircularSettingsOverlay/res/drawable/ic_notifications_alert.xml b/packages/overlays/IconPackCircularSettingsOverlay/res/drawable/ic_notifications_alert.xml new file mode 100644 index 000000000000..e66d9204769d --- /dev/null +++ b/packages/overlays/IconPackCircularSettingsOverlay/res/drawable/ic_notifications_alert.xml @@ -0,0 +1,34 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + Copyright (C) 2020 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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:height="24dp" + android:viewportHeight="24" + android:viewportWidth="24" + android:width="24dp" > + <path + android:fillColor="@android:color/white" + android:pathData="M5.85,3.01C3.72,4.82,2.5,7.46,2.5,10.25C2.5,10.66,2.84,11,3.25,11S4,10.66,4,10.25c0-2.35,1.03-4.57,2.82-6.1 C7.14,3.88,7.17,3.41,6.91,3.1C6.64,2.78,6.17,2.74,5.85,3.01z" /> + <path + android:fillColor="@android:color/white" + android:pathData="M21.5,10.25c0-2.79-1.22-5.43-3.35-7.24c-0.32-0.27-0.79-0.23-1.06,0.08c-0.27,0.32-0.23,0.79,0.08,1.06 C18.97,5.68,20,7.9,20,10.25c0,0.41,0.34,0.75,0.75,0.75S21.5,10.66,21.5,10.25z" /> + <path + android:fillColor="@android:color/white" + android:pathData="M12,2.5c-0.83,0-1.5,0.67-1.5,1.5v0.7C7.91,5.36,6,7.71,6,10.5V15c0,0.55-0.45,1-1,1s-1,0.45-1,1v2h16v-2 c0-0.55-0.45-1-1-1s-1-0.45-1-1v-4.5c0-2.79-1.91-5.14-4.5-5.8V4C13.5,3.17,12.83,2.5,12,2.5z M16.5,10.5V15 c0,1.21,0.86,2.22,2,2.45v0.05h-13v-0.05c1.14-0.23,2-1.24,2-2.45v-4.5C7.5,8.02,9.52,6,12,6S16.5,8.02,16.5,10.5z" /> + <path + android:fillColor="@android:color/white" + android:pathData="M14,20h-4c0,1.1,0.9,2,2,2S14,21.1,14,20z" /> +</vector>
\ No newline at end of file diff --git a/packages/overlays/IconPackFilledSettingsOverlay/res/drawable/ic_notifications_alert.xml b/packages/overlays/IconPackFilledSettingsOverlay/res/drawable/ic_notifications_alert.xml new file mode 100644 index 000000000000..2f5bdb0ecbe3 --- /dev/null +++ b/packages/overlays/IconPackFilledSettingsOverlay/res/drawable/ic_notifications_alert.xml @@ -0,0 +1,34 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + Copyright (C) 2020 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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:height="24dp" + android:viewportHeight="24" + android:viewportWidth="24" + android:width="24dp" > + <path + android:fillColor="@android:color/white" + android:pathData="M4.12,9.67C4.42,7.73,5.38,6,6.77,4.73C7.19,4.35,7.2,3.7,6.8,3.3c-0.39-0.39-1-0.39-1.4-0.03 C3.7,4.84,2.52,6.96,2.15,9.34c-0.1,0.61,0.37,1.16,0.99,1.16C3.63,10.5,4.04,10.15,4.12,9.67z" /> + <path + android:fillColor="@android:color/white" + android:pathData="M18.6,3.28c-0.4-0.37-1.02-0.36-1.4,0.02c-0.4,0.4-0.38,1.04,0.03,1.42c1.38,1.27,2.35,3,2.65,4.94 c0.08,0.49,0.5,0.84,0.98,0.84c0.61,0,1.09-0.55,0.99-1.16C21.47,6.96,20.29,4.84,18.6,3.28z" /> + <path + android:fillColor="@android:color/white" + android:pathData="M12,22c1.1,0,2-0.9,2-2h-4C10,21.1,10.9,22,12,22z" /> + <path + android:fillColor="@android:color/white" + android:pathData="M18,16v-5c0-3.07-1.64-5.64-4.5-6.32V4c0-0.83-0.67-1.5-1.5-1.5S10.5,3.17,10.5,4v0.68C7.63,5.36,6,7.92,6,11v5 l-2.15,2.15c-0.19,0.2-0.19,0.51,0.01,0.71C3.95,18.95,4.07,19,4.2,19h15.6c0.45,0,0.67-0.54,0.35-0.85L18,16z" /> +</vector>
\ No newline at end of file diff --git a/packages/overlays/IconPackKaiSettingsOverlay/res/drawable/ic_notifications_alert.xml b/packages/overlays/IconPackKaiSettingsOverlay/res/drawable/ic_notifications_alert.xml new file mode 100644 index 000000000000..c92bdf6dc62a --- /dev/null +++ b/packages/overlays/IconPackKaiSettingsOverlay/res/drawable/ic_notifications_alert.xml @@ -0,0 +1,21 @@ +<!-- + Copyright (C) 2020 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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 android:height="24dp" android:viewportHeight="24" android:viewportWidth="24" android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android"> + <path android:fillColor="@android:color/white" android:pathData="M6.81,3.81L5.75,2.75C3.45,4.76,2,7.71,2,11h1.5C3.5,8.13,4.79,5.55,6.81,3.81z"/> + <path android:fillColor="@android:color/white" android:pathData="M18.25,2.75l-1.06,1.06C19.21,5.55,20.5,8.13,20.5,11H22C22,7.71,20.55,4.76,18.25,2.75z"/> + <path android:fillColor="@android:color/white" android:pathData="M18,10.5c0-4.38-2.72-5.57-4.5-5.89V4c0-1.59-1.43-1.5-1.5-1.5c-0.05,0-1.5-0.09-1.5,1.5v0.62C8.72,4.94,6,6.14,6,10.5v7 H4V19h16v-1.5h-2V10.5z M16.5,17.5h-9v-7C7.5,7.57,8.94,5.95,12,6c3.07-0.05,4.5,1.55,4.5,4.5V17.5z"/> + <path android:fillColor="@android:color/white" android:pathData="M12,22c0.07,0,2,0.12,2-2h-4C10,22.12,11.91,22,12,22z"/> +</vector>
\ No newline at end of file diff --git a/packages/overlays/IconPackRoundedSettingsOverlay/res/drawable/ic_notifications_alert.xml b/packages/overlays/IconPackRoundedSettingsOverlay/res/drawable/ic_notifications_alert.xml new file mode 100644 index 000000000000..8f854e74f551 --- /dev/null +++ b/packages/overlays/IconPackRoundedSettingsOverlay/res/drawable/ic_notifications_alert.xml @@ -0,0 +1,34 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + Copyright (C) 2020 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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:height="24dp" + android:viewportHeight="24" + android:viewportWidth="24" + android:width="24dp" > + <path + android:fillColor="@android:color/white" + android:pathData="M14,20h-4c0,1.1,0.9,2,2,2S14,21.1,14,20z" /> + <path + android:fillColor="@android:color/white" + android:pathData="M12,2.5c-0.69,0-1.25,0.56-1.25,1.25v0.77C8.04,5.11,6,7.51,6,10.4V17H4.75C4.34,17,4,17.34,4,17.75s0.34,0.75,0.75,0.75 h14.5c0.41,0,0.75-0.34,0.75-0.75S19.66,17,19.25,17H18v-6.6c0-2.88-2.04-5.29-4.75-5.87V3.75C13.25,3.06,12.69,2.5,12,2.5z M16.5,10.4V17h-9v-6.6c0-2.48,2.02-4.5,4.5-4.5S16.5,7.91,16.5,10.4z" /> + <path + android:fillColor="@android:color/white" + android:pathData="M5.85,3.01C3.72,4.82,2.5,7.46,2.5,10.25C2.5,10.66,2.84,11,3.25,11S4,10.66,4,10.25c0-2.35,1.03-4.57,2.82-6.1 C7.14,3.88,7.17,3.41,6.91,3.1C6.64,2.78,6.17,2.74,5.85,3.01z" /> + <path + android:fillColor="@android:color/white" + android:pathData="M18.15,3.01c-0.32-0.27-0.79-0.23-1.06,0.08c-0.27,0.32-0.23,0.79,0.08,1.06C18.97,5.68,20,7.9,20,10.25 c0,0.41,0.34,0.75,0.75,0.75s0.75-0.34,0.75-0.75C21.5,7.46,20.28,4.82,18.15,3.01z" /> +</vector>
\ No newline at end of file diff --git a/packages/overlays/IconPackSamSettingsOverlay/res/drawable/ic_notifications_alert.xml b/packages/overlays/IconPackSamSettingsOverlay/res/drawable/ic_notifications_alert.xml new file mode 100644 index 000000000000..e022c63fdf06 --- /dev/null +++ b/packages/overlays/IconPackSamSettingsOverlay/res/drawable/ic_notifications_alert.xml @@ -0,0 +1,21 @@ +<!-- + Copyright (C) 2020 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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 android:height="24dp" android:viewportHeight="24" android:viewportWidth="24" android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android"> + <path android:fillColor="@android:color/white" android:pathData="M6.47,4.81c0.37-0.38,0.35-0.99-0.03-1.37c-0.4-0.4-1.05-0.39-1.44,0.02c-1.62,1.72-2.7,3.95-2.95,6.43 C2,10.48,2.46,11,3.05,11h0.01c0.51,0,0.93-0.38,0.98-0.88C4.24,8.07,5.13,6.22,6.47,4.81z"/> + <path android:fillColor="@android:color/white" android:pathData="M18.99,3.47c-0.39-0.41-1.04-0.42-1.44-0.02c-0.38,0.38-0.39,0.98-0.03,1.37c1.34,1.41,2.23,3.26,2.43,5.3 c0.05,0.5,0.48,0.88,0.98,0.88h0.01c0.59,0,1.05-0.52,0.99-1.11C21.69,7.42,20.61,5.19,18.99,3.47z"/> + <path android:fillColor="@android:color/white" android:pathData="M19,17h-1v-6c0-3.07-1.63-5.64-4.5-6.32V4c0-0.83-0.67-1.5-1.5-1.5c-0.83,0-1.5,0.67-1.5,1.5v0.68C7.64,5.36,6,7.92,6,11 v6H5c-0.55,0-1,0.45-1,1c0,0.55,0.45,1,1,1h14c0.55,0,1-0.45,1-1C20,17.45,19.55,17,19,17z"/> + <path android:fillColor="@android:color/white" android:pathData="M12,22c1.1,0,2-0.9,2-2h-4C10,21.1,10.9,22,12,22z"/> +</vector>
\ No newline at end of file diff --git a/packages/overlays/IconPackVictorSettingsOverlay/res/drawable/ic_notifications_alert.xml b/packages/overlays/IconPackVictorSettingsOverlay/res/drawable/ic_notifications_alert.xml new file mode 100644 index 000000000000..1e25d27f0eb3 --- /dev/null +++ b/packages/overlays/IconPackVictorSettingsOverlay/res/drawable/ic_notifications_alert.xml @@ -0,0 +1,21 @@ +<!-- + Copyright (C) 2020 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT 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 android:height="24dp" android:viewportHeight="24" android:viewportWidth="24" android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android"> + <path android:fillColor="@android:color/white" android:pathData="M18,6.5L16.5,5H13V3h-2v2H7.5L6,6.5v11H4V19h16v-1.5h-2V6.5z M7.5,17.5v-11h9v11H7.5z"/> + <path android:fillColor="@android:color/white" android:pathData="M12,22c1.1,0,2-0.9,2-2h-4C10,21.1,10.9,22,12,22z"/> + <path android:fillColor="@android:color/white" android:pathData="M6.81,3.81L5.75,2.75C3.45,4.76,2,7.71,2,11h1.5C3.5,8.13,4.79,5.55,6.81,3.81z"/> + <path android:fillColor="@android:color/white" android:pathData="M18.25,2.75l-1.06,1.06C19.21,5.55,20.5,8.13,20.5,11H22C22,7.71,20.55,4.76,18.25,2.75z"/> +</vector>
\ No newline at end of file diff --git a/services/accessibility/java/com/android/server/accessibility/magnification/FullScreenMagnificationController.java b/services/accessibility/java/com/android/server/accessibility/magnification/FullScreenMagnificationController.java index b6f2a47dd5e2..c583dcc2b1be 100644 --- a/services/accessibility/java/com/android/server/accessibility/magnification/FullScreenMagnificationController.java +++ b/services/accessibility/java/com/android/server/accessibility/magnification/FullScreenMagnificationController.java @@ -37,6 +37,7 @@ import android.util.SparseArray; import android.view.Display; import android.view.MagnificationSpec; import android.view.View; +import android.view.accessibility.MagnificationAnimationCallback; import android.view.animation.DecelerateInterpolator; import com.android.internal.R; @@ -63,7 +64,7 @@ public class FullScreenMagnificationController { private static final boolean DEBUG = false; private static final String LOG_TAG = "FullScreenMagnificationController"; - private static final Runnable STUB_RUNNABLE = () -> { + private static final MagnificationAnimationCallback STUB_ANIMATION_CALLBACK = success -> { }; public static final float MIN_SCALE = 1.0f; public static final float MAX_SCALE = 8.0f; @@ -304,18 +305,19 @@ public class FullScreenMagnificationController { } } - void sendSpecToAnimation(MagnificationSpec spec, Runnable endCallback) { + void sendSpecToAnimation(MagnificationSpec spec, + MagnificationAnimationCallback animationCallback) { if (DEBUG) { Slog.i(LOG_TAG, - "sendSpecToAnimation(spec = " + spec + ", endCallback = " + endCallback - + ")"); + "sendSpecToAnimation(spec = " + spec + ", animationCallback = " + + animationCallback + ")"); } if (Thread.currentThread().getId() == mMainThreadId) { - mSpecAnimationBridge.updateSentSpecMainThread(spec, endCallback); + mSpecAnimationBridge.updateSentSpecMainThread(spec, animationCallback); } else { final Message m = PooledLambda.obtainMessage( SpecAnimationBridge::updateSentSpecMainThread, - mSpecAnimationBridge, spec, endCallback); + mSpecAnimationBridge, spec, animationCallback); mControllerCtx.getHandler().sendMessage(m); } } @@ -415,11 +417,11 @@ public class FullScreenMagnificationController { @GuardedBy("mLock") boolean reset(boolean animate) { - return reset(transformToStubRunnable(animate)); + return reset(transformToStubCallback(animate)); } @GuardedBy("mLock") - boolean reset(Runnable endCallback) { + boolean reset(MagnificationAnimationCallback animationCallback) { if (!mRegistered) { return false; } @@ -430,7 +432,7 @@ public class FullScreenMagnificationController { onMagnificationChangedLocked(); } mIdOfLastServiceToMagnify = INVALID_ID; - sendSpecToAnimation(spec, endCallback); + sendSpecToAnimation(spec, animationCallback); return changed; } @@ -458,24 +460,23 @@ public class FullScreenMagnificationController { final float centerX = normPivotX + offsetX; final float centerY = normPivotY + offsetY; mIdOfLastServiceToMagnify = id; - return setScaleAndCenter(scale, centerX, centerY, transformToStubRunnable(animate), id); + return setScaleAndCenter(scale, centerX, centerY, transformToStubCallback(animate), id); } @GuardedBy("mLock") boolean setScaleAndCenter(float scale, float centerX, float centerY, - Runnable endCallback, int id) { + MagnificationAnimationCallback animationCallback, int id) { if (!mRegistered) { return false; } if (DEBUG) { Slog.i(LOG_TAG, "setScaleAndCenterLocked(scale = " + scale + ", centerX = " + centerX - + ", centerY = " + centerY + ", endCallback = " + endCallback - + ", id = " + id - + ")"); + + ", centerY = " + centerY + ", endCallback = " + + animationCallback + ", id = " + id + ")"); } final boolean changed = updateMagnificationSpecLocked(scale, centerX, centerY); - sendSpecToAnimation(mCurrentMagnificationSpec, endCallback); + sendSpecToAnimation(mCurrentMagnificationSpec, animationCallback); if (isMagnifying() && (id != INVALID_ID)) { mIdOfLastServiceToMagnify = id; } @@ -875,7 +876,7 @@ public class FullScreenMagnificationController { * the spec did not change */ public boolean reset(int displayId, boolean animate) { - return reset(displayId, animate ? STUB_RUNNABLE : null); + return reset(displayId, animate ? STUB_ANIMATION_CALLBACK : null); } /** @@ -883,18 +884,19 @@ public class FullScreenMagnificationController { * transition. * * @param displayId The logical display id. - * @param endCallback Called when the animation is ended or the spec did not change. + * @param animationCallback Called when the animation result is valid. * {@code null} to transition immediately * @return {@code true} if the magnification spec changed, {@code false} if * the spec did not change */ - public boolean reset(int displayId, Runnable endCallback) { + public boolean reset(int displayId, + MagnificationAnimationCallback animationCallback) { synchronized (mLock) { final DisplayMagnification display = mDisplays.get(displayId); if (display == null) { return false; } - return display.reset(endCallback); + return display.reset(animationCallback); } } @@ -946,7 +948,7 @@ public class FullScreenMagnificationController { return false; } return display.setScaleAndCenter(Float.NaN, centerX, centerY, - animate ? STUB_RUNNABLE : null, id); + animate ? STUB_ANIMATION_CALLBACK : null, id); } } @@ -970,7 +972,7 @@ public class FullScreenMagnificationController { public boolean setScaleAndCenter(int displayId, float scale, float centerX, float centerY, boolean animate, int id) { return setScaleAndCenter(displayId, scale, centerX, centerY, - transformToStubRunnable(animate), id); + transformToStubCallback(animate), id); } /** @@ -984,20 +986,20 @@ public class FullScreenMagnificationController { * center and scale, or {@link Float#NaN} to leave unchanged * @param centerY the screen-relative Y coordinate around which to * center and scale, or {@link Float#NaN} to leave unchanged - * @param endCallback called when the transition is finished successfully or the spec did not - * change. {@code null} to transition immediately. + * @param animationCallback Called when the animation result is valid. + * {@code null} to transition immediately * @param id the ID of the service requesting the change * @return {@code true} if the magnification spec changed, {@code false} if * the spec did not change */ public boolean setScaleAndCenter(int displayId, float scale, float centerX, float centerY, - Runnable endCallback, int id) { + MagnificationAnimationCallback animationCallback, int id) { synchronized (mLock) { final DisplayMagnification display = mDisplays.get(displayId); if (display == null) { return false; } - return display.setScaleAndCenter(scale, centerX, centerY, endCallback, id); + return display.setScaleAndCenter(scale, centerX, centerY, animationCallback, id); } } @@ -1230,7 +1232,7 @@ public class FullScreenMagnificationController { private final ValueAnimator mValueAnimator; // Called when the callee wants animating and the sent spec matches the target spec. - private Runnable mEndCallback; + private MagnificationAnimationCallback mAnimationCallback; private final Object mLock; private final int mDisplayId; @@ -1268,33 +1270,35 @@ public class FullScreenMagnificationController { } } - void updateSentSpecMainThread(MagnificationSpec spec, Runnable endCallback) { + void updateSentSpecMainThread(MagnificationSpec spec, + MagnificationAnimationCallback animationCallback) { if (mValueAnimator.isRunning()) { - // Avoid AnimationEnd Callback. - mEndCallback = null; mValueAnimator.cancel(); } - mEndCallback = endCallback; + mAnimationCallback = animationCallback; // If the current and sent specs don't match, update the sent spec. synchronized (mLock) { final boolean changed = !mSentMagnificationSpec.equals(spec); if (changed) { - if (mEndCallback != null) { + if (mAnimationCallback != null) { animateMagnificationSpecLocked(spec); } else { setMagnificationSpecLocked(spec); } } else { - sendEndCallbackMainThread(); + sendEndCallbackMainThread(true); } } } - private void sendEndCallbackMainThread() { - if (mEndCallback != null) { - mEndCallback.run(); - mEndCallback = null; + private void sendEndCallbackMainThread(boolean success) { + if (mAnimationCallback != null) { + if (DEBUG) { + Slog.d(LOG_TAG, "sendEndCallbackMainThread: " + success); + } + mAnimationCallback.onResult(success); + mAnimationCallback = null; } } @@ -1337,17 +1341,16 @@ public class FullScreenMagnificationController { @Override public void onAnimationStart(Animator animation) { - } @Override public void onAnimationEnd(Animator animation) { - sendEndCallbackMainThread(); + sendEndCallbackMainThread(true); } @Override public void onAnimationCancel(Animator animation) { - + sendEndCallbackMainThread(false); } @Override @@ -1481,7 +1484,7 @@ public class FullScreenMagnificationController { } @Nullable - private static Runnable transformToStubRunnable(boolean animate) { - return animate ? STUB_RUNNABLE : null; + private static MagnificationAnimationCallback transformToStubCallback(boolean animate) { + return animate ? STUB_ANIMATION_CALLBACK : null; } } diff --git a/services/backup/java/com/android/server/backup/restore/FullRestoreEngine.java b/services/backup/java/com/android/server/backup/restore/FullRestoreEngine.java index b9625397d237..16077cb6082f 100644 --- a/services/backup/java/com/android/server/backup/restore/FullRestoreEngine.java +++ b/services/backup/java/com/android/server/backup/restore/FullRestoreEngine.java @@ -228,7 +228,7 @@ public class FullRestoreEngine extends RestoreEngine { PackageManagerInternal.class); RestorePolicy restorePolicy = tarBackupReader.chooseRestorePolicy( mBackupManagerService.getPackageManager(), allowApks, info, signatures, - pmi, mUserId); + pmi, mUserId, mBackupEligibilityRules); mManifestSignatures.put(info.packageName, signatures); mPackagePolicies.put(pkg, restorePolicy); mPackageInstallers.put(pkg, info.installerPackageName); diff --git a/services/backup/java/com/android/server/backup/utils/TarBackupReader.java b/services/backup/java/com/android/server/backup/utils/TarBackupReader.java index 3789fa14e87b..6963248734a3 100644 --- a/services/backup/java/com/android/server/backup/utils/TarBackupReader.java +++ b/services/backup/java/com/android/server/backup/utils/TarBackupReader.java @@ -389,13 +389,29 @@ public class TarBackupReader { public RestorePolicy chooseRestorePolicy(PackageManager packageManager, boolean allowApks, FileMetadata info, Signature[] signatures, PackageManagerInternal pmi, int userId) { + return chooseRestorePolicy(packageManager, allowApks, info, signatures, pmi, userId, + BackupEligibilityRules.forBackup(packageManager, pmi, userId)); + } + + /** + * Chooses restore policy. + * + * @param packageManager - PackageManager instance. + * @param allowApks - allow restore set to include apks. + * @param info - file metadata. + * @param signatures - array of signatures parsed from backup file. + * @param userId - ID of the user for which restore is performed. + * @param eligibilityRules - {@link BackupEligibilityRules} for this operation. + * @return a restore policy constant. + */ + public RestorePolicy chooseRestorePolicy(PackageManager packageManager, + boolean allowApks, FileMetadata info, Signature[] signatures, + PackageManagerInternal pmi, int userId, BackupEligibilityRules eligibilityRules) { if (signatures == null) { return RestorePolicy.IGNORE; } RestorePolicy policy = RestorePolicy.IGNORE; - BackupEligibilityRules eligibilityRules = BackupEligibilityRules.forBackup(packageManager, - pmi, userId); // Okay, got the manifest info we need... try { PackageInfo pkgInfo = packageManager.getPackageInfoAsUser( diff --git a/services/core/java/com/android/server/BatteryService.java b/services/core/java/com/android/server/BatteryService.java index 65ac7844ec2b..d92706d2dd19 100644 --- a/services/core/java/com/android/server/BatteryService.java +++ b/services/core/java/com/android/server/BatteryService.java @@ -39,6 +39,7 @@ import android.os.BatteryManagerInternal; import android.os.BatteryProperty; import android.os.BatteryStats; import android.os.Binder; +import android.os.Build; import android.os.Bundle; import android.os.DropBoxManager; import android.os.FileUtils; @@ -59,6 +60,7 @@ import android.os.UEventObserver; import android.os.UserHandle; import android.provider.Settings; import android.service.battery.BatteryServiceDumpProto; +import android.sysprop.PowerProperties; import android.util.EventLog; import android.util.MutableInt; import android.util.Slog; @@ -182,6 +184,7 @@ public final class BatteryService extends SystemService { private int mChargeStartLevel; private boolean mUpdatesStopped; + private boolean mBatteryInputSuspended; private Led mLed; @@ -234,6 +237,8 @@ public final class BatteryService extends SystemService { invalidChargerObserver.startObserving( "DEVPATH=/devices/virtual/switch/invalid_charger"); } + + mBatteryInputSuspended = PowerProperties.battery_input_suspended().orElse(false); } @Override @@ -876,6 +881,10 @@ public final class BatteryService extends SystemService { pw.println(" reset [-f]"); pw.println(" Unfreeze battery state, returning to current hardware values."); pw.println(" -f: force a battery change broadcast be sent, prints new sequence."); + if (Build.IS_DEBUGGABLE) { + pw.println(" disable_charge"); + pw.println(" Suspend charging even if plugged in. "); + } } static final int OPTION_FORCE_UPDATE = 1<<0; @@ -997,6 +1006,20 @@ public final class BatteryService extends SystemService { } finally { Binder.restoreCallingIdentity(ident); } + if (mBatteryInputSuspended) { + PowerProperties.battery_input_suspended(false); + mBatteryInputSuspended = false; + } + } break; + case "suspend_input": { + if (!Build.IS_DEBUGGABLE) { + throw new SecurityException( + "battery suspend_input is only supported on debuggable builds"); + } + getContext().enforceCallingOrSelfPermission( + android.Manifest.permission.DEVICE_POWER, null); + PowerProperties.battery_input_suspended(true); + mBatteryInputSuspended = true; } break; default: return shell.handleDefaultCommands(cmd); diff --git a/services/core/java/com/android/server/BluetoothManagerService.java b/services/core/java/com/android/server/BluetoothManagerService.java index f372c6f85ec6..0d79240a4b59 100644 --- a/services/core/java/com/android/server/BluetoothManagerService.java +++ b/services/core/java/com/android/server/BluetoothManagerService.java @@ -166,6 +166,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub { private String mAddress; private String mName; private final ContentResolver mContentResolver; + private final int mUserId; private final RemoteCallbackList<IBluetoothManagerCallback> mCallbacks; private final RemoteCallbackList<IBluetoothStateChangeCallback> mStateChangeCallbacks; private IBinder mBluetoothBinder; @@ -481,6 +482,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub { mName = null; mErrorRecoveryRetryCounter = 0; mContentResolver = context.getContentResolver(); + mUserId = mContentResolver.getUserId(); // Observe BLE scan only mode settings change. registerForBleScanModeChange(); mCallbacks = new RemoteCallbackList<IBluetoothManagerCallback>(); @@ -625,7 +627,8 @@ class BluetoothManagerService extends IBluetoothManager.Stub { } if (mContext.getResources() .getBoolean(com.android.internal.R.bool.config_bluetooth_address_validation) - && Settings.Secure.getInt(mContentResolver, SECURE_SETTINGS_BLUETOOTH_ADDR_VALID, 0) + && Settings.Secure.getIntForUser(mContentResolver, + SECURE_SETTINGS_BLUETOOTH_ADDR_VALID, 0, mUserId) == 0) { // if the valid flag is not set, don't load the address and name if (DBG) { @@ -633,8 +636,10 @@ class BluetoothManagerService extends IBluetoothManager.Stub { } return; } - mName = Settings.Secure.getString(mContentResolver, SECURE_SETTINGS_BLUETOOTH_NAME); - mAddress = Settings.Secure.getString(mContentResolver, SECURE_SETTINGS_BLUETOOTH_ADDRESS); + mName = Settings.Secure.getStringForUser( + mContentResolver, SECURE_SETTINGS_BLUETOOTH_NAME, mUserId); + mAddress = Settings.Secure.getStringForUser( + mContentResolver, SECURE_SETTINGS_BLUETOOTH_ADDRESS, mUserId); if (DBG) { Slog.d(TAG, "Stored bluetooth Name=" + mName + ",Address=" + mAddress); } @@ -648,26 +653,31 @@ class BluetoothManagerService extends IBluetoothManager.Stub { */ private void storeNameAndAddress(String name, String address) { if (name != null) { - Settings.Secure.putString(mContentResolver, SECURE_SETTINGS_BLUETOOTH_NAME, name); + Settings.Secure.putStringForUser(mContentResolver, SECURE_SETTINGS_BLUETOOTH_NAME, name, + mUserId); mName = name; if (DBG) { - Slog.d(TAG, "Stored Bluetooth name: " + Settings.Secure.getString(mContentResolver, - SECURE_SETTINGS_BLUETOOTH_NAME)); + Slog.d(TAG, "Stored Bluetooth name: " + Settings.Secure.getStringForUser( + mContentResolver, SECURE_SETTINGS_BLUETOOTH_NAME, + mUserId)); } } if (address != null) { - Settings.Secure.putString(mContentResolver, SECURE_SETTINGS_BLUETOOTH_ADDRESS, address); + Settings.Secure.putStringForUser(mContentResolver, SECURE_SETTINGS_BLUETOOTH_ADDRESS, + address, mUserId); mAddress = address; if (DBG) { Slog.d(TAG, - "Stored Bluetoothaddress: " + Settings.Secure.getString(mContentResolver, - SECURE_SETTINGS_BLUETOOTH_ADDRESS)); + "Stored Bluetoothaddress: " + Settings.Secure.getStringForUser( + mContentResolver, SECURE_SETTINGS_BLUETOOTH_ADDRESS, + mUserId)); } } if ((name != null) && (address != null)) { - Settings.Secure.putInt(mContentResolver, SECURE_SETTINGS_BLUETOOTH_ADDR_VALID, 1); + Settings.Secure.putIntForUser(mContentResolver, SECURE_SETTINGS_BLUETOOTH_ADDR_VALID, 1, + mUserId); } } diff --git a/services/core/java/com/android/server/NetworkScorerAppManager.java b/services/core/java/com/android/server/NetworkScorerAppManager.java index 3bcb36fd0e00..4de40755419f 100644 --- a/services/core/java/com/android/server/NetworkScorerAppManager.java +++ b/services/core/java/com/android/server/NetworkScorerAppManager.java @@ -19,6 +19,7 @@ package com.android.server; import android.Manifest.permission; import android.annotation.Nullable; import android.content.ComponentName; +import android.content.ContentResolver; import android.content.Context; import android.content.Intent; import android.content.PermissionChecker; @@ -404,7 +405,8 @@ public class NetworkScorerAppManager { } public int getSecureInt(Context context, String name, int defaultValue) { - return Settings.Secure.getInt(context.getContentResolver(), name, defaultValue); + final ContentResolver cr = context.getContentResolver(); + return Settings.Secure.getIntForUser(cr, name, defaultValue, cr.getUserId()); } } } diff --git a/services/core/java/com/android/server/StorageManagerService.java b/services/core/java/com/android/server/StorageManagerService.java index 27c5d4a53956..eb18da2d2e13 100644 --- a/services/core/java/com/android/server/StorageManagerService.java +++ b/services/core/java/com/android/server/StorageManagerService.java @@ -4687,14 +4687,19 @@ class StorageManagerService extends IStorageManager.Stub } } - public void onAppOpsChanged(int code, int uid, @Nullable String packageName, int mode) { + public void onAppOpsChanged(int code, int uid, @Nullable String packageName, int mode, + int previousMode) { final long token = Binder.clearCallingIdentity(); try { // When using FUSE, we may need to kill the app if the op changes switch(code) { case OP_REQUEST_INSTALL_PACKAGES: - // Always kill regardless of op change, to remount apps /storage - killAppForOpChange(code, uid); + if (previousMode == MODE_ALLOWED || mode == MODE_ALLOWED) { + // If we transition to/from MODE_ALLOWED, kill the app to make + // sure it has the correct view of /storage. Changing between + // MODE_DEFAULT / MODE_ERRORED is a no-op + killAppForOpChange(code, uid); + } return; case OP_MANAGE_EXTERNAL_STORAGE: if (mode != MODE_ALLOWED) { diff --git a/services/core/java/com/android/server/TelephonyRegistry.java b/services/core/java/com/android/server/TelephonyRegistry.java index eb8308b56f2e..e433fbd94d4f 100644 --- a/services/core/java/com/android/server/TelephonyRegistry.java +++ b/services/core/java/com/android/server/TelephonyRegistry.java @@ -64,6 +64,7 @@ import android.telephony.DisconnectCause; import android.telephony.LocationAccessPolicy; import android.telephony.PhoneCapability; import android.telephony.PhoneStateListener; +import android.telephony.PhysicalChannelConfig; import android.telephony.PreciseCallState; import android.telephony.PreciseDataConnectionState; import android.telephony.PreciseDisconnectCause; @@ -142,13 +143,13 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { int callerUid; int callerPid; - int events; + long events; int subId = SubscriptionManager.INVALID_SUBSCRIPTION_ID; int phoneId = SubscriptionManager.INVALID_SIM_SLOT_INDEX; - boolean matchPhoneStateListenerEvent(int events) { + boolean matchPhoneStateListenerEvent(long events) { return (callback != null) && ((events & this.events) != 0); } @@ -177,7 +178,7 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { + onSubscriptionsChangedListenerCallback + " onOpportunisticSubscriptionsChangedListenererCallback=" + onOpportunisticSubscriptionsChangedListenerCallback + " subId=" + subId - + " phoneId=" + phoneId + " events=" + Integer.toHexString(events) + "}"; + + " phoneId=" + phoneId + " events=" + Long.toHexString(events) + "}"; } } @@ -306,6 +307,8 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { private final LocalLog mListenLog = new LocalLog(00); + private List<PhysicalChannelConfig> mPhysicalChannelConfigs; + /** * Per-phone map of precise data connection state. The key of the map is the pair of transport * type and APN setting. This is the cache to prevent redundant callbacks to the listeners. @@ -318,19 +321,19 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { // Starting in Q, almost all cellular location requires FINE location enforcement. // Prior to Q, cellular was available with COARSE location enforcement. Bits in this // list will be checked for COARSE on apps targeting P or earlier and FINE on Q or later. - static final int ENFORCE_LOCATION_PERMISSION_MASK = + static final long ENFORCE_LOCATION_PERMISSION_MASK = PhoneStateListener.LISTEN_CELL_LOCATION | PhoneStateListener.LISTEN_CELL_INFO | PhoneStateListener.LISTEN_REGISTRATION_FAILURE | PhoneStateListener.LISTEN_BARRING_INFO; - static final int ENFORCE_PHONE_STATE_PERMISSION_MASK = + static final long ENFORCE_PHONE_STATE_PERMISSION_MASK = PhoneStateListener.LISTEN_CALL_FORWARDING_INDICATOR | PhoneStateListener.LISTEN_MESSAGE_WAITING_INDICATOR | PhoneStateListener.LISTEN_EMERGENCY_NUMBER_LIST | PhoneStateListener.LISTEN_DISPLAY_INFO_CHANGED; - static final int ENFORCE_PRECISE_PHONE_STATE_PERMISSION_MASK = + static final long ENFORCE_PRECISE_PHONE_STATE_PERMISSION_MASK = PhoneStateListener.LISTEN_PRECISE_CALL_STATE | PhoneStateListener.LISTEN_PRECISE_DATA_CONNECTION_STATE | PhoneStateListener.LISTEN_CALL_DISCONNECT_CAUSES @@ -339,11 +342,11 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { | PhoneStateListener.LISTEN_REGISTRATION_FAILURE | PhoneStateListener.LISTEN_BARRING_INFO; - static final int READ_ACTIVE_EMERGENCY_SESSION_PERMISSION_MASK = + static final long READ_ACTIVE_EMERGENCY_SESSION_PERMISSION_MASK = PhoneStateListener.LISTEN_OUTGOING_EMERGENCY_CALL | PhoneStateListener.LISTEN_OUTGOING_EMERGENCY_SMS; - static final int READ_PRIVILEGED_PHONE_STATE_PERMISSION_MASK = + static final long READ_PRIVILEGED_PHONE_STATE_PERMISSION_MASK = PhoneStateListener.LISTEN_OEM_HOOK_RAW_EVENT | PhoneStateListener.LISTEN_SRVCC_STATE_CHANGED | PhoneStateListener.LISTEN_RADIO_POWER_STATE_CHANGED @@ -495,6 +498,7 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { cutListToSize(mImsReasonInfo, mNumPhones); cutListToSize(mPreciseDataConnectionStates, mNumPhones); cutListToSize(mBarringInfo, mNumPhones); + cutListToSize(mPhysicalChannelConfigs, mNumPhones); return; } @@ -528,6 +532,8 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { mPreciseDataConnectionStates.add(new ArrayMap<>()); mBarringInfo.add(i, new BarringInfo()); mTelephonyDisplayInfos[i] = null; + mPhysicalChannelConfigs.add(i, new PhysicalChannelConfig( + PhysicalChannelConfig.CONNECTION_UNKNOWN,0)); } } @@ -588,6 +594,7 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { mOutgoingSmsEmergencyNumber = new EmergencyNumber[numPhones]; mBarringInfo = new ArrayList<>(); mTelephonyDisplayInfos = new TelephonyDisplayInfo[numPhones]; + mPhysicalChannelConfigs = new ArrayList<>(); for (int i = 0; i < numPhones; i++) { mCallState[i] = TelephonyManager.CALL_STATE_IDLE; mDataActivity[i] = TelephonyManager.DATA_ACTIVITY_NONE; @@ -617,6 +624,8 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { mPreciseDataConnectionStates.add(new ArrayMap<>()); mBarringInfo.add(i, new BarringInfo()); mTelephonyDisplayInfos[i] = null; + mPhysicalChannelConfigs.add(i, new PhysicalChannelConfig( + PhysicalChannelConfig.CONNECTION_UNKNOWN,0)); } mAppOps = mContext.getSystemService(AppOpsManager.class); @@ -795,23 +804,23 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { @Override public void listenWithFeature(String callingPackage, String callingFeatureId, - IPhoneStateListener callback, int events, boolean notifyNow) { + IPhoneStateListener callback, long events, boolean notifyNow) { listenForSubscriber(SubscriptionManager.DEFAULT_SUBSCRIPTION_ID, callingPackage, callingFeatureId, callback, events, notifyNow); } @Override public void listenForSubscriber(int subId, String callingPackage, String callingFeatureId, - IPhoneStateListener callback, int events, boolean notifyNow) { + IPhoneStateListener callback, long events, boolean notifyNow) { listen(callingPackage, callingFeatureId, callback, events, notifyNow, subId); } private void listen(String callingPackage, @Nullable String callingFeatureId, - IPhoneStateListener callback, int events, boolean notifyNow, int subId) { + IPhoneStateListener callback, long events, boolean notifyNow, int subId) { int callerUserId = UserHandle.getCallingUserId(); mAppOps.checkPackage(Binder.getCallingUid(), callingPackage); String str = "listen: E pkg=" + pii(callingPackage) + " uid=" + Binder.getCallingUid() - + " events=0x" + Integer.toHexString(events) + " notifyNow=" + notifyNow + " subId=" + + " events=0x" + Long.toHexString(events) + " notifyNow=" + notifyNow + " subId=" + subId + " myUserId=" + UserHandle.myUserId() + " callerUserId=" + callerUserId; mListenLog.log(str); if (VDBG) { @@ -1098,6 +1107,14 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { remove(r.binder); } } + if ((events & PhoneStateListener.LISTEN_PHYSICAL_CHANNEL_CONFIGURATION) != 0) { + try { + r.callback.onPhysicalChannelConfigurationChanged( + mPhysicalChannelConfigs); + } catch (RemoteException ex) { + remove(r.binder); + } + } } } } else { @@ -2258,6 +2275,47 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { } } + /** + * Send a notification to registrants that the configs of physical channel has changed for + * a particular subscription. + * + * @param subId the subId + * @param configs a list of {@link PhysicalChannelConfig}, the configs of physical channel. + */ + public void notifyPhysicalChannelConfigurationForSubscriber( + int subId, List<PhysicalChannelConfig> configs) { + if (!checkNotifyPermission("notifyPhysicalChannelConfiguration()")) { + return; + } + + if (VDBG) { + log("notifyPhysicalChannelConfiguration: subId=" + subId + " configs=" + configs); + } + + synchronized (mRecords) { + int phoneId = SubscriptionManager.getPhoneId(subId); + if (validatePhoneId(phoneId)) { + mPhysicalChannelConfigs.set(phoneId, configs.get(phoneId)); + for (Record r : mRecords) { + if (r.matchPhoneStateListenerEvent( + PhoneStateListener.LISTEN_PHYSICAL_CHANNEL_CONFIGURATION) + && idMatch(r.subId, subId, phoneId)) { + try { + if (DBG_LOC) { + log("notifyPhysicalChannelConfiguration: " + + "mPhysicalChannelConfigs=" + + configs + " r=" + r); + } + r.callback.onPhysicalChannelConfigurationChanged(configs); + } catch (RemoteException ex) { + mRemoveList.add(r.binder); + } + } + } + } + handleRemoveListLocked(); + } + } @Override public void dump(FileDescriptor fd, PrintWriter writer, String[] args) { @@ -2310,6 +2368,7 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { pw.println("mEmergencyNumberList=" + mEmergencyNumberList); pw.println("mDefaultPhoneId=" + mDefaultPhoneId); pw.println("mDefaultSubId=" + mDefaultSubId); + pw.println("mPhysicalChannelConfigs=" + mPhysicalChannelConfigs); pw.decreaseIndent(); @@ -2536,7 +2595,7 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { == PackageManager.PERMISSION_GRANTED; } - private boolean checkListenerPermission(int events, int subId, String callingPackage, + private boolean checkListenerPermission(long events, int subId, String callingPackage, @Nullable String callingFeatureId, String message) { LocationAccessPolicy.LocationPermissionQuery.Builder locationQueryBuilder = new LocationAccessPolicy.LocationPermissionQuery.Builder() @@ -2742,7 +2801,7 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { } private void checkPossibleMissNotify(Record r, int phoneId) { - int events = r.events; + long events = r.events; if ((events & PhoneStateListener.LISTEN_SERVICE_STATE) != 0) { try { diff --git a/services/core/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java index 343e05d982fd..c441bd60f784 100644 --- a/services/core/java/com/android/server/am/ActiveServices.java +++ b/services/core/java/com/android/server/am/ActiveServices.java @@ -768,9 +768,7 @@ public final class ActiveServices { FrameworkStatsLog.write(FrameworkStatsLog.SERVICE_STATE_CHANGED, r.appInfo.uid, r.name.getPackageName(), r.name.getClassName(), FrameworkStatsLog.SERVICE_STATE_CHANGED__STATE__START); - synchronized (r.stats.getBatteryStats()) { - r.stats.startRunningLocked(); - } + mAm.mBatteryStatsService.noteServiceStartRunning(r.stats); String error = bringUpServiceLocked(r, service.getFlags(), callerFg, false, false); if (error != null) { return new ComponentName("!!", error); @@ -809,9 +807,7 @@ public final class ActiveServices { FrameworkStatsLog.write(FrameworkStatsLog.SERVICE_STATE_CHANGED, service.appInfo.uid, service.name.getPackageName(), service.name.getClassName(), FrameworkStatsLog.SERVICE_STATE_CHANGED__STATE__STOP); - synchronized (service.stats.getBatteryStats()) { - service.stats.stopRunningLocked(); - } + mAm.mBatteryStatsService.noteServiceStopRunning(service.stats); service.startRequested = false; if (service.tracker != null) { service.tracker.setStarted(false, mAm.mProcessStats.getMemFactorLocked(), @@ -970,9 +966,7 @@ public final class ActiveServices { FrameworkStatsLog.write(FrameworkStatsLog.SERVICE_STATE_CHANGED, r.appInfo.uid, r.name.getPackageName(), r.name.getClassName(), FrameworkStatsLog.SERVICE_STATE_CHANGED__STATE__STOP); - synchronized (r.stats.getBatteryStats()) { - r.stats.stopRunningLocked(); - } + mAm.mBatteryStatsService.noteServiceStopRunning(r.stats); r.startRequested = false; if (r.tracker != null) { r.tracker.setStarted(false, mAm.mProcessStats.getMemFactorLocked(), @@ -2518,7 +2512,8 @@ public final class ActiveServices { synchronized (stats) { ss = stats.getServiceStatsLocked( sInfo.applicationInfo.uid, name.getPackageName(), - name.getClassName()); + name.getClassName(), SystemClock.elapsedRealtime(), + SystemClock.uptimeMillis()); } r = new ServiceRecord(mAm, ss, className, name, definingPackageName, definingUid, filter, sInfo, callingFromFg, res); @@ -3056,9 +3051,7 @@ public final class ActiveServices { } FrameworkStatsLog.write(FrameworkStatsLog.SERVICE_LAUNCH_REPORTED, r.appInfo.uid, r.name.getPackageName(), r.name.getClassName()); - synchronized (r.stats.getBatteryStats()) { - r.stats.startLaunchedLocked(); - } + mAm.mBatteryStatsService.noteServiceStartLaunch(r.stats); mAm.notifyPackageUse(r.serviceInfo.packageName, PackageManager.NOTIFY_PACKAGE_USE_SERVICE); app.forceProcessStateUpTo(ActivityManager.PROCESS_STATE_SERVICE); @@ -3402,9 +3395,7 @@ public final class ActiveServices { smap.mDelayedStartList.remove(r); if (r.app != null) { - synchronized (r.stats.getBatteryStats()) { - r.stats.stopLaunchedLocked(); - } + mAm.mBatteryStatsService.noteServiceStopLaunch(r.stats); r.app.stopService(r); r.app.updateBoundClientUids(); if (r.whitelistManager) { @@ -3940,9 +3931,7 @@ public final class ActiveServices { // Clear app state from services. for (int i = app.numberOfRunningServices() - 1; i >= 0; i--) { ServiceRecord sr = app.getRunningServiceAt(i); - synchronized (sr.stats.getBatteryStats()) { - sr.stats.stopLaunchedLocked(); - } + mAm.mBatteryStatsService.noteServiceStopLaunch(sr.stats); if (sr.app != app && sr.app != null && !sr.app.isPersistent()) { sr.app.stopService(sr); sr.app.updateBoundClientUids(); diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java index a5d2011483bc..7e6649660aa9 100644 --- a/services/core/java/com/android/server/am/ActivityManagerService.java +++ b/services/core/java/com/android/server/am/ActivityManagerService.java @@ -133,7 +133,6 @@ import static com.android.server.wm.ActivityTaskManagerService.DUMP_STARTER_CMD; import static com.android.server.wm.ActivityTaskManagerService.RELAUNCH_REASON_NONE; import static com.android.server.wm.ActivityTaskManagerService.relaunchReasonToString; - import android.Manifest; import android.Manifest.permission; import android.annotation.BroadcastBehavior; @@ -143,8 +142,8 @@ import android.annotation.UserIdInt; import android.app.Activity; import android.app.ActivityManager; import android.app.ActivityManager.RunningTaskInfo; -import android.app.ActivityManager.StackInfo; import android.app.ActivityManagerInternal; +import android.app.ActivityTaskManager.RootTaskInfo; import android.app.ActivityThread; import android.app.AppGlobals; import android.app.AppOpsManager; @@ -342,7 +341,6 @@ import com.android.server.PackageWatchdog; import com.android.server.ServiceThread; import com.android.server.SystemConfig; import com.android.server.SystemService; -import com.android.server.SystemService.TargetUser; import com.android.server.SystemServiceManager; import com.android.server.ThreadPriorityBooster; import com.android.server.UserspaceRebootLogger; @@ -2835,14 +2833,16 @@ public class ActivityManagerService extends IActivityManager.Stub } final BatteryStatsImpl bstats = mBatteryStatsService.getActiveStatistics(); - synchronized(bstats) { - synchronized(mPidsSelfLocked) { - if (haveNewCpuStats) { - if (bstats.startAddingCpuLocked()) { - int totalUTime = 0; - int totalSTime = 0; - final int N = mProcessCpuTracker.countStats(); - for (int i=0; i<N; i++) { + synchronized (bstats) { + if (haveNewCpuStats) { + if (bstats.startAddingCpuLocked()) { + int totalUTime = 0; + int totalSTime = 0; + final int statsCount = mProcessCpuTracker.countStats(); + final long elapsedRealtime = SystemClock.elapsedRealtime(); + final long uptime = SystemClock.uptimeMillis(); + synchronized (mPidsSelfLocked) { + for (int i = 0; i < statsCount; i++) { ProcessCpuTracker.Stats st = mProcessCpuTracker.getStats(i); if (!st.working) { continue; @@ -2854,7 +2854,8 @@ public class ActivityManagerService extends IActivityManager.Stub BatteryStatsImpl.Uid.Proc ps = pr.curProcBatteryStats; if (ps == null || !ps.isActive()) { pr.curProcBatteryStats = ps = bstats.getProcessStatsLocked( - pr.info.uid, pr.processName); + pr.info.uid, pr.processName, + elapsedRealtime, uptime); } ps.addCpuTimeLocked(st.rel_utime, st.rel_stime); pr.curCpuTime += st.rel_utime + st.rel_stime; @@ -2865,20 +2866,22 @@ public class ActivityManagerService extends IActivityManager.Stub BatteryStatsImpl.Uid.Proc ps = st.batteryStats; if (ps == null || !ps.isActive()) { st.batteryStats = ps = bstats.getProcessStatsLocked( - bstats.mapUid(st.uid), st.name); + bstats.mapUid(st.uid), st.name, + elapsedRealtime, uptime); } ps.addCpuTimeLocked(st.rel_utime, st.rel_stime); } } - final int userTime = mProcessCpuTracker.getLastUserTime(); - final int systemTime = mProcessCpuTracker.getLastSystemTime(); - final int iowaitTime = mProcessCpuTracker.getLastIoWaitTime(); - final int irqTime = mProcessCpuTracker.getLastIrqTime(); - final int softIrqTime = mProcessCpuTracker.getLastSoftIrqTime(); - final int idleTime = mProcessCpuTracker.getLastIdleTime(); - bstats.finishAddingCpuLocked(totalUTime, totalSTime, userTime, - systemTime, iowaitTime, irqTime, softIrqTime, idleTime); } + + final int userTime = mProcessCpuTracker.getLastUserTime(); + final int systemTime = mProcessCpuTracker.getLastSystemTime(); + final int iowaitTime = mProcessCpuTracker.getLastIoWaitTime(); + final int irqTime = mProcessCpuTracker.getLastIrqTime(); + final int softIrqTime = mProcessCpuTracker.getLastSoftIrqTime(); + final int idleTime = mProcessCpuTracker.getLastIdleTime(); + bstats.finishAddingCpuLocked(totalUTime, totalSTime, userTime, + systemTime, iowaitTime, irqTime, softIrqTime, idleTime); } } @@ -3076,18 +3079,8 @@ public class ActivityManagerService extends IActivityManager.Stub Slog.d(TAG_SWITCH, "updateBatteryStats: comp=" + activity + "res=" + resumed); } - final BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics(); - FrameworkStatsLog.write(FrameworkStatsLog.ACTIVITY_FOREGROUND_STATE_CHANGED, - uid, activity.getPackageName(), activity.getShortClassName(), - resumed ? FrameworkStatsLog.ACTIVITY_FOREGROUND_STATE_CHANGED__STATE__FOREGROUND : - FrameworkStatsLog.ACTIVITY_FOREGROUND_STATE_CHANGED__STATE__BACKGROUND); - synchronized (stats) { - if (resumed) { - stats.noteActivityResumedLocked(uid); - } else { - stats.noteActivityPausedLocked(uid); - } - } + mBatteryStatsService.updateBatteryStatsOnActivityUsage(activity.getPackageName(), + activity.getShortClassName(), uid, userId, resumed); } /** @@ -3626,10 +3619,7 @@ public class ActivityManagerService extends IActivityManager.Stub } } - BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics(); - synchronized (stats) { - stats.noteProcessDiedLocked(app.info.uid, pid); - } + mBatteryStatsService.noteProcessDied(app.info.uid, pid); if (!app.killed) { if (!fromBinderDied) { @@ -6418,8 +6408,8 @@ public class ActivityManagerService extends IActivityManager.Stub } @Override - public List<StackInfo> getAllStackInfos() { - return mActivityTaskManager.getAllStackInfos(); + public List<RootTaskInfo> getAllRootTaskInfos() { + return mActivityTaskManager.getAllRootTaskInfos(); } @Override @@ -7300,53 +7290,6 @@ public class ActivityManagerService extends IActivityManager.Stub return uidRecord != null && !uidRecord.setIdle; } - /** - * Change the sched policy cgroup of a thread. - * - * <p>It is intended to be used in jni call of {@link Process#setThreadPriority(int, int)}. - * When a process is changing the priority of its threads, the sched policy of that - * thread may need to be changed accordingly - if the priority is changed to below - * or equal to {@link android.os.Process#THREAD_PRIORITY_BACKGROUND} or raising from it. - * However, because of the limitation of sepolicy, the thread priority change will - * fail for some processes. To solve it, we add this binder call in Activity Manager, - * so that the jni call of {@link Process#setThreadPriority(int, int)} could use it. - * - * @param tid tid of the thread to be changed. - * @param group The sched policy group to be changed to. - * - * @throws IllegalArgumentException if group is invalid. - * @throws SecurityException if no permission. - * - * @return Returns {@code true} if the sched policy is changed successfully; - * {@code false} otherwise. - */ - @Override - public boolean setSchedPolicyCgroup(final int tid, final int group) { - final int pid = Binder.getCallingPid(); - final int tgid = Process.getThreadGroupLeader(tid); - final int pgroup = Process.getProcessGroup(pid); - - // tid is not in the thread group of caller - if (pid != tgid) { - return false; - } - - // sched group is higher than its main process - if (group > pgroup) { - return false; - } - - try { - Process.setThreadGroup(tid, group); - return true; - } catch (IllegalArgumentException e) { - Slog.w(TAG, "Failed to set thread group, argument invalid:\n" + e); - } catch (SecurityException e) { - Slog.w(TAG, "Failed to set thread group, no permission:\n" + e); - } - return false; - } - @Override public void setPersistentVrThread(int tid) { mActivityTaskManager.setPersistentVrThread(tid); @@ -14582,10 +14525,7 @@ public class ActivityManagerService extends IActivityManager.Stub timeFormatPreferenceMsgValue, 0); mHandler.sendMessage(updateTimePreferenceMsg); } - BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics(); - synchronized (stats) { - stats.noteCurrentTimeChangedLocked(); - } + mBatteryStatsService.noteCurrentTimeChanged(); break; case Intent.ACTION_CLEAR_DNS_CACHE: mHandler.sendEmptyMessage(CLEAR_DNS_CACHE_MSG); @@ -15385,8 +15325,8 @@ public class ActivityManagerService extends IActivityManager.Stub } @Override - public StackInfo getFocusedStackInfo() throws RemoteException { - return mActivityTaskManager.getFocusedStackInfo(); + public RootTaskInfo getFocusedRootTaskInfo() throws RemoteException { + return mActivityTaskManager.getFocusedRootTaskInfo(); } @Override @@ -15957,7 +15897,6 @@ public class ActivityManagerService extends IActivityManager.Stub updateCpuStatsNow(); synchronized (this) { - BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics(); boolean doCpuKills = true; if (mLastPowerCheckUptime == 0) { doCpuKills = false; @@ -16004,10 +15943,8 @@ public class ActivityManagerService extends IActivityManager.Stub cpuLimit = mConstants.POWER_CHECK_MAX_CPU_4; } if (((cputimeUsed * 100) / uptimeSince) >= cpuLimit) { - synchronized (stats) { - stats.reportExcessiveCpuLocked(app.info.uid, app.processName, + mBatteryStatsService.reportExcessiveCpu(app.info.uid, app.processName, uptimeSince, cputimeUsed); - } app.kill("excessive cpu " + cputimeUsed + " during " + uptimeSince + " dur=" + checkDur + " limit=" + cpuLimit, ApplicationExitInfo.REASON_EXCESSIVE_RESOURCE_USAGE, @@ -17513,19 +17450,7 @@ public class ActivityManagerService extends IActivityManager.Stub @Override public void updateForegroundTimeIfOnBattery( String packageName, int uid, long cpuTimeDiff) { - synchronized (ActivityManagerService.this) { - if (!mBatteryStatsService.isOnBattery()) { - return; - } - final BatteryStatsImpl bsi = mBatteryStatsService.getActiveStatistics(); - synchronized (bsi) { - final BatteryStatsImpl.Uid.Proc ps = - bsi.getProcessStatsLocked(uid, packageName); - if (ps != null) { - ps.addForegroundTimeLocked(cpuTimeDiff); - } - } - } + mBatteryStatsService.updateForegroundTimeIfOnBattery(packageName, uid, cpuTimeDiff); } @Override diff --git a/services/core/java/com/android/server/am/ActivityManagerShellCommand.java b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java index a512cca7bac4..9ce8b11a7351 100644 --- a/services/core/java/com/android/server/am/ActivityManagerShellCommand.java +++ b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java @@ -28,6 +28,7 @@ import static android.view.Display.INVALID_DISPLAY; import android.app.ActivityManager; import android.app.ActivityOptions; import android.app.ActivityTaskManager; +import android.app.ActivityTaskManager.RootTaskInfo; import android.app.AppGlobals; import android.app.BroadcastOptions; import android.app.IActivityController; @@ -2586,7 +2587,7 @@ final class ActivityManagerShellCommand extends ShellCommand { case "list": return runStackList(pw); case "info": - return runStackInfo(pw); + return runRootTaskInfo(pw); case "move-top-activity-to-pinned-stack": return runMoveTopActivityToPinnedStack(pw); case "remove": @@ -2668,17 +2669,17 @@ final class ActivityManagerShellCommand extends ShellCommand { } int runStackList(PrintWriter pw) throws RemoteException { - List<ActivityManager.StackInfo> stacks = mTaskInterface.getAllStackInfos(); - for (ActivityManager.StackInfo info : stacks) { + List<RootTaskInfo> tasks = mTaskInterface.getAllRootTaskInfos(); + for (RootTaskInfo info : tasks) { pw.println(info); } return 0; } - int runStackInfo(PrintWriter pw) throws RemoteException { + int runRootTaskInfo(PrintWriter pw) throws RemoteException { int windowingMode = Integer.parseInt(getNextArgRequired()); int activityType = Integer.parseInt(getNextArgRequired()); - ActivityManager.StackInfo info = mTaskInterface.getStackInfo(windowingMode, activityType); + RootTaskInfo info = mTaskInterface.getRootTaskInfo(windowingMode, activityType); pw.println(info); return 0; } diff --git a/services/core/java/com/android/server/am/BatteryExternalStatsWorker.java b/services/core/java/com/android/server/am/BatteryExternalStatsWorker.java index 39f79ca2f13b..692b3f11a5f8 100644 --- a/services/core/java/com/android/server/am/BatteryExternalStatsWorker.java +++ b/services/core/java/com/android/server/am/BatteryExternalStatsWorker.java @@ -376,7 +376,8 @@ class BatteryExternalStatsWorker implements BatteryStatsImpl.ExternalStatsSync { for (int uid : uidsToRemove) { FrameworkStatsLog.write(FrameworkStatsLog.ISOLATED_UID_CHANGED, -1, uid, FrameworkStatsLog.ISOLATED_UID_CHANGED__EVENT__REMOVED); - mStats.removeIsolatedUidLocked(uid); + mStats.removeIsolatedUidLocked(uid, SystemClock.elapsedRealtime(), + SystemClock.uptimeMillis()); } mStats.clearPendingRemovedUids(); } @@ -473,11 +474,15 @@ class BatteryExternalStatsWorker implements BatteryStatsImpl.ExternalStatsSync { final WifiActivityEnergyInfo wifiInfo = awaitControllerInfo(wifiReceiver); final BluetoothActivityEnergyInfo bluetoothInfo = awaitControllerInfo(bluetoothReceiver); final ModemActivityInfo modemInfo = awaitControllerInfo(modemReceiver); + final long elapsedRealtime = SystemClock.elapsedRealtime(); + final long uptime = SystemClock.uptimeMillis(); + final long elapsedRealtimeUs = elapsedRealtime * 1000; + final long uptimeUs = uptime * 1000; synchronized (mStats) { mStats.addHistoryEventLocked( - SystemClock.elapsedRealtime(), - SystemClock.uptimeMillis(), + elapsedRealtime, + uptime, BatteryStats.HistoryItem.EVENT_COLLECT_EXTERNAL_STATS, reason, 0); @@ -490,17 +495,17 @@ class BatteryExternalStatsWorker implements BatteryStatsImpl.ExternalStatsSync { } if ((updateFlags & UPDATE_ALL) != 0) { - mStats.updateKernelWakelocksLocked(); - mStats.updateKernelMemoryBandwidthLocked(); + mStats.updateKernelWakelocksLocked(elapsedRealtimeUs); + mStats.updateKernelMemoryBandwidthLocked(elapsedRealtimeUs); } if ((updateFlags & UPDATE_RPM) != 0) { - mStats.updateRpmStatsLocked(); + mStats.updateRpmStatsLocked(elapsedRealtimeUs); } if (bluetoothInfo != null) { if (bluetoothInfo.isValid()) { - mStats.updateBluetoothStateLocked(bluetoothInfo); + mStats.updateBluetoothStateLocked(bluetoothInfo, elapsedRealtime, uptime); } else { Slog.w(TAG, "bluetooth info is invalid: " + bluetoothInfo); } @@ -512,7 +517,7 @@ class BatteryExternalStatsWorker implements BatteryStatsImpl.ExternalStatsSync { if (wifiInfo != null) { if (wifiInfo.isValid()) { - mStats.updateWifiState(extractDeltaLocked(wifiInfo)); + mStats.updateWifiState(extractDeltaLocked(wifiInfo), elapsedRealtime, uptime); } else { Slog.w(TAG, "wifi info is invalid: " + wifiInfo); } @@ -520,7 +525,7 @@ class BatteryExternalStatsWorker implements BatteryStatsImpl.ExternalStatsSync { if (modemInfo != null) { if (modemInfo.isValid()) { - mStats.updateMobileRadioState(modemInfo); + mStats.updateMobileRadioState(modemInfo, elapsedRealtime, uptime); } else { Slog.w(TAG, "modem info is invalid: " + modemInfo); } diff --git a/services/core/java/com/android/server/am/BatteryStatsService.java b/services/core/java/com/android/server/am/BatteryStatsService.java index d72998ba95f1..f42753287e35 100644 --- a/services/core/java/com/android/server/am/BatteryStatsService.java +++ b/services/core/java/com/android/server/am/BatteryStatsService.java @@ -25,6 +25,7 @@ import android.os.BatteryStats; import android.os.BatteryStatsInternal; import android.os.Binder; import android.os.Handler; +import android.os.HandlerThread; import android.os.IBinder; import android.os.Parcel; import android.os.ParcelFileDescriptor; @@ -62,7 +63,9 @@ import com.android.internal.os.RpmStats; import com.android.internal.util.DumpUtils; import com.android.internal.util.FrameworkStatsLog; import com.android.internal.util.ParseUtils; +import com.android.internal.util.function.pooled.PooledLambda; import com.android.server.LocalServices; +import com.android.server.Watchdog; import java.io.File; import java.io.FileDescriptor; @@ -76,6 +79,7 @@ import java.nio.charset.StandardCharsets; import java.util.Arrays; import java.util.Collection; import java.util.List; +import java.util.concurrent.CountDownLatch; import java.util.concurrent.ExecutionException; import java.util.concurrent.Future; @@ -86,7 +90,8 @@ import java.util.concurrent.Future; public final class BatteryStatsService extends IBatteryStats.Stub implements PowerManagerInternal.LowPowerModeListener, BatteryStatsImpl.PlatformIdleStateCallback, - BatteryStatsImpl.RailEnergyDataCallback { + BatteryStatsImpl.RailEnergyDataCallback, + Watchdog.Monitor { static final String TAG = "BatteryStatsService"; static final boolean DBG = false; @@ -110,6 +115,10 @@ public final class BatteryStatsService extends IBatteryStats.Stub private CharBuffer mUtf16BufferStat = CharBuffer.allocate(MAX_LOW_POWER_STATS_SIZE); private static final int MAX_LOW_POWER_STATS_SIZE = 4096; + private final HandlerThread mHandlerThread; + private final Handler mHandler; + private final Object mLock = new Object(); + /** * Replaces the information in the given rpmStats with up-to-date information. */ @@ -190,6 +199,9 @@ public final class BatteryStatsService extends IBatteryStats.Stub return (umi != null) ? umi.getUserIds() : null; } }; + mHandlerThread = new HandlerThread("batterystats-handler"); + mHandlerThread.start(); + mHandler = new Handler(mHandlerThread.getLooper()); mStats = new BatteryStatsImpl(systemDir, handler, this, this, mUserManagerUserInfoProvider); mWorker = new BatteryExternalStatsWorker(context, mStats); @@ -206,6 +218,7 @@ public final class BatteryStatsService extends IBatteryStats.Stub public void systemServicesReady() { mStats.systemServicesReady(mContext); + Watchdog.getInstance().addMonitor(this); } private final class LocalService extends BatteryStatsInternal { @@ -228,8 +241,20 @@ public final class BatteryStatsService extends IBatteryStats.Stub @Override public void noteBinderCallStats(int workSourceUid, long incrementatCallCount, Collection<BinderCallsStats.CallStat> callStats, int[] binderThreadNativeTids) { - mStats.noteBinderCallStats(workSourceUid, incrementatCallCount, callStats, - binderThreadNativeTids); + synchronized (BatteryStatsService.this.mLock) { + mHandler.sendMessage(PooledLambda.obtainMessage( + mStats::noteBinderCallStats, workSourceUid, incrementatCallCount, + callStats, binderThreadNativeTids, + SystemClock.elapsedRealtime(), SystemClock.uptimeMillis())); + } + } + } + + @Override + public void monitor() { + synchronized (mLock) { + } + synchronized (mStats) { } } @@ -250,6 +275,19 @@ public final class BatteryStatsService extends IBatteryStats.Stub awaitUninterruptibly(mWorker.scheduleSync(reason, flags)); } + private void awaitCompletion() { + synchronized (mLock) { + final CountDownLatch latch = new CountDownLatch(1); + mHandler.post(() -> { + latch.countDown(); + }); + try { + latch.await(); + } catch (InterruptedException e) { + } + } + } + /** * At the time when the constructor runs, the power manager has not yet been * initialized. So we initialize the low power observer later. @@ -259,8 +297,8 @@ public final class BatteryStatsService extends IBatteryStats.Stub powerMgr.registerLowPowerModeObserver(this); synchronized (mStats) { mStats.notePowerSaveModeLocked( - powerMgr.getLowPowerState(ServiceType.BATTERY_STATS) - .batterySaverEnabled); + powerMgr.getLowPowerState(ServiceType.BATTERY_STATS).batterySaverEnabled, + SystemClock.elapsedRealtime(), SystemClock.uptimeMillis()); } (new WakeupReasonThread()).start(); } @@ -268,6 +306,9 @@ public final class BatteryStatsService extends IBatteryStats.Stub public void shutdown() { Slog.w("BatteryStats", "Writing battery stats before shutdown..."); + // Drain the handler queue to make sure we've handled all pending works. + awaitCompletion(); + syncStats("shutdown", BatteryExternalStatsWorker.UPDATE_ALL); synchronized (mStats) { @@ -293,9 +334,16 @@ public final class BatteryStatsService extends IBatteryStats.Stub } @Override - public void onLowPowerModeChanged(PowerSaveState result) { - synchronized (mStats) { - mStats.notePowerSaveModeLocked(result.batterySaverEnabled); + public void onLowPowerModeChanged(final PowerSaveState result) { + synchronized (mLock) { + final long elapsedRealtime = SystemClock.elapsedRealtime(); + final long uptime = SystemClock.uptimeMillis(); + mHandler.post(() -> { + synchronized (mStats) { + mStats.notePowerSaveModeLocked(result.batterySaverEnabled, + elapsedRealtime, uptime); + } + }); } } @@ -313,7 +361,12 @@ public final class BatteryStatsService extends IBatteryStats.Stub * object to update with the latest info, then write to disk. */ public void scheduleWriteToDisk() { - mWorker.scheduleWrite(); + synchronized (mLock) { + // We still schedule it on the handler so we'll have all existing pending works done. + mHandler.post(() -> { + mWorker.scheduleWrite(); + }); + } } // These are for direct use by the activity manager... @@ -321,70 +374,124 @@ public final class BatteryStatsService extends IBatteryStats.Stub /** * Remove a UID from the BatteryStats and BatteryStats' external dependencies. */ - void removeUid(int uid) { - synchronized (mStats) { - mStats.removeUidStatsLocked(uid); + void removeUid(final int uid) { + synchronized (mLock) { + final long elapsedRealtime = SystemClock.elapsedRealtime(); + mHandler.post(() -> { + synchronized (mStats) { + mStats.removeUidStatsLocked(uid, elapsedRealtime); + } + }); } } - void onCleanupUser(int userId) { - synchronized (mStats) { - mStats.onCleanupUserLocked(userId); + void onCleanupUser(final int userId) { + synchronized (mLock) { + final long elapsedRealtime = SystemClock.elapsedRealtime(); + mHandler.post(() -> { + synchronized (mStats) { + mStats.onCleanupUserLocked(userId, elapsedRealtime); + } + }); } } - void onUserRemoved(int userId) { - synchronized (mStats) { - mStats.onUserRemovedLocked(userId); + void onUserRemoved(final int userId) { + synchronized (mLock) { + mHandler.post(() -> { + synchronized (mStats) { + mStats.onUserRemovedLocked(userId); + } + }); } } - void addIsolatedUid(int isolatedUid, int appUid) { - synchronized (mStats) { - mStats.addIsolatedUidLocked(isolatedUid, appUid); + void addIsolatedUid(final int isolatedUid, final int appUid) { + synchronized (mLock) { + final long elapsedRealtime = SystemClock.elapsedRealtime(); + final long uptime = SystemClock.uptimeMillis(); + mHandler.post(() -> { + synchronized (mStats) { + mStats.addIsolatedUidLocked(isolatedUid, appUid, elapsedRealtime, uptime); + } + }); } } - void removeIsolatedUid(int isolatedUid, int appUid) { - synchronized (mStats) { - mStats.scheduleRemoveIsolatedUidLocked(isolatedUid, appUid); + void removeIsolatedUid(final int isolatedUid, final int appUid) { + synchronized (mLock) { + mHandler.post(() -> { + synchronized (mStats) { + mStats.scheduleRemoveIsolatedUidLocked(isolatedUid, appUid); + } + }); } } - void noteProcessStart(String name, int uid) { - synchronized (mStats) { - mStats.noteProcessStartLocked(name, uid); - FrameworkStatsLog.write(FrameworkStatsLog.PROCESS_LIFE_CYCLE_STATE_CHANGED, uid, name, - FrameworkStatsLog.PROCESS_LIFE_CYCLE_STATE_CHANGED__STATE__STARTED); + void noteProcessStart(final String name, final int uid) { + synchronized (mLock) { + final long elapsedRealtime = SystemClock.elapsedRealtime(); + final long uptime = SystemClock.uptimeMillis(); + mHandler.post(() -> { + synchronized (mStats) { + mStats.noteProcessStartLocked(name, uid, elapsedRealtime, uptime); + } + }); } + FrameworkStatsLog.write(FrameworkStatsLog.PROCESS_LIFE_CYCLE_STATE_CHANGED, uid, name, + FrameworkStatsLog.PROCESS_LIFE_CYCLE_STATE_CHANGED__STATE__STARTED); } void noteProcessCrash(String name, int uid) { - synchronized (mStats) { - mStats.noteProcessCrashLocked(name, uid); - FrameworkStatsLog.write(FrameworkStatsLog.PROCESS_LIFE_CYCLE_STATE_CHANGED, uid, name, - FrameworkStatsLog.PROCESS_LIFE_CYCLE_STATE_CHANGED__STATE__CRASHED); + synchronized (mLock) { + final long elapsedRealtime = SystemClock.elapsedRealtime(); + final long uptime = SystemClock.uptimeMillis(); + mHandler.post(() -> { + synchronized (mStats) { + mStats.noteProcessCrashLocked(name, uid, elapsedRealtime, uptime); + } + }); } + FrameworkStatsLog.write(FrameworkStatsLog.PROCESS_LIFE_CYCLE_STATE_CHANGED, uid, name, + FrameworkStatsLog.PROCESS_LIFE_CYCLE_STATE_CHANGED__STATE__CRASHED); } void noteProcessAnr(String name, int uid) { - synchronized (mStats) { - mStats.noteProcessAnrLocked(name, uid); + synchronized (mLock) { + final long elapsedRealtime = SystemClock.elapsedRealtime(); + final long uptime = SystemClock.uptimeMillis(); + mHandler.post(() -> { + synchronized (mStats) { + mStats.noteProcessAnrLocked(name, uid, elapsedRealtime, uptime); + } + }); } } void noteProcessFinish(String name, int uid) { - synchronized (mStats) { - mStats.noteProcessFinishLocked(name, uid); - FrameworkStatsLog.write(FrameworkStatsLog.PROCESS_LIFE_CYCLE_STATE_CHANGED, uid, name, - FrameworkStatsLog.PROCESS_LIFE_CYCLE_STATE_CHANGED__STATE__FINISHED); + synchronized (mLock) { + final long elapsedRealtime = SystemClock.elapsedRealtime(); + final long uptime = SystemClock.uptimeMillis(); + mHandler.post(() -> { + synchronized (mStats) { + mStats.noteProcessFinishLocked(name, uid, elapsedRealtime, uptime); + } + }); } + FrameworkStatsLog.write(FrameworkStatsLog.PROCESS_LIFE_CYCLE_STATE_CHANGED, uid, name, + FrameworkStatsLog.PROCESS_LIFE_CYCLE_STATE_CHANGED__STATE__FINISHED); } /** @param state Process state from ActivityManager.java. */ void noteUidProcessState(int uid, int state) { - synchronized (mStats) { - mStats.noteUidProcessStateLocked(uid, state); + synchronized (mLock) { + final long elapsedRealtime = SystemClock.elapsedRealtime(); + final long uptime = SystemClock.uptimeMillis(); + mHandler.post(() -> { + synchronized (mStats) { + mStats.noteUidProcessStateLocked(uid, state, elapsedRealtime, uptime); + } + }); } } @@ -396,6 +503,9 @@ public final class BatteryStatsService extends IBatteryStats.Stub //Slog.i("foo", "SENDING BATTERY INFO:"); //mStats.dumpLocked(new LogPrinter(Log.INFO, "foo", Log.LOG_ID_SYSTEM)); Parcel out = Parcel.obtain(); + // Drain the handler queue to make sure we've handled all pending works, so we'll get + // an accurate stats. + awaitCompletion(); syncStats("get-stats", BatteryExternalStatsWorker.UPDATE_ALL); synchronized (mStats) { mStats.writeToParcel(out, 0); @@ -411,6 +521,9 @@ public final class BatteryStatsService extends IBatteryStats.Stub //Slog.i("foo", "SENDING BATTERY INFO:"); //mStats.dumpLocked(new LogPrinter(Log.INFO, "foo", Log.LOG_ID_SYSTEM)); Parcel out = Parcel.obtain(); + // Drain the handler queue to make sure we've handled all pending works, so we'll get + // an accurate stats. + awaitCompletion(); syncStats("get-stats", BatteryExternalStatsWorker.UPDATE_ALL); synchronized (mStats) { mStats.writeToParcel(out, 0); @@ -446,579 +559,1015 @@ public final class BatteryStatsService extends IBatteryStats.Stub } } - public void noteEvent(int code, String name, int uid) { + public void noteEvent(final int code, final String name, final int uid) { enforceCallingPermission(); - synchronized (mStats) { - mStats.noteEventLocked(code, name, uid); + synchronized (mLock) { + final long elapsedRealtime = SystemClock.elapsedRealtime(); + final long uptime = SystemClock.uptimeMillis(); + mHandler.post(() -> { + synchronized (mStats) { + mStats.noteEventLocked(code, name, uid, elapsedRealtime, uptime); + } + }); } } - public void noteSyncStart(String name, int uid) { + public void noteSyncStart(final String name, final int uid) { enforceCallingPermission(); - synchronized (mStats) { - mStats.noteSyncStartLocked(name, uid); - FrameworkStatsLog.write_non_chained(FrameworkStatsLog.SYNC_STATE_CHANGED, uid, null, - name, FrameworkStatsLog.SYNC_STATE_CHANGED__STATE__ON); + synchronized (mLock) { + final long elapsedRealtime = SystemClock.elapsedRealtime(); + final long uptime = SystemClock.uptimeMillis(); + mHandler.post(() -> { + synchronized (mStats) { + mStats.noteSyncStartLocked(name, uid, elapsedRealtime, uptime); + } + FrameworkStatsLog.write_non_chained(FrameworkStatsLog.SYNC_STATE_CHANGED, uid, null, + name, FrameworkStatsLog.SYNC_STATE_CHANGED__STATE__ON); + }); } } - public void noteSyncFinish(String name, int uid) { + public void noteSyncFinish(final String name, final int uid) { enforceCallingPermission(); - synchronized (mStats) { - mStats.noteSyncFinishLocked(name, uid); - FrameworkStatsLog.write_non_chained(FrameworkStatsLog.SYNC_STATE_CHANGED, uid, null, - name, FrameworkStatsLog.SYNC_STATE_CHANGED__STATE__OFF); + synchronized (mLock) { + final long elapsedRealtime = SystemClock.elapsedRealtime(); + final long uptime = SystemClock.uptimeMillis(); + mHandler.post(() -> { + synchronized (mStats) { + mStats.noteSyncFinishLocked(name, uid, elapsedRealtime, uptime); + } + FrameworkStatsLog.write_non_chained(FrameworkStatsLog.SYNC_STATE_CHANGED, uid, null, + name, FrameworkStatsLog.SYNC_STATE_CHANGED__STATE__OFF); + }); } } /** A scheduled job was started. */ - public void noteJobStart(String name, int uid) { + public void noteJobStart(final String name, final int uid) { enforceCallingPermission(); - synchronized (mStats) { - mStats.noteJobStartLocked(name, uid); + synchronized (mLock) { + final long elapsedRealtime = SystemClock.elapsedRealtime(); + final long uptime = SystemClock.uptimeMillis(); + mHandler.post(() -> { + synchronized (mStats) { + mStats.noteJobStartLocked(name, uid, elapsedRealtime, uptime); + } + }); } } /** A scheduled job was finished. */ - public void noteJobFinish(String name, int uid, int stopReason) { + public void noteJobFinish(final String name, final int uid, final int stopReason) { enforceCallingPermission(); - synchronized (mStats) { - mStats.noteJobFinishLocked(name, uid, stopReason); + synchronized (mLock) { + final long elapsedRealtime = SystemClock.elapsedRealtime(); + final long uptime = SystemClock.uptimeMillis(); + mHandler.post(() -> { + synchronized (mStats) { + mStats.noteJobFinishLocked(name, uid, stopReason, elapsedRealtime, uptime); + } + }); } } - void noteJobsDeferred(int uid, int numDeferred, long sinceLast) { + void noteJobsDeferred(final int uid, final int numDeferred, final long sinceLast) { // No need to enforce calling permission, as it is called from an internal interface - synchronized (mStats) { - mStats.noteJobsDeferredLocked(uid, numDeferred, sinceLast); + synchronized (mLock) { + final long elapsedRealtime = SystemClock.elapsedRealtime(); + final long uptime = SystemClock.uptimeMillis(); + mHandler.post(() -> { + synchronized (mStats) { + mStats.noteJobsDeferredLocked(uid, numDeferred, sinceLast, + elapsedRealtime, uptime); + } + }); } } - public void noteWakupAlarm(String name, int uid, WorkSource workSource, String tag) { + public void noteWakupAlarm(final String name, final int uid, final WorkSource workSource, + final String tag) { enforceCallingPermission(); - synchronized (mStats) { - mStats.noteWakupAlarmLocked(name, uid, workSource, tag); + synchronized (mLock) { + final long elapsedRealtime = SystemClock.elapsedRealtime(); + final long uptime = SystemClock.uptimeMillis(); + mHandler.post(() -> { + synchronized (mStats) { + mStats.noteWakupAlarmLocked(name, uid, workSource, tag, + elapsedRealtime, uptime); + } + }); } } - public void noteAlarmStart(String name, WorkSource workSource, int uid) { + public void noteAlarmStart(final String name, final WorkSource workSource, final int uid) { enforceCallingPermission(); - synchronized (mStats) { - mStats.noteAlarmStartLocked(name, workSource, uid); + synchronized (mLock) { + final long elapsedRealtime = SystemClock.elapsedRealtime(); + final long uptime = SystemClock.uptimeMillis(); + mHandler.post(() -> { + synchronized (mStats) { + mStats.noteAlarmStartLocked(name, workSource, uid, elapsedRealtime, uptime); + } + }); } } - public void noteAlarmFinish(String name, WorkSource workSource, int uid) { + public void noteAlarmFinish(final String name, final WorkSource workSource, final int uid) { enforceCallingPermission(); - synchronized (mStats) { - mStats.noteAlarmFinishLocked(name, workSource, uid); + synchronized (mLock) { + final long elapsedRealtime = SystemClock.elapsedRealtime(); + final long uptime = SystemClock.uptimeMillis(); + mHandler.post(() -> { + synchronized (mStats) { + mStats.noteAlarmFinishLocked(name, workSource, uid, elapsedRealtime, uptime); + } + }); } } - public void noteStartWakelock(int uid, int pid, String name, String historyName, int type, - boolean unimportantForLogging) { + public void noteStartWakelock(final int uid, final int pid, final String name, + final String historyName, final int type, final boolean unimportantForLogging) { enforceCallingPermission(); - synchronized (mStats) { - mStats.noteStartWakeLocked(uid, pid, null, name, historyName, type, - unimportantForLogging, SystemClock.elapsedRealtime(), - SystemClock.uptimeMillis()); + synchronized (mLock) { + final long elapsedRealtime = SystemClock.elapsedRealtime(); + final long uptime = SystemClock.uptimeMillis(); + mHandler.post(() -> { + synchronized (mStats) { + mStats.noteStartWakeLocked(uid, pid, null, name, historyName, type, + unimportantForLogging, elapsedRealtime, uptime); + } + }); } } - public void noteStopWakelock(int uid, int pid, String name, String historyName, int type) { + public void noteStopWakelock(final int uid, final int pid, final String name, + final String historyName, final int type) { enforceCallingPermission(); - synchronized (mStats) { - mStats.noteStopWakeLocked(uid, pid, null, name, historyName, type, - SystemClock.elapsedRealtime(), SystemClock.uptimeMillis()); + synchronized (mLock) { + final long elapsedRealtime = SystemClock.elapsedRealtime(); + final long uptime = SystemClock.uptimeMillis(); + mHandler.post(() -> { + synchronized (mStats) { + mStats.noteStopWakeLocked(uid, pid, null, name, historyName, type, + elapsedRealtime, uptime); + } + }); } } - public void noteStartWakelockFromSource(WorkSource ws, int pid, String name, - String historyName, int type, boolean unimportantForLogging) { + public void noteStartWakelockFromSource(final WorkSource ws, final int pid, final String name, + final String historyName, final int type, final boolean unimportantForLogging) { enforceCallingPermission(); - synchronized (mStats) { - mStats.noteStartWakeFromSourceLocked(ws, pid, name, historyName, - type, unimportantForLogging); + synchronized (mLock) { + final long elapsedRealtime = SystemClock.elapsedRealtime(); + final long uptime = SystemClock.uptimeMillis(); + mHandler.post(() -> { + synchronized (mStats) { + mStats.noteStartWakeFromSourceLocked(ws, pid, name, historyName, + type, unimportantForLogging, elapsedRealtime, uptime); + } + }); } } - public void noteChangeWakelockFromSource(WorkSource ws, int pid, String name, - String historyName, int type, WorkSource newWs, int newPid, String newName, - String newHistoryName, int newType, boolean newUnimportantForLogging) { + public void noteChangeWakelockFromSource(final WorkSource ws, final int pid, final String name, + final String historyName, final int type, final WorkSource newWs, final int newPid, + final String newName, final String newHistoryName, final int newType, + final boolean newUnimportantForLogging) { enforceCallingPermission(); - synchronized (mStats) { - mStats.noteChangeWakelockFromSourceLocked(ws, pid, name, historyName, type, - newWs, newPid, newName, newHistoryName, newType, newUnimportantForLogging); + synchronized (mLock) { + final long elapsedRealtime = SystemClock.elapsedRealtime(); + final long uptime = SystemClock.uptimeMillis(); + mHandler.post(() -> { + synchronized (mStats) { + mStats.noteChangeWakelockFromSourceLocked(ws, pid, name, historyName, type, + newWs, newPid, newName, newHistoryName, newType, + newUnimportantForLogging, elapsedRealtime, uptime); + } + }); } } - public void noteStopWakelockFromSource(WorkSource ws, int pid, String name, String historyName, - int type) { + public void noteStopWakelockFromSource(final WorkSource ws, final int pid, final String name, + final String historyName, final int type) { enforceCallingPermission(); - synchronized (mStats) { - mStats.noteStopWakeFromSourceLocked(ws, pid, name, historyName, type); + synchronized (mLock) { + final long elapsedRealtime = SystemClock.elapsedRealtime(); + final long uptime = SystemClock.uptimeMillis(); + mHandler.post(() -> { + synchronized (mStats) { + mStats.noteStopWakeFromSourceLocked(ws, pid, name, historyName, type, + elapsedRealtime, uptime); + } + }); } } @Override - public void noteLongPartialWakelockStart(String name, String historyName, int uid) { + public void noteLongPartialWakelockStart(final String name, final String historyName, + final int uid) { enforceCallingPermission(); - synchronized (mStats) { - mStats.noteLongPartialWakelockStart(name, historyName, uid); + synchronized (mLock) { + final long elapsedRealtime = SystemClock.elapsedRealtime(); + final long uptime = SystemClock.uptimeMillis(); + mHandler.post(() -> { + synchronized (mStats) { + mStats.noteLongPartialWakelockStart(name, historyName, uid, + elapsedRealtime, uptime); + } + }); } } @Override - public void noteLongPartialWakelockStartFromSource(String name, String historyName, - WorkSource workSource) { + public void noteLongPartialWakelockStartFromSource(final String name, final String historyName, + final WorkSource workSource) { enforceCallingPermission(); - synchronized (mStats) { - mStats.noteLongPartialWakelockStartFromSource(name, historyName, workSource); + synchronized (mLock) { + final long elapsedRealtime = SystemClock.elapsedRealtime(); + final long uptime = SystemClock.uptimeMillis(); + mHandler.post(() -> { + synchronized (mStats) { + mStats.noteLongPartialWakelockStartFromSource(name, historyName, workSource, + elapsedRealtime, uptime); + } + }); } } @Override - public void noteLongPartialWakelockFinish(String name, String historyName, int uid) { + public void noteLongPartialWakelockFinish(final String name, final String historyName, + final int uid) { enforceCallingPermission(); - synchronized (mStats) { - mStats.noteLongPartialWakelockFinish(name, historyName, uid); + synchronized (mLock) { + final long elapsedRealtime = SystemClock.elapsedRealtime(); + final long uptime = SystemClock.uptimeMillis(); + mHandler.post(() -> { + synchronized (mStats) { + mStats.noteLongPartialWakelockFinish(name, historyName, uid, + elapsedRealtime, uptime); + } + }); } } @Override - public void noteLongPartialWakelockFinishFromSource(String name, String historyName, - WorkSource workSource) { + public void noteLongPartialWakelockFinishFromSource(final String name, final String historyName, + final WorkSource workSource) { enforceCallingPermission(); - synchronized (mStats) { - mStats.noteLongPartialWakelockFinishFromSource(name, historyName, workSource); + synchronized (mLock) { + final long elapsedRealtime = SystemClock.elapsedRealtime(); + final long uptime = SystemClock.uptimeMillis(); + mHandler.post(() -> { + synchronized (mStats) { + mStats.noteLongPartialWakelockFinishFromSource(name, historyName, workSource, + elapsedRealtime, uptime); + } + }); } } - public void noteStartSensor(int uid, int sensor) { + public void noteStartSensor(final int uid, final int sensor) { enforceCallingPermission(); - synchronized (mStats) { - mStats.noteStartSensorLocked(uid, sensor); - FrameworkStatsLog.write_non_chained(FrameworkStatsLog.SENSOR_STATE_CHANGED, uid, null, - sensor, FrameworkStatsLog.SENSOR_STATE_CHANGED__STATE__ON); + synchronized (mLock) { + final long elapsedRealtime = SystemClock.elapsedRealtime(); + final long uptime = SystemClock.uptimeMillis(); + mHandler.post(() -> { + synchronized (mStats) { + mStats.noteStartSensorLocked(uid, sensor, elapsedRealtime, uptime); + } + FrameworkStatsLog.write_non_chained(FrameworkStatsLog.SENSOR_STATE_CHANGED, uid, + null, sensor, FrameworkStatsLog.SENSOR_STATE_CHANGED__STATE__ON); + }); } } - public void noteStopSensor(int uid, int sensor) { + public void noteStopSensor(final int uid, final int sensor) { enforceCallingPermission(); - synchronized (mStats) { - mStats.noteStopSensorLocked(uid, sensor); - FrameworkStatsLog.write_non_chained(FrameworkStatsLog.SENSOR_STATE_CHANGED, uid, null, - sensor, FrameworkStatsLog.SENSOR_STATE_CHANGED__STATE__OFF); + synchronized (mLock) { + final long elapsedRealtime = SystemClock.elapsedRealtime(); + final long uptime = SystemClock.uptimeMillis(); + mHandler.post(() -> { + synchronized (mStats) { + mStats.noteStopSensorLocked(uid, sensor, elapsedRealtime, uptime); + } + FrameworkStatsLog.write_non_chained(FrameworkStatsLog.SENSOR_STATE_CHANGED, uid, + null, sensor, FrameworkStatsLog.SENSOR_STATE_CHANGED__STATE__OFF); + }); } } - public void noteVibratorOn(int uid, long durationMillis) { + public void noteVibratorOn(final int uid, final long durationMillis) { enforceCallingPermission(); - synchronized (mStats) { - mStats.noteVibratorOnLocked(uid, durationMillis); + synchronized (mLock) { + final long elapsedRealtime = SystemClock.elapsedRealtime(); + final long uptime = SystemClock.uptimeMillis(); + mHandler.post(() -> { + synchronized (mStats) { + mStats.noteVibratorOnLocked(uid, durationMillis, elapsedRealtime, uptime); + } + }); } } - public void noteVibratorOff(int uid) { + public void noteVibratorOff(final int uid) { enforceCallingPermission(); - synchronized (mStats) { - mStats.noteVibratorOffLocked(uid); + synchronized (mLock) { + final long elapsedRealtime = SystemClock.elapsedRealtime(); + final long uptime = SystemClock.uptimeMillis(); + mHandler.post(() -> { + synchronized (mStats) { + mStats.noteVibratorOffLocked(uid, elapsedRealtime, uptime); + } + }); } } @Override - public void noteGpsChanged(WorkSource oldWs, WorkSource newWs) { + public void noteGpsChanged(final WorkSource oldWs, final WorkSource newWs) { enforceCallingPermission(); - synchronized (mStats) { - mStats.noteGpsChangedLocked(oldWs, newWs); + synchronized (mLock) { + final long elapsedRealtime = SystemClock.elapsedRealtime(); + final long uptime = SystemClock.uptimeMillis(); + mHandler.post(() -> { + synchronized (mStats) { + mStats.noteGpsChangedLocked(oldWs, newWs, elapsedRealtime, uptime); + } + }); } } - public void noteGpsSignalQuality(int signalLevel) { - synchronized (mStats) { - mStats.noteGpsSignalQualityLocked(signalLevel); + public void noteGpsSignalQuality(final int signalLevel) { + synchronized (mLock) { + final long elapsedRealtime = SystemClock.elapsedRealtime(); + final long uptime = SystemClock.uptimeMillis(); + mHandler.post(() -> { + synchronized (mStats) { + mStats.noteGpsSignalQualityLocked(signalLevel, elapsedRealtime, uptime); + } + }); } } - public void noteScreenState(int state) { + public void noteScreenState(final int state) { enforceCallingPermission(); - if (DBG) Slog.d(TAG, "begin noteScreenState"); - synchronized (mStats) { - FrameworkStatsLog.write(FrameworkStatsLog.SCREEN_STATE_CHANGED, state); - - mStats.noteScreenStateLocked(state); + synchronized (mLock) { + final long elapsedRealtime = SystemClock.elapsedRealtime(); + final long uptime = SystemClock.uptimeMillis(); + final long currentTime = System.currentTimeMillis(); + mHandler.post(() -> { + if (DBG) Slog.d(TAG, "begin noteScreenState"); + synchronized (mStats) { + mStats.noteScreenStateLocked(state, elapsedRealtime, uptime, currentTime); + } + FrameworkStatsLog.write(FrameworkStatsLog.SCREEN_STATE_CHANGED, state); + if (DBG) Slog.d(TAG, "end noteScreenState"); + }); } - if (DBG) Slog.d(TAG, "end noteScreenState"); } - public void noteScreenBrightness(int brightness) { + public void noteScreenBrightness(final int brightness) { enforceCallingPermission(); - synchronized (mStats) { - FrameworkStatsLog.write(FrameworkStatsLog.SCREEN_BRIGHTNESS_CHANGED, brightness); - mStats.noteScreenBrightnessLocked(brightness); + synchronized (mLock) { + final long elapsedRealtime = SystemClock.elapsedRealtime(); + final long uptime = SystemClock.uptimeMillis(); + mHandler.post(() -> { + synchronized (mStats) { + mStats.noteScreenBrightnessLocked(brightness, elapsedRealtime, uptime); + } + FrameworkStatsLog.write(FrameworkStatsLog.SCREEN_BRIGHTNESS_CHANGED, brightness); + }); } } - public void noteUserActivity(int uid, int event) { + public void noteUserActivity(final int uid, final int event) { enforceCallingPermission(); - synchronized (mStats) { - mStats.noteUserActivityLocked(uid, event); + synchronized (mLock) { + final long elapsedRealtime = SystemClock.elapsedRealtime(); + final long uptime = SystemClock.uptimeMillis(); + mHandler.post(() -> { + synchronized (mStats) { + mStats.noteUserActivityLocked(uid, event, elapsedRealtime, uptime); + } + }); } } - public void noteWakeUp(String reason, int reasonUid) { + public void noteWakeUp(final String reason, final int reasonUid) { enforceCallingPermission(); - synchronized (mStats) { - mStats.noteWakeUpLocked(reason, reasonUid); + synchronized (mLock) { + final long elapsedRealtime = SystemClock.elapsedRealtime(); + final long uptime = SystemClock.uptimeMillis(); + mHandler.post(() -> { + synchronized (mStats) { + mStats.noteWakeUpLocked(reason, reasonUid, elapsedRealtime, uptime); + } + }); } } - public void noteInteractive(boolean interactive) { + public void noteInteractive(final boolean interactive) { enforceCallingPermission(); - synchronized (mStats) { - mStats.noteInteractiveLocked(interactive); + synchronized (mLock) { + final long elapsedRealtime = SystemClock.elapsedRealtime(); + mHandler.post(() -> { + synchronized (mStats) { + mStats.noteInteractiveLocked(interactive, elapsedRealtime); + } + }); } } - public void noteConnectivityChanged(int type, String extra) { + public void noteConnectivityChanged(final int type, final String extra) { enforceCallingPermission(); - synchronized (mStats) { - mStats.noteConnectivityChangedLocked(type, extra); + synchronized (mLock) { + final long elapsedRealtime = SystemClock.elapsedRealtime(); + final long uptime = SystemClock.uptimeMillis(); + mHandler.post(() -> { + synchronized (mStats) { + mStats.noteConnectivityChangedLocked(type, extra, elapsedRealtime, uptime); + } + }); } } - public void noteMobileRadioPowerState(int powerState, long timestampNs, int uid) { + public void noteMobileRadioPowerState(final int powerState, final long timestampNs, + final int uid) { enforceCallingPermission(); - final boolean update; - synchronized (mStats) { - update = mStats.noteMobileRadioPowerStateLocked(powerState, timestampNs, uid); - } + synchronized (mLock) { + final long elapsedRealtime = SystemClock.elapsedRealtime(); + final long uptime = SystemClock.uptimeMillis(); + mHandler.post(() -> { + final boolean update; + synchronized (mStats) { + update = mStats.noteMobileRadioPowerStateLocked(powerState, timestampNs, uid, + elapsedRealtime, uptime); + } - if (update) { - mWorker.scheduleSync("modem-data", BatteryExternalStatsWorker.UPDATE_RADIO); + if (update) { + mWorker.scheduleSync("modem-data", BatteryExternalStatsWorker.UPDATE_RADIO); + } + }); } } public void notePhoneOn() { enforceCallingPermission(); - synchronized (mStats) { - mStats.notePhoneOnLocked(); + synchronized (mLock) { + final long elapsedRealtime = SystemClock.elapsedRealtime(); + final long uptime = SystemClock.uptimeMillis(); + mHandler.post(() -> { + synchronized (mStats) { + mStats.notePhoneOnLocked(elapsedRealtime, uptime); + } + }); } } public void notePhoneOff() { enforceCallingPermission(); - synchronized (mStats) { - mStats.notePhoneOffLocked(); + synchronized (mLock) { + final long elapsedRealtime = SystemClock.elapsedRealtime(); + final long uptime = SystemClock.uptimeMillis(); + mHandler.post(() -> { + synchronized (mStats) { + mStats.notePhoneOffLocked(elapsedRealtime, uptime); + } + }); } } - public void notePhoneSignalStrength(SignalStrength signalStrength) { + public void notePhoneSignalStrength(final SignalStrength signalStrength) { enforceCallingPermission(); - synchronized (mStats) { - mStats.notePhoneSignalStrengthLocked(signalStrength); + synchronized (mLock) { + final long elapsedRealtime = SystemClock.elapsedRealtime(); + final long uptime = SystemClock.uptimeMillis(); + mHandler.post(() -> { + synchronized (mStats) { + mStats.notePhoneSignalStrengthLocked(signalStrength, elapsedRealtime, uptime); + } + }); } } - public void notePhoneDataConnectionState(int dataType, boolean hasData, int serviceType) { + public void notePhoneDataConnectionState(final int dataType, final boolean hasData, + final int serviceType) { enforceCallingPermission(); - synchronized (mStats) { - mStats.notePhoneDataConnectionStateLocked(dataType, hasData, serviceType); + synchronized (mLock) { + final long elapsedRealtime = SystemClock.elapsedRealtime(); + final long uptime = SystemClock.uptimeMillis(); + mHandler.post(() -> { + synchronized (mStats) { + mStats.notePhoneDataConnectionStateLocked(dataType, hasData, serviceType, + elapsedRealtime, uptime); + } + }); } } - public void notePhoneState(int state) { + public void notePhoneState(final int state) { enforceCallingPermission(); - int simState = mContext.getSystemService(TelephonyManager.class).getSimState(); - synchronized (mStats) { - mStats.notePhoneStateLocked(state, simState); + synchronized (mLock) { + final long elapsedRealtime = SystemClock.elapsedRealtime(); + final long uptime = SystemClock.uptimeMillis(); + mHandler.post(() -> { + int simState = mContext.getSystemService(TelephonyManager.class).getSimState(); + synchronized (mStats) { + mStats.notePhoneStateLocked(state, simState, elapsedRealtime, uptime); + } + }); } } public void noteWifiOn() { enforceCallingPermission(); - synchronized (mStats) { - mStats.noteWifiOnLocked(); + synchronized (mLock) { + final long elapsedRealtime = SystemClock.elapsedRealtime(); + final long uptime = SystemClock.uptimeMillis(); + mHandler.post(() -> { + synchronized (mStats) { + mStats.noteWifiOnLocked(elapsedRealtime, uptime); + } + FrameworkStatsLog.write(FrameworkStatsLog.WIFI_ENABLED_STATE_CHANGED, + FrameworkStatsLog.WIFI_ENABLED_STATE_CHANGED__STATE__ON); + }); } - FrameworkStatsLog.write(FrameworkStatsLog.WIFI_ENABLED_STATE_CHANGED, - FrameworkStatsLog.WIFI_ENABLED_STATE_CHANGED__STATE__ON); } public void noteWifiOff() { enforceCallingPermission(); - synchronized (mStats) { - mStats.noteWifiOffLocked(); + synchronized (mLock) { + final long elapsedRealtime = SystemClock.elapsedRealtime(); + final long uptime = SystemClock.uptimeMillis(); + mHandler.post(() -> { + synchronized (mStats) { + mStats.noteWifiOffLocked(elapsedRealtime, uptime); + } + FrameworkStatsLog.write(FrameworkStatsLog.WIFI_ENABLED_STATE_CHANGED, + FrameworkStatsLog.WIFI_ENABLED_STATE_CHANGED__STATE__OFF); + }); } - FrameworkStatsLog.write(FrameworkStatsLog.WIFI_ENABLED_STATE_CHANGED, - FrameworkStatsLog.WIFI_ENABLED_STATE_CHANGED__STATE__OFF); } - public void noteStartAudio(int uid) { + public void noteStartAudio(final int uid) { enforceCallingPermission(); - synchronized (mStats) { - mStats.noteAudioOnLocked(uid); - FrameworkStatsLog.write_non_chained(FrameworkStatsLog.AUDIO_STATE_CHANGED, uid, null, - FrameworkStatsLog.AUDIO_STATE_CHANGED__STATE__ON); + synchronized (mLock) { + final long elapsedRealtime = SystemClock.elapsedRealtime(); + final long uptime = SystemClock.uptimeMillis(); + mHandler.post(() -> { + synchronized (mStats) { + mStats.noteAudioOnLocked(uid, elapsedRealtime, uptime); + } + FrameworkStatsLog.write_non_chained(FrameworkStatsLog.AUDIO_STATE_CHANGED, uid, + null, FrameworkStatsLog.AUDIO_STATE_CHANGED__STATE__ON); + }); } } - public void noteStopAudio(int uid) { + public void noteStopAudio(final int uid) { enforceCallingPermission(); - synchronized (mStats) { - mStats.noteAudioOffLocked(uid); - FrameworkStatsLog.write_non_chained(FrameworkStatsLog.AUDIO_STATE_CHANGED, uid, null, - FrameworkStatsLog.AUDIO_STATE_CHANGED__STATE__OFF); + synchronized (mLock) { + final long elapsedRealtime = SystemClock.elapsedRealtime(); + final long uptime = SystemClock.uptimeMillis(); + mHandler.post(() -> { + synchronized (mStats) { + mStats.noteAudioOffLocked(uid, elapsedRealtime, uptime); + } + FrameworkStatsLog.write_non_chained(FrameworkStatsLog.AUDIO_STATE_CHANGED, uid, + null, FrameworkStatsLog.AUDIO_STATE_CHANGED__STATE__OFF); + }); } } - public void noteStartVideo(int uid) { + public void noteStartVideo(final int uid) { enforceCallingPermission(); - synchronized (mStats) { - mStats.noteVideoOnLocked(uid); - FrameworkStatsLog.write_non_chained(FrameworkStatsLog.MEDIA_CODEC_STATE_CHANGED, uid, - null, FrameworkStatsLog.MEDIA_CODEC_STATE_CHANGED__STATE__ON); + synchronized (mLock) { + final long elapsedRealtime = SystemClock.elapsedRealtime(); + final long uptime = SystemClock.uptimeMillis(); + mHandler.post(() -> { + synchronized (mStats) { + mStats.noteVideoOnLocked(uid, elapsedRealtime, uptime); + } + FrameworkStatsLog.write_non_chained(FrameworkStatsLog.MEDIA_CODEC_STATE_CHANGED, + uid, null, FrameworkStatsLog.MEDIA_CODEC_STATE_CHANGED__STATE__ON); + }); } } - public void noteStopVideo(int uid) { + public void noteStopVideo(final int uid) { enforceCallingPermission(); - synchronized (mStats) { - mStats.noteVideoOffLocked(uid); - FrameworkStatsLog.write_non_chained(FrameworkStatsLog.MEDIA_CODEC_STATE_CHANGED, uid, - null, FrameworkStatsLog.MEDIA_CODEC_STATE_CHANGED__STATE__OFF); + synchronized (mLock) { + final long elapsedRealtime = SystemClock.elapsedRealtime(); + final long uptime = SystemClock.uptimeMillis(); + mHandler.post(() -> { + synchronized (mStats) { + mStats.noteVideoOffLocked(uid, elapsedRealtime, uptime); + } + FrameworkStatsLog.write_non_chained(FrameworkStatsLog.MEDIA_CODEC_STATE_CHANGED, + uid, null, FrameworkStatsLog.MEDIA_CODEC_STATE_CHANGED__STATE__OFF); + }); } } public void noteResetAudio() { enforceCallingPermission(); - synchronized (mStats) { - mStats.noteResetAudioLocked(); - FrameworkStatsLog.write_non_chained(FrameworkStatsLog.AUDIO_STATE_CHANGED, -1, null, - FrameworkStatsLog.AUDIO_STATE_CHANGED__STATE__RESET); + synchronized (mLock) { + final long elapsedRealtime = SystemClock.elapsedRealtime(); + final long uptime = SystemClock.uptimeMillis(); + mHandler.post(() -> { + synchronized (mStats) { + mStats.noteResetAudioLocked(elapsedRealtime, uptime); + } + FrameworkStatsLog.write_non_chained(FrameworkStatsLog.AUDIO_STATE_CHANGED, -1, null, + FrameworkStatsLog.AUDIO_STATE_CHANGED__STATE__RESET); + }); } } public void noteResetVideo() { enforceCallingPermission(); - synchronized (mStats) { - mStats.noteResetVideoLocked(); - FrameworkStatsLog.write_non_chained(FrameworkStatsLog.MEDIA_CODEC_STATE_CHANGED, -1, - null, FrameworkStatsLog.MEDIA_CODEC_STATE_CHANGED__STATE__RESET); + synchronized (mLock) { + final long elapsedRealtime = SystemClock.elapsedRealtime(); + final long uptime = SystemClock.uptimeMillis(); + mHandler.post(() -> { + synchronized (mStats) { + mStats.noteResetVideoLocked(elapsedRealtime, uptime); + } + FrameworkStatsLog.write_non_chained(FrameworkStatsLog.MEDIA_CODEC_STATE_CHANGED, -1, + null, FrameworkStatsLog.MEDIA_CODEC_STATE_CHANGED__STATE__RESET); + }); } } - public void noteFlashlightOn(int uid) { + public void noteFlashlightOn(final int uid) { enforceCallingPermission(); - synchronized (mStats) { - mStats.noteFlashlightOnLocked(uid); - FrameworkStatsLog.write_non_chained(FrameworkStatsLog.FLASHLIGHT_STATE_CHANGED, uid, - null, FrameworkStatsLog.FLASHLIGHT_STATE_CHANGED__STATE__ON); + synchronized (mLock) { + final long elapsedRealtime = SystemClock.elapsedRealtime(); + final long uptime = SystemClock.uptimeMillis(); + mHandler.post(() -> { + synchronized (mStats) { + mStats.noteFlashlightOnLocked(uid, elapsedRealtime, uptime); + } + FrameworkStatsLog.write_non_chained(FrameworkStatsLog.FLASHLIGHT_STATE_CHANGED, uid, + null, FrameworkStatsLog.FLASHLIGHT_STATE_CHANGED__STATE__ON); + }); } } - public void noteFlashlightOff(int uid) { + public void noteFlashlightOff(final int uid) { enforceCallingPermission(); - synchronized (mStats) { - mStats.noteFlashlightOffLocked(uid); - FrameworkStatsLog.write_non_chained(FrameworkStatsLog.FLASHLIGHT_STATE_CHANGED, uid, - null, FrameworkStatsLog.FLASHLIGHT_STATE_CHANGED__STATE__OFF); + synchronized (mLock) { + final long elapsedRealtime = SystemClock.elapsedRealtime(); + final long uptime = SystemClock.uptimeMillis(); + mHandler.post(() -> { + synchronized (mStats) { + mStats.noteFlashlightOffLocked(uid, elapsedRealtime, uptime); + } + FrameworkStatsLog.write_non_chained(FrameworkStatsLog.FLASHLIGHT_STATE_CHANGED, uid, + null, FrameworkStatsLog.FLASHLIGHT_STATE_CHANGED__STATE__OFF); + }); } } - public void noteStartCamera(int uid) { + public void noteStartCamera(final int uid) { enforceCallingPermission(); if (DBG) Slog.d(TAG, "begin noteStartCamera"); - synchronized (mStats) { - mStats.noteCameraOnLocked(uid); - FrameworkStatsLog.write_non_chained(FrameworkStatsLog.CAMERA_STATE_CHANGED, uid, null, - FrameworkStatsLog.CAMERA_STATE_CHANGED__STATE__ON); + synchronized (mLock) { + final long elapsedRealtime = SystemClock.elapsedRealtime(); + final long uptime = SystemClock.uptimeMillis(); + mHandler.post(() -> { + synchronized (mStats) { + mStats.noteCameraOnLocked(uid, elapsedRealtime, uptime); + } + FrameworkStatsLog.write_non_chained(FrameworkStatsLog.CAMERA_STATE_CHANGED, uid, + null, FrameworkStatsLog.CAMERA_STATE_CHANGED__STATE__ON); + }); } if (DBG) Slog.d(TAG, "end noteStartCamera"); } - public void noteStopCamera(int uid) { + public void noteStopCamera(final int uid) { enforceCallingPermission(); - synchronized (mStats) { - mStats.noteCameraOffLocked(uid); - FrameworkStatsLog.write_non_chained(FrameworkStatsLog.CAMERA_STATE_CHANGED, uid, null, - FrameworkStatsLog.CAMERA_STATE_CHANGED__STATE__OFF); + synchronized (mLock) { + final long elapsedRealtime = SystemClock.elapsedRealtime(); + final long uptime = SystemClock.uptimeMillis(); + mHandler.post(() -> { + synchronized (mStats) { + mStats.noteCameraOffLocked(uid, elapsedRealtime, uptime); + } + FrameworkStatsLog.write_non_chained(FrameworkStatsLog.CAMERA_STATE_CHANGED, uid, + null, FrameworkStatsLog.CAMERA_STATE_CHANGED__STATE__OFF); + }); } } public void noteResetCamera() { enforceCallingPermission(); - synchronized (mStats) { - mStats.noteResetCameraLocked(); - FrameworkStatsLog.write_non_chained(FrameworkStatsLog.CAMERA_STATE_CHANGED, -1, null, - FrameworkStatsLog.CAMERA_STATE_CHANGED__STATE__RESET); + synchronized (mLock) { + final long elapsedRealtime = SystemClock.elapsedRealtime(); + final long uptime = SystemClock.uptimeMillis(); + mHandler.post(() -> { + synchronized (mStats) { + mStats.noteResetCameraLocked(elapsedRealtime, uptime); + } + FrameworkStatsLog.write_non_chained(FrameworkStatsLog.CAMERA_STATE_CHANGED, -1, + null, FrameworkStatsLog.CAMERA_STATE_CHANGED__STATE__RESET); + }); } } public void noteResetFlashlight() { enforceCallingPermission(); - synchronized (mStats) { - mStats.noteResetFlashlightLocked(); - FrameworkStatsLog.write_non_chained(FrameworkStatsLog.FLASHLIGHT_STATE_CHANGED, -1, - null, FrameworkStatsLog.FLASHLIGHT_STATE_CHANGED__STATE__RESET); + synchronized (mLock) { + final long elapsedRealtime = SystemClock.elapsedRealtime(); + final long uptime = SystemClock.uptimeMillis(); + mHandler.post(() -> { + synchronized (mStats) { + mStats.noteResetFlashlightLocked(elapsedRealtime, uptime); + } + FrameworkStatsLog.write_non_chained(FrameworkStatsLog.FLASHLIGHT_STATE_CHANGED, -1, + null, FrameworkStatsLog.FLASHLIGHT_STATE_CHANGED__STATE__RESET); + }); } } @Override - public void noteWifiRadioPowerState(int powerState, long tsNanos, int uid) { - enforceCallingPermission(); - - // There was a change in WiFi power state. - // Collect data now for the past activity. - synchronized (mStats) { - if (mStats.isOnBattery()) { - final String type = (powerState == DataConnectionRealTimeInfo.DC_POWER_STATE_HIGH || - powerState == DataConnectionRealTimeInfo.DC_POWER_STATE_MEDIUM) ? "active" - : "inactive"; - mWorker.scheduleSync("wifi-data: " + type, BatteryExternalStatsWorker.UPDATE_WIFI); - } - mStats.noteWifiRadioPowerState(powerState, tsNanos, uid); + public void noteWifiRadioPowerState(final int powerState, final long tsNanos, final int uid) { + enforceCallingPermission(); + synchronized (mLock) { + final long elapsedRealtime = SystemClock.elapsedRealtime(); + final long uptime = SystemClock.uptimeMillis(); + mHandler.post(() -> { + // There was a change in WiFi power state. + // Collect data now for the past activity. + synchronized (mStats) { + if (mStats.isOnBattery()) { + final String type = + (powerState == DataConnectionRealTimeInfo.DC_POWER_STATE_HIGH + || powerState == DataConnectionRealTimeInfo.DC_POWER_STATE_MEDIUM) + ? "active" : "inactive"; + mWorker.scheduleSync("wifi-data: " + type, + BatteryExternalStatsWorker.UPDATE_WIFI); + } + mStats.noteWifiRadioPowerState(powerState, tsNanos, uid, + elapsedRealtime, uptime); + } + }); } } - public void noteWifiRunning(WorkSource ws) { + public void noteWifiRunning(final WorkSource ws) { enforceCallingPermission(); - synchronized (mStats) { - mStats.noteWifiRunningLocked(ws); + synchronized (mLock) { + final long elapsedRealtime = SystemClock.elapsedRealtime(); + final long uptime = SystemClock.uptimeMillis(); + mHandler.post(() -> { + synchronized (mStats) { + mStats.noteWifiRunningLocked(ws, elapsedRealtime, uptime); + } + // TODO: Log WIFI_RUNNING_STATE_CHANGED in a better spot to include Hotspot too. + FrameworkStatsLog.write(FrameworkStatsLog.WIFI_RUNNING_STATE_CHANGED, + ws, FrameworkStatsLog.WIFI_RUNNING_STATE_CHANGED__STATE__ON); + }); } - // TODO: Log WIFI_RUNNING_STATE_CHANGED in a better spot to include Hotspot too. - FrameworkStatsLog.write(FrameworkStatsLog.WIFI_RUNNING_STATE_CHANGED, - ws, FrameworkStatsLog.WIFI_RUNNING_STATE_CHANGED__STATE__ON); } - public void noteWifiRunningChanged(WorkSource oldWs, WorkSource newWs) { + public void noteWifiRunningChanged(final WorkSource oldWs, final WorkSource newWs) { enforceCallingPermission(); - synchronized (mStats) { - mStats.noteWifiRunningChangedLocked(oldWs, newWs); + synchronized (mLock) { + final long elapsedRealtime = SystemClock.elapsedRealtime(); + final long uptime = SystemClock.uptimeMillis(); + mHandler.post(() -> { + synchronized (mStats) { + mStats.noteWifiRunningChangedLocked(oldWs, newWs, elapsedRealtime, uptime); + } + FrameworkStatsLog.write(FrameworkStatsLog.WIFI_RUNNING_STATE_CHANGED, + newWs, FrameworkStatsLog.WIFI_RUNNING_STATE_CHANGED__STATE__ON); + FrameworkStatsLog.write(FrameworkStatsLog.WIFI_RUNNING_STATE_CHANGED, + oldWs, FrameworkStatsLog.WIFI_RUNNING_STATE_CHANGED__STATE__OFF); + }); } - FrameworkStatsLog.write(FrameworkStatsLog.WIFI_RUNNING_STATE_CHANGED, - newWs, FrameworkStatsLog.WIFI_RUNNING_STATE_CHANGED__STATE__ON); - FrameworkStatsLog.write(FrameworkStatsLog.WIFI_RUNNING_STATE_CHANGED, - oldWs, FrameworkStatsLog.WIFI_RUNNING_STATE_CHANGED__STATE__OFF); } - public void noteWifiStopped(WorkSource ws) { + public void noteWifiStopped(final WorkSource ws) { enforceCallingPermission(); - synchronized (mStats) { - mStats.noteWifiStoppedLocked(ws); + synchronized (mLock) { + final long elapsedRealtime = SystemClock.elapsedRealtime(); + final long uptime = SystemClock.uptimeMillis(); + mHandler.post(() -> { + synchronized (mStats) { + mStats.noteWifiStoppedLocked(ws, elapsedRealtime, uptime); + } + FrameworkStatsLog.write(FrameworkStatsLog.WIFI_RUNNING_STATE_CHANGED, + ws, FrameworkStatsLog.WIFI_RUNNING_STATE_CHANGED__STATE__OFF); + }); } - FrameworkStatsLog.write(FrameworkStatsLog.WIFI_RUNNING_STATE_CHANGED, - ws, FrameworkStatsLog.WIFI_RUNNING_STATE_CHANGED__STATE__OFF); } - public void noteWifiState(int wifiState, String accessPoint) { + public void noteWifiState(final int wifiState, final String accessPoint) { enforceCallingPermission(); - synchronized (mStats) { - mStats.noteWifiStateLocked(wifiState, accessPoint); + synchronized (mLock) { + final long elapsedRealtime = SystemClock.elapsedRealtime(); + mHandler.post(() -> { + synchronized (mStats) { + mStats.noteWifiStateLocked(wifiState, accessPoint, elapsedRealtime); + } + }); } } - public void noteWifiSupplicantStateChanged(int supplState, boolean failedAuth) { + public void noteWifiSupplicantStateChanged(final int supplState, final boolean failedAuth) { enforceCallingPermission(); - synchronized (mStats) { - mStats.noteWifiSupplicantStateChangedLocked(supplState, failedAuth); + synchronized (mLock) { + final long elapsedRealtime = SystemClock.elapsedRealtime(); + final long uptime = SystemClock.uptimeMillis(); + mHandler.post(() -> { + synchronized (mStats) { + mStats.noteWifiSupplicantStateChangedLocked(supplState, failedAuth, + elapsedRealtime, uptime); + } + }); } } - public void noteWifiRssiChanged(int newRssi) { + public void noteWifiRssiChanged(final int newRssi) { enforceCallingPermission(); - synchronized (mStats) { - mStats.noteWifiRssiChangedLocked(newRssi); + synchronized (mLock) { + final long elapsedRealtime = SystemClock.elapsedRealtime(); + final long uptime = SystemClock.uptimeMillis(); + mHandler.post(() -> { + synchronized (mStats) { + mStats.noteWifiRssiChangedLocked(newRssi, elapsedRealtime, uptime); + } + }); } } - public void noteFullWifiLockAcquired(int uid) { + public void noteFullWifiLockAcquired(final int uid) { enforceCallingPermission(); - synchronized (mStats) { - mStats.noteFullWifiLockAcquiredLocked(uid); + synchronized (mLock) { + final long elapsedRealtime = SystemClock.elapsedRealtime(); + final long uptime = SystemClock.uptimeMillis(); + mHandler.post(() -> { + synchronized (mStats) { + mStats.noteFullWifiLockAcquiredLocked(uid, elapsedRealtime, uptime); + } + }); } } - public void noteFullWifiLockReleased(int uid) { + public void noteFullWifiLockReleased(final int uid) { enforceCallingPermission(); - synchronized (mStats) { - mStats.noteFullWifiLockReleasedLocked(uid); + synchronized (mLock) { + final long elapsedRealtime = SystemClock.elapsedRealtime(); + final long uptime = SystemClock.uptimeMillis(); + mHandler.post(() -> { + synchronized (mStats) { + mStats.noteFullWifiLockReleasedLocked(uid, elapsedRealtime, uptime); + } + }); } } - public void noteWifiScanStarted(int uid) { + public void noteWifiScanStarted(final int uid) { enforceCallingPermission(); - synchronized (mStats) { - mStats.noteWifiScanStartedLocked(uid); + synchronized (mLock) { + final long elapsedRealtime = SystemClock.elapsedRealtime(); + final long uptime = SystemClock.uptimeMillis(); + mHandler.post(() -> { + synchronized (mStats) { + mStats.noteWifiScanStartedLocked(uid, elapsedRealtime, uptime); + } + }); } } - public void noteWifiScanStopped(int uid) { + public void noteWifiScanStopped(final int uid) { enforceCallingPermission(); - synchronized (mStats) { - mStats.noteWifiScanStoppedLocked(uid); + synchronized (mLock) { + final long elapsedRealtime = SystemClock.elapsedRealtime(); + final long uptime = SystemClock.uptimeMillis(); + mHandler.post(() -> { + synchronized (mStats) { + mStats.noteWifiScanStoppedLocked(uid, elapsedRealtime, uptime); + } + }); } } - public void noteWifiMulticastEnabled(int uid) { + public void noteWifiMulticastEnabled(final int uid) { enforceCallingPermission(); - synchronized (mStats) { - mStats.noteWifiMulticastEnabledLocked(uid); + synchronized (mLock) { + final long elapsedRealtime = SystemClock.elapsedRealtime(); + final long uptime = SystemClock.uptimeMillis(); + mHandler.post(() -> { + synchronized (mStats) { + mStats.noteWifiMulticastEnabledLocked(uid, elapsedRealtime, uptime); + } + }); } } - public void noteWifiMulticastDisabled(int uid) { + public void noteWifiMulticastDisabled(final int uid) { enforceCallingPermission(); - synchronized (mStats) { - mStats.noteWifiMulticastDisabledLocked(uid); + synchronized (mLock) { + final long elapsedRealtime = SystemClock.elapsedRealtime(); + final long uptime = SystemClock.uptimeMillis(); + mHandler.post(() -> { + synchronized (mStats) { + mStats.noteWifiMulticastDisabledLocked(uid, elapsedRealtime, uptime); + } + }); } } - public void noteFullWifiLockAcquiredFromSource(WorkSource ws) { + public void noteFullWifiLockAcquiredFromSource(final WorkSource ws) { enforceCallingPermission(); - synchronized (mStats) { - mStats.noteFullWifiLockAcquiredFromSourceLocked(ws); + synchronized (mLock) { + final long elapsedRealtime = SystemClock.elapsedRealtime(); + final long uptime = SystemClock.uptimeMillis(); + mHandler.post(() -> { + synchronized (mStats) { + mStats.noteFullWifiLockAcquiredFromSourceLocked(ws, elapsedRealtime, uptime); + } + }); } } - public void noteFullWifiLockReleasedFromSource(WorkSource ws) { + public void noteFullWifiLockReleasedFromSource(final WorkSource ws) { enforceCallingPermission(); - synchronized (mStats) { - mStats.noteFullWifiLockReleasedFromSourceLocked(ws); + synchronized (mLock) { + final long elapsedRealtime = SystemClock.elapsedRealtime(); + final long uptime = SystemClock.uptimeMillis(); + mHandler.post(() -> { + synchronized (mStats) { + mStats.noteFullWifiLockReleasedFromSourceLocked(ws, elapsedRealtime, uptime); + } + }); } } - public void noteWifiScanStartedFromSource(WorkSource ws) { + public void noteWifiScanStartedFromSource(final WorkSource ws) { enforceCallingPermission(); - synchronized (mStats) { - mStats.noteWifiScanStartedFromSourceLocked(ws); + synchronized (mLock) { + final long elapsedRealtime = SystemClock.elapsedRealtime(); + final long uptime = SystemClock.uptimeMillis(); + mHandler.post(() -> { + synchronized (mStats) { + mStats.noteWifiScanStartedFromSourceLocked(ws, elapsedRealtime, uptime); + } + }); } } - public void noteWifiScanStoppedFromSource(WorkSource ws) { + public void noteWifiScanStoppedFromSource(final WorkSource ws) { enforceCallingPermission(); - synchronized (mStats) { - mStats.noteWifiScanStoppedFromSourceLocked(ws); + synchronized (mLock) { + final long elapsedRealtime = SystemClock.elapsedRealtime(); + final long uptime = SystemClock.uptimeMillis(); + mHandler.post(() -> { + synchronized (mStats) { + mStats.noteWifiScanStoppedFromSourceLocked(ws, elapsedRealtime, uptime); + } + }); } } - public void noteWifiBatchedScanStartedFromSource(WorkSource ws, int csph) { + public void noteWifiBatchedScanStartedFromSource(final WorkSource ws, final int csph) { enforceCallingPermission(); - synchronized (mStats) { - mStats.noteWifiBatchedScanStartedFromSourceLocked(ws, csph); + synchronized (mLock) { + final long elapsedRealtime = SystemClock.elapsedRealtime(); + final long uptime = SystemClock.uptimeMillis(); + mHandler.post(() -> { + synchronized (mStats) { + mStats.noteWifiBatchedScanStartedFromSourceLocked(ws, csph, + elapsedRealtime, uptime); + } + }); } } - public void noteWifiBatchedScanStoppedFromSource(WorkSource ws) { + public void noteWifiBatchedScanStoppedFromSource(final WorkSource ws) { enforceCallingPermission(); - synchronized (mStats) { - mStats.noteWifiBatchedScanStoppedFromSourceLocked(ws); + synchronized (mLock) { + final long elapsedRealtime = SystemClock.elapsedRealtime(); + final long uptime = SystemClock.uptimeMillis(); + mHandler.post(() -> { + synchronized (mStats) { + mStats.noteWifiBatchedScanStoppedFromSourceLocked(ws, elapsedRealtime, uptime); + } + }); } } @Override - public void noteNetworkInterfaceType(String iface, int networkType) { + public void noteNetworkInterfaceType(final String iface, final int networkType) { enforceCallingPermission(); - mStats.noteNetworkInterfaceType(iface, networkType); + synchronized (mLock) { + mHandler.post(() -> { + mStats.noteNetworkInterfaceType(iface, networkType); + }); + } } @Override @@ -1027,66 +1576,119 @@ public final class BatteryStatsService extends IBatteryStats.Stub // During device boot, qtaguid isn't enabled until after the inital // loading of battery stats. Now that they're enabled, take our initial // snapshot for future delta calculation. - mWorker.scheduleSync("network-stats-enabled", - BatteryExternalStatsWorker.UPDATE_RADIO | BatteryExternalStatsWorker.UPDATE_WIFI); + synchronized (mLock) { + // Still schedule it on the handler to make sure we have existing pending works done + mHandler.post(() -> { + mWorker.scheduleSync("network-stats-enabled", + BatteryExternalStatsWorker.UPDATE_RADIO + | BatteryExternalStatsWorker.UPDATE_WIFI); + }); + } } @Override - public void noteDeviceIdleMode(int mode, String activeReason, int activeUid) { + public void noteDeviceIdleMode(final int mode, final String activeReason, final int activeUid) { enforceCallingPermission(); - synchronized (mStats) { - mStats.noteDeviceIdleModeLocked(mode, activeReason, activeUid); + synchronized (mLock) { + final long elapsedRealtime = SystemClock.elapsedRealtime(); + final long uptime = SystemClock.uptimeMillis(); + mHandler.post(() -> { + synchronized (mStats) { + mStats.noteDeviceIdleModeLocked(mode, activeReason, activeUid, + elapsedRealtime, uptime); + } + }); } } - public void notePackageInstalled(String pkgName, long versionCode) { + public void notePackageInstalled(final String pkgName, final long versionCode) { enforceCallingPermission(); - synchronized (mStats) { - mStats.notePackageInstalledLocked(pkgName, versionCode); + synchronized (mLock) { + final long elapsedRealtime = SystemClock.elapsedRealtime(); + final long uptime = SystemClock.uptimeMillis(); + mHandler.post(() -> { + synchronized (mStats) { + mStats.notePackageInstalledLocked(pkgName, versionCode, + elapsedRealtime, uptime); + } + }); } } - public void notePackageUninstalled(String pkgName) { + public void notePackageUninstalled(final String pkgName) { enforceCallingPermission(); - synchronized (mStats) { - mStats.notePackageUninstalledLocked(pkgName); + synchronized (mLock) { + final long elapsedRealtime = SystemClock.elapsedRealtime(); + final long uptime = SystemClock.uptimeMillis(); + mHandler.post(() -> { + synchronized (mStats) { + mStats.notePackageUninstalledLocked(pkgName, elapsedRealtime, uptime); + } + }); } } @Override - public void noteBleScanStarted(WorkSource ws, boolean isUnoptimized) { + public void noteBleScanStarted(final WorkSource ws, final boolean isUnoptimized) { enforceCallingPermission(); - synchronized (mStats) { - mStats.noteBluetoothScanStartedFromSourceLocked(ws, isUnoptimized); + synchronized (mLock) { + final long elapsedRealtime = SystemClock.elapsedRealtime(); + final long uptime = SystemClock.uptimeMillis(); + mHandler.post(() -> { + synchronized (mStats) { + mStats.noteBluetoothScanStartedFromSourceLocked(ws, isUnoptimized, + elapsedRealtime, uptime); + } + }); } } @Override - public void noteBleScanStopped(WorkSource ws, boolean isUnoptimized) { + public void noteBleScanStopped(final WorkSource ws, final boolean isUnoptimized) { enforceCallingPermission(); - synchronized (mStats) { - mStats.noteBluetoothScanStoppedFromSourceLocked(ws, isUnoptimized); + synchronized (mLock) { + final long elapsedRealtime = SystemClock.elapsedRealtime(); + final long uptime = SystemClock.uptimeMillis(); + mHandler.post(() -> { + synchronized (mStats) { + mStats.noteBluetoothScanStoppedFromSourceLocked(ws, isUnoptimized, + uptime, elapsedRealtime); + } + }); } } @Override public void noteResetBleScan() { enforceCallingPermission(); - synchronized (mStats) { - mStats.noteResetBluetoothScanLocked(); + synchronized (mLock) { + final long elapsedRealtime = SystemClock.elapsedRealtime(); + final long uptime = SystemClock.uptimeMillis(); + mHandler.post(() -> { + synchronized (mStats) { + mStats.noteResetBluetoothScanLocked(elapsedRealtime, uptime); + } + }); } } @Override - public void noteBleScanResults(WorkSource ws, int numNewResults) { + public void noteBleScanResults(final WorkSource ws, final int numNewResults) { enforceCallingPermission(); - synchronized (mStats) { - mStats.noteBluetoothScanResultsFromSourceLocked(ws, numNewResults); + synchronized (mLock) { + final long elapsedRealtime = SystemClock.elapsedRealtime(); + final long uptime = SystemClock.uptimeMillis(); + mHandler.post(() -> { + synchronized (mStats) { + mStats.noteBluetoothScanResultsFromSourceLocked(ws, numNewResults, + elapsedRealtime, uptime); + } + }); } } @Override - public void noteWifiControllerActivity(WifiActivityEnergyInfo info) { + public void noteWifiControllerActivity(final WifiActivityEnergyInfo info) { enforceCallingPermission(); if (info == null || !info.isValid()) { @@ -1094,24 +1696,36 @@ public final class BatteryStatsService extends IBatteryStats.Stub return; } - mStats.updateWifiState(info); + synchronized (mLock) { + final long elapsedRealtime = SystemClock.elapsedRealtime(); + final long uptime = SystemClock.uptimeMillis(); + mHandler.post(() -> { + mStats.updateWifiState(info, elapsedRealtime, uptime); + }); + } } @Override - public void noteBluetoothControllerActivity(BluetoothActivityEnergyInfo info) { + public void noteBluetoothControllerActivity(final BluetoothActivityEnergyInfo info) { enforceCallingPermission(); if (info == null || !info.isValid()) { Slog.e(TAG, "invalid bluetooth data given: " + info); return; } - synchronized (mStats) { - mStats.updateBluetoothStateLocked(info); + synchronized (mLock) { + final long elapsedRealtime = SystemClock.elapsedRealtime(); + final long uptime = SystemClock.uptimeMillis(); + mHandler.post(() -> { + synchronized (mStats) { + mStats.updateBluetoothStateLocked(info, elapsedRealtime, uptime); + } + }); } } @Override - public void noteModemControllerActivity(ModemActivityInfo info) { + public void noteModemControllerActivity(final ModemActivityInfo info) { enforceCallingPermission(); if (info == null || !info.isValid()) { @@ -1119,7 +1733,13 @@ public final class BatteryStatsService extends IBatteryStats.Stub return; } - mStats.updateMobileRadioState(info); + synchronized (mLock) { + final long elapsedRealtime = SystemClock.elapsedRealtime(); + final long uptime = SystemClock.uptimeMillis(); + mHandler.post(() -> { + mStats.updateMobileRadioState(info, elapsedRealtime, uptime); + }); + } } public boolean isOnBattery() { @@ -1132,32 +1752,43 @@ public final class BatteryStatsService extends IBatteryStats.Stub final int chargeFullUAh, final long chargeTimeToFullSeconds) { enforceCallingPermission(); - // BatteryService calls us here and we may update external state. It would be wrong - // to block such a low level service like BatteryService on external stats like WiFi. - mWorker.scheduleRunnable(() -> { - synchronized (mStats) { - final boolean onBattery = BatteryStatsImpl.isOnBattery(plugType, status); - if (mStats.isOnBattery() == onBattery) { - // The battery state has not changed, so we don't need to sync external - // stats immediately. - mStats.setBatteryStateLocked(status, health, plugType, level, temp, volt, - chargeUAh, chargeFullUAh, chargeTimeToFullSeconds); - return; - } - } + synchronized (mLock) { + final long elapsedRealtime = SystemClock.elapsedRealtime(); + final long uptime = SystemClock.uptimeMillis(); + final long currentTime = System.currentTimeMillis(); + // We still schedule this task over the handler thread to make sure we've had + // all existing pending work handled before setting the battery state + mHandler.post(() -> { + // BatteryService calls us here and we may update external state. It would be wrong + // to block such a low level service like BatteryService on external stats like WiFi + mWorker.scheduleRunnable(() -> { + synchronized (mStats) { + final boolean onBattery = BatteryStatsImpl.isOnBattery(plugType, status); + if (mStats.isOnBattery() == onBattery) { + // The battery state has not changed, so we don't need to sync external + // stats immediately. + mStats.setBatteryStateLocked(status, health, plugType, level, temp, + volt, chargeUAh, chargeFullUAh, chargeTimeToFullSeconds, + elapsedRealtime, uptime, currentTime); + return; + } + } - // Sync external stats first as the battery has changed states. If we don't sync - // before changing the state, we may not collect the relevant data later. - // Order here is guaranteed since we're scheduling from the same thread and we are - // using a single threaded executor. - mWorker.scheduleSync("battery-state", BatteryExternalStatsWorker.UPDATE_ALL); - mWorker.scheduleRunnable(() -> { - synchronized (mStats) { - mStats.setBatteryStateLocked(status, health, plugType, level, temp, volt, - chargeUAh, chargeFullUAh, chargeTimeToFullSeconds); - } + // Sync external stats first as the battery has changed states. If we don't sync + // before changing the state, we may not collect the relevant data later. + // Order here is guaranteed since we're scheduling from the same thread and we + // are using a single threaded executor. + mWorker.scheduleSync("battery-state", BatteryExternalStatsWorker.UPDATE_ALL); + mWorker.scheduleRunnable(() -> { + synchronized (mStats) { + mStats.setBatteryStateLocked(status, health, plugType, level, temp, + volt, chargeUAh, chargeFullUAh, chargeTimeToFullSeconds, + elapsedRealtime, uptime, currentTime); + } + }); + }); }); - }); + } } public long getAwakeTimeBattery() { @@ -1205,8 +1836,12 @@ public final class BatteryStatsService extends IBatteryStats.Stub try { String reason; while ((reason = waitWakeup()) != null) { + // Wait for the completion of pending works if there is any + awaitCompletion(); + synchronized (mStats) { - mStats.noteWakeupReasonLocked(reason); + mStats.noteWakeupReasonLocked(reason, + SystemClock.elapsedRealtime(), SystemClock.uptimeMillis()); } } } catch (RuntimeException e) { @@ -1273,12 +1908,16 @@ public final class BatteryStatsService extends IBatteryStats.Stub } private void dumpSettings(PrintWriter pw) { + // Wait for the completion of pending works if there is any + awaitCompletion(); synchronized (mStats) { mStats.dumpConstantsLocked(pw); } } private void dumpCpuStats(PrintWriter pw) { + // Wait for the completion of pending works if there is any + awaitCompletion(); synchronized (mStats) { mStats.dumpCpuStatsLocked(pw); } @@ -1292,14 +1931,20 @@ public final class BatteryStatsService extends IBatteryStats.Stub return -1; } if ("full-wake-history".equals(args[i]) || "full-history".equals(args[i])) { + // Wait for the completion of pending works if there is any + awaitCompletion(); synchronized (mStats) { mStats.setRecordAllHistoryLocked(enable); } } else if ("no-auto-reset".equals(args[i])) { + // Wait for the completion of pending works if there is any + awaitCompletion(); synchronized (mStats) { mStats.setNoAutoReset(enable); } } else if ("pretend-screen-off".equals(args[i])) { + // Wait for the completion of pending works if there is any + awaitCompletion(); synchronized (mStats) { mStats.setPretendScreenOff(enable); } @@ -1350,6 +1995,7 @@ public final class BatteryStatsService extends IBatteryStats.Stub return; } final long events = ParseUtils.parseLong(args[i], 0); + awaitCompletion(); synchronized (mStats) { mStats.createFakeHistoryEvents(events); pw.println("Battery history create events started."); @@ -1365,6 +2011,7 @@ public final class BatteryStatsService extends IBatteryStats.Stub } else if ("--daily".equals(arg)) { flags |= BatteryStats.DUMP_DAILY_ONLY; } else if ("--reset".equals(arg)) { + awaitCompletion(); synchronized (mStats) { mStats.resetAllStatsCmdLocked(); pw.println("Battery stats reset."); @@ -1372,6 +2019,7 @@ public final class BatteryStatsService extends IBatteryStats.Stub } mWorker.scheduleSync("dump", BatteryExternalStatsWorker.UPDATE_ALL); } else if ("--write".equals(arg)) { + awaitCompletion(); syncStats("dump", BatteryExternalStatsWorker.UPDATE_ALL); synchronized (mStats) { mStats.writeSyncLocked(); @@ -1379,12 +2027,14 @@ public final class BatteryStatsService extends IBatteryStats.Stub noOutput = true; } } else if ("--new-daily".equals(arg)) { + awaitCompletion(); synchronized (mStats) { mStats.recordDailyStatsLocked(); pw.println("New daily stats written."); noOutput = true; } } else if ("--read-daily".equals(arg)) { + awaitCompletion(); synchronized (mStats) { mStats.readDailyStatsLocked(); pw.println("Last daily stats read."); @@ -1441,6 +2091,7 @@ public final class BatteryStatsService extends IBatteryStats.Stub if (BatteryStatsHelper.checkWifiOnly(mContext)) { flags |= BatteryStats.DUMP_DEVICE_WIFI_ONLY; } + awaitCompletion(); // Fetch data from external sources and update the BatteryStatsImpl object with them. syncStats("dump", BatteryExternalStatsWorker.UPDATE_ALL); } finally { @@ -1489,6 +2140,7 @@ public final class BatteryStatsService extends IBatteryStats.Stub } } if (DBG) Slog.d(TAG, "begin dumpProtoLocked from UID " + Binder.getCallingUid()); + awaitCompletion(); synchronized (mStats) { mStats.dumpProtoLocked(mContext, fd, apps, flags, historyStart); if (writeData) { @@ -1528,6 +2180,7 @@ public final class BatteryStatsService extends IBatteryStats.Stub } } if (DBG) Slog.d(TAG, "begin dumpCheckinLocked from UID " + Binder.getCallingUid()); + awaitCompletion(); synchronized (mStats) { mStats.dumpCheckinLocked(mContext, pw, apps, flags, historyStart); if (writeData) { @@ -1537,6 +2190,7 @@ public final class BatteryStatsService extends IBatteryStats.Stub if (DBG) Slog.d(TAG, "end dumpCheckinLocked"); } else { if (DBG) Slog.d(TAG, "begin dumpLocked from UID " + Binder.getCallingUid()); + awaitCompletion(); synchronized (mStats) { mStats.dumpLocked(mContext, pw, flags, reqUid, historyStart); if (writeData) { @@ -1552,6 +2206,8 @@ public final class BatteryStatsService extends IBatteryStats.Stub * @hide */ public CellularBatteryStats getCellularBatteryStats() { + // Wait for the completion of pending works if there is any + awaitCompletion(); synchronized (mStats) { return mStats.getCellularBatteryStats(); } @@ -1562,6 +2218,8 @@ public final class BatteryStatsService extends IBatteryStats.Stub * @hide */ public WifiBatteryStats getWifiBatteryStats() { + // Wait for the completion of pending works if there is any + awaitCompletion(); synchronized (mStats) { return mStats.getWifiBatteryStats(); } @@ -1572,6 +2230,8 @@ public final class BatteryStatsService extends IBatteryStats.Stub * @hide */ public GpsBatteryStats getGpsBatteryStats() { + // Wait for the completion of pending works if there is any + awaitCompletion(); synchronized (mStats) { return mStats.getGpsBatteryStats(); } @@ -1588,6 +2248,8 @@ public final class BatteryStatsService extends IBatteryStats.Stub } long ident = Binder.clearCallingIdentity(); try { + // Wait for the completion of pending works if there is any + awaitCompletion(); if (shouldCollectExternalStats()) { syncStats("get-health-stats-for-uids", BatteryExternalStatsWorker.UPDATE_ALL); } @@ -1614,6 +2276,8 @@ public final class BatteryStatsService extends IBatteryStats.Stub long ident = Binder.clearCallingIdentity(); int i=-1; try { + // Wait for the completion of pending works if there is any + awaitCompletion(); if (shouldCollectExternalStats()) { syncStats("get-health-stats-for-uids", BatteryExternalStatsWorker.UPDATE_ALL); } @@ -1685,4 +2349,124 @@ public final class BatteryStatsService extends IBatteryStats.Stub Binder.restoreCallingIdentity(ident); } } + + void updateForegroundTimeIfOnBattery(final String packageName, final int uid, + final long cpuTimeDiff) { + synchronized (mLock) { + final long elapsedRealtime = SystemClock.elapsedRealtime(); + final long uptime = SystemClock.uptimeMillis(); + mHandler.post(() -> { + if (!isOnBattery()) { + return; + } + synchronized (mStats) { + final BatteryStatsImpl.Uid.Proc ps = + mStats.getProcessStatsLocked(uid, packageName, elapsedRealtime, uptime); + if (ps != null) { + ps.addForegroundTimeLocked(cpuTimeDiff); + } + } + }); + } + } + + void noteCurrentTimeChanged() { + synchronized (mLock) { + final long currentTime = System.currentTimeMillis(); + final long elapsedRealtime = SystemClock.elapsedRealtime(); + final long uptime = SystemClock.uptimeMillis(); + mHandler.post(() -> { + synchronized (mStats) { + mStats.noteCurrentTimeChangedLocked(currentTime, elapsedRealtime, uptime); + } + }); + } + } + + void updateBatteryStatsOnActivityUsage(final String packageName, final String className, + final int uid, final int userId, final boolean resumed) { + synchronized (mLock) { + final long elapsedRealtime = SystemClock.elapsedRealtime(); + final long uptime = SystemClock.uptimeMillis(); + mHandler.post(() -> { + FrameworkStatsLog.write(FrameworkStatsLog.ACTIVITY_FOREGROUND_STATE_CHANGED, + uid, packageName, className, + resumed + ? FrameworkStatsLog.ACTIVITY_FOREGROUND_STATE_CHANGED__STATE__FOREGROUND + : FrameworkStatsLog.ACTIVITY_FOREGROUND_STATE_CHANGED__STATE__BACKGROUND); + synchronized (mStats) { + if (resumed) { + mStats.noteActivityResumedLocked(uid, elapsedRealtime, uptime); + } else { + mStats.noteActivityPausedLocked(uid, elapsedRealtime, uptime); + } + } + }); + } + } + + void noteProcessDied(final int uid, final int pid) { + synchronized (mLock) { + mHandler.post(() -> { + synchronized (mStats) { + mStats.noteProcessDiedLocked(uid, pid); + } + }); + } + } + + void reportExcessiveCpu(final int uid, final String processName, final long uptimeSince, + long cputimeUsed) { + synchronized (mLock) { + mHandler.post(() -> { + synchronized (mStats) { + mStats.reportExcessiveCpuLocked(uid, processName, uptimeSince, cputimeUsed); + } + }); + } + } + + void noteServiceStartRunning(final BatteryStatsImpl.Uid.Pkg.Serv stats) { + synchronized (mLock) { + final long uptime = SystemClock.uptimeMillis(); + mHandler.post(() -> { + synchronized (mStats) { + stats.startRunningLocked(uptime); + } + }); + } + } + + void noteServiceStopRunning(final BatteryStatsImpl.Uid.Pkg.Serv stats) { + synchronized (mLock) { + final long uptime = SystemClock.uptimeMillis(); + mHandler.post(() -> { + synchronized (mStats) { + stats.stopRunningLocked(uptime); + } + }); + } + } + + void noteServiceStartLaunch(final BatteryStatsImpl.Uid.Pkg.Serv stats) { + synchronized (mLock) { + final long uptime = SystemClock.uptimeMillis(); + mHandler.post(() -> { + synchronized (mStats) { + stats.startLaunchedLocked(uptime); + } + }); + } + } + + void noteServiceStopLaunch(final BatteryStatsImpl.Uid.Pkg.Serv stats) { + synchronized (mLock) { + final long uptime = SystemClock.uptimeMillis(); + mHandler.post(() -> { + synchronized (mStats) { + stats.stopLaunchedLocked(uptime); + } + }); + } + } } diff --git a/services/core/java/com/android/server/am/CachedAppOptimizer.java b/services/core/java/com/android/server/am/CachedAppOptimizer.java index c5047e5eed03..966038986791 100644 --- a/services/core/java/com/android/server/am/CachedAppOptimizer.java +++ b/services/core/java/com/android/server/am/CachedAppOptimizer.java @@ -479,6 +479,21 @@ public final class CachedAppOptimizer { private static native void enableFreezerInternal(boolean enable); /** + * Informs binder that a process is about to be frozen. If freezer is enabled on a process via + * this method, this method will synchronously dispatch all pending transactions to the + * specified pid. This method will not add significant latencies when unfreezing. + * After freezing binder calls, binder will block all transaction to the frozen pid, and return + * an error to the sending process. + * + * @param pid the target pid for which binder transactions are to be frozen + * @param freeze specifies whether to flush transactions and then freeze (true) or unfreeze + * binder for the specificed pid. + * + * @throws RuntimeException in case a flush/freeze operation could not complete successfully. + */ + private static native void freezeBinder(int pid, boolean freeze); + + /** * Determines whether the freezer is supported by this system */ public static boolean isFreezerSupported() { @@ -727,6 +742,13 @@ public final class CachedAppOptimizer { } if (!app.frozen) { + try { + freezeBinder(app.pid, false); + } catch (RuntimeException e) { + // TODO: it might be preferable to kill the target pid in this case + Slog.e(TAG_AM, "Unable to unfreeze binder for " + app.pid + " " + app.processName); + } + if (DEBUG_FREEZER) { Slog.d(TAG_AM, "sync unfroze " + app.pid + " " + app.processName); } @@ -1039,6 +1061,14 @@ public final class CachedAppOptimizer { return; } + try { + freezeBinder(pid, true); + } catch (RuntimeException e) { + // TODO: it might be preferable to kill the target pid in this case + Slog.e(TAG_AM, "Unable to freeze binder for " + pid + " " + name); + return; + } + if (pid == 0 || proc.frozen) { // Already frozen or not a real process, either one being // launched or one being killed diff --git a/services/core/java/com/android/server/appop/AppOpsService.java b/services/core/java/com/android/server/appop/AppOpsService.java index dfe8af155a04..b56b09d707af 100644 --- a/services/core/java/com/android/server/appop/AppOpsService.java +++ b/services/core/java/com/android/server/appop/AppOpsService.java @@ -2206,6 +2206,7 @@ public class AppOpsService extends IAppOpsService.Stub { updatePermissionRevokedCompat(uid, code, mode); } + int previousMode; synchronized (this) { final int defaultMode = AppOpsManager.opToDefaultMode(code); @@ -2214,12 +2215,14 @@ public class AppOpsService extends IAppOpsService.Stub { if (mode == defaultMode) { return; } + previousMode = AppOpsManager.MODE_DEFAULT; uidState = new UidState(uid); uidState.opModes = new SparseIntArray(); uidState.opModes.put(code, mode); mUidStates.put(uid, uidState); scheduleWriteLocked(); } else if (uidState.opModes == null) { + previousMode = AppOpsManager.MODE_DEFAULT; if (mode != defaultMode) { uidState.opModes = new SparseIntArray(); uidState.opModes.put(code, mode); @@ -2229,6 +2232,7 @@ public class AppOpsService extends IAppOpsService.Stub { if (uidState.opModes.indexOfKey(code) >= 0 && uidState.opModes.get(code) == mode) { return; } + previousMode = uidState.opModes.get(code); if (mode == defaultMode) { uidState.opModes.delete(code); if (uidState.opModes.size() <= 0) { @@ -2243,7 +2247,7 @@ public class AppOpsService extends IAppOpsService.Stub { } notifyOpChangedForAllPkgsInUid(code, uid, false, permissionPolicyCallback); - notifyOpChangedSync(code, uid, null, mode); + notifyOpChangedSync(code, uid, null, mode, previousMode); } /** @@ -2420,11 +2424,12 @@ public class AppOpsService extends IAppOpsService.Stub { } } - private void notifyOpChangedSync(int code, int uid, @NonNull String packageName, int mode) { + private void notifyOpChangedSync(int code, int uid, @NonNull String packageName, int mode, + int previousMode) { final StorageManagerInternal storageManagerInternal = LocalServices.getService(StorageManagerInternal.class); if (storageManagerInternal != null) { - storageManagerInternal.onAppOpsChanged(code, uid, packageName, mode); + storageManagerInternal.onAppOpsChanged(code, uid, packageName, mode, previousMode); } } @@ -2458,11 +2463,13 @@ public class AppOpsService extends IAppOpsService.Stub { return; } + int previousMode = AppOpsManager.MODE_DEFAULT; synchronized (this) { UidState uidState = getUidStateLocked(uid, false); Op op = getOpLocked(code, uid, packageName, null, bypass, true); if (op != null) { if (op.mode != mode) { + previousMode = op.mode; op.mode = mode; if (uidState != null) { uidState.evalForegroundOps(mOpModeWatchers); @@ -2499,7 +2506,7 @@ public class AppOpsService extends IAppOpsService.Stub { this, repCbs, code, uid, packageName)); } - notifyOpChangedSync(code, uid, packageName, mode); + notifyOpChangedSync(code, uid, packageName, mode, previousMode); } private void notifyOpChanged(ArraySet<ModeCallback> callbacks, int code, @@ -2542,7 +2549,7 @@ public class AppOpsService extends IAppOpsService.Stub { } private static ArrayList<ChangeRec> addChange(ArrayList<ChangeRec> reports, - int op, int uid, String packageName) { + int op, int uid, String packageName, int previousMode) { boolean duplicate = false; if (reports == null) { reports = new ArrayList<>(); @@ -2557,7 +2564,7 @@ public class AppOpsService extends IAppOpsService.Stub { } } if (!duplicate) { - reports.add(new ChangeRec(op, uid, packageName)); + reports.add(new ChangeRec(op, uid, packageName, previousMode)); } return reports; @@ -2565,7 +2572,7 @@ public class AppOpsService extends IAppOpsService.Stub { private static HashMap<ModeCallback, ArrayList<ChangeRec>> addCallbacks( HashMap<ModeCallback, ArrayList<ChangeRec>> callbacks, - int op, int uid, String packageName, ArraySet<ModeCallback> cbs) { + int op, int uid, String packageName, int previousMode, ArraySet<ModeCallback> cbs) { if (cbs == null) { return callbacks; } @@ -2576,7 +2583,7 @@ public class AppOpsService extends IAppOpsService.Stub { for (int i=0; i<N; i++) { ModeCallback cb = cbs.valueAt(i); ArrayList<ChangeRec> reports = callbacks.get(cb); - ArrayList<ChangeRec> changed = addChange(reports, op, uid, packageName); + ArrayList<ChangeRec> changed = addChange(reports, op, uid, packageName, previousMode); if (changed != reports) { callbacks.put(cb, changed); } @@ -2588,11 +2595,13 @@ public class AppOpsService extends IAppOpsService.Stub { final int op; final int uid; final String pkg; + final int previous_mode; - ChangeRec(int _op, int _uid, String _pkg) { + ChangeRec(int _op, int _uid, String _pkg, int _previous_mode) { op = _op; uid = _uid; pkg = _pkg; + previous_mode = _previous_mode; } } @@ -2628,18 +2637,19 @@ public class AppOpsService extends IAppOpsService.Stub { for (int j = uidOpCount - 1; j >= 0; j--) { final int code = opModes.keyAt(j); if (AppOpsManager.opAllowsReset(code)) { + int previousMode = opModes.valueAt(j); opModes.removeAt(j); if (opModes.size() <= 0) { uidState.opModes = null; } for (String packageName : getPackagesForUid(uidState.uid)) { callbacks = addCallbacks(callbacks, code, uidState.uid, packageName, - mOpModeWatchers.get(code)); + previousMode, mOpModeWatchers.get(code)); callbacks = addCallbacks(callbacks, code, uidState.uid, packageName, - mPackageModeWatchers.get(packageName)); + previousMode, mPackageModeWatchers.get(packageName)); allChanges = addChange(allChanges, code, uidState.uid, - packageName); + packageName, previousMode); } } } @@ -2670,16 +2680,18 @@ public class AppOpsService extends IAppOpsService.Stub { Op curOp = pkgOps.valueAt(j); if (AppOpsManager.opAllowsReset(curOp.op) && curOp.mode != AppOpsManager.opToDefaultMode(curOp.op)) { + int previousMode = curOp.mode; curOp.mode = AppOpsManager.opToDefaultMode(curOp.op); changed = true; uidChanged = true; final int uid = curOp.uidState.uid; callbacks = addCallbacks(callbacks, curOp.op, uid, packageName, - mOpModeWatchers.get(curOp.op)); + previousMode, mOpModeWatchers.get(curOp.op)); callbacks = addCallbacks(callbacks, curOp.op, uid, packageName, - mPackageModeWatchers.get(packageName)); + previousMode, mPackageModeWatchers.get(packageName)); - allChanges = addChange(allChanges, curOp.op, uid, packageName); + allChanges = addChange(allChanges, curOp.op, uid, packageName, + previousMode); curOp.removeAttributionsWithNoTime(); if (curOp.mAttributions.isEmpty()) { pkgOps.removeAt(j); @@ -2720,7 +2732,7 @@ public class AppOpsService extends IAppOpsService.Stub { for (int i = 0; i < numChanges; i++) { ChangeRec change = allChanges.get(i); notifyOpChangedSync(change.op, change.uid, change.pkg, - AppOpsManager.opToDefaultMode(change.op)); + AppOpsManager.opToDefaultMode(change.op), change.previous_mode); } } } @@ -3926,7 +3938,7 @@ public class AppOpsService extends IAppOpsService.Stub { if (!isAttributionTagValid) { String msg = "attributionTag " + attributionTag + " not declared in" - + "manifest of " + packageName; + + " manifest of " + packageName; try { if (mPlatformCompat.isChangeEnabledByPackageName( SECURITY_EXCEPTION_ON_INVALID_ATTRIBUTION_TAG_CHANGE, packageName, diff --git a/services/core/java/com/android/server/audio/AudioDeviceBroker.java b/services/core/java/com/android/server/audio/AudioDeviceBroker.java index 5447605a36d1..1615998f7787 100644 --- a/services/core/java/com/android/server/audio/AudioDeviceBroker.java +++ b/services/core/java/com/android/server/audio/AudioDeviceBroker.java @@ -28,6 +28,7 @@ import android.media.AudioDeviceAttributes; import android.media.AudioRoutesInfo; import android.media.AudioSystem; import android.media.IAudioRoutesObserver; +import android.media.ICapturePresetDevicesRoleDispatcher; import android.media.IStrategyPreferredDevicesDispatcher; import android.media.MediaMetrics; import android.os.Binder; @@ -546,6 +547,25 @@ import java.util.concurrent.atomic.AtomicBoolean; mDeviceInventory.unregisterStrategyPreferredDevicesDispatcher(dispatcher); } + /*package*/ int setPreferredDevicesForCapturePresetSync(int capturePreset, + @NonNull List<AudioDeviceAttributes> devices) { + return mDeviceInventory.setPreferredDevicesForCapturePresetSync(capturePreset, devices); + } + + /*package*/ int clearPreferredDevicesForCapturePresetSync(int capturePreset) { + return mDeviceInventory.clearPreferredDevicesForCapturePresetSync(capturePreset); + } + + /*package*/ void registerCapturePresetDevicesRoleDispatcher( + @NonNull ICapturePresetDevicesRoleDispatcher dispatcher) { + mDeviceInventory.registerCapturePresetDevicesRoleDispatcher(dispatcher); + } + + /*package*/ void unregisterCapturePresetDevicesRoleDispatcher( + @NonNull ICapturePresetDevicesRoleDispatcher dispatcher) { + mDeviceInventory.unregisterCapturePresetDevicesRoleDispatcher(dispatcher); + } + //--------------------------------------------------------------------- // Communication with (to) AudioService //TODO check whether the AudioService methods are candidates to move here @@ -694,6 +714,17 @@ import java.util.concurrent.atomic.AtomicBoolean; sendIMsgNoDelay(MSG_I_SAVE_REMOVE_PREF_DEVICES_FOR_STRATEGY, SENDMSG_QUEUE, strategy); } + /*package*/ void postSaveSetPreferredDevicesForCapturePreset( + int capturePreset, List<AudioDeviceAttributes> devices) { + sendILMsgNoDelay( + MSG_IL_SAVE_PREF_DEVICES_FOR_CAPTURE_PRESET, SENDMSG_QUEUE, capturePreset, devices); + } + + /*package*/ void postSaveClearPreferredDevicesForCapturePreset(int capturePreset) { + sendIMsgNoDelay( + MSG_I_SAVE_CLEAR_PREF_DEVICES_FOR_CAPTURE_PRESET, SENDMSG_QUEUE, capturePreset); + } + //--------------------------------------------------------------------- // Method forwarding between the helper classes (BtHelper, AudioDeviceInventory) // only call from a "handle"* method or "on"* method @@ -1098,6 +1129,17 @@ import java.util.concurrent.atomic.AtomicBoolean; case MSG_CHECK_MUTE_MUSIC: checkMessagesMuteMusic(0); break; + case MSG_IL_SAVE_PREF_DEVICES_FOR_CAPTURE_PRESET: { + final int capturePreset = msg.arg1; + final List<AudioDeviceAttributes> devices = + (List<AudioDeviceAttributes>) msg.obj; + mDeviceInventory.onSaveSetPreferredDevicesForCapturePreset( + capturePreset, devices); + } break; + case MSG_I_SAVE_CLEAR_PREF_DEVICES_FOR_CAPTURE_PRESET: { + final int capturePreset = msg.arg1; + mDeviceInventory.onSaveClearPreferredDevicesForCapturePreset(capturePreset); + } break; default: Log.wtf(TAG, "Invalid message " + msg.what); } @@ -1174,6 +1216,9 @@ import java.util.concurrent.atomic.AtomicBoolean; private static final int MSG_CHECK_MUTE_MUSIC = 36; private static final int MSG_REPORT_NEW_ROUTES_A2DP = 37; + private static final int MSG_IL_SAVE_PREF_DEVICES_FOR_CAPTURE_PRESET = 38; + private static final int MSG_I_SAVE_CLEAR_PREF_DEVICES_FOR_CAPTURE_PRESET = 39; + private static boolean isMessageHandledUnderWakelock(int msgId) { switch(msgId) { diff --git a/services/core/java/com/android/server/audio/AudioDeviceInventory.java b/services/core/java/com/android/server/audio/AudioDeviceInventory.java index fbf07cc591ff..33a8a30243de 100644 --- a/services/core/java/com/android/server/audio/AudioDeviceInventory.java +++ b/services/core/java/com/android/server/audio/AudioDeviceInventory.java @@ -31,6 +31,7 @@ import android.media.AudioPort; import android.media.AudioRoutesInfo; import android.media.AudioSystem; import android.media.IAudioRoutesObserver; +import android.media.ICapturePresetDevicesRoleDispatcher; import android.media.IStrategyPreferredDevicesDispatcher; import android.media.MediaMetrics; import android.os.Binder; @@ -140,6 +141,10 @@ public class AudioDeviceInventory { private final ArrayMap<Integer, List<AudioDeviceAttributes>> mPreferredDevices = new ArrayMap<>(); + // List of preferred devices of capture preset + private final ArrayMap<Integer, List<AudioDeviceAttributes>> mPreferredDevicesForCapturePreset = + new ArrayMap<>(); + // the wrapper for AudioSystem static methods, allows us to spy AudioSystem private final @NonNull AudioSystemAdapter mAudioSystem; @@ -154,6 +159,10 @@ public class AudioDeviceInventory { final RemoteCallbackList<IStrategyPreferredDevicesDispatcher> mPrefDevDispatchers = new RemoteCallbackList<IStrategyPreferredDevicesDispatcher>(); + // Monitoring of devices for role and capture preset + final RemoteCallbackList<ICapturePresetDevicesRoleDispatcher> mDevRoleCapturePresetDispatchers = + new RemoteCallbackList<ICapturePresetDevicesRoleDispatcher>(); + /*package*/ AudioDeviceInventory(@NonNull AudioDeviceBroker broker) { mDeviceBroker = broker; mAudioSystem = AudioSystemAdapter.getDefaultAdapter(); @@ -243,6 +252,9 @@ public class AudioDeviceInventory { pw.println(" " + prefix + " type:0x" + Integer.toHexString(keyType) + " (" + AudioSystem.getDeviceName(keyType) + ") addr:" + valueAddress); }); + mPreferredDevicesForCapturePreset.forEach((capturePreset, devices) -> { + pw.println(" " + prefix + "capturePreset:" + capturePreset + + " devices:" + devices); }); } //------------------------------------------------------------ @@ -270,6 +282,9 @@ public class AudioDeviceInventory { mAudioSystem.setDevicesRoleForStrategy( strategy, AudioSystem.DEVICE_ROLE_PREFERRED, devices); }); } + synchronized (mPreferredDevicesForCapturePreset) { + // TODO: call audiosystem to restore + } } // only public for mocking/spying @@ -613,6 +628,20 @@ public class AudioDeviceInventory { dispatchPreferredDevice(strategy, new ArrayList<AudioDeviceAttributes>()); } + /*package*/ void onSaveSetPreferredDevicesForCapturePreset( + int capturePreset, @NonNull List<AudioDeviceAttributes> devices) { + mPreferredDevicesForCapturePreset.put(capturePreset, devices); + dispatchDevicesRoleForCapturePreset( + capturePreset, AudioSystem.DEVICE_ROLE_PREFERRED, devices); + } + + /*package*/ void onSaveClearPreferredDevicesForCapturePreset(int capturePreset) { + mPreferredDevicesForCapturePreset.remove(capturePreset); + dispatchDevicesRoleForCapturePreset( + capturePreset, AudioSystem.DEVICE_ROLE_PREFERRED, + new ArrayList<AudioDeviceAttributes>()); + } + //------------------------------------------------------------ // @@ -651,6 +680,41 @@ public class AudioDeviceInventory { mPrefDevDispatchers.unregister(dispatcher); } + /*package*/ int setPreferredDevicesForCapturePresetSync( + int capturePreset, @NonNull List<AudioDeviceAttributes> devices) { + final long identity = Binder.clearCallingIdentity(); + final int status = mAudioSystem.setDevicesRoleForCapturePreset( + capturePreset, AudioSystem.DEVICE_ROLE_PREFERRED, devices); + Binder.restoreCallingIdentity(identity); + + if (status == AudioSystem.SUCCESS) { + mDeviceBroker.postSaveSetPreferredDevicesForCapturePreset(capturePreset, devices); + } + return status; + } + + /*package*/ int clearPreferredDevicesForCapturePresetSync(int capturePreset) { + final long identity = Binder.clearCallingIdentity(); + final int status = mAudioSystem.clearDevicesRoleForCapturePreset( + capturePreset, AudioSystem.DEVICE_ROLE_PREFERRED); + Binder.restoreCallingIdentity(identity); + + if (status == AudioSystem.SUCCESS) { + mDeviceBroker.postSaveClearPreferredDevicesForCapturePreset(capturePreset); + } + return status; + } + + /*package*/ void registerCapturePresetDevicesRoleDispatcher( + @NonNull ICapturePresetDevicesRoleDispatcher dispatcher) { + mDevRoleCapturePresetDispatchers.register(dispatcher); + } + + /*package*/ void unregisterCapturePresetDevicesRoleDispatcher( + @NonNull ICapturePresetDevicesRoleDispatcher dispatcher) { + mDevRoleCapturePresetDispatchers.unregister(dispatcher); + } + /** * Implements the communication with AudioSystem to (dis)connect a device in the native layers * @param connect true if connection @@ -1306,6 +1370,19 @@ public class AudioDeviceInventory { mPrefDevDispatchers.finishBroadcast(); } + private void dispatchDevicesRoleForCapturePreset( + int capturePreset, int role, @NonNull List<AudioDeviceAttributes> devices) { + final int nbDispatchers = mDevRoleCapturePresetDispatchers.beginBroadcast(); + for (int i = 0; i < nbDispatchers; ++i) { + try { + mDevRoleCapturePresetDispatchers.getBroadcastItem(i).dispatchDevicesRoleChanged( + capturePreset, role, devices); + } catch (RemoteException e) { + } + } + mDevRoleCapturePresetDispatchers.finishBroadcast(); + } + //---------------------------------------------------------- // For tests only diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java index 4378490d19c5..f63c2ee5ee94 100755..100644 --- a/services/core/java/com/android/server/audio/AudioService.java +++ b/services/core/java/com/android/server/audio/AudioService.java @@ -84,6 +84,7 @@ import android.media.IAudioFocusDispatcher; import android.media.IAudioRoutesObserver; import android.media.IAudioServerStateDispatcher; import android.media.IAudioService; +import android.media.ICapturePresetDevicesRoleDispatcher; import android.media.IPlaybackConfigDispatcher; import android.media.IRecordingConfigDispatcher; import android.media.IRingtonePlayer; @@ -1987,6 +1988,94 @@ public class AudioService extends IAudioService.Stub mDeviceBroker.unregisterStrategyPreferredDevicesDispatcher(dispatcher); } + /** + * @see AudioManager#setPreferredDeviceForCapturePreset(int, AudioDeviceAttributes) + */ + public int setPreferredDevicesForCapturePreset( + int capturePreset, List<AudioDeviceAttributes> devices) { + if (devices == null) { + return AudioSystem.ERROR; + } + enforceModifyAudioRoutingPermission(); + final String logString = String.format( + "setPreferredDevicesForCapturePreset u/pid:%d/%d source:%d dev:%s", + Binder.getCallingUid(), Binder.getCallingPid(), capturePreset, + devices.stream().map(e -> e.toString()).collect(Collectors.joining(","))); + sDeviceLogger.log(new AudioEventLogger.StringEvent(logString).printLog(TAG)); + if (devices.stream().anyMatch(device -> + device.getRole() == AudioDeviceAttributes.ROLE_OUTPUT)) { + Log.e(TAG, "Unsupported output routing in " + logString); + return AudioSystem.ERROR; + } + + final int status = mDeviceBroker.setPreferredDevicesForCapturePresetSync( + capturePreset, devices); + if (status != AudioSystem.SUCCESS) { + Log.e(TAG, String.format("Error %d in %s)", status, logString)); + } + + return status; + } + + /** @see AudioManager#clearPreferredDevicesForCapturePreset(int) */ + public int clearPreferredDevicesForCapturePreset(int capturePreset) { + enforceModifyAudioRoutingPermission(); + final String logString = String.format( + "removePreferredDeviceForCapturePreset source:%d", capturePreset); + sDeviceLogger.log(new AudioEventLogger.StringEvent(logString).printLog(TAG)); + + final int status = mDeviceBroker.clearPreferredDevicesForCapturePresetSync(capturePreset); + if (status != AudioSystem.SUCCESS) { + Log.e(TAG, String.format("Error %d in %s", status, logString)); + } + return status; + } + + /** + * @see AudioManager#getPreferredDevicesForCapturePreset(int) + */ + public List<AudioDeviceAttributes> getPreferredDevicesForCapturePreset(int capturePreset) { + enforceModifyAudioRoutingPermission(); + List<AudioDeviceAttributes> devices = new ArrayList<>(); + final long identity = Binder.clearCallingIdentity(); + final int status = AudioSystem.getDevicesForRoleAndCapturePreset( + capturePreset, AudioSystem.DEVICE_ROLE_PREFERRED, devices); + Binder.restoreCallingIdentity(identity); + if (status != AudioSystem.SUCCESS) { + Log.e(TAG, String.format("Error %d in getPreferredDeviceForCapturePreset(%d)", + status, capturePreset)); + return new ArrayList<AudioDeviceAttributes>(); + } else { + return devices; + } + } + + /** + * @see AudioManager#addOnPreferredDevicesForCapturePresetChangedListener( + * Executor, OnPreferredDevicesForCapturePresetChangedListener) + */ + public void registerCapturePresetDevicesRoleDispatcher( + @Nullable ICapturePresetDevicesRoleDispatcher dispatcher) { + if (dispatcher == null) { + return; + } + enforceModifyAudioRoutingPermission(); + mDeviceBroker.registerCapturePresetDevicesRoleDispatcher(dispatcher); + } + + /** + * @see AudioManager#removeOnPreferredDevicesForCapturePresetChangedListener( + * AudioManager.OnPreferredDevicesForCapturePresetChangedListener) + */ + public void unregisterCapturePresetDevicesRoleDispatcher( + @Nullable ICapturePresetDevicesRoleDispatcher dispatcher) { + if (dispatcher == null) { + return; + } + enforceModifyAudioRoutingPermission(); + mDeviceBroker.unregisterCapturePresetDevicesRoleDispatcher(dispatcher); + } + /** @see AudioManager#getDevicesForAttributes(AudioAttributes) */ public @NonNull ArrayList<AudioDeviceAttributes> getDevicesForAttributes( @NonNull AudioAttributes attributes) { @@ -4097,6 +4186,62 @@ public class AudioService extends IAudioService.Stub } } + /** @see AudioManager#adjustSuggestedStreamVolumeForUid(int, int, int, String, int, int, int) */ + @Override + public void adjustSuggestedStreamVolumeForUid(int streamType, int direction, int flags, + @NonNull String packageName, int uid, int pid, UserHandle userHandle, + int targetSdkVersion) { + if (Binder.getCallingUid() != Process.SYSTEM_UID) { + throw new SecurityException("Should only be called from system process"); + } + + final boolean hasModifyAudioSettings = + mContext.checkPermission(Manifest.permission.MODIFY_AUDIO_SETTINGS, pid, uid) + == PackageManager.PERMISSION_GRANTED; + // direction and stream type swap here because the public + // adjustSuggested has a different order than the other methods. + adjustSuggestedStreamVolume(direction, streamType, flags, packageName, packageName, uid, + hasModifyAudioSettings, VOL_ADJUST_NORMAL); + } + + /** @see AudioManager#adjustStreamVolumeForUid(int, int, int, String, int, int, int) */ + @Override + public void adjustStreamVolumeForUid(int streamType, int direction, int flags, + @NonNull String packageName, int uid, int pid, UserHandle userHandle, + int targetSdkVersion) { + if (Binder.getCallingUid() != Process.SYSTEM_UID) { + throw new SecurityException("Should only be called from system process"); + } + + if (direction != AudioManager.ADJUST_SAME) { + sVolumeLogger.log(new VolumeEvent(VolumeEvent.VOL_ADJUST_VOL_UID, streamType, + direction/*val1*/, flags/*val2*/, + new StringBuilder(packageName).append(" uid:").append(uid) + .toString())); + } + final boolean hasModifyAudioSettings = + mContext.checkPermission(Manifest.permission.MODIFY_AUDIO_SETTINGS, pid, uid) + == PackageManager.PERMISSION_GRANTED; + adjustStreamVolume(streamType, direction, flags, packageName, packageName, uid, + hasModifyAudioSettings, VOL_ADJUST_NORMAL); + } + + /** @see AudioManager#setStreamVolumeForUid(int, int, int, String, int, int, int) */ + @Override + public void setStreamVolumeForUid(int streamType, int index, int flags, + @NonNull String packageName, int uid, int pid, UserHandle userHandle, + int targetSdkVersion) { + if (Binder.getCallingUid() != Process.SYSTEM_UID) { + throw new SecurityException("Should only be called from system process"); + } + + final boolean hasModifyAudioSettings = + mContext.checkPermission(Manifest.permission.MODIFY_AUDIO_SETTINGS, pid, uid) + == PackageManager.PERMISSION_GRANTED; + setStreamVolume(streamType, index, flags, packageName, packageName, uid, + hasModifyAudioSettings); + } + //========================================================================================== // Sound Effects //========================================================================================== @@ -7982,43 +8127,6 @@ public class AudioService extends IAudioService.Stub } @Override - public void adjustSuggestedStreamVolumeForUid(int streamType, int direction, int flags, - String callingPackage, int uid, int pid) { - final boolean hasModifyAudioSettings = - mContext.checkPermission(Manifest.permission.MODIFY_AUDIO_SETTINGS, pid, uid) - == PackageManager.PERMISSION_GRANTED; - // direction and stream type swap here because the public - // adjustSuggested has a different order than the other methods. - adjustSuggestedStreamVolume(direction, streamType, flags, callingPackage, - callingPackage, uid, hasModifyAudioSettings, VOL_ADJUST_NORMAL); - } - - @Override - public void adjustStreamVolumeForUid(int streamType, int direction, int flags, - String callingPackage, int uid, int pid) { - if (direction != AudioManager.ADJUST_SAME) { - sVolumeLogger.log(new VolumeEvent(VolumeEvent.VOL_ADJUST_VOL_UID, streamType, - direction/*val1*/, flags/*val2*/, new StringBuilder(callingPackage) - .append(" uid:").append(uid).toString())); - } - final boolean hasModifyAudioSettings = - mContext.checkPermission(Manifest.permission.MODIFY_AUDIO_SETTINGS, pid, uid) - == PackageManager.PERMISSION_GRANTED; - adjustStreamVolume(streamType, direction, flags, callingPackage, - callingPackage, uid, hasModifyAudioSettings, VOL_ADJUST_NORMAL); - } - - @Override - public void setStreamVolumeForUid(int streamType, int direction, int flags, - String callingPackage, int uid, int pid) { - final boolean hasModifyAudioSettings = - mContext.checkPermission(Manifest.permission.MODIFY_AUDIO_SETTINGS, pid, uid) - == PackageManager.PERMISSION_GRANTED; - setStreamVolume(streamType, direction, flags, callingPackage, callingPackage, uid, - hasModifyAudioSettings); - } - - @Override public int getRingerModeInternal() { return AudioService.this.getRingerModeInternal(); } diff --git a/services/core/java/com/android/server/audio/AudioSystemAdapter.java b/services/core/java/com/android/server/audio/AudioSystemAdapter.java index a0e1ca78a5e7..ae64990fd8d0 100644 --- a/services/core/java/com/android/server/audio/AudioSystemAdapter.java +++ b/services/core/java/com/android/server/audio/AudioSystemAdapter.java @@ -101,6 +101,40 @@ public class AudioSystemAdapter { } /** + * Same as (@link AudioSystem#setDevicesRoleForCapturePreset(int, List)) + * @param capturePreset + * @param role + * @param devices + * @return + */ + public int setDevicesRoleForCapturePreset(int capturePreset, int role, + @NonNull List<AudioDeviceAttributes> devices) { + return AudioSystem.setDevicesRoleForCapturePreset(capturePreset, role, devices); + } + + /** + * Same as {@link AudioSystem#removeDevicesRoleForCapturePreset(int, int)} + * @param capturePreset + * @param role + * @param devicesToRemove + * @return + */ + public int removeDevicesRoleForCapturePreset( + int capturePreset, int role, @NonNull List<AudioDeviceAttributes> devicesToRemove) { + return AudioSystem.removeDevicesRoleForCapturePreset(capturePreset, role, devicesToRemove); + } + + /** + * Same as {@link AudioSystem#} + * @param capturePreset + * @param role + * @return + */ + public int clearDevicesRoleForCapturePreset(int capturePreset, int role) { + return AudioSystem.clearDevicesRoleForCapturePreset(capturePreset, role); + } + + /** * Same as {@link AudioSystem#setParameters(String)} * @param keyValuePairs * @return diff --git a/services/core/java/com/android/server/audio/MediaFocusControl.java b/services/core/java/com/android/server/audio/MediaFocusControl.java index bbc29b0bf89b..f02bb8ffe17f 100755..100644 --- a/services/core/java/com/android/server/audio/MediaFocusControl.java +++ b/services/core/java/com/android/server/audio/MediaFocusControl.java @@ -19,6 +19,7 @@ package com.android.server.audio; import android.annotation.NonNull; import android.annotation.Nullable; import android.app.AppOpsManager; +import android.content.ContentResolver; import android.content.Context; import android.media.AudioAttributes; import android.media.AudioFocusInfo; @@ -94,8 +95,9 @@ public class MediaFocusControl implements PlayerFocusEnforcer { mContext = cntxt; mAppOps = (AppOpsManager)mContext.getSystemService(Context.APP_OPS_SERVICE); mFocusEnforcer = pfe; - mMultiAudioFocusEnabled = Settings.System.getInt(mContext.getContentResolver(), - Settings.System.MULTI_AUDIO_FOCUS_ENABLED, 0) != 0; + final ContentResolver cr = mContext.getContentResolver(); + mMultiAudioFocusEnabled = Settings.System.getIntForUser(cr, + Settings.System.MULTI_AUDIO_FOCUS_ENABLED, 0, cr.getUserId()) != 0; } protected void dump(PrintWriter pw) { @@ -1081,8 +1083,9 @@ public class MediaFocusControl implements PlayerFocusEnforcer { public void updateMultiAudioFocus(boolean enabled) { Log.d(TAG, "updateMultiAudioFocus( " + enabled + " )"); mMultiAudioFocusEnabled = enabled; - Settings.System.putInt(mContext.getContentResolver(), - Settings.System.MULTI_AUDIO_FOCUS_ENABLED, enabled ? 1 : 0); + final ContentResolver cr = mContext.getContentResolver(); + Settings.System.putIntForUser(cr, + Settings.System.MULTI_AUDIO_FOCUS_ENABLED, enabled ? 1 : 0, cr.getUserId()); if (!mFocusStack.isEmpty()) { final FocusRequester fr = mFocusStack.peek(); fr.handleFocusLoss(AudioManager.AUDIOFOCUS_LOSS, null, false); diff --git a/services/core/java/com/android/server/biometrics/sensors/AcquisitionClient.java b/services/core/java/com/android/server/biometrics/sensors/AcquisitionClient.java index 73fc17aa26f1..9898d7676178 100644 --- a/services/core/java/com/android/server/biometrics/sensors/AcquisitionClient.java +++ b/services/core/java/com/android/server/biometrics/sensors/AcquisitionClient.java @@ -98,7 +98,11 @@ public abstract class AcquisitionClient<T> extends ClientMonitor<T> implements I } if (finish) { - mCallback.onClientFinished(this, false /* success */); + if (mCallback == null) { + Slog.e(TAG, "Callback is null, perhaps the client hasn't been started yet?"); + } else { + mCallback.onClientFinished(this, false /* success */); + } } } diff --git a/services/core/java/com/android/server/biometrics/sensors/ClientMonitor.java b/services/core/java/com/android/server/biometrics/sensors/ClientMonitor.java index e585b48d49b6..3c9dddd0b905 100644 --- a/services/core/java/com/android/server/biometrics/sensors/ClientMonitor.java +++ b/services/core/java/com/android/server/biometrics/sensors/ClientMonitor.java @@ -176,6 +176,9 @@ public abstract class ClientMonitor<T> extends LoggableMonitor implements IBinde // TODO(b/157790417): Move this to the scheduler void binderDiedInternal(boolean clearListener) { + Slog.e(TAG, "Binder died, owner: " + getOwnerString() + + ", operation: " + this.getClass().getName()); + if (isAlreadyDone()) { Slog.w(TAG, "Binder died but client is finished, ignoring"); return; diff --git a/services/core/java/com/android/server/biometrics/sensors/face/Face10.java b/services/core/java/com/android/server/biometrics/sensors/face/Face10.java index d9c62df3f3ea..d2c35feccc11 100644 --- a/services/core/java/com/android/server/biometrics/sensors/face/Face10.java +++ b/services/core/java/com/android/server/biometrics/sensors/face/Face10.java @@ -25,12 +25,14 @@ import android.app.UserSwitchObserver; import android.content.Context; import android.content.pm.UserInfo; import android.hardware.biometrics.BiometricConstants; +import android.hardware.biometrics.BiometricFaceConstants; import android.hardware.biometrics.BiometricsProtoEnums; import android.hardware.biometrics.face.V1_0.IBiometricsFace; import android.hardware.biometrics.face.V1_0.IBiometricsFaceClientCallback; import android.hardware.face.Face; import android.hardware.face.FaceSensorProperties; import android.hardware.face.IFaceServiceReceiver; +import android.os.Binder; import android.os.Build; import android.os.Handler; import android.os.IBinder; @@ -109,6 +111,9 @@ class Face10 implements IHwBinder.DeathRecipient { @Override public void onUserSwitching(int newUserId) { scheduleInternalCleanup(newUserId); + scheduleGetFeature(new Binder(), newUserId, + BiometricFaceConstants.FEATURE_REQUIRE_ATTENTION, + null, mContext.getOpPackageName()); } }; @@ -360,6 +365,9 @@ class Face10 implements IHwBinder.DeathRecipient { if (halId != 0) { scheduleLoadAuthenticatorIds(); scheduleInternalCleanup(ActivityManager.getCurrentUser()); + scheduleGetFeature(new Binder(), ActivityManager.getCurrentUser(), + BiometricFaceConstants.FEATURE_REQUIRE_ATTENTION, + null, mContext.getOpPackageName()); } else { Slog.e(TAG, "Unable to set callback"); mDaemon = null; @@ -450,7 +458,7 @@ class Face10 implements IHwBinder.DeathRecipient { } void scheduleGetFeature(@NonNull IBinder token, int userId, int feature, - @NonNull IFaceServiceReceiver receiver, @NonNull String opPackageName) { + @Nullable ClientMonitorCallbackConverter listener, @NonNull String opPackageName) { mHandler.post(() -> { final List<Face> faces = getEnrolledFaces(userId); if (faces.isEmpty()) { @@ -461,10 +469,22 @@ class Face10 implements IHwBinder.DeathRecipient { scheduleUpdateActiveUserWithoutHandler(userId); final int faceId = faces.get(0).getBiometricId(); - final FaceGetFeatureClient client = new FaceGetFeatureClient(mContext, - mLazyDaemon, token, new ClientMonitorCallbackConverter(receiver), userId, - opPackageName, mSensorId, feature, faceId); - mScheduler.scheduleClientMonitor(client); + final FaceGetFeatureClient client = new FaceGetFeatureClient(mContext, mLazyDaemon, + token, listener, userId, opPackageName, mSensorId, feature, faceId); + mScheduler.scheduleClientMonitor(client, new ClientMonitor.Callback() { + @Override + public void onClientFinished( + @NonNull ClientMonitor<?> clientMonitor, boolean success) { + if (success && feature == BiometricFaceConstants.FEATURE_REQUIRE_ATTENTION) { + final int settingsValue = client.getValue() ? 1 : 0; + Slog.d(TAG, "Updating attention value for user: " + userId + + " to value: " + settingsValue); + Settings.Secure.putIntForUser(mContext.getContentResolver(), + Settings.Secure.FACE_UNLOCK_ATTENTION_REQUIRED, + settingsValue, userId); + } + } + }); }); } @@ -490,8 +510,15 @@ class Face10 implements IHwBinder.DeathRecipient { if (mCurrentChallengeOwner != null) { Slog.w(TAG, "Current challenge owner: " + mCurrentChallengeOwner + ", interrupted by: " + opPackageName); + final ClientMonitorCallbackConverter listener = + mCurrentChallengeOwner.getListener(); + if (listener == null) { + Slog.w(TAG, "Null listener, skip sending interruption callback"); + return; + } + try { - mCurrentChallengeOwner.getListener().onChallengeInterrupted(mSensorId); + listener.onChallengeInterrupted(mSensorId); } catch (RemoteException e) { Slog.e(TAG, "Unable to notify challenge interrupted", e); } @@ -504,7 +531,7 @@ class Face10 implements IHwBinder.DeathRecipient { @Override public void onClientStarted(@NonNull ClientMonitor<?> clientMonitor) { if (client != clientMonitor) { - Slog.e(TAG, "scheduleGenerateChallenge, mismatched client." + Slog.e(TAG, "scheduleGenerateChallenge onClientStarted, mismatched client." + " Expecting: " + client + ", received: " + clientMonitor); return; } diff --git a/services/core/java/com/android/server/biometrics/sensors/face/FaceGetFeatureClient.java b/services/core/java/com/android/server/biometrics/sensors/face/FaceGetFeatureClient.java index 8c7b99d6eb52..33b2b6ada24c 100644 --- a/services/core/java/com/android/server/biometrics/sensors/face/FaceGetFeatureClient.java +++ b/services/core/java/com/android/server/biometrics/sensors/face/FaceGetFeatureClient.java @@ -17,6 +17,7 @@ package com.android.server.biometrics.sensors.face; import android.annotation.NonNull; +import android.annotation.Nullable; import android.content.Context; import android.hardware.biometrics.BiometricsProtoEnums; import android.hardware.biometrics.face.V1_0.IBiometricsFace; @@ -39,9 +40,10 @@ public class FaceGetFeatureClient extends ClientMonitor<IBiometricsFace> { private final int mFeature; private final int mFaceId; + private boolean mValue; FaceGetFeatureClient(@NonNull Context context, @NonNull LazyDaemon<IBiometricsFace> lazyDaemon, - @NonNull IBinder token, @NonNull ClientMonitorCallbackConverter listener, int userId, + @NonNull IBinder token, @Nullable ClientMonitorCallbackConverter listener, int userId, @NonNull String owner, int sensorId, int feature, int faceId) { super(context, lazyDaemon, token, listener, userId, owner, 0 /* cookie */, sensorId, BiometricsProtoEnums.MODALITY_UNKNOWN, BiometricsProtoEnums.ACTION_UNKNOWN, @@ -54,7 +56,9 @@ public class FaceGetFeatureClient extends ClientMonitor<IBiometricsFace> { @Override public void unableToStart() { try { - getListener().onFeatureGet(false /* success */, mFeature, false /* value */); + if (getListener() != null) { + getListener().onFeatureGet(false /* success */, mFeature, false /* value */); + } } catch (RemoteException e) { Slog.e(TAG, "Unable to send error", e); } @@ -70,11 +74,18 @@ public class FaceGetFeatureClient extends ClientMonitor<IBiometricsFace> { protected void startHalOperation() { try { final OptionalBool result = getFreshDaemon().getFeature(mFeature, mFaceId); - getListener().onFeatureGet(result.status == Status.OK, mFeature, result.value); + mValue = result.value; + if (getListener() != null) { + getListener().onFeatureGet(result.status == Status.OK, mFeature, mValue); + } mCallback.onClientFinished(this, true /* success */); } catch (RemoteException e) { Slog.e(TAG, "Unable to getFeature", e); mCallback.onClientFinished(this, false /* success */); } } + + boolean getValue() { + return mValue; + } } diff --git a/services/core/java/com/android/server/biometrics/sensors/face/FaceService.java b/services/core/java/com/android/server/biometrics/sensors/face/FaceService.java index b689106bbc44..c6664f4d96ff 100644 --- a/services/core/java/com/android/server/biometrics/sensors/face/FaceService.java +++ b/services/core/java/com/android/server/biometrics/sensors/face/FaceService.java @@ -25,9 +25,9 @@ import android.hardware.biometrics.BiometricsProtoEnums; import android.hardware.biometrics.IBiometricSensorReceiver; import android.hardware.biometrics.IBiometricServiceLockoutResetCallback; import android.hardware.face.Face; +import android.hardware.face.FaceSensorProperties; import android.hardware.face.IFaceService; import android.hardware.face.IFaceServiceReceiver; -import android.hardware.face.FaceSensorProperties; import android.os.Binder; import android.os.IBinder; import android.os.NativeHandle; @@ -303,7 +303,8 @@ public class FaceService extends SystemService { public void getFeature(final IBinder token, int userId, int feature, IFaceServiceReceiver receiver, final String opPackageName) { Utils.checkPermission(getContext(), MANAGE_BIOMETRIC); - mFace10.scheduleGetFeature(token, userId, feature, receiver, opPackageName); + mFace10.scheduleGetFeature(token, userId, feature, + new ClientMonitorCallbackConverter(receiver), opPackageName); } @Override // Binder call diff --git a/services/core/java/com/android/server/clipboard/ClipboardService.java b/services/core/java/com/android/server/clipboard/ClipboardService.java index a0bc7d8954fb..5d2f51230c12 100644 --- a/services/core/java/com/android/server/clipboard/ClipboardService.java +++ b/services/core/java/com/android/server/clipboard/ClipboardService.java @@ -57,10 +57,12 @@ import android.text.TextUtils; import android.util.Slog; import android.util.SparseArray; import android.view.autofill.AutofillManagerInternal; +import android.widget.Toast; import com.android.server.LocalServices; import com.android.server.SystemService; import com.android.server.SystemService.TargetUser; +import com.android.server.UiThread; import com.android.server.contentcapture.ContentCaptureManagerInternal; import com.android.server.uri.UriGrantsManagerInternal; import com.android.server.wm.WindowManagerInternal; @@ -391,7 +393,9 @@ public class ClipboardService extends SystemService { return null; } addActiveOwnerLocked(intendingUid, pkg); - return getClipboard(intendingUserId).primaryClip; + PerUserClipboard clipboard = getClipboard(intendingUserId); + maybeNotify(pkg, intendingUid, intendingUserId, clipboard); + return clipboard.primaryClip; } } @@ -821,4 +825,65 @@ public class ClipboardService extends SystemService { return appOpsResult == AppOpsManager.MODE_ALLOWED; } + + /** + * Potentially notifies the user (via a toast) about an app accessing the clipboard. + * TODO(b/167676460): STOPSHIP as we don't want this code as-is to launch. Just an experiment. + */ + private void maybeNotify(String callingPackage, int uid, @UserIdInt int userId, + PerUserClipboard clipboard) { + if (clipboard.primaryClip == null) { + return; + } + if (Settings.Global.getInt(getContext().getContentResolver(), + "clipboard_access_toast_enabled", 0) == 0) { + return; + } + // Don't notify if the app accessing the clipboard is the same as the current owner. + if (UserHandle.isSameApp(uid, clipboard.primaryClipUid)) { + return; + } + // Exclude some special cases. It's a bit wasteful to check these again here, but for now + // beneficial to have all the logic contained in this single (probably temporary) method. + String defaultIme = Settings.Secure.getStringForUser(getContext().getContentResolver(), + Settings.Secure.DEFAULT_INPUT_METHOD, userId); + if (!TextUtils.isEmpty(defaultIme)) { + final String imePkg = ComponentName.unflattenFromString(defaultIme).getPackageName(); + if (imePkg.equals(callingPackage)) { + return; + } + } + if (mContentCaptureInternal != null + && mContentCaptureInternal.isContentCaptureServiceForUser(uid, userId)) { + return; + } + if (mAutofillInternal != null + && mAutofillInternal.isAugmentedAutofillServiceForUser(uid, userId)) { + return; + } + // Load the labels for the calling app and the app that set the clipboard content. + final long ident = Binder.clearCallingIdentity(); + try { + final IPackageManager pm = AppGlobals.getPackageManager(); + String message; + final CharSequence callingLabel = mPm.getApplicationLabel( + pm.getApplicationInfo(callingPackage, 0, userId)); + final String[] packagesForUid = pm.getPackagesForUid(clipboard.primaryClipUid); + if (packagesForUid != null && packagesForUid.length > 0) { + final CharSequence clipLabel = mPm.getApplicationLabel( + pm.getApplicationInfo(packagesForUid[0], 0, + UserHandle.getUserId(clipboard.primaryClipUid))); + message = callingLabel + " pasted from " + clipLabel; + } else { + message = callingLabel + " pasted from clipboard"; + } + Slog.i(TAG, message); + Toast.makeText(getContext(), UiThread.get().getLooper(), message, Toast.LENGTH_SHORT) + .show(); + } catch (RemoteException e) { + /* ignore */ + } finally { + Binder.restoreCallingIdentity(ident); + } + } } diff --git a/services/core/java/com/android/server/display/AutomaticBrightnessController.java b/services/core/java/com/android/server/display/AutomaticBrightnessController.java index 36d69c93c1cb..f42e18acc821 100644 --- a/services/core/java/com/android/server/display/AutomaticBrightnessController.java +++ b/services/core/java/com/android/server/display/AutomaticBrightnessController.java @@ -17,8 +17,8 @@ package com.android.server.display; import android.annotation.Nullable; -import android.app.ActivityManager.StackInfo; import android.app.ActivityTaskManager; +import android.app.ActivityTaskManager.RootTaskInfo; import android.app.IActivityTaskManager; import android.app.TaskStackListener; import android.content.Context; @@ -846,7 +846,7 @@ class AutomaticBrightnessController { public void run() { try { // The foreground app is the top activity of the focused tasks stack. - final StackInfo info = mActivityTaskManager.getFocusedStackInfo(); + final RootTaskInfo info = mActivityTaskManager.getFocusedRootTaskInfo(); if (info == null || info.topActivity == null) { return; } diff --git a/services/core/java/com/android/server/display/BrightnessTracker.java b/services/core/java/com/android/server/display/BrightnessTracker.java index eea1980012a4..9e82d4fe6233 100644 --- a/services/core/java/com/android/server/display/BrightnessTracker.java +++ b/services/core/java/com/android/server/display/BrightnessTracker.java @@ -20,6 +20,7 @@ import android.annotation.Nullable; import android.annotation.UserIdInt; import android.app.ActivityManager; import android.app.ActivityTaskManager; +import android.app.ActivityTaskManager.RootTaskInfo; import android.content.BroadcastReceiver; import android.content.ContentResolver; import android.content.Context; @@ -377,14 +378,14 @@ public class BrightnessTracker { } try { - final ActivityManager.StackInfo focusedStack = mInjector.getFocusedStack(); - if (focusedStack != null && focusedStack.topActivity != null) { - builder.setUserId(focusedStack.userId); - builder.setPackageName(focusedStack.topActivity.getPackageName()); + final RootTaskInfo focusedTask = mInjector.getFocusedStack(); + if (focusedTask != null && focusedTask.topActivity != null) { + builder.setUserId(focusedTask.userId); + builder.setPackageName(focusedTask.topActivity.getPackageName()); } else { // Ignore the event because we can't determine user / package. if (DEBUG) { - Slog.d(TAG, "Ignoring event due to null focusedStack."); + Slog.d(TAG, "Ignoring event due to null focusedTask."); } return; } @@ -1104,8 +1105,8 @@ public class BrightnessTracker { } } - public ActivityManager.StackInfo getFocusedStack() throws RemoteException { - return ActivityTaskManager.getService().getFocusedStackInfo(); + public RootTaskInfo getFocusedStack() throws RemoteException { + return ActivityTaskManager.getService().getFocusedRootTaskInfo(); } public void scheduleIdleJob(Context context) { diff --git a/services/core/java/com/android/server/display/ColorFade.java b/services/core/java/com/android/server/display/ColorFade.java index ad3cd67ad65b..73f788901dc9 100644 --- a/services/core/java/com/android/server/display/ColorFade.java +++ b/services/core/java/com/android/server/display/ColorFade.java @@ -493,6 +493,10 @@ final class ColorFade { == Display.COLOR_MODE_DISPLAY_P3; SurfaceControl.ScreenshotHardwareBuffer screenshotBuffer = mDisplayManagerInternal.systemScreenshot(mDisplayId); + if (screenshotBuffer == null) { + Slog.e(TAG, "Failed to take screenshot. Buffer is null"); + return false; + } s.attachAndQueueBufferWithColorSpace(screenshotBuffer.getHardwareBuffer(), screenshotBuffer.getColorSpace()); diff --git a/services/core/java/com/android/server/display/DisplayModeDirector.java b/services/core/java/com/android/server/display/DisplayModeDirector.java index 3c050804f01d..cc6687f8566d 100644 --- a/services/core/java/com/android/server/display/DisplayModeDirector.java +++ b/services/core/java/com/android/server/display/DisplayModeDirector.java @@ -869,10 +869,11 @@ public class DisplayModeDirector { } private void updateRefreshRateSettingLocked() { - float minRefreshRate = Settings.System.getFloat(mContext.getContentResolver(), - Settings.System.MIN_REFRESH_RATE, 0f); - float peakRefreshRate = Settings.System.getFloat(mContext.getContentResolver(), - Settings.System.PEAK_REFRESH_RATE, mDefaultPeakRefreshRate); + final ContentResolver cr = mContext.getContentResolver(); + float minRefreshRate = Settings.System.getFloatForUser(cr, + Settings.System.MIN_REFRESH_RATE, 0f, cr.getUserId()); + float peakRefreshRate = Settings.System.getFloatForUser(cr, + Settings.System.PEAK_REFRESH_RATE, mDefaultPeakRefreshRate, cr.getUserId()); updateRefreshRateSettingLocked(minRefreshRate, peakRefreshRate, mDefaultRefreshRate); } @@ -1301,8 +1302,9 @@ public class DisplayModeDirector { } // TODO: brightnessfloat: make it use float not int private void onBrightnessChangedLocked() { - int brightness = Settings.System.getInt(mContext.getContentResolver(), - Settings.System.SCREEN_BRIGHTNESS, -1); + final ContentResolver cr = mContext.getContentResolver(); + int brightness = Settings.System.getIntForUser(cr, + Settings.System.SCREEN_BRIGHTNESS, -1, cr.getUserId()); Vote vote = null; boolean insideZone = isInsideZone(brightness, mAmbientLux); diff --git a/services/core/java/com/android/server/hdmi/HdmiCecController.java b/services/core/java/com/android/server/hdmi/HdmiCecController.java index 7b52ddef29bc..7dc4d6e8efcf 100644 --- a/services/core/java/com/android/server/hdmi/HdmiCecController.java +++ b/services/core/java/com/android/server/hdmi/HdmiCecController.java @@ -893,7 +893,7 @@ final class HdmiCecController { @Override public void serviceDied(long cookie) { if (cookie == HDMI_CEC_HAL_DEATH_COOKIE) { - HdmiLogger.error(TAG, "Service died cokkie : " + cookie + "; reconnecting"); + HdmiLogger.error("Service died cookie : " + cookie + "; reconnecting"); connectToHal(); } } diff --git a/services/core/java/com/android/server/location/gnss/GnssLocationProvider.java b/services/core/java/com/android/server/location/gnss/GnssLocationProvider.java index 3e5b6e3f462f..a4486d7b5898 100644 --- a/services/core/java/com/android/server/location/gnss/GnssLocationProvider.java +++ b/services/core/java/com/android/server/location/gnss/GnssLocationProvider.java @@ -85,7 +85,9 @@ import java.io.FileDescriptor; import java.io.PrintWriter; import java.util.ArrayList; import java.util.Arrays; +import java.util.HashSet; import java.util.List; +import java.util.Set; /** * A GNSS implementation of LocationProvider used by LocationManager. @@ -181,7 +183,6 @@ public class GnssLocationProvider extends AbstractLocationProvider implements private static final int INJECT_NTP_TIME = 5; // PSDS stands for Predicted Satellite Data Service private static final int DOWNLOAD_PSDS_DATA = 6; - private static final int DOWNLOAD_PSDS_DATA_FINISHED = 11; private static final int INITIALIZE_HANDLER = 13; private static final int REQUEST_LOCATION = 16; private static final int REPORT_LOCATION = 17; // HAL reports location @@ -288,6 +289,7 @@ public class GnssLocationProvider extends AbstractLocationProvider implements private static final long DOWNLOAD_PSDS_DATA_TIMEOUT_MS = 60 * 1000; private static final long WAKELOCK_TIMEOUT_MILLIS = 30 * 1000; + @GuardedBy("mLock") private final ExponentialBackOff mPsdsBackOff = new ExponentialBackOff(RETRY_INTERVAL, MAX_RETRY_INTERVAL); @@ -297,14 +299,8 @@ public class GnssLocationProvider extends AbstractLocationProvider implements private boolean mShutdown; - // states for injecting ntp and downloading psds data - private static final int STATE_PENDING_NETWORK = 0; - private static final int STATE_DOWNLOADING = 1; - private static final int STATE_IDLE = 2; - - // flags to trigger NTP or PSDS data download when network becomes available - // initialized to true so we do NTP and PSDS when the network comes up after booting - private int mDownloadPsdsDataPending = STATE_PENDING_NETWORK; + @GuardedBy("mLock") + private Set<Integer> mPendingDownloadPsdsTypes = new HashSet<>(); // true if GPS is navigating private boolean mNavigating; @@ -610,6 +606,8 @@ public class GnssLocationProvider extends AbstractLocationProvider implements mNIHandler = new GpsNetInitiatedHandler(context, mNetInitiatedListener, mSuplEsEnabled); + // Trigger PSDS data download when the network comes up after booting. + mPendingDownloadPsdsTypes.add(GnssPsdsDownloader.LONG_TERM_PSDS_SERVER_INDEX); mNetworkConnectivityHandler = new GnssNetworkConnectivityHandler(context, GnssLocationProvider.this::onNetworkAvailable, mLooper, mNIHandler); @@ -670,10 +668,13 @@ public class GnssLocationProvider extends AbstractLocationProvider implements */ private void onNetworkAvailable() { mNtpTimeHelper.onNetworkAvailable(); - if (mDownloadPsdsDataPending == STATE_PENDING_NETWORK) { - if (mSupportsPsds) { - // Download only if supported, (prevents an unnecessary on-boot download) - psdsDownloadRequest(/* psdsType= */ GnssPsdsDownloader.LONG_TERM_PSDS_SERVER_INDEX); + // Download only if supported, (prevents an unnecessary on-boot download) + if (mSupportsPsds) { + synchronized (mLock) { + for (int psdsType : mPendingDownloadPsdsTypes) { + downloadPsdsData(psdsType); + } + mPendingDownloadPsdsTypes.clear(); } } } @@ -799,17 +800,13 @@ public class GnssLocationProvider extends AbstractLocationProvider implements Log.d(TAG, "handleDownloadPsdsData() called when PSDS not supported"); return; } - if (mDownloadPsdsDataPending == STATE_DOWNLOADING) { - // already downloading data - return; - } if (!mNetworkConnectivityHandler.isDataNetworkConnected()) { // try again when network is up - mDownloadPsdsDataPending = STATE_PENDING_NETWORK; + synchronized (mLock) { + mPendingDownloadPsdsTypes.add(psdsType); + } return; } - mDownloadPsdsDataPending = STATE_DOWNLOADING; - synchronized (mLock) { // hold wake lock while task runs mDownloadPsdsWakeLock.acquire(DOWNLOAD_PSDS_DATA_TIMEOUT_MS); @@ -820,20 +817,24 @@ public class GnssLocationProvider extends AbstractLocationProvider implements mGnssConfiguration.getProperties()); byte[] data = psdsDownloader.downloadPsdsData(psdsType); if (data != null) { - if (DEBUG) Log.d(TAG, "calling native_inject_psds_data"); - native_inject_psds_data(data, data.length, psdsType); - mPsdsBackOff.reset(); - } - - sendMessage(DOWNLOAD_PSDS_DATA_FINISHED, 0, null); - - if (data == null) { - // try again later - // since this is delayed and not urgent we do not hold a wake lock here - // the arg2 below should not be 1 otherwise the wakelock will be under-locked. + mHandler.post(() -> { + if (DEBUG) Log.d(TAG, "calling native_inject_psds_data"); + native_inject_psds_data(data, data.length, psdsType); + synchronized (mLock) { + mPsdsBackOff.reset(); + } + }); + } else { + // Try download PSDS data again later according to backoff time. + // Since this is delayed and not urgent, we do not hold a wake lock here. + // The arg2 below should not be 1 otherwise the wakelock will be under-locked. + long backoffMillis; + synchronized (mLock) { + backoffMillis = mPsdsBackOff.nextBackoffMillis(); + } mHandler.sendMessageDelayed( mHandler.obtainMessage(DOWNLOAD_PSDS_DATA, psdsType, 0, null), - mPsdsBackOff.nextBackoffMillis()); + backoffMillis); } // Release wake lock held by task, synchronize on mLock in case multiple @@ -1128,7 +1129,7 @@ public class GnssLocationProvider extends AbstractLocationProvider implements requestUtcTime(); } else if ("force_psds_injection".equals(command)) { if (mSupportsPsds) { - psdsDownloadRequest(/* psdsType= */ + downloadPsdsData(/* psdsType= */ GnssPsdsDownloader.LONG_TERM_PSDS_SERVER_INDEX); } } else { @@ -1581,8 +1582,8 @@ public class GnssLocationProvider extends AbstractLocationProvider implements reportLocation(locations); } - void psdsDownloadRequest(int psdsType) { - if (DEBUG) Log.d(TAG, "psdsDownloadRequest. psdsType: " + psdsType); + void downloadPsdsData(int psdsType) { + if (DEBUG) Log.d(TAG, "downloadPsdsData. psdsType: " + psdsType); sendMessage(DOWNLOAD_PSDS_DATA, psdsType, null); } @@ -1896,9 +1897,6 @@ public class GnssLocationProvider extends AbstractLocationProvider implements case DOWNLOAD_PSDS_DATA: handleDownloadPsdsData(msg.arg1); break; - case DOWNLOAD_PSDS_DATA_FINISHED: - mDownloadPsdsDataPending = STATE_IDLE; - break; case INITIALIZE_HANDLER: handleInitialize(); break; @@ -2007,8 +2005,6 @@ public class GnssLocationProvider extends AbstractLocationProvider implements return "REQUEST_LOCATION"; case DOWNLOAD_PSDS_DATA: return "DOWNLOAD_PSDS_DATA"; - case DOWNLOAD_PSDS_DATA_FINISHED: - return "DOWNLOAD_PSDS_DATA_FINISHED"; case INITIALIZE_HANDLER: return "INITIALIZE_HANDLER"; case REPORT_LOCATION: diff --git a/services/core/java/com/android/server/location/gnss/GnssManagerService.java b/services/core/java/com/android/server/location/gnss/GnssManagerService.java index 8e81f29550d6..2bf6af25422a 100644 --- a/services/core/java/com/android/server/location/gnss/GnssManagerService.java +++ b/services/core/java/com/android/server/location/gnss/GnssManagerService.java @@ -519,7 +519,7 @@ public class GnssManagerService implements GnssNative.Callbacks { @Override public void psdsDownloadRequest(int psdsType) { - mGnssLocationProvider.psdsDownloadRequest(psdsType); + mGnssLocationProvider.downloadPsdsData(psdsType); } @Override diff --git a/services/core/java/com/android/server/location/util/SystemSettingsHelper.java b/services/core/java/com/android/server/location/util/SystemSettingsHelper.java index ff4ba914cb9c..39aeaba16579 100644 --- a/services/core/java/com/android/server/location/util/SystemSettingsHelper.java +++ b/services/core/java/com/android/server/location/util/SystemSettingsHelper.java @@ -29,6 +29,7 @@ import static com.android.server.location.LocationManagerService.D; import static com.android.server.location.LocationManagerService.TAG; import android.app.ActivityManager; +import android.content.ContentResolver; import android.content.Context; import android.database.ContentObserver; import android.net.Uri; @@ -330,11 +331,13 @@ public class SystemSettingsHelper extends SettingsHelper { @Override public float getCoarseLocationAccuracyM() { long identity = Binder.clearCallingIdentity(); + final ContentResolver cr = mContext.getContentResolver(); try { - return Settings.Secure.getFloat( - mContext.getContentResolver(), + return Settings.Secure.getFloatForUser( + cr, LOCATION_COARSE_ACCURACY_M, - DEFAULT_COARSE_LOCATION_ACCURACY_M); + DEFAULT_COARSE_LOCATION_ACCURACY_M, + cr.getUserId()); } finally { Binder.restoreCallingIdentity(identity); } diff --git a/services/core/java/com/android/server/locksettings/LockSettingsService.java b/services/core/java/com/android/server/locksettings/LockSettingsService.java index 26c3132167d3..dbc725ea93e8 100644 --- a/services/core/java/com/android/server/locksettings/LockSettingsService.java +++ b/services/core/java/com/android/server/locksettings/LockSettingsService.java @@ -837,7 +837,7 @@ public class LockSettingsService extends ILockSettings.Stub { if (getString("migrated", null, 0) == null) { final ContentResolver cr = mContext.getContentResolver(); for (String validSetting : VALID_SETTINGS) { - String value = Settings.Secure.getString(cr, validSetting); + String value = Settings.Secure.getStringForUser(cr, validSetting, cr.getUserId()); if (value != null) { setString(validSetting, value, 0); } diff --git a/services/core/java/com/android/server/media/MediaSessionRecord.java b/services/core/java/com/android/server/media/MediaSessionRecord.java index 1e02f49c43e4..793cfcd77414 100644 --- a/services/core/java/com/android/server/media/MediaSessionRecord.java +++ b/services/core/java/com/android/server/media/MediaSessionRecord.java @@ -23,7 +23,6 @@ import android.content.Intent; import android.content.pm.ParceledListSlice; import android.media.AudioAttributes; import android.media.AudioManager; -import android.media.AudioManagerInternal; import android.media.AudioSystem; import android.media.MediaMetadata; import android.media.Rating; @@ -53,8 +52,6 @@ import android.os.SystemClock; import android.util.Log; import android.view.KeyEvent; -import com.android.server.LocalServices; - import java.io.PrintWriter; import java.util.ArrayList; import java.util.Arrays; @@ -144,7 +141,6 @@ public class MediaSessionRecord implements IBinder.DeathRecipient, MediaSessionR // Volume handling fields private AudioAttributes mAudioAttrs; private AudioManager mAudioManager; - private AudioManagerInternal mAudioManagerInternal; private int mVolumeType = PlaybackInfo.PLAYBACK_TYPE_LOCAL; private int mVolumeControlType = VolumeProvider.VOLUME_CONTROL_ABSOLUTE; private int mMaxVolume = 0; @@ -179,7 +175,6 @@ public class MediaSessionRecord implements IBinder.DeathRecipient, MediaSessionR mContext = mService.getContext(); mHandler = new MessageHandler(handlerLooper); mAudioManager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE); - mAudioManagerInternal = LocalServices.getService(AudioManagerInternal.class); mAudioAttrs = DEFAULT_ATTRIBUTES; mPolicies = policies; @@ -328,8 +323,9 @@ public class MediaSessionRecord implements IBinder.DeathRecipient, MediaSessionR @Override public void run() { try { - mAudioManagerInternal.setStreamVolumeForUid(stream, volumeValue, flags, - opPackageName, uid, pid); + mAudioManager.setStreamVolumeForUid(stream, volumeValue, flags, + opPackageName, uid, pid, + mContext.getApplicationInfo().targetSdkVersion); } catch (IllegalArgumentException | SecurityException e) { Log.e(TAG, "Cannot set volume: stream=" + stream + ", value=" + volumeValue + ", flags=" + flags, e); @@ -518,16 +514,19 @@ public class MediaSessionRecord implements IBinder.DeathRecipient, MediaSessionR try { if (useSuggested) { if (AudioSystem.isStreamActive(stream, 0)) { - mAudioManagerInternal.adjustSuggestedStreamVolumeForUid(stream, - direction, flags, opPackageName, uid, pid); + mAudioManager.adjustSuggestedStreamVolumeForUid(stream, + direction, flags, opPackageName, uid, pid, + mContext.getApplicationInfo().targetSdkVersion); } else { - mAudioManagerInternal.adjustSuggestedStreamVolumeForUid( + mAudioManager.adjustSuggestedStreamVolumeForUid( AudioManager.USE_DEFAULT_STREAM_TYPE, direction, - flags | previousFlagPlaySound, opPackageName, uid, pid); + flags | previousFlagPlaySound, opPackageName, uid, pid, + mContext.getApplicationInfo().targetSdkVersion); } } else { - mAudioManagerInternal.adjustStreamVolumeForUid(stream, direction, flags, - opPackageName, uid, pid); + mAudioManager.adjustStreamVolumeForUid(stream, direction, flags, + opPackageName, uid, pid, + mContext.getApplicationInfo().targetSdkVersion); } } catch (IllegalArgumentException | SecurityException e) { Log.e(TAG, "Cannot adjust volume: direction=" + direction + ", stream=" diff --git a/services/core/java/com/android/server/media/MediaSessionService.java b/services/core/java/com/android/server/media/MediaSessionService.java index 9521611c241d..d34502922b66 100644 --- a/services/core/java/com/android/server/media/MediaSessionService.java +++ b/services/core/java/com/android/server/media/MediaSessionService.java @@ -42,7 +42,6 @@ import android.content.pm.PackageManager; import android.content.pm.ParceledListSlice; import android.content.pm.UserInfo; import android.media.AudioManager; -import android.media.AudioManagerInternal; import android.media.AudioPlaybackConfiguration; import android.media.AudioSystem; import android.media.IRemoteVolumeController; @@ -85,7 +84,6 @@ import android.view.ViewConfiguration; import com.android.internal.R; import com.android.internal.annotations.GuardedBy; import com.android.internal.util.DumpUtils; -import com.android.server.LocalServices; import com.android.server.SystemService; import com.android.server.SystemService.TargetUser; import com.android.server.Watchdog; @@ -136,7 +134,7 @@ public class MediaSessionService extends SystemService implements Monitor { new ArrayList<>(); private KeyguardManager mKeyguardManager; - private AudioManagerInternal mAudioManagerInternal; + private AudioManager mAudioManager; private ContentResolver mContentResolver; private boolean mHasFeatureLeanback; @@ -162,6 +160,7 @@ public class MediaSessionService extends SystemService implements Monitor { PowerManager pm = mContext.getSystemService(PowerManager.class); mMediaEventWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "handleMediaEvent"); mNotificationManager = mContext.getSystemService(NotificationManager.class); + mAudioManager = mContext.getSystemService(AudioManager.class); } @Override @@ -169,7 +168,6 @@ public class MediaSessionService extends SystemService implements Monitor { publishBinderService(Context.MEDIA_SESSION_SERVICE, mSessionManagerImpl); Watchdog.getInstance().addMonitor(this); mKeyguardManager = (KeyguardManager) mContext.getSystemService(Context.KEYGUARD_SERVICE); - mAudioManagerInternal = LocalServices.getService(AudioManagerInternal.class); mAudioPlayerStateMonitor = AudioPlayerStateMonitor.getInstance(mContext); mAudioPlayerStateMonitor.registerListener( (config, isRemoved) -> { @@ -2057,8 +2055,9 @@ public class MediaSessionService extends SystemService implements Monitor { callingPid = pid; } try { - mAudioManagerInternal.adjustSuggestedStreamVolumeForUid(suggestedStream, - direction, flags, callingOpPackageName, callingUid, callingPid); + mAudioManager.adjustSuggestedStreamVolumeForUid(suggestedStream, + direction, flags, callingOpPackageName, callingUid, callingPid, + getContext().getApplicationInfo().targetSdkVersion); } catch (SecurityException | IllegalArgumentException e) { Log.e(TAG, "Cannot adjust volume: direction=" + direction + ", suggestedStream=" + suggestedStream + ", flags=" + flags diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java index 12419a9fcafa..52e90218fd24 100755 --- a/services/core/java/com/android/server/notification/NotificationManagerService.java +++ b/services/core/java/com/android/server/notification/NotificationManagerService.java @@ -1684,8 +1684,10 @@ public class NotificationManagerService extends SystemService { final IntArray userIds = mUserProfiles.getCurrentProfileIds(); for (int i = 0; i < userIds.size(); i++) { - mArchive.updateHistoryEnabled(userIds.get(i), Settings.Secure.getInt(resolver, - Settings.Secure.NOTIFICATION_HISTORY_ENABLED, 0) == 1); + mArchive.updateHistoryEnabled(userIds.get(i), + Settings.Secure.getIntForUser(resolver, + Settings.Secure.NOTIFICATION_HISTORY_ENABLED, 0, + userIds.get(i)) == 1); } } if (uri == null || NOTIFICATION_SHOW_MEDIA_ON_QUICK_SETTINGS_URI.equals(uri)) { @@ -6259,6 +6261,8 @@ public class NotificationManagerService extends SystemService { for (NotificationRecord r : enqueued) { if (r.mUpdateTimeMs > mWhen) { // At least one enqueue was posted after the cancel, so we're invalid + Slog.i(TAG, "notification cancel ignored due to newer enqueued entry" + + "key=" + r.getSbn().getKey()); return; } } @@ -7146,9 +7150,10 @@ public class NotificationManagerService extends SystemService { } protected void playInCallNotification() { + final ContentResolver cr = getContext().getContentResolver(); if (mAudioManager.getRingerModeInternal() == AudioManager.RINGER_MODE_NORMAL - && Settings.Secure.getInt(getContext().getContentResolver(), - Settings.Secure.IN_CALL_NOTIFICATION_ENABLED, 1) != 0) { + && Settings.Secure.getIntForUser(cr, + Settings.Secure.IN_CALL_NOTIFICATION_ENABLED, 1, cr.getUserId()) != 0) { new Thread() { @Override public void run() { @@ -8460,7 +8465,10 @@ public class NotificationManagerService extends SystemService { if (Notification.CATEGORY_CAR_EMERGENCY.equals(notification.category) || Notification.CATEGORY_CAR_WARNING.equals(notification.category) || Notification.CATEGORY_CAR_INFORMATION.equals(notification.category)) { - checkCallerIsSystem(); + getContext().enforceCallingPermission( + android.Manifest.permission.SEND_CATEGORY_CAR_NOTIFICATIONS, + String.format("Notification category %s restricted", + notification.category)); } } diff --git a/services/core/java/com/android/server/om/OverlayActorEnforcer.java b/services/core/java/com/android/server/om/OverlayActorEnforcer.java index 8c03c6ce3092..8121a43e9060 100644 --- a/services/core/java/com/android/server/om/OverlayActorEnforcer.java +++ b/services/core/java/com/android/server/om/OverlayActorEnforcer.java @@ -26,6 +26,7 @@ import android.os.Process; import android.text.TextUtils; import android.util.Pair; +import com.android.internal.annotations.VisibleForTesting; import com.android.internal.util.ArrayUtils; import com.android.internal.util.CollectionUtils; @@ -66,7 +67,7 @@ public class OverlayActorEnforcer { String actorNamespace = actorUri.getAuthority(); Map<String, String> namespace = namedActors.get(actorNamespace); - if (namespace == null) { + if (ArrayUtils.isEmpty(namespace)) { return Pair.create(null, ActorState.MISSING_NAMESPACE); } @@ -102,21 +103,32 @@ public class OverlayActorEnforcer { * See {@link OverlayActorEnforcer} class comment for actor requirements. * @return true if the actor is allowed to act on the target overlayInfo */ - private ActorState isAllowedActor(String methodName, OverlayInfo overlayInfo, + @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE) + public ActorState isAllowedActor(String methodName, OverlayInfo overlayInfo, int callingUid, int userId) { + // Checked first to avoid package not found errors, which are ignored for calls from shell switch (callingUid) { case Process.ROOT_UID: case Process.SYSTEM_UID: return ActorState.ALLOWED; } + final String targetPackageName = overlayInfo.targetPackageName; + final PackageInfo targetPkgInfo = mPackageManager.getPackageInfo(targetPackageName, userId); + if (targetPkgInfo == null) { + return ActorState.TARGET_NOT_FOUND; + } + + if ((targetPkgInfo.applicationInfo.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0) { + return ActorState.ALLOWED; + } + String[] callingPackageNames = mPackageManager.getPackagesForUid(callingUid); if (ArrayUtils.isEmpty(callingPackageNames)) { return ActorState.NO_PACKAGES_FOR_UID; } // A target is always an allowed actor for itself - String targetPackageName = overlayInfo.targetPackageName; if (ArrayUtils.contains(callingPackageNames, targetPackageName)) { return ActorState.ALLOWED; } @@ -149,7 +161,7 @@ public class OverlayActorEnforcer { targetOverlayable = mPackageManager.getOverlayableForTarget(targetPackageName, targetOverlayableName, userId); } catch (IOException e) { - return ActorState.UNABLE_TO_GET_TARGET; + return ActorState.UNABLE_TO_GET_TARGET_OVERLAYABLE; } if (targetOverlayable == null) { @@ -189,7 +201,7 @@ public class OverlayActorEnforcer { } // Currently only pre-installed apps can be actors - if (!appInfo.isSystemApp() && !appInfo.isUpdatedSystemApp()) { + if (!appInfo.isSystemApp()) { return ActorState.ACTOR_NOT_PREINSTALLED; } @@ -203,22 +215,25 @@ public class OverlayActorEnforcer { /** * For easier logging/debugging, a set of all possible failure/success states when running * enforcement. + * + * The ordering of this enum should be maintained in the order that cases are checked in code, + * as this ordering is used inside OverlayActorEnforcerTests. */ public enum ActorState { - ALLOWED, - INVALID_ACTOR, - MISSING_NAMESPACE, - MISSING_PACKAGE, - MISSING_APP_INFO, - ACTOR_NOT_PREINSTALLED, + TARGET_NOT_FOUND, NO_PACKAGES_FOR_UID, - MISSING_ACTOR_NAME, - ERROR_READING_OVERLAYABLE, MISSING_TARGET_OVERLAYABLE_NAME, + MISSING_LEGACY_PERMISSION, + ERROR_READING_OVERLAYABLE, + UNABLE_TO_GET_TARGET_OVERLAYABLE, MISSING_OVERLAYABLE, INVALID_OVERLAYABLE_ACTOR_NAME, NO_NAMED_ACTORS, - UNABLE_TO_GET_TARGET, - MISSING_LEGACY_PERMISSION + MISSING_NAMESPACE, + MISSING_ACTOR_NAME, + MISSING_APP_INFO, + ACTOR_NOT_PREINSTALLED, + INVALID_ACTOR, + ALLOWED } } diff --git a/services/core/java/com/android/server/pm/ApexManager.java b/services/core/java/com/android/server/pm/ApexManager.java index 07527c2a15d8..5b5ec4221093 100644 --- a/services/core/java/com/android/server/pm/ApexManager.java +++ b/services/core/java/com/android/server/pm/ApexManager.java @@ -778,7 +778,7 @@ public abstract class ApexManager { void registerApkInApex(AndroidPackage pkg) { synchronized (mLock) { for (ActiveApexInfo aai : mActiveApexInfosCache) { - if (pkg.getBaseCodePath().startsWith(aai.apexDirectory.getAbsolutePath())) { + if (pkg.getBaseApkPath().startsWith(aai.apexDirectory.getAbsolutePath())) { List<String> apks = mApksInApex.get(aai.apexModuleName); if (apks == null) { apks = Lists.newArrayList(); diff --git a/services/core/java/com/android/server/pm/ComponentResolver.java b/services/core/java/com/android/server/pm/ComponentResolver.java index d25ddad174f9..4be509b3f464 100644 --- a/services/core/java/com/android/server/pm/ComponentResolver.java +++ b/services/core/java/com/android/server/pm/ComponentResolver.java @@ -623,7 +623,6 @@ public class ComponentResolver { AndroidPackage pkg = sPackageManagerInternal.getPackage(p.getPackageName()); if (pkg != null) { - // TODO(b/135203078): Print AppInfo? pw.print(" applicationInfo="); pw.println(pkg.toAppInfoWithoutState()); } } diff --git a/services/core/java/com/android/server/pm/OtaDexoptService.java b/services/core/java/com/android/server/pm/OtaDexoptService.java index eddab76de5ee..7db2319b5164 100644 --- a/services/core/java/com/android/server/pm/OtaDexoptService.java +++ b/services/core/java/com/android/server/pm/OtaDexoptService.java @@ -384,17 +384,17 @@ public class OtaDexoptService extends IOtaDexopt.Stub { if (!PackageDexOptimizer.canOptimizePackage(pkg)) { continue; } - if (pkg.getCodePath() == null) { + if (pkg.getPath() == null) { Slog.w(TAG, "Package " + pkg + " can be optimized but has null codePath"); continue; } // If the path is in /system, /vendor, /product or /system_ext, ignore. It will // have been ota-dexopted into /data/ota and moved into the dalvik-cache already. - if (pkg.getCodePath().startsWith("/system") - || pkg.getCodePath().startsWith("/vendor") - || pkg.getCodePath().startsWith("/product") - || pkg.getCodePath().startsWith("/system_ext")) { + if (pkg.getPath().startsWith("/system") + || pkg.getPath().startsWith("/vendor") + || pkg.getPath().startsWith("/product") + || pkg.getPath().startsWith("/system_ext")) { continue; } @@ -408,7 +408,7 @@ public class OtaDexoptService extends IOtaDexopt.Stub { for (String dexCodeInstructionSet : dexCodeInstructionSets) { for (String path : paths) { String oatDir = PackageDexOptimizer.getOatDir( - new File(pkg.getCodePath())).getAbsolutePath(); + new File(pkg.getPath())).getAbsolutePath(); // TODO: Check first whether there is an artifact, to save the roundtrip time. diff --git a/services/core/java/com/android/server/pm/PackageAbiHelperImpl.java b/services/core/java/com/android/server/pm/PackageAbiHelperImpl.java index 8af7e1f4f6d1..da4ea16d0bfd 100644 --- a/services/core/java/com/android/server/pm/PackageAbiHelperImpl.java +++ b/services/core/java/com/android/server/pm/PackageAbiHelperImpl.java @@ -136,7 +136,7 @@ final class PackageAbiHelperImpl implements PackageAbiHelper { // Trying to derive the paths, thus need the raw ABI info from the parsed package, and the // current state in PackageSetting is irrelevant. return deriveNativeLibraryPaths(new Abis(pkg.getPrimaryCpuAbi(), pkg.getSecondaryCpuAbi()), - appLib32InstallDir, pkg.getCodePath(), pkg.getBaseCodePath(), pkg.isSystem(), + appLib32InstallDir, pkg.getPath(), pkg.getBaseApkPath(), pkg.isSystem(), isUpdatedSystemApp); } @@ -205,11 +205,11 @@ final class PackageAbiHelperImpl implements PackageAbiHelper { @Override public Abis getBundledAppAbis(AndroidPackage pkg) { - final String apkName = deriveCodePathName(pkg.getCodePath()); + final String apkName = deriveCodePathName(pkg.getPath()); // If "/system/lib64/apkname" exists, assume that is the per-package // native library directory to use; otherwise use "/system/lib/apkname". - final String apkRoot = calculateBundledApkRoot(pkg.getBaseCodePath()); + final String apkRoot = calculateBundledApkRoot(pkg.getBaseApkPath()); final Abis abis = getBundledAppAbi(pkg, apkRoot, apkName); return abis; } @@ -223,7 +223,7 @@ final class PackageAbiHelperImpl implements PackageAbiHelper { * @param apkName the name of the installed package. */ private Abis getBundledAppAbi(AndroidPackage pkg, String apkRoot, String apkName) { - final File codeFile = new File(pkg.getCodePath()); + final File codeFile = new File(pkg.getPath()); final boolean has64BitLibs; final boolean has32BitLibs; @@ -304,15 +304,15 @@ final class PackageAbiHelperImpl implements PackageAbiHelper { String pkgRawSecondaryCpuAbi = AndroidPackageUtils.getRawSecondaryCpuAbi(pkg); final NativeLibraryPaths initialLibraryPaths = deriveNativeLibraryPaths( new Abis(pkgRawPrimaryCpuAbi, pkgRawSecondaryCpuAbi), - PackageManagerService.sAppLib32InstallDir, pkg.getCodePath(), - pkg.getBaseCodePath(), pkg.isSystem(), + PackageManagerService.sAppLib32InstallDir, pkg.getPath(), + pkg.getBaseApkPath(), pkg.isSystem(), isUpdatedSystemApp); final boolean extractLibs = shouldExtractLibs(pkg, isUpdatedSystemApp); final String nativeLibraryRootStr = initialLibraryPaths.nativeLibraryRootDir; final boolean useIsaSpecificSubdirs = initialLibraryPaths.nativeLibraryRootRequiresIsa; - final boolean onIncremental = isIncrementalPath(pkg.getCodePath()); + final boolean onIncremental = isIncrementalPath(pkg.getPath()); String primaryCpuAbi = null; String secondaryCpuAbi = null; @@ -453,7 +453,7 @@ final class PackageAbiHelperImpl implements PackageAbiHelper { final Abis abis = new Abis(primaryCpuAbi, secondaryCpuAbi); return new Pair<>(abis, deriveNativeLibraryPaths(abis, PackageManagerService.sAppLib32InstallDir, - pkg.getCodePath(), pkg.getBaseCodePath(), pkg.isSystem(), + pkg.getPath(), pkg.getBaseApkPath(), pkg.isSystem(), isUpdatedSystemApp)); } diff --git a/services/core/java/com/android/server/pm/PackageDexOptimizer.java b/services/core/java/com/android/server/pm/PackageDexOptimizer.java index 0d8ba3e54801..42e6d8f0bf83 100644 --- a/services/core/java/com/android/server/pm/PackageDexOptimizer.java +++ b/services/core/java/com/android/server/pm/PackageDexOptimizer.java @@ -199,7 +199,7 @@ public class PackageDexOptimizer { throw new IllegalStateException("Inconsistent information " + "between PackageParser.Package and its ApplicationInfo. " + "pkg.getAllCodePaths=" + paths - + " pkg.getBaseCodePath=" + pkg.getBaseCodePath() + + " pkg.getBaseCodePath=" + pkg.getBaseApkPath() + " pkg.getSplitCodePaths=" + (splitCodePaths == null ? "null" : Arrays.toString(splitCodePaths))); } @@ -772,7 +772,7 @@ public class PackageDexOptimizer { if (!AndroidPackageUtils.canHaveOatDir(pkg, isUpdatedSystemApp)) { return null; } - File codePath = new File(pkg.getCodePath()); + File codePath = new File(pkg.getPath()); if (!codePath.isDirectory()) { return null; } diff --git a/services/core/java/com/android/server/pm/PackageInstallerService.java b/services/core/java/com/android/server/pm/PackageInstallerService.java index 162bfee8848d..155af82289d4 100644 --- a/services/core/java/com/android/server/pm/PackageInstallerService.java +++ b/services/core/java/com/android/server/pm/PackageInstallerService.java @@ -656,7 +656,7 @@ public class PackageInstallerService extends IPackageInstaller.Stub implements throw new IllegalArgumentException("Invalid install mode: " + params.mode); } - // If caller requested explicit location, sanity check it, otherwise + // If caller requested explicit location, validity check it, otherwise // resolve the best internal or adopted location. if ((params.installFlags & PackageManager.INSTALL_INTERNAL) != 0) { if (!PackageHelper.fitsOnInternal(mContext, params)) { @@ -688,7 +688,7 @@ public class PackageInstallerService extends IPackageInstaller.Stub implements final int sessionId; final PackageInstallerSession session; synchronized (mSessions) { - // Sanity check that installer isn't going crazy + // Check that the installer does not have too many active sessions. final int activeCount = getSessionCount(mSessions, callingUid); if (mContext.checkCallingOrSelfPermission(Manifest.permission.INSTALL_PACKAGES) == PackageManager.PERMISSION_GRANTED) { diff --git a/services/core/java/com/android/server/pm/PackageInstallerSession.java b/services/core/java/com/android/server/pm/PackageInstallerSession.java index 51164ba412b3..17cd8f58c3a3 100644 --- a/services/core/java/com/android/server/pm/PackageInstallerSession.java +++ b/services/core/java/com/android/server/pm/PackageInstallerSession.java @@ -249,6 +249,9 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { private final PackageManagerService mPm; private final Handler mHandler; private final PackageSessionProvider mSessionProvider; + /** + * Note all calls must be done outside {@link #mLock} to prevent lock inversion. + */ private final StagingManager mStagingManager; final int sessionId; @@ -389,6 +392,20 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { private String mStagedSessionErrorMessage; /** + * The callback to run when pre-reboot verification has ended. Used by {@link #abandonStaged()} + * to delay session clean-up until it is safe to do so. + */ + @GuardedBy("mLock") + @Nullable + private Runnable mPendingAbandonCallback; + /** + * {@code true} if pre-reboot verification is ongoing which means it is not safe for + * {@link #abandon()} to clean up staging directories. + */ + @GuardedBy("mLock") + private boolean mInPreRebootVerification; + + /** * Path to the validated base APK for this session, which may point at an * APK inside the session (when the session defines the base), or it may * point at the existing base APK (when adding splits to an existing app). @@ -978,7 +995,7 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { private ParcelFileDescriptor doWriteInternal(String name, long offsetBytes, long lengthBytes, ParcelFileDescriptor incomingFd) throws IOException { - // Quick sanity check of state, and allocate a pipe for ourselves. We + // Quick validity check of state, and allocate a pipe for ourselves. We // then do heavy disk allocation outside the lock, but this open pipe // will block any attempted install transitions. final RevocableFileDescriptor fd; @@ -1454,26 +1471,54 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { // TODO(patb): since the work done here for a parent session in a multi-package install is // mostly superficial, consider splitting this method for the parent and // single / child sessions. - synchronized (mLock) { - if (mCommitted) { - return true; + try { + synchronized (mLock) { + if (mCommitted) { + return true; + } + // Read transfers from the original owner stay open, but as the session's data + // cannot be modified anymore, there is no leak of information. For staged sessions, + // further validation is performed by the staging manager. + if (!params.isMultiPackage) { + if (!prepareDataLoaderLocked()) { + return false; + } + + if (isApexInstallation()) { + validateApexInstallLocked(); + } else { + validateApkInstallLocked(); + } + } } - if (!streamAndValidateLocked()) { - return false; + if (params.isStaged) { + mStagingManager.checkNonOverlappingWithStagedSessions(this); } - // Client staging is fully done at this point - mClientProgress = 1f; - computeProgressLocked(true); + synchronized (mLock) { + if (mDestroyed) { + throw new PackageManagerException(INSTALL_FAILED_INTERNAL_ERROR, + "Session destroyed"); + } + // Client staging is fully done at this point + mClientProgress = 1f; + computeProgressLocked(true); - // This ongoing commit should keep session active, even though client - // will probably close their end. - mActiveCount.incrementAndGet(); + // This ongoing commit should keep session active, even though client + // will probably close their end. + mActiveCount.incrementAndGet(); - mCommitted = true; + mCommitted = true; + } + return true; + } catch (PackageManagerException e) { + throw onSessionValidationFailure(e); + } catch (Throwable e) { + // Convert all exceptions into package manager exceptions as only those are handled + // in the code above. + throw onSessionValidationFailure(new PackageManagerException(e)); } - return true; } @GuardedBy("mLock") @@ -1511,44 +1556,6 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { } } - /** - * Prepare DataLoader and stream content for DataLoader sessions. - * Validate the contents of all session. - * - * @return false if the data loader could not be prepared. - * @throws PackageManagerException when an unrecoverable exception is encountered - */ - @GuardedBy("mLock") - private boolean streamAndValidateLocked() throws PackageManagerException { - try { - // Read transfers from the original owner stay open, but as the session's data cannot - // be modified anymore, there is no leak of information. For staged sessions, further - // validation is performed by the staging manager. - if (!params.isMultiPackage) { - if (!prepareDataLoaderLocked()) { - return false; - } - - if (isApexInstallation()) { - validateApexInstallLocked(); - } else { - validateApkInstallLocked(); - } - } - - if (params.isStaged) { - mStagingManager.checkNonOverlappingWithStagedSessions(this); - } - return true; - } catch (PackageManagerException e) { - throw onSessionValidationFailure(e); - } catch (Throwable e) { - // Convert all exceptions into package manager exceptions as only those are handled - // in the code above. - throw onSessionValidationFailure(new PackageManagerException(e)); - } - } - private PackageManagerException onSessionValidationFailure(PackageManagerException e) { onSessionValidationFailure(e.error, ExceptionUtils.getCompleteMessage(e)); return e; @@ -1571,7 +1578,7 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { SessionInfo.STAGED_SESSION_VERIFICATION_FAILED, msgWithErrorCode); // TODO(b/136257624): Remove this once all verification logic has been transferred out // of StagingManager. - mStagingManager.notifyVerificationComplete(sessionId); + mStagingManager.notifyVerificationComplete(this); } else { // Dispatch message to remove session from PackageInstallerService. dispatchSessionFinished(error, msg, null); @@ -1837,21 +1844,6 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { throws PackageManagerException { assertNotLocked("makeSessionActive"); - synchronized (mLock) { - if (mRelinquished) { - throw new PackageManagerException(INSTALL_FAILED_INTERNAL_ERROR, - "Session relinquished"); - } - if (mDestroyed) { - throw new PackageManagerException(INSTALL_FAILED_INTERNAL_ERROR, - "Session destroyed"); - } - if (!mSealed) { - throw new PackageManagerException(INSTALL_FAILED_INTERNAL_ERROR, - "Session not sealed"); - } - } - // TODO(b/159331446): Move this to makeSessionActiveForInstall and update javadoc if (!params.isMultiPackage && needToAskForPermissions()) { // User needs to confirm installation; @@ -1881,6 +1873,19 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { @GuardedBy("mLock") private PackageManagerService.VerificationParams makeVerificationParamsLocked() throws PackageManagerException { + if (mRelinquished) { + throw new PackageManagerException(INSTALL_FAILED_INTERNAL_ERROR, + "Session relinquished"); + } + if (mDestroyed) { + throw new PackageManagerException(INSTALL_FAILED_INTERNAL_ERROR, + "Session destroyed"); + } + if (!mSealed) { + throw new PackageManagerException(INSTALL_FAILED_INTERNAL_ERROR, + "Session not sealed"); + } + // TODO(b/136257624): Some logic in this if block probably belongs in // makeInstallParams(). if (!params.isMultiPackage && !isApexInstallation()) { @@ -2078,7 +2083,7 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { if (ps == null) { return 0; } - final File apkDirOrPath = ps.getCodePath(); + final File apkDirOrPath = ps.getPath(); if (apkDirOrPath == null) { return 0; } @@ -2787,14 +2792,9 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { } private void abandonStaged() { + final Runnable r; synchronized (mLock) { - if (mDestroyed) { - // If a user abandons staged session in an unsafe state, then system will try to - // abandon the destroyed staged session when it is safe on behalf of the user. - assertCallerIsOwnerOrRootOrSystemLocked(); - } else { - assertCallerIsOwnerOrRootLocked(); - } + assertCallerIsOwnerOrRootLocked(); if (isStagedAndInTerminalState()) { // We keep the session in the database if it's in a finalized state. It will be // removed by PackageInstallerService when the last update time is old enough. @@ -2803,17 +2803,25 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { return; } mDestroyed = true; - if (mCommitted) { - if (!mStagingManager.abortCommittedSessionLocked(this)) { - // Do not clean up the staged session from system. It is not safe yet. - mCallback.onStagedSessionChanged(this); - return; + boolean isCommitted = mCommitted; + List<PackageInstallerSession> childSessions = getChildSessionsLocked(); + r = () -> { + assertNotLocked("abandonStaged"); + if (isCommitted) { + mStagingManager.abortCommittedSession(this); } + cleanStageDir(childSessions); + destroyInternal(); + dispatchSessionFinished(INSTALL_FAILED_ABORTED, "Session was abandoned", null); + }; + if (mInPreRebootVerification) { + // Pre-reboot verification is ongoing. It is not safe to clean up the session yet. + mPendingAbandonCallback = r; + mCallback.onStagedSessionChanged(this); + return; } - cleanStageDir(getChildSessionsLocked()); - destroyInternal(); } - dispatchSessionFinished(INSTALL_FAILED_ABORTED, "Session was abandoned", null); + r.run(); } @Override @@ -2830,6 +2838,50 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { } } + /** + * Notified by the staging manager that pre-reboot verification is about to start. The return + * value should be checked to decide whether it is OK to start pre-reboot verification. In + * the case of a destroyed session, {@code false} is returned and there is no need to start + * pre-reboot verification. + */ + boolean notifyStagedStartPreRebootVerification() { + synchronized (mLock) { + if (mInPreRebootVerification) { + throw new IllegalStateException("Pre-reboot verification has started"); + } + if (mDestroyed) { + return false; + } + mInPreRebootVerification = true; + return true; + } + } + + private void dispatchPendingAbandonCallback() { + final Runnable callback; + synchronized (mLock) { + callback = mPendingAbandonCallback; + mPendingAbandonCallback = null; + } + if (callback != null) { + callback.run(); + } + } + + /** + * Notified by the staging manager that pre-reboot verification has ended. Now it is safe to + * clean up the session if {@link #abandon()} has been called previously. + */ + void notifyStagedEndPreRebootVerification() { + synchronized (mLock) { + if (!mInPreRebootVerification) { + throw new IllegalStateException("Pre-reboot verification not started"); + } + mInPreRebootVerification = false; + } + dispatchPendingAbandonCallback(); + } + @Override public boolean isMultiPackage() { return params.isMultiPackage; @@ -3744,7 +3796,7 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { out.endTag(null, TAG_SESSION); } - // Sanity check to be performed when the session is restored from an external file. Only one + // Validity check to be performed when the session is restored from an external file. Only one // of the session states should be true, or none of them. private static boolean isStagedSessionStateValid(boolean isReady, boolean isApplied, boolean isFailed) { diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java index c6269eba8120..ed2c058b5c8a 100644 --- a/services/core/java/com/android/server/pm/PackageManagerService.java +++ b/services/core/java/com/android/server/pm/PackageManagerService.java @@ -2220,7 +2220,7 @@ public class PackageManagerService extends IPackageManager.Stub // Send installed broadcasts if the package is not a static shared lib. if (res.pkg.getStaticSharedLibName() == null) { mProcessLoggingHandler.invalidateProcessLoggingBaseApkHash( - res.pkg.getBaseCodePath()); + res.pkg.getBaseApkPath()); // Send added for users that see the package for the first time // sendPackageAddedForNewUsers also deals with system apps @@ -3101,7 +3101,7 @@ public class PackageManagerService extends IPackageManager.Stub final int packageSettingCount = mSettings.mPackages.size(); for (int i = packageSettingCount - 1; i >= 0; i--) { PackageSetting ps = mSettings.mPackages.valueAt(i); - if (!isExternal(ps) && (ps.getCodePath() == null || !ps.getCodePath().exists()) + if (!isExternal(ps) && (ps.getPath() == null || !ps.getPath().exists()) && mSettings.getDisabledSystemPkgLPr(ps.name) != null) { mSettings.mPackages.removeAt(i); mSettings.enableSystemPackageLPw(ps.name); @@ -3266,11 +3266,11 @@ public class PackageManagerService extends IPackageManager.Stub logCriticalInfo(Log.WARN, "Expecting better updated system app for " + ps.name + "; removing system app. Last known" - + " codePath=" + ps.getCodePathString() + + " codePath=" + ps.getPathString() + ", versionCode=" + ps.versionCode + "; scanned versionCode=" + scannedPkg.getLongVersionCode()); removePackageLI(scannedPkg, true); - mExpectingBetter.put(ps.name, ps.getCodePath()); + mExpectingBetter.put(ps.name, ps.getPath()); } continue; @@ -3293,14 +3293,14 @@ public class PackageManagerService extends IPackageManager.Stub // code path, but, changes the package name. final PackageSetting disabledPs = mSettings.getDisabledSystemPkgLPr(ps.name); - if (disabledPs.getCodePath() == null || !disabledPs.getCodePath().exists() + if (disabledPs.getPath() == null || !disabledPs.getPath().exists() || disabledPs.pkg == null) { possiblyDeletedUpdatedSystemApps.add(ps.name); } else { // We're expecting that the system app should remain disabled, but add // it to expecting better to recover in case the data version cannot // be scanned. - mExpectingBetter.put(disabledPs.name, disabledPs.getCodePath()); + mExpectingBetter.put(disabledPs.name, disabledPs.getPath()); } } } @@ -3344,6 +3344,7 @@ public class PackageManagerService extends IPackageManager.Stub // Remove disable package settings for updated system apps that were // removed via an OTA. If the update is no longer present, remove the // app completely. Otherwise, revoke their system privileges. + final int[] userIds = mUserManager.getUserIds(); for (int i = possiblyDeletedUpdatedSystemApps.size() - 1; i >= 0; --i) { final String packageName = possiblyDeletedUpdatedSystemApps.get(i); final AndroidPackage pkg = mPackages.get(packageName); @@ -3372,7 +3373,7 @@ public class PackageManagerService extends IPackageManager.Stub // special privileges removePackageLI(pkg, true); try { - final File codePath = new File(pkg.getCodePath()); + final File codePath = new File(pkg.getPath()); scanPackageTracedLI(codePath, 0, scanFlags, 0, null); } catch (PackageManagerException e) { Slog.e(TAG, "Failed to parse updated, ex-system package: " @@ -3386,7 +3387,7 @@ public class PackageManagerService extends IPackageManager.Stub // partition], completely remove the package data. final PackageSetting ps = mSettings.mPackages.get(packageName); if (ps != null && mPackages.get(packageName) == null) { - removePackageDataLIF(ps, null, null, 0, false); + removePackageDataLIF(ps, userIds, null, 0, false); } logCriticalInfo(Log.WARN, msg); @@ -3853,8 +3854,9 @@ public class PackageManagerService extends IPackageManager.Stub // If we don't, installing the system package fails during scan enableSystemPackageLPw(stubPkg); } - installPackageFromSystemLIF(stubPkg.getCodePath(), null /*allUserHandles*/, - null /*origUserHandles*/, true /*writeSettings*/); + installPackageFromSystemLIF(stubPkg.getPath(), + mUserManager.getUserIds() /*allUserHandles*/, null /*origUserHandles*/, + true /*writeSettings*/); } catch (PackageManagerException pme) { // Serious WTF; we have to be able to install the stub Slog.wtf(TAG, "Failed to restore system package:" + stubPkg.getPackageName(), @@ -3876,7 +3878,7 @@ public class PackageManagerService extends IPackageManager.Stub clearAppDataLIF(pkg, UserHandle.USER_ALL, FLAG_STORAGE_DE | FLAG_STORAGE_CE | FLAG_STORAGE_EXTERNAL | Installer.FLAG_CLEAR_CODE_CACHE_ONLY); mDexManager.notifyPackageUpdated(pkg.getPackageName(), - pkg.getBaseCodePath(), pkg.getSplitCodePaths()); + pkg.getBaseApkPath(), pkg.getSplitCodePaths()); } return true; } @@ -3888,10 +3890,10 @@ public class PackageManagerService extends IPackageManager.Stub Slog.i(TAG, "Uncompressing system stub; pkg: " + stubPkg.getPackageName()); } // uncompress the binary to its eventual destination on /data - final File scanFile = decompressPackage(stubPkg.getPackageName(), stubPkg.getCodePath()); + final File scanFile = decompressPackage(stubPkg.getPackageName(), stubPkg.getPath()); if (scanFile == null) { throw new PackageManagerException( - "Unable to decompress stub at " + stubPkg.getCodePath()); + "Unable to decompress stub at " + stubPkg.getPath()); } synchronized (mLock) { mSettings.disableSystemPackageLPw(stubPkg.getPackageName(), true /*replaced*/); @@ -9259,11 +9261,11 @@ public class PackageManagerService extends IPackageManager.Stub // When upgrading from pre-N MR1, verify the package time stamp using the package // directory and not the APK file. final long lastModifiedTime = mIsPreNMR1Upgrade - ? new File(parsedPackage.getCodePath()).lastModified() + ? new File(parsedPackage.getPath()).lastModified() : getLastModifiedTime(parsedPackage); final VersionInfo settingsVersionForPackage = getSettingsVersionForPackage(parsedPackage); if (ps != null && !forceCollect - && ps.getCodePathString().equals(parsedPackage.getCodePath()) + && ps.getPathString().equals(parsedPackage.getPath()) && ps.timeStamp == lastModifiedTime && !isCompatSignatureUpdateNeeded(settingsVersionForPackage) && !isRecoverSignatureUpdateNeeded(settingsVersionForPackage)) { @@ -9281,8 +9283,8 @@ public class PackageManagerService extends IPackageManager.Stub Slog.w(TAG, "PackageSetting for " + ps.name + " is missing signatures. Collecting certs again to recover them."); } else { - Slog.i(TAG, parsedPackage.getCodePath() + " changed; collecting certs" + - (forceCollect ? " (forced)" : "")); + Slog.i(TAG, parsedPackage.getPath() + " changed; collecting certs" + + (forceCollect ? " (forced)" : "")); } try { @@ -9366,7 +9368,7 @@ public class PackageManagerService extends IPackageManager.Stub * Returns if forced apk verification can be skipped for the whole package, including splits. */ private boolean canSkipForcedPackageVerification(AndroidPackage pkg) { - if (!canSkipForcedApkVerification(pkg.getBaseCodePath())) { + if (!canSkipForcedApkVerification(pkg.getBaseApkPath())) { return false; } // TODO: Allow base and splits to be verified individually. @@ -9497,7 +9499,7 @@ public class PackageManagerService extends IPackageManager.Stub } final boolean newPkgChangedPaths = pkgAlreadyExists - && !pkgSetting.getCodePathString().equals(parsedPackage.getCodePath()); + && !pkgSetting.getPathString().equals(parsedPackage.getPath()); final boolean newPkgVersionGreater = pkgAlreadyExists && parsedPackage.getLongVersionCode() > pkgSetting.versionCode; final boolean isSystemPkgBetter = scanSystemPartition && isSystemPkgUpdated @@ -9516,11 +9518,11 @@ public class PackageManagerService extends IPackageManager.Stub "System package updated;" + " name: " + pkgSetting.name + "; " + pkgSetting.versionCode + " --> " + parsedPackage.getLongVersionCode() - + "; " + pkgSetting.getCodePathString() - + " --> " + parsedPackage.getCodePath()); + + "; " + pkgSetting.getPathString() + + " --> " + parsedPackage.getPath()); final InstallArgs args = createInstallArgsForExisting( - pkgSetting.getCodePathString(), getAppDexInstructionSets( + pkgSetting.getPathString(), getAppDexInstructionSets( pkgSetting.primaryCpuAbiString, pkgSetting.secondaryCpuAbiString)); args.cleanUpResourcesLI(); synchronized (mLock) { @@ -9533,7 +9535,7 @@ public class PackageManagerService extends IPackageManager.Stub // equal to the version on the /data partition. Throw an exception and use // the application already installed on the /data partition. throw new PackageManagerException(Log.WARN, "Package " + parsedPackage.getPackageName() - + " at " + parsedPackage.getCodePath() + " ignored: updated version " + + " at " + parsedPackage.getPath() + " ignored: updated version " + pkgSetting.versionCode + " better than this " + parsedPackage.getLongVersionCode()); } @@ -9582,8 +9584,8 @@ public class PackageManagerService extends IPackageManager.Stub try (@SuppressWarnings("unused") PackageFreezer freezer = freezePackage( parsedPackage.getPackageName(), "scanPackageInternalLI")) { - deletePackageLIF(parsedPackage.getPackageName(), null, true, null, 0, null, - false, null); + deletePackageLIF(parsedPackage.getPackageName(), null, true, + mUserManager.getUserIds(), 0, null, false, null); } pkgSetting = null; } else if (newPkgVersionGreater) { @@ -9595,10 +9597,10 @@ public class PackageManagerService extends IPackageManager.Stub + " name: " + pkgSetting.name + "; " + pkgSetting.versionCode + " --> " + parsedPackage.getLongVersionCode() - + "; " + pkgSetting.getCodePathString() + " --> " - + parsedPackage.getCodePath()); + + "; " + pkgSetting.getPathString() + " --> " + + parsedPackage.getPath()); InstallArgs args = createInstallArgsForExisting( - pkgSetting.getCodePathString(), getAppDexInstructionSets( + pkgSetting.getPathString(), getAppDexInstructionSets( pkgSetting.primaryCpuAbiString, pkgSetting.secondaryCpuAbiString)); synchronized (mInstallLock) { args.cleanUpResourcesLI(); @@ -9611,10 +9613,10 @@ public class PackageManagerService extends IPackageManager.Stub logCriticalInfo(Log.INFO, "System package disabled;" + " name: " + pkgSetting.name - + "; old: " + pkgSetting.getCodePathString() + " @ " + + "; old: " + pkgSetting.getPathString() + " @ " + pkgSetting.versionCode - + "; new: " + parsedPackage.getCodePath() + " @ " - + parsedPackage.getCodePath()); + + "; new: " + parsedPackage.getPath() + " @ " + + parsedPackage.getPath()); } } @@ -9795,7 +9797,7 @@ public class PackageManagerService extends IPackageManager.Stub * Return the prebuilt profile path given a package base code path. */ private static String getPrebuildProfilePath(AndroidPackage pkg) { - return pkg.getBaseCodePath() + ".prof"; + return pkg.getBaseApkPath() + ".prof"; } /** @@ -11448,7 +11450,7 @@ public class PackageManagerService extends IPackageManager.Stub if (changedAbiCodePath == null) { changedAbiCodePath = new ArrayList<>(); } - changedAbiCodePath.add(ps.getCodePathString()); + changedAbiCodePath.add(ps.getPathString()); } } } @@ -11543,7 +11545,7 @@ public class PackageManagerService extends IPackageManager.Stub } // Initialize package source and resource directories - final File destCodeFile = new File(parsedPackage.getCodePath()); + final File destCodeFile = new File(parsedPackage.getPath()); // We keep references to the derived CPU Abis from settings in oder to reuse // them in the case where we're not upgrading or booting for the first time. @@ -11881,9 +11883,9 @@ public class PackageManagerService extends IPackageManager.Stub private static void assertCodePolicy(AndroidPackage pkg) throws PackageManagerException { final boolean shouldHaveCode = pkg.isHasCode(); - if (shouldHaveCode && !apkHasCode(pkg.getBaseCodePath())) { + if (shouldHaveCode && !apkHasCode(pkg.getBaseApkPath())) { throw new PackageManagerException(INSTALL_FAILED_INVALID_APK, - "Package " + pkg.getBaseCodePath() + " code is missing"); + "Package " + pkg.getBaseApkPath() + " code is missing"); } if (!ArrayUtils.isEmpty(pkg.getSplitCodePaths())) { @@ -11915,7 +11917,7 @@ public class PackageManagerService extends IPackageManager.Stub if (parsedPackage.isDirectBootAware()) { parsedPackage.setAllComponentsDirectBootAware(true); } - if (compressedFileExists(parsedPackage.getCodePath())) { + if (compressedFileExists(parsedPackage.getPath())) { parsedPackage.setStub(true); } } else { @@ -12006,7 +12008,7 @@ public class PackageManagerService extends IPackageManager.Stub assertCodePolicy(pkg); } - if (pkg.getCodePath() == null) { + if (pkg.getPath() == null) { // Bail out. The resource and code paths haven't been set. throw new PackageManagerException(INSTALL_FAILED_INVALID_APK, "Code and resource paths haven't been set correctly"); @@ -12033,7 +12035,7 @@ public class PackageManagerService extends IPackageManager.Stub if (mAndroidApplication != null) { Slog.w(TAG, "*************************************************"); Slog.w(TAG, "Core android package being redefined. Skipping."); - Slog.w(TAG, " codePath=" + pkg.getCodePath()); + Slog.w(TAG, " codePath=" + pkg.getPath()); Slog.w(TAG, "*************************************************"); throw new PackageManagerException(INSTALL_FAILED_DUPLICATE_PACKAGE, "Core android package being redefined. Skipping."); @@ -12189,14 +12191,14 @@ public class PackageManagerService extends IPackageManager.Stub PackageSetting known = mSettings.getPackageLPr(pkg.getPackageName()); if (known != null) { if (DEBUG_PACKAGE_SCANNING) { - Log.d(TAG, "Examining " + pkg.getCodePath() - + " and requiring known path " + known.getCodePathString()); + Log.d(TAG, "Examining " + pkg.getPath() + + " and requiring known path " + known.getPathString()); } - if (!pkg.getCodePath().equals(known.getCodePathString())) { + if (!pkg.getPath().equals(known.getPathString())) { throw new PackageManagerException(INSTALL_FAILED_PACKAGE_CHANGED, "Application package " + pkg.getPackageName() - + " found at " + pkg.getCodePath() - + " but expected at " + known.getCodePathString() + + " found at " + pkg.getPath() + + " but expected at " + known.getPathString() + "; ignoring."); } } else { @@ -14530,13 +14532,11 @@ public class PackageManagerService extends IPackageManager.Stub Log.v(TAG, "restoreAndPostInstall userId=" + userId + " package=" + res.pkg); } - // 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. + // A restore should be requested at this point if (a) the install + // succeeded, (b) the operation is not an update. final boolean update = res.removedInfo != null && res.removedInfo.removedPackage != null; - boolean allowBackup = res.pkg != null && res.pkg.isAllowBackup(); - boolean doRestore = !update && allowBackup; + boolean doRestore = !update && res.pkg != null; // Set up the post-install work request bookkeeping. This will be used // and cleaned up by the post-install event handling regardless of whether @@ -15785,7 +15785,7 @@ public class PackageManagerService extends IPackageManager.Stub abstract boolean doRename(int status, ParsedPackage parsedPackage); abstract int doPostInstall(int status, int uid); - /** @see PackageSettingBase#getCodePath() */ + /** @see PackageSettingBase#getPath() */ abstract String getCodePath(); // Need installer lock especially for dex file removal. @@ -15966,7 +15966,7 @@ public class PackageManagerService extends IPackageManager.Stub return false; } parsedPackage.setBaseCodePath(FileUtils.rewriteAfterRename(beforeCodeFile, - afterCodeFile, parsedPackage.getBaseCodePath())); + afterCodeFile, parsedPackage.getBaseApkPath())); parsedPackage.setSplitCodePaths(FileUtils.rewriteAfterRename(beforeCodeFile, afterCodeFile, parsedPackage.getSplitCodePaths())); @@ -16233,7 +16233,7 @@ public class PackageManagerService extends IPackageManager.Stub InstallSource installSource = installArgs.installSource; final String installerPackageName = installSource.installerPackageName; - if (DEBUG_INSTALL) Slog.d(TAG, "New package installed in " + pkg.getCodePath()); + if (DEBUG_INSTALL) Slog.d(TAG, "New package installed in " + pkg.getPath()); synchronized (mLock) { // NOTE: This changes slightly to include UPDATE_PERMISSIONS_ALL regardless of the size of pkg.permissions mPermissionManager.updatePermissions(pkgName, pkg); @@ -16388,9 +16388,11 @@ public class PackageManagerService extends IPackageManager.Stub */ private static class CommitRequest { final Map<String, ReconciledPackage> reconciledPackages; + @NonNull final int[] mAllUsers; - private CommitRequest(Map<String, ReconciledPackage> reconciledPackages, int[] allUsers) { + private CommitRequest(Map<String, ReconciledPackage> reconciledPackages, + @NonNull int[] allUsers) { this.reconciledPackages = reconciledPackages; this.mAllUsers = allUsers; } @@ -16870,7 +16872,7 @@ public class PackageManagerService extends IPackageManager.Stub // which means we are replacing another update that is already // installed. We need to make sure to delete the older one's .apk. res.removedInfo.args = createInstallArgsForExisting( - oldPackage.getCodePath(), + oldPackage.getPath(), getAppDexInstructionSets( AndroidPackageUtils.getPrimaryCpuAbi(oldPackage, deletedPkgSetting), @@ -16913,7 +16915,7 @@ public class PackageManagerService extends IPackageManager.Stub if (ps1.mOldCodePaths == null) { ps1.mOldCodePaths = new ArraySet<>(); } - Collections.addAll(ps1.mOldCodePaths, oldPackage.getBaseCodePath()); + Collections.addAll(ps1.mOldCodePaths, oldPackage.getBaseApkPath()); if (oldPackage.getSplitCodePaths() != null) { Collections.addAll(ps1.mOldCodePaths, oldPackage.getSplitCodePaths()); } @@ -17078,7 +17080,7 @@ public class PackageManagerService extends IPackageManager.Stub // For incremental installs, we bypass the verifier prior to install. Now // that we know the package is valid, send a notice to the verifier with // the root hash of the base.apk. - final String baseCodePath = request.installResult.pkg.getBaseCodePath(); + final String baseCodePath = request.installResult.pkg.getBaseApkPath(); final String[] splitCodePaths = request.installResult.pkg.getSplitCodePaths(); final Uri originUri = Uri.fromFile(args.origin.resolvedFile); final int verificationId = mPendingVerificationToken++; @@ -17123,9 +17125,9 @@ public class PackageManagerService extends IPackageManager.Stub final AndroidPackage pkg = reconciledPkg.pkgSetting.pkg; final String packageName = pkg.getPackageName(); final boolean onIncremental = mIncrementalManager != null - && isIncrementalPath(pkg.getCodePath()); + && isIncrementalPath(pkg.getPath()); if (onIncremental) { - IncrementalStorage storage = mIncrementalManager.openStorage(pkg.getCodePath()); + IncrementalStorage storage = mIncrementalManager.openStorage(pkg.getPath()); if (storage == null) { throw new IllegalArgumentException( "Install: null storage for incremental package " + packageName); @@ -17139,7 +17141,7 @@ public class PackageManagerService extends IPackageManager.Stub } if (reconciledPkg.prepareResult.replace) { mDexManager.notifyPackageUpdated(pkg.getPackageName(), - pkg.getBaseCodePath(), pkg.getSplitCodePaths()); + pkg.getBaseApkPath(), pkg.getSplitCodePaths()); } // Prepare the application profiles for the new code paths. @@ -17759,7 +17761,6 @@ public class PackageManagerService extends IPackageManager.Stub oldPackage = mPackages.get(pkgName11); existingPackage = oldPackage; if (DEBUG_INSTALL) { - // TODO(b/135203078): PackageImpl.toString() Slog.d(TAG, "replacePackageLI: new=" + parsedPackage + ", old=" + oldPackage); } @@ -17793,7 +17794,7 @@ public class PackageManagerService extends IPackageManager.Stub final byte[] digestBytes; try { final MessageDigest digest = MessageDigest.getInstance("SHA-512"); - updateDigest(digest, new File(parsedPackage.getBaseCodePath())); + updateDigest(digest, new File(parsedPackage.getBaseApkPath())); if (!ArrayUtils.isEmpty(parsedPackage.getSplitCodePaths())) { for (String path : parsedPackage.getSplitCodePaths()) { updateDigest(digest, new File(path)); @@ -17973,7 +17974,7 @@ public class PackageManagerService extends IPackageManager.Stub synchronized (mLock) { final PackageSetting ps = mSettings.mPackages.get(pkg.getPackageName()); if (ps != null && ps.isPrivileged()) { - fsverityCandidates.put(pkg.getBaseCodePath(), null); + fsverityCandidates.put(pkg.getBaseApkPath(), null); if (pkg.getSplitCodePaths() != null) { for (String splitPath : pkg.getSplitCodePaths()) { fsverityCandidates.put(splitPath, null); @@ -17984,11 +17985,11 @@ public class PackageManagerService extends IPackageManager.Stub } else { // NB: These files will become only accessible if the signing key is loaded in kernel's // .fs-verity keyring. - fsverityCandidates.put(pkg.getBaseCodePath(), - VerityUtils.getFsveritySignatureFilePath(pkg.getBaseCodePath())); + fsverityCandidates.put(pkg.getBaseApkPath(), + VerityUtils.getFsveritySignatureFilePath(pkg.getBaseApkPath())); final String dmPath = DexMetadataHelper.buildDexMetadataPathForApk( - pkg.getBaseCodePath()); + pkg.getBaseApkPath()); if (new File(dmPath).exists()) { fsverityCandidates.put(dmPath, VerityUtils.getFsveritySignatureFilePath(dmPath)); } @@ -18903,7 +18904,7 @@ public class PackageManagerService extends IPackageManager.Stub * make sure this flag is set for partially installed apps. If not its meaningless to * delete a partially installed application. */ - private void removePackageDataLIF(final PackageSetting deletedPs, int[] allUserHandles, + private void removePackageDataLIF(final PackageSetting deletedPs, @NonNull int[] allUserHandles, PackageRemovedInfo outInfo, int flags, boolean writeSettings) { String packageName = deletedPs.name; if (DEBUG_REMOVE) Slog.d(TAG, "removePackageDataLI: " + deletedPs); @@ -18991,7 +18992,7 @@ public class PackageManagerService extends IPackageManager.Stub } // make sure to preserve per-user disabled state if this removal was just // a downgrade of a system app to the factory package - if (allUserHandles != null && outInfo != null && outInfo.origUsers != null) { + if (outInfo != null && outInfo.origUsers != null) { if (DEBUG_REMOVE) { Slog.d(TAG, "Propagating install state across downgrade"); } @@ -19044,11 +19045,10 @@ public class PackageManagerService extends IPackageManager.Stub * Tries to delete system package. */ private void deleteSystemPackageLIF(DeletePackageAction action, PackageSetting deletedPs, - int[] allUserHandles, int flags, @Nullable PackageRemovedInfo outInfo, + @NonNull int[] allUserHandles, int flags, @Nullable PackageRemovedInfo outInfo, boolean writeSettings) throws SystemDeleteException { - final boolean applyUserRestrictions = - (allUserHandles != null) && outInfo != null && (outInfo.origUsers != null); + final boolean applyUserRestrictions = outInfo != null && (outInfo.origUsers != null); final AndroidPackage deletedPkg = deletedPs.pkg; // Confirm if the system package has been updated // An updated system app can be deleted. This will also have to restore @@ -19100,7 +19100,7 @@ public class PackageManagerService extends IPackageManager.Stub // Install the system package if (DEBUG_REMOVE) Slog.d(TAG, "Re-installing system package: " + disabledPs); try { - installPackageFromSystemLIF(disabledPs.getCodePathString(), allUserHandles, + installPackageFromSystemLIF(disabledPs.getPathString(), allUserHandles, outInfo == null ? null : outInfo.origUsers, writeSettings); } catch (PackageManagerException e) { Slog.w(TAG, "Failed to restore system package:" + deletedPkg.getPackageName() + ": " @@ -19132,7 +19132,7 @@ public class PackageManagerService extends IPackageManager.Stub * Installs a package that's already on the system partition. */ private AndroidPackage installPackageFromSystemLIF(@NonNull String codePathString, - @Nullable int[] allUserHandles, @Nullable int[] origUserHandles, boolean writeSettings) + @NonNull int[] allUserHandles, @Nullable int[] origUserHandles, boolean writeSettings) throws PackageManagerException { final File codePath = new File(codePathString); @ParseFlags int parseFlags = @@ -19174,8 +19174,7 @@ public class PackageManagerService extends IPackageManager.Stub // and granting install permissions. mPermissionManager.updatePermissions(pkg.getPackageName(), pkg); - final boolean applyUserRestrictions - = (allUserHandles != null) && (origUserHandles != null); + final boolean applyUserRestrictions = origUserHandles != null; if (applyUserRestrictions) { boolean installedStateChanged = false; if (DEBUG_REMOVE) { @@ -19212,7 +19211,7 @@ public class PackageManagerService extends IPackageManager.Stub } private void deleteInstalledPackageLIF(PackageSetting ps, - boolean deleteCodeAndResources, int flags, int[] allUserHandles, + boolean deleteCodeAndResources, int flags, @NonNull int[] allUserHandles, PackageRemovedInfo outInfo, boolean writeSettings) { synchronized (mLock) { if (outInfo != null) { @@ -19226,7 +19225,7 @@ public class PackageManagerService extends IPackageManager.Stub // Delete application code and resources only for parent packages if (deleteCodeAndResources && (outInfo != null)) { outInfo.args = createInstallArgsForExisting( - ps.getCodePathString(), getAppDexInstructionSets( + ps.getPathString(), getAppDexInstructionSets( ps.primaryCpuAbiString, ps.secondaryCpuAbiString)); if (DEBUG_SD_INSTALL) Slog.i(TAG, "args=" + outInfo.args); } @@ -19332,7 +19331,7 @@ public class PackageManagerService extends IPackageManager.Stub * This method handles package deletion in general */ private boolean deletePackageLIF(@NonNull String packageName, UserHandle user, - boolean deleteCodeAndResources, int[] allUserHandles, int flags, + boolean deleteCodeAndResources, @NonNull int[] allUserHandles, int flags, PackageRemovedInfo outInfo, boolean writeSettings, ParsedPackage replacingPackage) { final DeletePackageAction action; @@ -19369,7 +19368,7 @@ public class PackageManagerService extends IPackageManager.Stub /** Deletes a package. Only throws when install of a disabled package fails. */ private void executeDeletePackageLIF(DeletePackageAction action, String packageName, boolean deleteCodeAndResources, - int[] allUserHandles, boolean writeSettings, + @NonNull int[] allUserHandles, boolean writeSettings, ParsedPackage replacingPackage) throws SystemDeleteException { final PackageSetting ps = action.deletingPs; final PackageRemovedInfo outInfo = action.outInfo; @@ -19768,7 +19767,7 @@ public class PackageManagerService extends IPackageManager.Stub final String[] packageNames = { packageName }; final long[] ceDataInodes = { ps.getCeDataInode(userId) }; - final String[] codePaths = { ps.getCodePathString() }; + final String[] codePaths = { ps.getPathString() }; try { mInstaller.getAppSize(ps.volumeUuid, packageNames, userId, 0, @@ -19865,7 +19864,7 @@ public class PackageManagerService extends IPackageManager.Stub final PreferredIntentResolver pir = mSettings.editPreferredActivitiesLPw(userId); final ArrayList<PreferredActivity> existing = pir.findFilters(filter); if (removeExisting && existing != null) { - removeFiltersLocked(pir, filter, existing); + mSettings.removeFiltersLPw(pir, filter, existing); } pir.addFilter(new PreferredActivity(filter, match, set, activity, always)); scheduleWritePackageRestrictionsLocked(userId); @@ -19966,7 +19965,7 @@ public class PackageManagerService extends IPackageManager.Stub } } if (existing != null) { - removeFiltersLocked(pir, filter, existing); + mSettings.removeFiltersLPw(pir, filter, existing); } } } @@ -19974,22 +19973,6 @@ public class PackageManagerService extends IPackageManager.Stub "Replacing preferred", false); } - private void removeFiltersLocked(@NonNull PreferredIntentResolver pir, - @NonNull IntentFilter filter, @NonNull List<PreferredActivity> existing) { - if (DEBUG_PREFERRED) { - Slog.i(TAG, existing.size() + " preferred matches for:"); - filter.dump(new LogPrinter(Log.INFO, TAG), " "); - } - for (int i = existing.size() - 1; i >= 0; --i) { - final PreferredActivity pa = existing.get(i); - if (DEBUG_PREFERRED) { - Slog.i(TAG, "Removing preferred activity " + pa.mPref.mComponent + ":"); - pa.dump(new LogPrinter(Log.INFO, TAG), " "); - } - pir.removeFilter(pa); - } - } - @Override public void clearPackagePreferredActivities(String packageName) { final int callingUid = Binder.getCallingUid(); @@ -22711,11 +22694,11 @@ public class PackageManagerService extends IPackageManager.Stub synchronized (mInstallLock) { final AndroidPackage pkg; try { - pkg = scanPackageTracedLI(ps.getCodePath(), parseFlags, SCAN_INITIAL, 0, null); + pkg = scanPackageTracedLI(ps.getPath(), parseFlags, SCAN_INITIAL, 0, null); loaded.add(pkg); } catch (PackageManagerException e) { - Slog.w(TAG, "Failed to scan " + ps.getCodePath() + ": " + e.getMessage()); + Slog.w(TAG, "Failed to scan " + ps.getPath() + ": " + e.getMessage()); } if (!Build.FINGERPRINT.equals(ver.fingerprint)) { @@ -22784,6 +22767,7 @@ public class PackageManagerService extends IPackageManager.Stub return; } + final int[] userIds = mUserManager.getUserIds(); final ArrayList<AndroidPackage> unloaded = new ArrayList<>(); synchronized (mInstallLock) { synchronized (mLock) { @@ -22797,11 +22781,11 @@ public class PackageManagerService extends IPackageManager.Stub try (PackageFreezer freezer = freezePackageForDelete(ps.name, deleteFlags, "unloadPrivatePackagesInner")) { - if (deletePackageLIF(ps.name, null, false, null, deleteFlags, outInfo, + if (deletePackageLIF(ps.name, null, false, userIds, deleteFlags, outInfo, false, null)) { unloaded.add(pkg); } else { - Slog.w(TAG, "Failed to unload " + ps.getCodePath()); + Slog.w(TAG, "Failed to unload " + ps.getPath()); } } @@ -22855,7 +22839,7 @@ public class PackageManagerService extends IPackageManager.Stub final int packageCount = mSettings.mPackages.size(); for (int i = 0; i < packageCount; i++) { final PackageSetting ps = mSettings.mPackages.valueAt(i); - codePaths.add(ps.getCodePath().getAbsolutePath()); + codePaths.add(ps.getPath().getAbsolutePath()); } return codePaths; } @@ -23431,7 +23415,7 @@ public class PackageManagerService extends IPackageManager.Stub currentVolumeUuid = ps.volumeUuid; - final File probe = new File(pkg.getCodePath()); + final File probe = new File(pkg.getPath()); final File probeOat = new File(probe, "oat"); if (!probe.isDirectory() || !probeOat.isDirectory()) { throw new PackageManagerException(MOVE_FAILED_INTERNAL_ERROR, @@ -23453,7 +23437,7 @@ public class PackageManagerService extends IPackageManager.Stub } isCurrentLocationExternal = pkg.isExternalStorage(); - codeFile = new File(pkg.getCodePath()); + codeFile = new File(pkg.getPath()); installSource = ps.installSource; packageAbiOverride = ps.cpuAbiOverrideString; appId = UserHandle.getAppId(pkg.getUid()); @@ -24884,7 +24868,7 @@ public class PackageManagerService extends IPackageManager.Stub mApexManager.getApksInApex(apexPackages.get(i).packageName); for (int j = 0, apksInApex = apkNames.size(); j < apksInApex; j++) { final AndroidPackage pkg = getPackage(apkNames.get(j)); - cacher.cleanCachedResult(new File(pkg.getCodePath())); + cacher.cleanCachedResult(new File(pkg.getPath())); } } } @@ -24960,7 +24944,7 @@ public class PackageManagerService extends IPackageManager.Stub Slog.e(TAG, "failed to find package " + packageName); return false; } - overlayPaths.add(pkg.getBaseCodePath()); + overlayPaths.add(pkg.getBaseApkPath()); } } @@ -25676,7 +25660,7 @@ public class PackageManagerService extends IPackageManager.Stub pkgSetting.getPkgState().isUpdatedSystemApp())) { return null; } - File codePath = new File(pkg.getCodePath()); + File codePath = new File(pkg.getPath()); if (codePath.isDirectory()) { return PackageDexOptimizer.getOatDir(codePath).getAbsolutePath(); } diff --git a/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java b/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java index 5553cd0e2fb8..e5dad8570254 100644 --- a/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java +++ b/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java @@ -326,11 +326,11 @@ public class PackageManagerServiceUtils { } public static long getLastModifiedTime(AndroidPackage pkg) { - final File srcFile = new File(pkg.getCodePath()); + final File srcFile = new File(pkg.getPath()); if (!srcFile.isDirectory()) { return srcFile.lastModified(); } - final File baseFile = new File(pkg.getBaseCodePath()); + final File baseFile = new File(pkg.getBaseApkPath()); long maxModifiedTime = baseFile.lastModified(); if (pkg.getSplitCodePaths() != null) { for (int i = pkg.getSplitCodePaths().length - 1; i >=0; --i) { diff --git a/services/core/java/com/android/server/pm/PackageManagerShellCommandDataLoader.java b/services/core/java/com/android/server/pm/PackageManagerShellCommandDataLoader.java index 3614cc047bf8..2bbca79741bd 100644 --- a/services/core/java/com/android/server/pm/PackageManagerShellCommandDataLoader.java +++ b/services/core/java/com/android/server/pm/PackageManagerShellCommandDataLoader.java @@ -67,7 +67,6 @@ public class PackageManagerShellCommandDataLoader extends DataLoaderService { } } - // Sanity check. if (sShellCommands.size() > TOO_MANY_PENDING_SHELL_COMMANDS) { Slog.e(TAG, "Too many pending shell commands: " + sShellCommands.size()); } diff --git a/services/core/java/com/android/server/pm/PackageSetting.java b/services/core/java/com/android/server/pm/PackageSetting.java index a3a727367c56..4476e8ac8d90 100644 --- a/services/core/java/com/android/server/pm/PackageSetting.java +++ b/services/core/java/com/android/server/pm/PackageSetting.java @@ -44,8 +44,33 @@ import java.util.Set; public class PackageSetting extends PackageSettingBase { int appId; + /** + * This can be null whenever a physical APK on device is missing. This can be the result of + * removing an external storage device where the APK resides. + * + * This will result in the system reading the {@link PackageSetting} from disk, but without + * being able to parse the base APK's AndroidManifest.xml to read all of its metadata. The data + * that is written and read in {@link Settings} includes a minimal set of metadata needed to + * perform other checks in the system. + * + * This is important in order to enforce uniqueness within the system, as the package, even if + * on a removed storage device, is still considered installed. Another package of the same + * application ID or declaring the same permissions or similar cannot be installed. + * + * Re-attaching the storage device to make the APK available should allow the user to use the + * app once the device reboots or otherwise re-scans it. + * + * It is expected that all code that uses a {@link PackageSetting} understands this inner field + * may be null. Note that this relationship only works one way. It should not be possible to + * have an entry inside {@link PackageManagerService#mPackages} without a corresponding + * {@link PackageSetting} inside {@link Settings#mPackages}. + * + * @deprecated Use {@link #getPkg()}. The setter is favored to avoid unintended mutation. + */ @Nullable + @Deprecated public AndroidPackage pkg; + /** * WARNING. The object reference is important. We perform integer equality and NOT * object equality to check whether shared user settings are the same. @@ -104,6 +129,12 @@ public class PackageSetting extends PackageSettingBase { doCopy(orig); } + /** @see #pkg **/ + @Nullable + public AndroidPackage getPkg() { + return pkg; + } + public int getSharedUserId() { if (sharedUser != null) { return sharedUser.userId; @@ -200,7 +231,6 @@ public class PackageSetting extends PackageSettingBase { return installPermissionsFixed; } - // TODO(b/135203078): Remove these in favor of reading from the package directly public boolean isPrivileged() { return (pkgPrivateFlags & ApplicationInfo.PRIVATE_FLAG_PRIVILEGED) != 0; } diff --git a/services/core/java/com/android/server/pm/PackageSettingBase.java b/services/core/java/com/android/server/pm/PackageSettingBase.java index 6010344b8c65..a7bbf8d66aac 100644 --- a/services/core/java/com/android/server/pm/PackageSettingBase.java +++ b/services/core/java/com/android/server/pm/PackageSettingBase.java @@ -40,6 +40,7 @@ import android.util.SparseArray; import android.util.proto.ProtoOutputStream; import com.android.internal.annotations.VisibleForTesting; +import com.android.server.pm.parsing.pkg.AndroidPackage; import java.io.File; import java.util.Arrays; @@ -59,13 +60,9 @@ public abstract class PackageSettingBase extends SettingBase { public final String name; final String realName; - /** - * Path where this package was found on disk. For monolithic packages - * this is path to single base APK file; for cluster packages this is - * path to the cluster directory. - */ - private File mCodePath; - private String mCodePathString; + /** @see AndroidPackage#getPath() */ + private File mPath; + private String mPathString; String[] usesStaticLibraries; long[] usesStaticLibrariesVersions; @@ -136,7 +133,7 @@ public abstract class PackageSettingBase extends SettingBase { boolean forceQueryableOverride; - PackageSettingBase(String name, String realName, @NonNull File codePath, + PackageSettingBase(String name, String realName, @NonNull File path, String legacyNativeLibraryPathString, String primaryCpuAbiString, String secondaryCpuAbiString, String cpuAbiOverrideString, long pVersionCode, int pkgFlags, int pkgPrivateFlags, @@ -146,7 +143,7 @@ public abstract class PackageSettingBase extends SettingBase { this.realName = realName; this.usesStaticLibraries = usesStaticLibraries; this.usesStaticLibrariesVersions = usesStaticLibrariesVersions; - setCodePath(codePath); + setPath(path); this.legacyNativeLibraryPathString = legacyNativeLibraryPathString; this.primaryCpuAbiString = primaryCpuAbiString; this.secondaryCpuAbiString = secondaryCpuAbiString; @@ -230,7 +227,7 @@ public abstract class PackageSettingBase extends SettingBase { } private void doCopy(PackageSettingBase orig) { - setCodePath(orig.getCodePath()); + setPath(orig.getPath()); cpuAbiOverrideString = orig.cpuAbiOverrideString; firstInstallTime = orig.firstInstallTime; installPermissionsFixed = orig.installPermissionsFixed; @@ -697,18 +694,23 @@ public abstract class PackageSettingBase extends SettingBase { return userState.harmfulAppWarning; } - PackageSettingBase setCodePath(@NonNull File codePath) { - this.mCodePath = codePath; - this.mCodePathString = codePath.toString(); + /** + * @see #mPath + */ + PackageSettingBase setPath(@NonNull File path) { + this.mPath = path; + this.mPathString = path.toString(); return this; } - File getCodePath() { - return mCodePath; + /** @see #mPath */ + File getPath() { + return mPath; } - String getCodePathString() { - return mCodePathString; + /** @see #mPath */ + String getPathString() { + return mPathString; } /** @@ -733,7 +735,7 @@ public abstract class PackageSettingBase extends SettingBase { protected PackageSettingBase updateFrom(PackageSettingBase other) { super.copyFrom(other); - setCodePath(other.getCodePath()); + setPath(other.getPath()); this.usesStaticLibraries = other.usesStaticLibraries; this.usesStaticLibrariesVersions = other.usesStaticLibrariesVersions; this.legacyNativeLibraryPathString = other.legacyNativeLibraryPathString; diff --git a/services/core/java/com/android/server/pm/Settings.java b/services/core/java/com/android/server/pm/Settings.java index 659e2a32e267..74bc49dd9108 100644 --- a/services/core/java/com/android/server/pm/Settings.java +++ b/services/core/java/com/android/server/pm/Settings.java @@ -102,7 +102,6 @@ import com.android.internal.util.XmlUtils; import com.android.permission.persistence.RuntimePermissionsPersistence; import com.android.permission.persistence.RuntimePermissionsState; import com.android.server.LocalServices; -import com.android.server.pm.Installer.Batch; import com.android.server.pm.Installer.InstallerException; import com.android.server.pm.parsing.PackageInfoUtils; import com.android.server.pm.parsing.pkg.AndroidPackage; @@ -307,8 +306,8 @@ public final class Settings { private final ArrayMap<String, KernelPackageState> mKernelMapping = new ArrayMap<>(); // List of replaced system applications - private final ArrayMap<String, PackageSetting> mDisabledSysPackages = - new ArrayMap<String, PackageSetting>(); + @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE) + final ArrayMap<String, PackageSetting> mDisabledSysPackages = new ArrayMap<>(); /** List of packages that are blocked for uninstall for specific users */ private final SparseArray<ArraySet<String>> mBlockUninstallPackages = new SparseArray<>(); @@ -539,7 +538,7 @@ public final class Settings { return null; } p.getPkgState().setUpdatedSystemApp(false); - PackageSetting ret = addPackageLPw(name, p.realName, p.getCodePath(), + PackageSetting ret = addPackageLPw(name, p.realName, p.getPath(), p.legacyNativeLibraryPathString, p.primaryCpuAbiString, p.secondaryCpuAbiString, p.cpuAbiOverrideString, p.appId, p.versionCode, p.pkgFlags, p.pkgPrivateFlags, @@ -646,7 +645,7 @@ public final class Settings { if (PackageManagerService.DEBUG_UPGRADE) Log.v(PackageManagerService.TAG, "Package " + pkgName + " is adopting original package " + originalPkg.name); pkgSetting = new PackageSetting(originalPkg, pkgName /*realPkgName*/); - pkgSetting.setCodePath(codePath); + pkgSetting.setPath(codePath); pkgSetting.legacyNativeLibraryPathString = legacyNativeLibraryPath; pkgSetting.pkgFlags = pkgFlags; pkgSetting.pkgPrivateFlags = pkgPrivateFlags; @@ -771,12 +770,12 @@ public final class Settings { "Updating application package " + pkgName + " failed"); } - if (!pkgSetting.getCodePath().equals(codePath)) { + if (!pkgSetting.getPath().equals(codePath)) { final boolean isSystem = pkgSetting.isSystem(); Slog.i(PackageManagerService.TAG, "Update" + (isSystem ? " system" : "") + " package " + pkgName - + " code path from " + pkgSetting.getCodePathString() + + " code path from " + pkgSetting.getPathString() + " to " + codePath.toString() + "; Retain data and using new"); if (!isSystem) { @@ -798,7 +797,7 @@ public final class Settings { // internal to external storage or vice versa. pkgSetting.legacyNativeLibraryPathString = legacyNativeLibraryPath; } - pkgSetting.setCodePath(codePath); + pkgSetting.setPath(codePath); } // If what we are scanning is a system (and possibly privileged) package, // then make it so, regardless of whether it was previously installed only @@ -2175,32 +2174,24 @@ public final class Settings { void readUsesStaticLibLPw(XmlPullParser parser, PackageSetting outPs) throws IOException, XmlPullParserException { - int outerDepth = parser.getDepth(); - int type; - while ((type = parser.next()) != XmlPullParser.END_DOCUMENT - && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) { - if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) { - continue; - } - String libName = parser.getAttributeValue(null, ATTR_NAME); - String libVersionStr = parser.getAttributeValue(null, ATTR_VERSION); - - long libVersion = -1; - try { - libVersion = Long.parseLong(libVersionStr); - } catch (NumberFormatException e) { - // ignore - } + String libName = parser.getAttributeValue(null, ATTR_NAME); + String libVersionStr = parser.getAttributeValue(null, ATTR_VERSION); - if (libName != null && libVersion >= 0) { - outPs.usesStaticLibraries = ArrayUtils.appendElement(String.class, - outPs.usesStaticLibraries, libName); - outPs.usesStaticLibrariesVersions = ArrayUtils.appendLong( - outPs.usesStaticLibrariesVersions, libVersion); - } + long libVersion = -1; + try { + libVersion = Long.parseLong(libVersionStr); + } catch (NumberFormatException e) { + // ignore + } - XmlUtils.skipCurrentTag(parser); + if (libName != null && libVersion >= 0) { + outPs.usesStaticLibraries = ArrayUtils.appendElement(String.class, + outPs.usesStaticLibraries, libName); + outPs.usesStaticLibrariesVersions = ArrayUtils.appendLong( + outPs.usesStaticLibrariesVersions, libVersion); } + + XmlUtils.skipCurrentTag(parser); } void writeUsesStaticLibLPw(XmlSerializer serializer, String[] usesStaticLibraries, @@ -2711,7 +2702,7 @@ public final class Settings { if (pkg.realName != null) { serializer.attribute(null, "realName", pkg.realName); } - serializer.attribute(null, "codePath", pkg.getCodePathString()); + serializer.attribute(null, "codePath", pkg.getPathString()); serializer.attribute(null, "ft", Long.toHexString(pkg.timeStamp)); serializer.attribute(null, "it", Long.toHexString(pkg.firstInstallTime)); serializer.attribute(null, "ut", Long.toHexString(pkg.lastUpdateTime)); @@ -2753,7 +2744,7 @@ public final class Settings { if (pkg.realName != null) { serializer.attribute(null, "realName", pkg.realName); } - serializer.attribute(null, "codePath", pkg.getCodePathString()); + serializer.attribute(null, "codePath", pkg.getPathString()); if (pkg.legacyNativeLibraryPathString != null) { serializer.attribute(null, "nativeLibraryPath", pkg.legacyNativeLibraryPathString); @@ -3192,6 +3183,22 @@ public final class Settings { } } + void removeFiltersLPw(@NonNull PreferredIntentResolver pir, + @NonNull IntentFilter filter, @NonNull List<PreferredActivity> existing) { + if (PackageManagerService.DEBUG_PREFERRED) { + Slog.i(TAG, existing.size() + " preferred matches for:"); + filter.dump(new LogPrinter(Log.INFO, TAG), " "); + } + for (int i = existing.size() - 1; i >= 0; --i) { + final PreferredActivity pa = existing.get(i); + if (PackageManagerService.DEBUG_PREFERRED) { + Slog.i(TAG, "Removing preferred activity " + pa.mPref.mComponent + ":"); + pa.dump(new LogPrinter(Log.INFO, TAG), " "); + } + pir.removeFilter(pa); + } + } + private void applyDefaultPreferredActivityLPw( PackageManagerInternal pmInternal, IntentFilter tmpPa, ComponentName cn, int userId) { // The initial preferences only specify the target activity @@ -3395,8 +3402,13 @@ public final class Settings { Slog.w(TAG, "Malformed mimetype " + intent.getType() + " for " + cn); } } + final PreferredIntentResolver pir = editPreferredActivitiesLPw(userId); + final List<PreferredActivity> existing = pir.findFilters(filter); + if (existing != null) { + removeFiltersLPw(pir, filter, existing); + } PreferredActivity pa = new PreferredActivity(filter, systemMatch, set, cn, true); - editPreferredActivitiesLPw(userId).addFilter(pa); + pir.addFilter(pa); } else if (haveNonSys == null) { StringBuilder sb = new StringBuilder(); sb.append("No component "); @@ -3855,6 +3867,8 @@ public final class Settings { readDomainVerificationLPw(parser, packageSetting); } else if (tagName.equals(TAG_MIME_GROUP)) { packageSetting.mimeGroups = readMimeGroupLPw(parser, packageSetting.mimeGroups); + } else if (tagName.equals(TAG_USES_STATIC_LIB)) { + readUsesStaticLibLPw(parser, packageSetting); } else { PackageManagerService.reportSettingsProblem(Log.WARN, "Unknown element under <package>: " + parser.getName()); @@ -4541,9 +4555,9 @@ public final class Settings { pw.print(prefix); pw.print(" sharedUser="); pw.println(ps.sharedUser); } pw.print(prefix); pw.print(" pkg="); pw.println(pkg); - pw.print(prefix); pw.print(" codePath="); pw.println(ps.getCodePathString()); + pw.print(prefix); pw.print(" codePath="); pw.println(ps.getPathString()); if (permissionNames == null) { - pw.print(prefix); pw.print(" resourcePath="); pw.println(ps.getCodePathString()); + pw.print(prefix); pw.print(" resourcePath="); pw.println(ps.getPathString()); pw.print(prefix); pw.print(" legacyNativeLibraryDir="); pw.println(ps.legacyNativeLibraryPathString); pw.print(prefix); pw.print(" extractNativeLibs="); @@ -4561,10 +4575,10 @@ public final class Settings { pw.println(); if (pkg != null) { pw.print(prefix); pw.print(" versionName="); pw.println(pkg.getVersionName()); + pw.print(prefix); pw.print(" usesNonSdkApi="); pw.println(pkg.isUsesNonSdkApi()); pw.print(prefix); pw.print(" splits="); dumpSplitNames(pw, pkg); pw.println(); final int apkSigningVersion = pkg.getSigningDetails().signatureSchemeVersion; pw.print(prefix); pw.print(" apkSigningVersion="); pw.println(apkSigningVersion); - // TODO(b/135203078): Is there anything to print here with AppInfo removed? pw.print(prefix); pw.print(" applicationInfo="); pw.println(pkg.toAppInfoToString()); pw.print(prefix); pw.print(" flags="); @@ -5160,7 +5174,6 @@ public final class Settings { } void dumpComponents(PrintWriter pw, String prefix, PackageSetting ps) { - // TODO(b/135203078): ParsedComponent toString methods for dumping dumpComponents(pw, prefix, "activities:", ps.pkg.getActivities()); dumpComponents(pw, prefix, "services:", ps.pkg.getServices()); dumpComponents(pw, prefix, "receivers:", ps.pkg.getReceivers()); diff --git a/services/core/java/com/android/server/pm/StagingManager.java b/services/core/java/com/android/server/pm/StagingManager.java index 0c4eaec32ba5..462b21535371 100644 --- a/services/core/java/com/android/server/pm/StagingManager.java +++ b/services/core/java/com/android/server/pm/StagingManager.java @@ -60,7 +60,6 @@ import android.util.ArraySet; import android.util.IntArray; import android.util.Slog; import android.util.SparseArray; -import android.util.SparseBooleanArray; import android.util.SparseIntArray; import android.util.apk.ApkSignatureVerifier; @@ -1028,22 +1027,12 @@ public class StagingManager { /** * <p>Abort committed staged session - * - * <p>This method must be called while holding {@link PackageInstallerSession#mLock}. - * - * <p>The method returns {@code false} to indicate it is not safe to clean up the session from - * system yet. When it is safe, the method returns {@code true}. - * - * <p> When it is safe to clean up, {@link StagingManager} will call - * {@link PackageInstallerSession#abandon()} on the session again. - * - * @return {@code true} if it is safe to cleanup the session resources, otherwise {@code false}. */ - boolean abortCommittedSessionLocked(@NonNull PackageInstallerSession session) { + void abortCommittedSession(@NonNull PackageInstallerSession session) { int sessionId = session.sessionId; - if (session.isStagedSessionApplied()) { - Slog.w(TAG, "Cannot abort applied session : " + sessionId); - return false; + if (session.isStagedAndInTerminalState()) { + Slog.w(TAG, "Cannot abort session in final state: " + sessionId); + return; } if (!session.isDestroyed()) { throw new IllegalStateException("Committed session must be destroyed before aborting it" @@ -1051,15 +1040,7 @@ public class StagingManager { } if (getStagedSession(sessionId) == null) { Slog.w(TAG, "Session " + sessionId + " has been abandoned already"); - return false; - } - - // If pre-reboot verification is running, then return false. StagingManager will call - // abandon again when pre-reboot verification ends. - if (mPreRebootVerificationHandler.isVerificationRunning(sessionId)) { - Slog.w(TAG, "Session " + sessionId + " aborted before pre-reboot " - + "verification completed."); - return false; + return; } // A session could be marked ready once its pre-reboot verification ends @@ -1075,7 +1056,6 @@ public class StagingManager { // Session was successfully aborted from apexd (if required) and pre-reboot verification // is also complete. It is now safe to clean up the session from system. abortSession(session); - return true; } /** @@ -1264,8 +1244,8 @@ public class StagingManager { // TODO(b/136257624): Temporary API to let PMS communicate with StagingManager. When all // verification logic is extracted out of StagingManager into PMS, we can remove // this. - void notifyVerificationComplete(int sessionId) { - mPreRebootVerificationHandler.onPreRebootVerificationComplete(sessionId); + void notifyVerificationComplete(PackageInstallerSession session) { + mPreRebootVerificationHandler.onPreRebootVerificationComplete(session); } // TODO(b/136257624): Temporary API to let PMS communicate with StagingManager. When all @@ -1279,8 +1259,6 @@ public class StagingManager { // Hold session ids before handler gets ready to do the verification. private IntArray mPendingSessionIds; private boolean mIsReady; - @GuardedBy("mVerificationRunning") - private final SparseBooleanArray mVerificationRunning = new SparseBooleanArray(); PreRebootVerificationHandler(Looper looper) { super(looper); @@ -1316,7 +1294,7 @@ public class StagingManager { } if (session.isDestroyed() || session.isStagedSessionFailed()) { // No point in running verification on a destroyed/failed session - onPreRebootVerificationComplete(sessionId); + onPreRebootVerificationComplete(session); return; } switch (msg.what) { @@ -1357,15 +1335,10 @@ public class StagingManager { } PackageInstallerSession session = getStagedSession(sessionId); - synchronized (mVerificationRunning) { - // Do not start verification on a session that has been abandoned - if (session == null || session.isDestroyed()) { - return; - } + if (session != null && session.notifyStagedStartPreRebootVerification()) { Slog.d(TAG, "Starting preRebootVerification for session " + sessionId); - mVerificationRunning.put(sessionId, true); + obtainMessage(MSG_PRE_REBOOT_VERIFICATION_START, sessionId, 0).sendToTarget(); } - obtainMessage(MSG_PRE_REBOOT_VERIFICATION_START, sessionId, 0).sendToTarget(); } private void onPreRebootVerificationFailure(PackageInstallerSession session, @@ -1376,28 +1349,14 @@ public class StagingManager { // failed on next step and staging directory for session will be deleted. } session.setStagedSessionFailed(errorCode, errorMessage); - onPreRebootVerificationComplete(session.sessionId); + onPreRebootVerificationComplete(session); } // Things to do when pre-reboot verification completes for a particular sessionId - private void onPreRebootVerificationComplete(int sessionId) { - // Remove it from mVerificationRunning so that verification is considered complete - synchronized (mVerificationRunning) { - Slog.d(TAG, "Stopping preRebootVerification for session " + sessionId); - mVerificationRunning.delete(sessionId); - } - // Check if the session was destroyed while pre-reboot verification was running. If so, - // abandon it again. - PackageInstallerSession session = getStagedSession(sessionId); - if (session != null && session.isDestroyed()) { - session.abandon(); - } - } - - private boolean isVerificationRunning(int sessionId) { - synchronized (mVerificationRunning) { - return mVerificationRunning.get(sessionId); - } + private void onPreRebootVerificationComplete(PackageInstallerSession session) { + int sessionId = session.sessionId; + Slog.d(TAG, "Stopping preRebootVerification for session " + sessionId); + session.notifyStagedEndPreRebootVerification(); } private void notifyPreRebootVerification_Start_Complete(int sessionId) { @@ -1516,7 +1475,7 @@ public class StagingManager { // or activate its apex, there won't be any files to work with as they will be cleaned // up by the system as part of abandonment. If session is abandoned before this point, // then the session is already destroyed and cannot be marked ready anymore. - onPreRebootVerificationComplete(session.sessionId); + onPreRebootVerificationComplete(session); // Proactively mark session as ready before calling apexd. Although this call order // looks counter-intuitive, this is the easiest way to ensure that session won't end up 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 8000c639139f..587cb825fbb0 100644 --- a/services/core/java/com/android/server/pm/dex/ArtManagerService.java +++ b/services/core/java/com/android/server/pm/dex/ArtManagerService.java @@ -486,7 +486,7 @@ public class ArtManagerService extends android.content.pm.dex.IArtManager.Stub { public boolean compileLayouts(AndroidPackage pkg) { try { final String packageName = pkg.getPackageName(); - final String apkPath = pkg.getBaseCodePath(); + final String apkPath = pkg.getBaseApkPath(); // TODO(b/143971007): Use a cross-user directory File dataDir = PackageInfoWithoutStateUtils.getDataDir(pkg, UserHandle.myUserId()); final String outDexFile = dataDir.getAbsolutePath() + "/code_cache/compiled_view.dex"; @@ -524,7 +524,7 @@ public class ArtManagerService extends android.content.pm.dex.IArtManager.Stub { private ArrayMap<String, String> getPackageProfileNames(AndroidPackage pkg) { ArrayMap<String, String> result = new ArrayMap<>(); if (pkg.isHasCode()) { - result.put(pkg.getBaseCodePath(), ArtManager.getProfileName(null)); + result.put(pkg.getBaseApkPath(), ArtManager.getProfileName(null)); } String[] splitCodePaths = pkg.getSplitCodePaths(); diff --git a/services/core/java/com/android/server/pm/dex/DexoptUtils.java b/services/core/java/com/android/server/pm/dex/DexoptUtils.java index 6807388fa2b2..fa0183642f94 100644 --- a/services/core/java/com/android/server/pm/dex/DexoptUtils.java +++ b/services/core/java/com/android/server/pm/dex/DexoptUtils.java @@ -18,12 +18,12 @@ package com.android.server.pm.dex; import android.content.pm.ApplicationInfo; import android.content.pm.SharedLibraryInfo; -import com.android.server.pm.parsing.pkg.AndroidPackage; import android.util.Slog; import android.util.SparseArray; import com.android.internal.os.ClassLoaderFactory; import com.android.internal.util.ArrayUtils; +import com.android.server.pm.parsing.pkg.AndroidPackage; import java.io.File; import java.util.List; @@ -90,7 +90,7 @@ public final class DexoptUtils { // The splits have an implicit dependency on the base apk. // This means that we have to add the base apk file in addition to the shared libraries. - String baseApkName = new File(pkg.getBaseCodePath()).getName(); + String baseApkName = new File(pkg.getBaseApkPath()).getName(); String baseClassPath = baseApkName; // The result is stored in classLoaderContexts. @@ -401,7 +401,7 @@ public final class DexoptUtils { * Assumes that the application declares a non-null array of splits. */ private static String[] getSplitRelativeCodePaths(AndroidPackage pkg) { - String baseCodePath = new File(pkg.getBaseCodePath()).getParent(); + String baseCodePath = new File(pkg.getBaseApkPath()).getParent(); String[] splitCodePaths = pkg.getSplitCodePaths(); String[] splitRelativeCodePaths = new String[ArrayUtils.size(splitCodePaths)]; for (int i = 0; i < splitRelativeCodePaths.length; i++) { diff --git a/services/core/java/com/android/server/pm/dex/ViewCompiler.java b/services/core/java/com/android/server/pm/dex/ViewCompiler.java index 5506a523cd60..a5672664f6fd 100644 --- a/services/core/java/com/android/server/pm/dex/ViewCompiler.java +++ b/services/core/java/com/android/server/pm/dex/ViewCompiler.java @@ -40,7 +40,7 @@ public class ViewCompiler { public boolean compileLayouts(AndroidPackage pkg) { try { final String packageName = pkg.getPackageName(); - final String apkPath = pkg.getBaseCodePath(); + final String apkPath = pkg.getBaseApkPath(); // TODO(b/143971007): Use a cross-user directory File dataDir = PackageInfoWithoutStateUtils.getDataDir(pkg, UserHandle.myUserId()); final String outDexFile = dataDir.getAbsolutePath() + "/code_cache/compiled_view.dex"; diff --git a/services/core/java/com/android/server/pm/parsing/PackageCacher.java b/services/core/java/com/android/server/pm/parsing/PackageCacher.java index 99c6dd1f0312..74ec16140c94 100644 --- a/services/core/java/com/android/server/pm/parsing/PackageCacher.java +++ b/services/core/java/com/android/server/pm/parsing/PackageCacher.java @@ -79,7 +79,6 @@ public class PackageCacher { final PackageParserCacheHelper.ReadHelper helper = new PackageParserCacheHelper.ReadHelper(p); helper.startAndInstall(); - // TODO(b/135203078): Hide PackageImpl constructor? ParsedPackage pkg = new PackageImpl(p); p.recycle(); diff --git a/services/core/java/com/android/server/pm/parsing/PackageInfoUtils.java b/services/core/java/com/android/server/pm/parsing/PackageInfoUtils.java index 09b4f8967729..d695a01109ff 100644 --- a/services/core/java/com/android/server/pm/parsing/PackageInfoUtils.java +++ b/services/core/java/com/android/server/pm/parsing/PackageInfoUtils.java @@ -35,6 +35,7 @@ import android.content.pm.ProviderInfo; import android.content.pm.ServiceInfo; import android.content.pm.SharedLibraryInfo; import android.content.pm.parsing.PackageInfoWithoutStateUtils; +import android.content.pm.parsing.ParsingUtils; import android.content.pm.parsing.component.ComponentParseUtils; import android.content.pm.parsing.component.ParsedActivity; import android.content.pm.parsing.component.ParsedComponent; @@ -73,7 +74,7 @@ import java.util.Set; * @hide **/ public class PackageInfoUtils { - private static final String TAG = PackageParser2.TAG; + private static final String TAG = ParsingUtils.TAG; /** * @param pkgSetting See {@link PackageInfoUtils} for description of pkgSetting usage. @@ -207,7 +208,6 @@ public class PackageInfoUtils { public static ApplicationInfo generateApplicationInfo(AndroidPackage pkg, @PackageManager.ApplicationInfoFlags int flags, PackageUserState state, int userId, @Nullable PackageSetting pkgSetting) { - // TODO(b/135203078): Consider cases where we don't have a PkgSetting if (pkg == null) { return null; } @@ -354,7 +354,6 @@ public class PackageInfoUtils { return null; } - // TODO(b/135203078): Add setting related state info.primaryCpuAbi = AndroidPackageUtils.getPrimaryCpuAbi(pkg, pkgSetting); info.secondaryCpuAbi = AndroidPackageUtils.getSecondaryCpuAbi(pkg, pkgSetting); info.nativeLibraryDir = pkg.getNativeLibraryDir(); @@ -454,7 +453,6 @@ public class PackageInfoUtils { /** @see ApplicationInfo#flags */ public static int appInfoFlags(AndroidPackage pkg, @Nullable PackageSetting pkgSetting) { - // TODO(b/135203078): Add setting related state // @formatter:off int pkgWithoutStateFlags = PackageInfoWithoutStateUtils.appInfoFlags(pkg) | flag(pkg.isSystem(), ApplicationInfo.FLAG_SYSTEM) diff --git a/services/core/java/com/android/server/pm/parsing/PackageParser2.java b/services/core/java/com/android/server/pm/parsing/PackageParser2.java index 1145057452c2..851ddd1eae48 100644 --- a/services/core/java/com/android/server/pm/parsing/PackageParser2.java +++ b/services/core/java/com/android/server/pm/parsing/PackageParser2.java @@ -71,7 +71,7 @@ public class PackageParser2 implements AutoCloseable { return platformCompat.isChangeEnabled(changeId, appInfo); } catch (Exception e) { // This shouldn't happen, but assume enforcement if it does - Slog.wtf(ParsingUtils.TAG, "IPlatformCompat query failed", e); + Slog.wtf(TAG, "IPlatformCompat query failed", e); return true; } } @@ -87,7 +87,7 @@ public class PackageParser2 implements AutoCloseable { }); } - static final String TAG = "PackageParser2"; + private static final String TAG = ParsingUtils.TAG; private static final boolean LOG_PARSE_TIMINGS = Build.IS_DEBUGGABLE; private static final int LOG_PARSE_TIMINGS_THRESHOLD_MS = 100; diff --git a/services/core/java/com/android/server/pm/parsing/pkg/AndroidPackage.java b/services/core/java/com/android/server/pm/parsing/pkg/AndroidPackage.java index 39784cf32cea..a13680ad32af 100644 --- a/services/core/java/com/android/server/pm/parsing/pkg/AndroidPackage.java +++ b/services/core/java/com/android/server/pm/parsing/pkg/AndroidPackage.java @@ -23,7 +23,6 @@ import android.content.pm.ApplicationInfo; import android.content.pm.PackageInfo; import android.content.pm.PackageParser; import android.content.pm.PermissionGroupInfo; -import android.content.pm.SharedLibraryInfo; import android.content.pm.parsing.ParsingPackageRead; import android.content.pm.parsing.component.ParsedAttribution; import android.content.pm.parsing.component.ParsedIntentInfo; @@ -65,18 +64,16 @@ public interface AndroidPackage extends PkgAppInfo, PkgPackageInfo, ParsingPacka /** Path of base APK */ @NonNull - String getBaseCodePath(); + String getBaseApkPath(); /** Revision code of base APK */ int getBaseRevisionCode(); /** - * Path where this package was found on disk. For monolithic packages - * this is path to single base APK file; for cluster packages this is - * path to the cluster directory. + * The path to the folder containing the base APK and any installed splits. */ @NonNull - String getCodePath(); + String getPath(); /** * Permissions requested but not in the manifest. These may have been split or migrated from diff --git a/services/core/java/com/android/server/pm/parsing/pkg/AndroidPackageUtils.java b/services/core/java/com/android/server/pm/parsing/pkg/AndroidPackageUtils.java index a6f02e7842d3..0a56e1343418 100644 --- a/services/core/java/com/android/server/pm/parsing/pkg/AndroidPackageUtils.java +++ b/services/core/java/com/android/server/pm/parsing/pkg/AndroidPackageUtils.java @@ -58,7 +58,7 @@ public class AndroidPackageUtils { PackageImpl pkg = (PackageImpl) aPkg; ArrayList<String> paths = new ArrayList<>(); if (pkg.isHasCode()) { - paths.add(pkg.getBaseCodePath()); + paths.add(pkg.getBaseApkPath()); } String[] splitCodePaths = pkg.getSplitCodePaths(); if (!ArrayUtils.isEmpty(splitCodePaths)) { @@ -77,7 +77,7 @@ public class AndroidPackageUtils { public static List<String> getAllCodePaths(AndroidPackage aPkg) { PackageImpl pkg = (PackageImpl) aPkg; ArrayList<String> paths = new ArrayList<>(); - paths.add(pkg.getBaseCodePath()); + paths.add(pkg.getBaseApkPath()); String[] splitCodePaths = pkg.getSplitCodePaths(); if (!ArrayUtils.isEmpty(splitCodePaths)) { @@ -147,7 +147,7 @@ public class AndroidPackageUtils { if (pkg.isSystem() && !isUpdatedSystemApp) { return false; } - if (IncrementalManager.isIncrementalPath(pkg.getCodePath())) { + if (IncrementalManager.isIncrementalPath(pkg.getPath())) { return false; } return true; diff --git a/services/core/java/com/android/server/pm/parsing/pkg/PackageImpl.java b/services/core/java/com/android/server/pm/parsing/pkg/PackageImpl.java index 43365fa4b3e6..0e3e110bdc56 100644 --- a/services/core/java/com/android/server/pm/parsing/pkg/PackageImpl.java +++ b/services/core/java/com/android/server/pm/parsing/pkg/PackageImpl.java @@ -136,9 +136,9 @@ public final class PackageImpl extends ParsingPackageImpl implements ParsedPacka private int uid = -1; @VisibleForTesting - public PackageImpl(@NonNull String packageName, @NonNull String baseCodePath, - @NonNull String codePath, @Nullable TypedArray manifestArray, boolean isCoreApp) { - super(packageName, baseCodePath, codePath, manifestArray); + public PackageImpl(@NonNull String packageName, @NonNull String baseApkPath, + @NonNull String path, @Nullable TypedArray manifestArray, boolean isCoreApp) { + super(packageName, baseApkPath, path, manifestArray); this.manifestPackageName = this.packageName; this.coreApp = isCoreApp; } @@ -247,7 +247,7 @@ public final class PackageImpl extends ParsingPackageImpl implements ParsedPacka @Override public PackageImpl setCodePath(@NonNull String value) { - this.codePath = value; + this.mPath = value; return this; } @@ -322,7 +322,7 @@ public final class PackageImpl extends ParsingPackageImpl implements ParsedPacka @Override public PackageImpl setBaseCodePath(@NonNull String baseCodePath) { - this.baseCodePath = TextUtils.safeIntern(baseCodePath); + this.mBaseApkPath = TextUtils.safeIntern(baseCodePath); return this; } @@ -430,7 +430,7 @@ public final class PackageImpl extends ParsingPackageImpl implements ParsedPacka @Deprecated @Override public String toAppInfoToString() { - return "ApplicationInfo{" + return "PackageImpl{" + Integer.toHexString(System.identityHashCode(this)) + " " + getPackageName() + "}"; } 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 ffdcc227b7f1..1cfc5b135cfa 100644 --- a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java +++ b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java @@ -3526,7 +3526,7 @@ public class PermissionManagerService extends IPermissionManager.Stub { deniedPermissions == null || !deniedPermissions.contains(perm); if (permissionViolation) { Slog.w(TAG, "Privileged permission " + perm + " for package " - + pkg.getPackageName() + " (" + pkg.getCodePath() + + pkg.getPackageName() + " (" + pkg.getPath() + ") not in privapp-permissions whitelist"); if (RoSystemProperties.CONTROL_PRIVAPP_PERMISSIONS_ENFORCE) { @@ -3534,7 +3534,7 @@ public class PermissionManagerService extends IPermissionManager.Stub { mPrivappPermissionsViolations = new ArraySet<>(); } mPrivappPermissionsViolations.add( - pkg.getPackageName() + " (" + pkg.getCodePath() + "): " + pkg.getPackageName() + " (" + pkg.getPath() + "): " + perm); } } else { diff --git a/services/core/java/com/android/server/policy/PermissionPolicyService.java b/services/core/java/com/android/server/policy/PermissionPolicyService.java index ae2b040d0a89..e1cd9e334f4c 100644 --- a/services/core/java/com/android/server/policy/PermissionPolicyService.java +++ b/services/core/java/com/android/server/policy/PermissionPolicyService.java @@ -31,6 +31,7 @@ import android.annotation.UserIdInt; import android.app.AppOpsManager; import android.app.AppOpsManagerInternal; import android.content.BroadcastReceiver; +import android.content.ContentResolver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; @@ -242,8 +243,9 @@ public final class PermissionPolicyService extends SystemService { public void onReceive(Context context, Intent intent) { boolean hasSetupRun = true; try { - hasSetupRun = Settings.Secure.getInt(getContext().getContentResolver(), - Settings.Secure.USER_SETUP_COMPLETE) != 0; + final ContentResolver cr = getContext().getContentResolver(); + hasSetupRun = Settings.Secure.getIntForUser(cr, + Settings.Secure.USER_SETUP_COMPLETE, cr.getUserId()) != 0; } catch (Settings.SettingNotFoundException e) { // Ignore error, assume setup has run } diff --git a/services/core/java/com/android/server/slice/SliceManagerService.java b/services/core/java/com/android/server/slice/SliceManagerService.java index 5aedfc19028b..2a74b3d23829 100644 --- a/services/core/java/com/android/server/slice/SliceManagerService.java +++ b/services/core/java/com/android/server/slice/SliceManagerService.java @@ -28,6 +28,8 @@ import static android.os.Process.SYSTEM_UID; import android.Manifest.permission; import android.annotation.NonNull; import android.app.AppOpsManager; +import android.app.role.OnRoleHoldersChangedListener; +import android.app.role.RoleManager; import android.app.slice.ISliceManager; import android.app.slice.SliceSpec; import android.app.usage.UsageStatsManagerInternal; @@ -39,7 +41,9 @@ import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.content.pm.PackageManager; +import android.content.pm.PackageManagerInternal; import android.content.pm.ProviderInfo; +import android.content.pm.ResolveInfo; import android.net.Uri; import android.os.Binder; import android.os.Handler; @@ -61,6 +65,7 @@ import com.android.internal.app.AssistUtils; import com.android.server.LocalServices; import com.android.server.ServiceThread; import com.android.server.SystemService; +import com.android.server.SystemService.TargetUser; import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParserException; @@ -72,7 +77,10 @@ import java.io.ByteArrayOutputStream; import java.io.FileDescriptor; import java.io.IOException; import java.util.ArrayList; +import java.util.List; import java.util.Objects; +import java.util.concurrent.Executor; +import java.util.function.Supplier; public class SliceManagerService extends ISliceManager.Stub { @@ -80,13 +88,16 @@ public class SliceManagerService extends ISliceManager.Stub { private final Object mLock = new Object(); private final Context mContext; + private final PackageManagerInternal mPackageManagerInternal; private final AppOpsManager mAppOps; private final AssistUtils mAssistUtils; @GuardedBy("mLock") private final ArrayMap<Uri, PinnedSliceState> mPinnedSlicesByUri = new ArrayMap<>(); @GuardedBy("mLock") - private final SparseArray<String> mLastAssistantPackage = new SparseArray<>(); + private final SparseArray<PackageMatchingCache> mAssistantLookup = new SparseArray<>(); + @GuardedBy("mLock") + private final SparseArray<PackageMatchingCache> mHomeLookup = new SparseArray<>(); private final Handler mHandler; private final SlicePermissionManager mPermissions; @@ -99,6 +110,8 @@ public class SliceManagerService extends ISliceManager.Stub { @VisibleForTesting SliceManagerService(Context context, Looper looper) { mContext = context; + mPackageManagerInternal = Objects.requireNonNull( + LocalServices.getService(PackageManagerInternal.class)); mAppOps = context.getSystemService(AppOpsManager.class); mAssistUtils = new AssistUtils(context); mHandler = new Handler(looper); @@ -111,6 +124,7 @@ public class SliceManagerService extends ISliceManager.Stub { filter.addAction(Intent.ACTION_PACKAGE_DATA_CLEARED); filter.addAction(Intent.ACTION_PACKAGE_REMOVED); filter.addDataScheme("package"); + mRoleObserver = new RoleObserver(); mContext.registerReceiverAsUser(mReceiver, UserHandle.ALL, filter, null, mHandler); } @@ -160,7 +174,8 @@ public class SliceManagerService extends ISliceManager.Stub { mHandler.post(() -> { if (slicePkg != null && !Objects.equals(pkg, slicePkg)) { mAppUsageStats.reportEvent(slicePkg, user, - isAssistant(pkg, user) ? SLICE_PINNED_PRIV : SLICE_PINNED); + isAssistant(pkg, user) || isDefaultHomeApp(pkg, user) + ? SLICE_PINNED_PRIV : SLICE_PINNED); } }); } @@ -425,19 +440,38 @@ public class SliceManagerService extends ISliceManager.Stub { private boolean hasFullSliceAccess(String pkg, int userId) { long ident = Binder.clearCallingIdentity(); try { - return isAssistant(pkg, userId) || isGrantedFullAccess(pkg, userId); + boolean ret = isDefaultHomeApp(pkg, userId) || isAssistant(pkg, userId) + || isGrantedFullAccess(pkg, userId); + return ret; } finally { Binder.restoreCallingIdentity(ident); } } private boolean isAssistant(String pkg, int userId) { - if (pkg == null) return false; - if (!pkg.equals(mLastAssistantPackage.get(userId))) { - // Failed on cached value, try updating. - mLastAssistantPackage.put(userId, getAssistant(userId)); + return getAssistantMatcher(userId).matches(pkg); + } + + private boolean isDefaultHomeApp(String pkg, int userId) { + return getHomeMatcher(userId).matches(pkg); + } + + private PackageMatchingCache getAssistantMatcher(int userId) { + PackageMatchingCache matcher = mAssistantLookup.get(userId); + if (matcher == null) { + matcher = new PackageMatchingCache(() -> getAssistant(userId)); + mAssistantLookup.put(userId, matcher); } - return pkg.equals(mLastAssistantPackage.get(userId)); + return matcher; + } + + private PackageMatchingCache getHomeMatcher(int userId) { + PackageMatchingCache matcher = mHomeLookup.get(userId); + if (matcher == null) { + matcher = new PackageMatchingCache(() -> getDefaultHome(userId)); + mHomeLookup.put(userId, matcher); + } + return matcher; } private String getAssistant(int userId) { @@ -448,6 +482,111 @@ public class SliceManagerService extends ISliceManager.Stub { return cn.getPackageName(); } + /** + * A cached value of the default home app + */ + private String mCachedDefaultHome = null; + + // Based on getDefaultHome in ShortcutService. + // TODO: Unify if possible + @VisibleForTesting + protected String getDefaultHome(int userId) { + + // Set VERIFY to true to run the cache in "shadow" mode for cache + // testing. Do not commit set to true; + final boolean VERIFY = false; + + if (mCachedDefaultHome != null) { + if (!VERIFY) { + return mCachedDefaultHome; + } + } + + final long token = Binder.clearCallingIdentity(); + try { + final List<ResolveInfo> allHomeCandidates = new ArrayList<>(); + + // Default launcher from package manager. + final ComponentName defaultLauncher = mPackageManagerInternal + .getHomeActivitiesAsUser(allHomeCandidates, userId); + + ComponentName detected = defaultLauncher; + + // Cache the default launcher. It is not a problem if the + // launcher is null - eventually, the default launcher will be + // set to something non-null. + mCachedDefaultHome = ((detected != null) ? detected.getPackageName() : null); + + if (detected == null) { + // If we reach here, that means it's the first check since the user was created, + // and there's already multiple launchers and there's no default set. + // Find the system one with the highest priority. + // (We need to check the priority too because of FallbackHome in Settings.) + // If there's no system launcher yet, then no one can access slices, until + // the user explicitly sets one. + final int size = allHomeCandidates.size(); + + int lastPriority = Integer.MIN_VALUE; + for (int i = 0; i < size; i++) { + final ResolveInfo ri = allHomeCandidates.get(i); + if (!ri.activityInfo.applicationInfo.isSystemApp()) { + continue; + } + if (ri.priority < lastPriority) { + continue; + } + detected = ri.activityInfo.getComponentName(); + lastPriority = ri.priority; + } + } + final String ret = ((detected != null) ? detected.getPackageName() : null); + if (VERIFY) { + if (mCachedDefaultHome != null && !mCachedDefaultHome.equals(ret)) { + Slog.e(TAG, "getDefaultHome() cache failure, is " + + mCachedDefaultHome + " should be " + ret); + } + } + return ret; + } finally { + Binder.restoreCallingIdentity(token); + } + } + + public void invalidateCachedDefaultHome() { + mCachedDefaultHome = null; + } + + /** + * Listen for changes in the roles, and invalidate the cached default + * home as necessary. + */ + private RoleObserver mRoleObserver; + + class RoleObserver implements OnRoleHoldersChangedListener { + private RoleManager mRm; + private final Executor mExecutor; + + RoleObserver() { + mExecutor = mContext.getMainExecutor(); + register(); + } + + public void register() { + mRm = mContext.getSystemService(RoleManager.class); + if (mRm != null) { + mRm.addOnRoleHoldersChangedListenerAsUser(mExecutor, this, UserHandle.ALL); + invalidateCachedDefaultHome(); + } + } + + @Override + public void onRoleHoldersChanged(@NonNull String roleName, @NonNull UserHandle user) { + if (RoleManager.ROLE_HOME.equals(roleName)) { + invalidateCachedDefaultHome(); + } + } + } + private boolean isGrantedFullAccess(String pkg, int userId) { return mPermissions.hasFullAccess(pkg, userId); } @@ -496,6 +635,30 @@ public class SliceManagerService extends ISliceManager.Stub { return mPermissions.getAllPackagesGranted(pkg); } + /** + * Holder that caches a package that has access to a slice. + */ + static class PackageMatchingCache { + + private final Supplier<String> mPkgSource; + private String mCurrentPkg; + + public PackageMatchingCache(Supplier<String> pkgSource) { + mPkgSource = pkgSource; + } + + public boolean matches(String pkgCandidate) { + if (pkgCandidate == null) return false; + + if (Objects.equals(pkgCandidate, mCurrentPkg)) { + return true; + } + // Failed on cached value, try updating. + mCurrentPkg = mPkgSource.get(); + return Objects.equals(pkgCandidate, mCurrentPkg); + } + } + public static class Lifecycle extends SystemService { private SliceManagerService mService; diff --git a/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java b/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java index f74cd611e9d0..0314cf8605bc 100644 --- a/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java +++ b/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java @@ -3005,10 +3005,10 @@ public class StatsPullAtomService extends SystemService { Settings.Secure.FACE_UNLOCK_KEYGUARD_ENABLED, 1, userId); int unlockDismissesKeyguard = Settings.Secure.getIntForUser( mContext.getContentResolver(), - Settings.Secure.FACE_UNLOCK_DISMISSES_KEYGUARD, 0, userId); + Settings.Secure.FACE_UNLOCK_DISMISSES_KEYGUARD, 1, userId); int unlockAttentionRequired = Settings.Secure.getIntForUser( mContext.getContentResolver(), - Settings.Secure.FACE_UNLOCK_ATTENTION_REQUIRED, 1, userId); + Settings.Secure.FACE_UNLOCK_ATTENTION_REQUIRED, 0, userId); int unlockAppEnabled = Settings.Secure.getIntForUser( mContext.getContentResolver(), Settings.Secure.FACE_UNLOCK_APP_ENABLED, 1, userId); diff --git a/services/core/java/com/android/server/telecom/InternalServiceRepository.java b/services/core/java/com/android/server/telecom/InternalServiceRepository.java new file mode 100644 index 000000000000..76ea5c788bd7 --- /dev/null +++ b/services/core/java/com/android/server/telecom/InternalServiceRepository.java @@ -0,0 +1,63 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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.telecom; + +import android.content.Context; +import android.os.Binder; +import android.os.Process; + +import com.android.internal.telecom.IDeviceIdleControllerAdapter; +import com.android.internal.telecom.IInternalServiceRetriever; +import com.android.server.DeviceIdleInternal; + +/** + * The Telecom APK can not access services stored in LocalService directly and since it is in the + * SYSTEM process, it also can not use the *Manager interfaces + * (see {@link Context#enforceCallingPermission(String, String)}). Instead, we must wrap these local + * services in binder interfaces to allow Telecom access. + */ +public class InternalServiceRepository extends IInternalServiceRetriever.Stub { + + private final IDeviceIdleControllerAdapter.Stub mDeviceIdleControllerAdapter = + new IDeviceIdleControllerAdapter.Stub() { + @Override + public void exemptAppTemporarilyForEvent(String packageName, long duration, int userHandle, + String reason) { + mDeviceIdleController.addPowerSaveTempWhitelistApp(Process.myUid(), packageName, + duration, userHandle, true /*sync*/, reason); + } + }; + + private final DeviceIdleInternal mDeviceIdleController; + + public InternalServiceRepository(DeviceIdleInternal deviceIdleController) { + mDeviceIdleController = deviceIdleController; + } + + @Override + public IDeviceIdleControllerAdapter getDeviceIdleController() { + ensureSystemProcess(); + return mDeviceIdleControllerAdapter; + } + + private void ensureSystemProcess() { + if (Binder.getCallingUid() != Process.SYSTEM_UID) { + // Correctness check - this should never happen. + throw new SecurityException("SYSTEM ONLY API."); + } + } +} diff --git a/services/core/java/com/android/server/telecom/OWNERS b/services/core/java/com/android/server/telecom/OWNERS new file mode 100644 index 000000000000..39be2c1aecc4 --- /dev/null +++ b/services/core/java/com/android/server/telecom/OWNERS @@ -0,0 +1,6 @@ +breadley@google.com +hallliu@google.com +tgunn@google.com +xiaotonj@google.com +shuoq@google.com +rgreenwalt@google.com diff --git a/services/core/java/com/android/server/telecom/TelecomLoaderService.java b/services/core/java/com/android/server/telecom/TelecomLoaderService.java index a853529f49e4..52ad893a9ace 100644 --- a/services/core/java/com/android/server/telecom/TelecomLoaderService.java +++ b/services/core/java/com/android/server/telecom/TelecomLoaderService.java @@ -35,7 +35,10 @@ import android.util.IntArray; import android.util.Slog; import com.android.internal.annotations.GuardedBy; +import com.android.internal.telecom.ITelecomLoader; +import com.android.internal.telecom.ITelecomService; import com.android.internal.telephony.SmsApplication; +import com.android.server.DeviceIdleInternal; import com.android.server.LocalServices; import com.android.server.SystemService; import com.android.server.pm.UserManagerService; @@ -53,16 +56,13 @@ public class TelecomLoaderService extends SystemService { @Override public void onServiceConnected(ComponentName name, IBinder service) { // Normally, we would listen for death here, but since telecom runs in the same process - // as this loader (process="system") thats redundant here. + // as this loader (process="system") that's redundant here. try { - service.linkToDeath(new IBinder.DeathRecipient() { - @Override - public void binderDied() { - connectToTelecom(); - } - }, 0); + ITelecomLoader telecomLoader = ITelecomLoader.Stub.asInterface(service); + ITelecomService telecomService = telecomLoader.createTelecomService(mServiceRepo); + SmsApplication.getDefaultMmsApplication(mContext, false); - ServiceManager.addService(Context.TELECOM_SERVICE, service); + ServiceManager.addService(Context.TELECOM_SERVICE, telecomService.asBinder()); synchronized (mLock) { final PermissionManagerServiceInternal permissionManager = @@ -114,6 +114,8 @@ public class TelecomLoaderService extends SystemService { @GuardedBy("mLock") private TelecomServiceConnection mServiceConnection; + private InternalServiceRepository mServiceRepo; + public TelecomLoaderService(Context context) { super(context); mContext = context; @@ -129,6 +131,8 @@ public class TelecomLoaderService extends SystemService { if (phase == PHASE_ACTIVITY_MANAGER_READY) { registerDefaultAppNotifier(); registerCarrierConfigChangedReceiver(); + // core services will have already been loaded. + setupServiceRepository(); connectToTelecom(); } } @@ -154,6 +158,11 @@ public class TelecomLoaderService extends SystemService { } } + private void setupServiceRepository() { + DeviceIdleInternal deviceIdleInternal = getLocalService(DeviceIdleInternal.class); + mServiceRepo = new InternalServiceRepository(deviceIdleInternal); + } + private void registerDefaultAppProviders() { final PermissionManagerServiceInternal permissionManager = diff --git a/services/core/java/com/android/server/timezonedetector/ConfigurationInternal.java b/services/core/java/com/android/server/timezonedetector/ConfigurationInternal.java index aee3d8d3499b..b68c54fc6365 100644 --- a/services/core/java/com/android/server/timezonedetector/ConfigurationInternal.java +++ b/services/core/java/com/android/server/timezonedetector/ConfigurationInternal.java @@ -25,6 +25,7 @@ import android.annotation.NonNull; import android.annotation.UserIdInt; import android.app.timezonedetector.TimeZoneCapabilities; import android.app.timezonedetector.TimeZoneConfiguration; +import android.os.UserHandle; import java.util.Objects; @@ -56,6 +57,12 @@ public final class ConfigurationInternal { return mUserId; } + /** Returns the handle of the user this configuration is associated with. */ + @NonNull + public UserHandle getUserHandle() { + return UserHandle.of(mUserId); + } + /** Returns true if the user allowed to modify time zone configuration. */ public boolean isUserConfigAllowed() { return mUserConfigAllowed; @@ -198,13 +205,13 @@ public final class ConfigurationInternal { @Override public String toString() { - return "TimeZoneDetectorConfiguration{" + return "ConfigurationInternal{" + "mUserId=" + mUserId - + "mUserConfigAllowed=" + mUserConfigAllowed - + "mAutoDetectionSupported=" + mAutoDetectionSupported - + "mAutoDetectionEnabled=" + mAutoDetectionEnabled - + "mLocationEnabled=" + mLocationEnabled - + "mGeoDetectionEnabled=" + mGeoDetectionEnabled + + ", mUserConfigAllowed=" + mUserConfigAllowed + + ", mAutoDetectionSupported=" + mAutoDetectionSupported + + ", mAutoDetectionEnabled=" + mAutoDetectionEnabled + + ", mLocationEnabled=" + mLocationEnabled + + ", mGeoDetectionEnabled=" + mGeoDetectionEnabled + '}'; } diff --git a/services/core/java/com/android/server/timezonedetector/TimeZoneDetectorShellCommand.java b/services/core/java/com/android/server/timezonedetector/TimeZoneDetectorShellCommand.java index 3230ef192b4b..a8d5c0282025 100644 --- a/services/core/java/com/android/server/timezonedetector/TimeZoneDetectorShellCommand.java +++ b/services/core/java/com/android/server/timezonedetector/TimeZoneDetectorShellCommand.java @@ -23,7 +23,7 @@ import java.io.PrintWriter; import java.util.function.Consumer; import java.util.function.Supplier; -/** Implemented the shell command interface for {@link TimeZoneDetectorService}. */ +/** Implements the shell command interface for {@link TimeZoneDetectorService}. */ class TimeZoneDetectorShellCommand extends ShellCommand { private final TimeZoneDetectorService mInterface; diff --git a/services/core/java/com/android/server/trust/TrustManagerService.java b/services/core/java/com/android/server/trust/TrustManagerService.java index 386f390c6cb9..89b108c24630 100644 --- a/services/core/java/com/android/server/trust/TrustManagerService.java +++ b/services/core/java/com/android/server/trust/TrustManagerService.java @@ -126,6 +126,8 @@ public class TrustManagerService extends SystemService { private static final String TRUST_TIMEOUT_ALARM_TAG = "TrustManagerService.trustTimeoutForUser"; private static final long TRUST_TIMEOUT_IN_MILLIS = 4 * 60 * 60 * 1000; + private static final String PRIV_NAMESPACE = "http://schemas.android.com/apk/prv/res/android"; + private final ArraySet<AgentInfo> mActiveAgents = new ArraySet<>(); private final ArrayList<ITrustListener> mTrustListeners = new ArrayList<>(); private final Receiver mReceiver = new Receiver(); @@ -811,8 +813,8 @@ public class TrustManagerService extends SystemService { TypedArray sa = res .obtainAttributes(attrs, com.android.internal.R.styleable.TrustAgent); cn = sa.getString(com.android.internal.R.styleable.TrustAgent_settingsActivity); - canUnlockProfile = sa.getBoolean( - com.android.internal.R.styleable.TrustAgent_unlockProfile, false); + canUnlockProfile = attrs.getAttributeBooleanValue( + PRIV_NAMESPACE, "unlockProfile", false); sa.recycle(); } catch (PackageManager.NameNotFoundException e) { caughtException = e; diff --git a/services/core/java/com/android/server/uri/UriGrantsManagerService.java b/services/core/java/com/android/server/uri/UriGrantsManagerService.java index 0b0bb7059f3b..53d51463295f 100644 --- a/services/core/java/com/android/server/uri/UriGrantsManagerService.java +++ b/services/core/java/com/android/server/uri/UriGrantsManagerService.java @@ -115,7 +115,7 @@ public class UriGrantsManagerService extends IUriGrantsManager.Stub { private static final String TAG = "UriGrantsManagerService"; // Maximum number of persisted Uri grants a package is allowed private static final int MAX_PERSISTED_URI_GRANTS = 512; - private static final boolean ENABLE_DYNAMIC_PERMISSIONS = true; + private static final boolean ENABLE_DYNAMIC_PERMISSIONS = false; private final Object mLock = new Object(); private final H mH; diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java index 56e404c8f409..ad281247a719 100644 --- a/services/core/java/com/android/server/wm/ActivityRecord.java +++ b/services/core/java/com/android/server/wm/ActivityRecord.java @@ -133,6 +133,7 @@ import static com.android.server.wm.ActivityRecordProto.LAST_SURFACE_SHOWING; import static com.android.server.wm.ActivityRecordProto.NAME; import static com.android.server.wm.ActivityRecordProto.NUM_DRAWN_WINDOWS; import static com.android.server.wm.ActivityRecordProto.NUM_INTERESTING_WINDOWS; +import static com.android.server.wm.ActivityRecordProto.PIP_AUTO_ENTER_ALLOWED; import static com.android.server.wm.ActivityRecordProto.PROC_ID; import static com.android.server.wm.ActivityRecordProto.REPORTED_DRAWN; import static com.android.server.wm.ActivityRecordProto.REPORTED_VISIBLE; @@ -4627,18 +4628,26 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A mDisplayContent.mUnknownAppVisibilityController.notifyLaunched(this); } - /** @return {@code true} if this activity should be made visible. */ - boolean shouldBeVisible(boolean behindFullscreenActivity, boolean ignoringKeyguard) { + private void updateVisibleIgnoringKeyguard(boolean behindFullscreenActivity) { // Check whether activity should be visible without Keyguard influence visibleIgnoringKeyguard = (!behindFullscreenActivity || mLaunchTaskBehind) && okToShowLocked(); + } + + /** @return {@code true} if this activity should be made visible. */ + private boolean shouldBeVisible(boolean behindFullscreenActivity, boolean ignoringKeyguard) { + updateVisibleIgnoringKeyguard(behindFullscreenActivity); if (ignoringKeyguard) { return visibleIgnoringKeyguard; } + return shouldBeVisibleUnchecked(); + } + + boolean shouldBeVisibleUnchecked() { final Task stack = getRootTask(); - if (stack == null) { + if (stack == null || !visibleIgnoringKeyguard) { return false; } @@ -4651,26 +4660,30 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A return false; } - // Check if the activity is on a sleeping display, and if it can turn it ON. - if (mDisplayContent.isSleeping()) { - final boolean canTurnScreenOn = !mSetToSleep || canTurnScreenOn() - || canShowWhenLocked() || containsDismissKeyguardWindow(); - if (!canTurnScreenOn) { - return false; - } + // Check if the activity is on a sleeping display + // TODO b/163993448 mSetToSleep is required when restarting an existing activity, try to + // remove it if possible. + if (mSetToSleep && mDisplayContent.isSleeping()) { + return false; } + return mStackSupervisor.getKeyguardController().checkKeyguardVisibility(this); + } + + void updateVisibility(boolean behindFullscreenActivity) { + updateVisibleIgnoringKeyguard(behindFullscreenActivity); + final Task task = getRootTask(); + if (task == null || !visibleIgnoringKeyguard) { + return; + } // Now check whether it's really visible depending on Keyguard state, and update // {@link ActivityStack} internal states. // Inform the method if this activity is the top activity of this stack, but exclude the // case where this is the top activity in a pinned stack. - final boolean isTop = this == stack.getTopNonFinishingActivity(); - final boolean isTopNotPinnedStack = stack.isAttached() - && stack.getDisplayArea().isTopNotFinishNotPinnedStack(stack); - final boolean visibleIgnoringDisplayStatus = stack.checkKeyguardVisibility(this, - visibleIgnoringKeyguard, isTop && isTopNotPinnedStack); - - return visibleIgnoringDisplayStatus; + final boolean isTop = this == task.getTopNonFinishingActivity(); + final boolean isTopNotPinnedStack = task.isAttached() + && task.getDisplayArea().isTopNotFinishNotPinnedStack(task); + task.updateKeyguardVisibility(this, isTop && isTopNotPinnedStack); } boolean shouldBeVisible() { @@ -4741,6 +4754,11 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A // returns. Just need to confirm this reasoning makes sense. final boolean deferHidingClient = canEnterPictureInPicture && !isState(STARTED, STOPPING, STOPPED, PAUSED); + if (deferHidingClient && pictureInPictureArgs.isAutoEnterAllowed()) { + // Go ahead and just put the activity in pip if it supports auto-pip. + mAtmService.enterPictureInPictureMode(this, pictureInPictureArgs); + return; + } setDeferHidingClient(deferHidingClient); setVisibility(false); @@ -6637,8 +6655,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A final Configuration resolvedConfig = getResolvedOverrideConfiguration(); final Rect resolvedBounds = resolvedConfig.windowConfiguration.getBounds(); final int requestedOrientation = getRequestedConfigurationOrientation(); - final boolean orientationRequested = requestedOrientation != ORIENTATION_UNDEFINED - && !mDisplayContent.ignoreRotationForApps(); + final boolean orientationRequested = requestedOrientation != ORIENTATION_UNDEFINED; final int orientation = orientationRequested ? requestedOrientation : newParentConfiguration.orientation; @@ -7532,10 +7549,8 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A return false; } final Task stack = getRootTask(); - return stack != null - && !stack.inMultiWindowMode() - && stack.checkKeyguardVisibility(this, true /* shouldBeVisible */, - stack.topRunningActivity() == this /* isTop */); + return stack != null && !stack.inMultiWindowMode() + && mStackSupervisor.getKeyguardController().checkKeyguardVisibility(this); } void setTurnScreenOn(boolean turnScreenOn) { @@ -7678,6 +7693,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A if (hasProcess()) { proto.write(PROC_ID, app.getPid()); } + proto.write(PIP_AUTO_ENTER_ALLOWED, pictureInPictureArgs.isAutoEnterAllowed()); } @Override diff --git a/services/core/java/com/android/server/wm/ActivityStackSupervisor.java b/services/core/java/com/android/server/wm/ActivityStackSupervisor.java index 9df192b76f9a..5196416e2cd3 100644 --- a/services/core/java/com/android/server/wm/ActivityStackSupervisor.java +++ b/services/core/java/com/android/server/wm/ActivityStackSupervisor.java @@ -759,8 +759,7 @@ public class ActivityStackSupervisor implements RecentTasks.Callbacks { false /* markFrozenIfConfigChanged */, true /* deferResume */); } - if (r.getRootTask().checkKeyguardVisibility(r, true /* shouldBeVisible */, - true /* isTop */) && r.allowMoveToFront()) { + if (mKeyguardController.checkKeyguardVisibility(r) && r.allowMoveToFront()) { // We only set the visibility to true if the activity is not being launched in // background, and is allowed to be visible based on keyguard state. This avoids // setting this into motion in window manager that is later cancelled due to later @@ -2298,11 +2297,15 @@ public class ActivityStackSupervisor implements RecentTasks.Callbacks { } /** Ends a batch of visibility updates. */ - void endActivityVisibilityUpdate() { - mVisibilityTransactionDepth--; - if (mVisibilityTransactionDepth == 0) { + void endActivityVisibilityUpdate(ActivityRecord starting, int configChanges, + boolean preserveWindows, boolean notifyClients) { + if (mVisibilityTransactionDepth == 1) { getKeyguardController().visibilitiesUpdated(); + // commit visibility to activities + mRootWindowContainer.commitActivitiesVisible(starting, configChanges, preserveWindows, + notifyClients); } + mVisibilityTransactionDepth--; } /** Returns {@code true} if the caller is on the path to update visibility. */ diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java index 505233cd8a4a..2657eb29b06c 100644 --- a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java +++ b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java @@ -137,6 +137,7 @@ import android.app.ActivityManager; import android.app.ActivityManagerInternal; import android.app.ActivityOptions; import android.app.ActivityTaskManager; +import android.app.ActivityTaskManager.RootTaskInfo; import android.app.ActivityThread; import android.app.AlertDialog; import android.app.AppGlobals; @@ -253,7 +254,6 @@ import com.android.internal.util.function.pooled.PooledLambda; import com.android.server.AttributeCache; import com.android.server.LocalServices; import com.android.server.SystemService; -import com.android.server.SystemService.TargetUser; import com.android.server.SystemServiceManager; import com.android.server.UiThread; import com.android.server.Watchdog; @@ -2159,14 +2159,14 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { } @Override - public ActivityManager.StackInfo getFocusedStackInfo() throws RemoteException { - enforceCallerIsRecentsOrHasPermission(MANAGE_ACTIVITY_STACKS, "getStackInfo()"); + public RootTaskInfo getFocusedRootTaskInfo() throws RemoteException { + enforceCallerIsRecentsOrHasPermission(MANAGE_ACTIVITY_STACKS, "getFocusedRootTaskInfo()"); long ident = Binder.clearCallingIdentity(); try { synchronized (mGlobalLock) { Task focusedStack = getTopDisplayFocusedStack(); if (focusedStack != null) { - return mRootWindowContainer.getStackInfo(focusedStack.mTaskId); + return mRootWindowContainer.getRootTaskInfo(focusedStack.mTaskId); } return null; } @@ -2894,14 +2894,13 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { } } - // TODO(148895075): deprecate and replace with task equivalents @Override - public List<ActivityManager.StackInfo> getAllStackInfos() { - enforceCallerIsRecentsOrHasPermission(MANAGE_ACTIVITY_STACKS, "getAllStackInfos()"); + public List<RootTaskInfo> getAllRootTaskInfos() { + enforceCallerIsRecentsOrHasPermission(MANAGE_ACTIVITY_STACKS, "getAllRootTaskInfos()"); long ident = Binder.clearCallingIdentity(); try { synchronized (mGlobalLock) { - return mRootWindowContainer.getAllStackInfos(INVALID_DISPLAY); + return mRootWindowContainer.getAllRootTaskInfos(INVALID_DISPLAY); } } finally { Binder.restoreCallingIdentity(ident); @@ -2909,26 +2908,26 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { } @Override - public ActivityManager.StackInfo getStackInfo(int windowingMode, int activityType) { - enforceCallerIsRecentsOrHasPermission(MANAGE_ACTIVITY_STACKS, "getStackInfo()"); + public RootTaskInfo getRootTaskInfo(int windowingMode, int activityType) { + enforceCallerIsRecentsOrHasPermission(MANAGE_ACTIVITY_STACKS, "getRootTaskInfo()"); long ident = Binder.clearCallingIdentity(); try { synchronized (mGlobalLock) { - return mRootWindowContainer.getStackInfo(windowingMode, activityType); + return mRootWindowContainer.getRootTaskInfo(windowingMode, activityType); } } finally { Binder.restoreCallingIdentity(ident); } } - // TODO(148895075): deprecate and replace with task equivalents @Override - public List<ActivityManager.StackInfo> getAllStackInfosOnDisplay(int displayId) { - enforceCallerIsRecentsOrHasPermission(MANAGE_ACTIVITY_STACKS, "getAllStackInfos()"); + public List<RootTaskInfo> getAllRootTaskInfosOnDisplay(int displayId) { + enforceCallerIsRecentsOrHasPermission(MANAGE_ACTIVITY_STACKS, + "getAllRootTaskInfosOnDisplay()"); long ident = Binder.clearCallingIdentity(); try { synchronized (mGlobalLock) { - return mRootWindowContainer.getAllStackInfos(displayId); + return mRootWindowContainer.getAllRootTaskInfos(displayId); } } finally { Binder.restoreCallingIdentity(ident); @@ -2936,13 +2935,13 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { } @Override - public ActivityManager.StackInfo getStackInfoOnDisplay(int windowingMode, int activityType, + public RootTaskInfo getRootTaskInfoOnDisplay(int windowingMode, int activityType, int displayId) { - enforceCallerIsRecentsOrHasPermission(MANAGE_ACTIVITY_STACKS, "getStackInfo()"); + enforceCallerIsRecentsOrHasPermission(MANAGE_ACTIVITY_STACKS, "getRootTaskInfoOnDisplay()"); long ident = Binder.clearCallingIdentity(); try { synchronized (mGlobalLock) { - return mRootWindowContainer.getStackInfo(windowingMode, activityType, displayId); + return mRootWindowContainer.getRootTaskInfo(windowingMode, activityType, displayId); } } finally { Binder.restoreCallingIdentity(ident); @@ -4059,6 +4058,60 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { && r.getRootTask().isInTask(r) != null; } + /** + * Puts the given activity in picture in picture mode if possible. + * + * @return true if the activity is now in picture-in-picture mode, or false if it could not + * enter picture-in-picture mode. + */ + boolean enterPictureInPictureMode(ActivityRecord r, final PictureInPictureParams params) { + // If the activity is already in picture in picture mode, then just return early + if (isInPictureInPictureMode(r)) { + return true; + } + + // Activity supports picture-in-picture, now check that we can enter PiP at this + // point, if it is + if (!r.checkEnterPictureInPictureState("enterPictureInPictureMode", + false /* beforeStopping */)) { + return false; + } + + final Runnable enterPipRunnable = () -> { + synchronized (mGlobalLock) { + if (r.getParent() == null) { + Slog.e(TAG, "Skip enterPictureInPictureMode, destroyed " + r); + return; + } + // Only update the saved args from the args that are set + r.setPictureInPictureParams(params); + final float aspectRatio = r.pictureInPictureArgs.getAspectRatio(); + final List<RemoteAction> actions = r.pictureInPictureArgs.getActions(); + mRootWindowContainer.moveActivityToPinnedStack( + r, "enterPictureInPictureMode"); + final Task stack = r.getRootTask(); + stack.setPictureInPictureAspectRatio(aspectRatio); + stack.setPictureInPictureActions(actions); + } + }; + + if (isKeyguardLocked()) { + // If the keyguard is showing or occluded, then try and dismiss it before + // entering picture-in-picture (this will prompt the user to authenticate if the + // device is currently locked). + dismissKeyguard(r.appToken, new KeyguardDismissCallback() { + @Override + public void onDismissSucceeded() { + mH.post(enterPipRunnable); + } + }, null /* message */); + } else { + // Enter picture in picture immediately otherwise + enterPipRunnable.run(); + } + return true; + } + @Override public boolean enterPictureInPictureMode(IBinder token, final PictureInPictureParams params) { final long origId = Binder.clearCallingIdentity(); @@ -4066,52 +4119,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { synchronized (mGlobalLock) { final ActivityRecord r = ensureValidPictureInPictureActivityParamsLocked( "enterPictureInPictureMode", token, params); - - // If the activity is already in picture in picture mode, then just return early - if (isInPictureInPictureMode(r)) { - return true; - } - - // Activity supports picture-in-picture, now check that we can enter PiP at this - // point, if it is - if (!r.checkEnterPictureInPictureState("enterPictureInPictureMode", - false /* beforeStopping */)) { - return false; - } - - final Runnable enterPipRunnable = () -> { - synchronized (mGlobalLock) { - if (r.getParent() == null) { - Slog.e(TAG, "Skip enterPictureInPictureMode, destroyed " + r); - return; - } - // Only update the saved args from the args that are set - r.setPictureInPictureParams(params); - final float aspectRatio = r.pictureInPictureArgs.getAspectRatio(); - final List<RemoteAction> actions = r.pictureInPictureArgs.getActions(); - mRootWindowContainer.moveActivityToPinnedStack( - r, "enterPictureInPictureMode"); - final Task stack = r.getRootTask(); - stack.setPictureInPictureAspectRatio(aspectRatio); - stack.setPictureInPictureActions(actions); - } - }; - - if (isKeyguardLocked()) { - // If the keyguard is showing or occluded, then try and dismiss it before - // entering picture-in-picture (this will prompt the user to authenticate if the - // device is currently locked). - dismissKeyguard(token, new KeyguardDismissCallback() { - @Override - public void onDismissSucceeded() { - mH.post(enterPipRunnable); - } - }, null /* message */); - } else { - // Enter picture in picture immediately otherwise - enterPipRunnable.run(); - } - return true; + return enterPictureInPictureMode(r, params); } } finally { Binder.restoreCallingIdentity(origId); @@ -4857,6 +4865,11 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { "Requested PIP on an activity that doesn't support it"); } + if (activity.pictureInPictureArgs.isAutoEnterAllowed()) { + enterPictureInPictureMode(activity, activity.pictureInPictureArgs); + return; + } + try { final ClientTransaction transaction = ClientTransaction.obtain( activity.app.getThread(), diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java index aa8069a76330..4db121b6ea33 100644 --- a/services/core/java/com/android/server/wm/DisplayContent.java +++ b/services/core/java/com/android/server/wm/DisplayContent.java @@ -28,7 +28,6 @@ import static android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW; import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED; import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_SECONDARY; import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED; -import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_USER; import static android.content.res.Configuration.ORIENTATION_LANDSCAPE; import static android.content.res.Configuration.ORIENTATION_PORTRAIT; import static android.content.res.Configuration.ORIENTATION_UNDEFINED; @@ -36,20 +35,21 @@ import static android.os.Build.VERSION_CODES.N; import static android.os.Trace.TRACE_TAG_WINDOW_MANAGER; import static android.util.DisplayMetrics.DENSITY_DEFAULT; import static android.view.Display.DEFAULT_DISPLAY; +import static android.view.Display.FLAG_CAN_SHOW_WITH_INSECURE_KEYGUARD; import static android.view.Display.FLAG_PRIVATE; import static android.view.Display.FLAG_SHOULD_SHOW_SYSTEM_DECORATIONS; import static android.view.Display.INVALID_DISPLAY; import static android.view.Display.REMOVE_MODE_DESTROY_CONTENT; import static android.view.InsetsState.ITYPE_IME; import static android.view.InsetsState.ITYPE_LEFT_GESTURES; +import static android.view.InsetsState.ITYPE_NAVIGATION_BAR; import static android.view.InsetsState.ITYPE_RIGHT_GESTURES; import static android.view.Surface.ROTATION_0; import static android.view.Surface.ROTATION_180; import static android.view.Surface.ROTATION_270; import static android.view.Surface.ROTATION_90; import static android.view.View.GONE; -import static android.view.View.SYSTEM_UI_FLAG_HIDE_NAVIGATION; -import static android.view.View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY; +import static android.view.WindowInsetsController.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE; import static android.view.WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW; import static android.view.WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE; import static android.view.WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE; @@ -367,13 +367,6 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp final float mCloseToSquareMaxAspectRatio; /** - * If this is true, we would not rotate the display for apps. The rotation would be either the - * sensor rotation or the user rotation, controlled by - * {@link WindowManagerPolicy.UserRotationMode}. - */ - private boolean mIgnoreRotationForApps; - - /** * Keep track of wallpaper visibility to notify changes. */ private boolean mLastWallpaperVisible = false; @@ -618,6 +611,12 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp */ private boolean mInEnsureActivitiesVisible = false; + /** + * Last window to be requested focus via {@code SurfaceControl.Transaction#setFocusedWindow} to + * prevent duplicate requests to input. + */ + WindowState mLastRequestedFocus = null; + private final Consumer<WindowState> mUpdateWindowsForAnimator = w -> { WindowStateAnimator winAnimator = w.mWinAnimator; final ActivityRecord activity = w.mActivityRecord; @@ -1751,26 +1750,6 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp mDisplayFrames.onDisplayInfoUpdated(mDisplayInfo, calculateDisplayCutoutForRotation(mDisplayInfo.rotation)); - - // Not much of use to rotate the display for apps since it's close to square. - mIgnoreRotationForApps = isNonDecorDisplayCloseToSquare(Surface.ROTATION_0, width, height); - } - - /** @return {@code true} if the orientation requested from application will be ignored. */ - boolean ignoreRotationForApps() { - return mIgnoreRotationForApps; - } - - private boolean isNonDecorDisplayCloseToSquare(int rotation, int width, int height) { - final DisplayCutout displayCutout = - calculateDisplayCutoutForRotation(rotation).getDisplayCutout(); - final int uiMode = mWmService.mPolicy.getUiMode(); - final int w = mDisplayPolicy.getNonDecorDisplayWidth( - width, height, rotation, uiMode, displayCutout); - final int h = mDisplayPolicy.getNonDecorDisplayHeight( - width, height, rotation, uiMode, displayCutout); - final float aspectRatio = Math.max(w, h) / (float) Math.min(w, h); - return aspectRatio <= mCloseToSquareMaxAspectRatio; } /** @@ -2336,10 +2315,6 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp int getOrientation() { mLastOrientationSource = null; - if (mIgnoreRotationForApps) { - return SCREEN_ORIENTATION_USER; - } - if (mWmService.mDisplayFrozen) { if (mWmService.mPolicy.isKeyguardLocked()) { // Use the last orientation the while the display is frozen with the keyguard @@ -3488,7 +3463,11 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp return false; } return mWmService.mDisplayWindowSettings.shouldShowImeLocked(this) - || mWmService.mForceDesktopModeOnExternalDisplays; + || forceDesktopMode(); + } + + boolean forceDesktopMode() { + return mWmService.mForceDesktopModeOnExternalDisplays && !isDefaultDisplay && !isPrivate(); } private void setInputMethodTarget(WindowState target, boolean targetWaitingAnim) { @@ -4542,7 +4521,7 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp boolean supportsSystemDecorations() { return (mWmService.mDisplayWindowSettings.shouldShowSystemDecorsLocked(this) || (mDisplay.getFlags() & FLAG_SHOULD_SHOW_SYSTEM_DECORATIONS) != 0 - || mWmService.mForceDesktopModeOnExternalDisplays) + || forceDesktopMode()) // VR virtual display will be used to run and render 2D app within a VR experience. && mDisplayId != mWmService.mVr2dDisplayId // Do not show system decorations on untrusted virtual display. @@ -4749,7 +4728,7 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp } // Apply restriction if necessary. - if (needsGestureExclusionRestrictions(w, mLastDispatchedSystemUiVisibility)) { + if (needsGestureExclusionRestrictions(w, false /* ignoreRequest */)) { // Processes the region along the left edge. remainingLeftRight[0] = addToGlobalAndConsumeLimit(local, outExclusion, leftEdge, @@ -4766,7 +4745,7 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp outExclusion.op(middle, Op.UNION); middle.recycle(); } else { - boolean loggable = needsGestureExclusionRestrictions(w, 0 /* lastSysUiVis */); + boolean loggable = needsGestureExclusionRestrictions(w, true /* ignoreRequest */); if (loggable) { addToGlobalAndConsumeLimit(local, outExclusion, leftEdge, Integer.MAX_VALUE, w, EXCLUSION_LEFT); @@ -4788,17 +4767,21 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp } /** - * @return Whether gesture exclusion area should be restricted from the window depending on the - * current SystemUI visibility flags. + * Returns whether gesture exclusion area should be restricted from the window depending on the + * window/activity types and the requested navigation bar visibility and the behavior. + * + * @param win The target window. + * @param ignoreRequest If this is {@code true}, only the window/activity types are considered. + * @return {@code true} if the gesture exclusion restrictions are needed. */ - private static boolean needsGestureExclusionRestrictions(WindowState win, int sysUiVisibility) { + private static boolean needsGestureExclusionRestrictions(WindowState win, + boolean ignoreRequest) { final int type = win.mAttrs.type; - final int stickyHideNavFlags = - SYSTEM_UI_FLAG_HIDE_NAVIGATION | SYSTEM_UI_FLAG_IMMERSIVE_STICKY; final boolean stickyHideNav = - (sysUiVisibility & stickyHideNavFlags) == stickyHideNavFlags; - return !stickyHideNav && type != TYPE_INPUT_METHOD && type != TYPE_NOTIFICATION_SHADE - && win.getActivityType() != ACTIVITY_TYPE_HOME; + !win.getRequestedInsetsState().getSourceOrDefaultVisibility(ITYPE_NAVIGATION_BAR) + && win.mAttrs.insetsFlags.behavior == BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE; + return (!stickyHideNav || ignoreRequest) && type != TYPE_INPUT_METHOD + && type != TYPE_NOTIFICATION_SHADE && win.getActivityType() != ACTIVITY_TYPE_HOME; } /** @@ -4814,7 +4797,7 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp && type != TYPE_APPLICATION_STARTING && type != TYPE_NAVIGATION_BAR && (attrs.flags & FLAG_NOT_TOUCHABLE) == 0 - && needsGestureExclusionRestrictions(win, 0 /* sysUiVisibility */) + && needsGestureExclusionRestrictions(win, true /* ignoreRequest */) && win.getDisplayContent().mDisplayPolicy.hasSideGestures(); } @@ -5289,6 +5272,14 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp mSingleTaskInstance = true; } + /** + * Check if the display has {@link Display#FLAG_CAN_SHOW_WITH_INSECURE_KEYGUARD} applied. + */ + boolean canShowWithInsecureKeyguard() { + final int flags = mDisplay.getFlags(); + return (flags & FLAG_CAN_SHOW_WITH_INSECURE_KEYGUARD) != 0; + } + /** Returns true if the display can only contain one task */ boolean isSingleTaskInstance() { return mSingleTaskInstance; diff --git a/services/core/java/com/android/server/wm/DisplayPolicy.java b/services/core/java/com/android/server/wm/DisplayPolicy.java index 4998624b9097..779f6b2d30cc 100644 --- a/services/core/java/com/android/server/wm/DisplayPolicy.java +++ b/services/core/java/com/android/server/wm/DisplayPolicy.java @@ -900,10 +900,6 @@ public class DisplayPolicy { (int) attrs.hideTimeoutMilliseconds, AccessibilityManager.FLAG_CONTENT_TEXT); attrs.windowAnimations = com.android.internal.R.style.Animation_Toast; - // Toast can show with below conditions when the screen is locked. - if (canToastShowWhenLocked(callingPid)) { - attrs.flags |= WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED; - } // Toasts can't be clickable attrs.flags |= WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE; break; @@ -934,16 +930,6 @@ public class DisplayPolicy { } /** - * @return {@code true} if the calling activity initiate toast and is visible with - * {@link WindowManager.LayoutParams#FLAG_SHOW_WHEN_LOCKED} flag. - */ - boolean canToastShowWhenLocked(int callingPid) { - return mDisplayContent.forAllWindows(w -> { - return callingPid == w.mSession.mPid && w.isVisible() && w.canShowWhenLocked(); - }, true /* traverseTopToBottom */); - } - - /** * Check if a window can be added to the system. * * Currently enforces that two window types are singletons per display: @@ -1528,7 +1514,7 @@ public class DisplayPolicy { if (mInputConsumer == null) { return; } - showNavigationBar(); + showSystemBars(); // Any user activity always causes us to show the // navigation controls, if they had been hidden. // We also clear the low profile and only content @@ -1563,13 +1549,13 @@ public class DisplayPolicy { } } - private void showNavigationBar() { + private void showSystemBars() { final InsetsSourceProvider provider = mDisplayContent.getInsetsStateController() .peekSourceProvider(ITYPE_NAVIGATION_BAR); final InsetsControlTarget target = provider != null ? provider.getControlTarget() : null; if (target != null) { - target.showInsets(Type.navigationBars(), false /* fromIme */); + target.showInsets(Type.systemBars(), false /* fromIme */); } } } diff --git a/services/core/java/com/android/server/wm/DisplayRotation.java b/services/core/java/com/android/server/wm/DisplayRotation.java index 0206787ef226..0f43e49b568b 100644 --- a/services/core/java/com/android/server/wm/DisplayRotation.java +++ b/services/core/java/com/android/server/wm/DisplayRotation.java @@ -330,10 +330,8 @@ public class DisplayRotation { // It's also not likely to rotate a TV screen. final boolean isTv = mContext.getPackageManager().hasSystemFeature( PackageManager.FEATURE_LEANBACK); - final boolean forceDesktopMode = - mService.mForceDesktopModeOnExternalDisplays && !isDefaultDisplay; mDefaultFixedToUserRotation = - (isCar || isTv || mService.mIsPc || forceDesktopMode) + (isCar || isTv || mService.mIsPc || mDisplayContent.forceDesktopMode()) // For debug purposes the next line turns this feature off with: // $ adb shell setprop config.override_forced_orient true // $ adb shell wm size reset diff --git a/services/core/java/com/android/server/wm/DisplayWindowSettings.java b/services/core/java/com/android/server/wm/DisplayWindowSettings.java index df7c07055e87..c8c83a6e34f0 100644 --- a/services/core/java/com/android/server/wm/DisplayWindowSettings.java +++ b/services/core/java/com/android/server/wm/DisplayWindowSettings.java @@ -248,7 +248,7 @@ class DisplayWindowSettings { writeSettingsIfNeeded(entry, displayInfo); } - private int getWindowingModeLocked(Entry entry, int displayId) { + private int getWindowingModeLocked(Entry entry, DisplayContent dc) { int windowingMode = entry != null ? entry.mWindowingMode : WindowConfiguration.WINDOWING_MODE_UNDEFINED; // This display used to be in freeform, but we don't support freeform anymore, so fall @@ -259,10 +259,8 @@ class DisplayWindowSettings { } // No record is present so use default windowing mode policy. if (windowingMode == WindowConfiguration.WINDOWING_MODE_UNDEFINED) { - final boolean forceDesktopMode = mService.mForceDesktopModeOnExternalDisplays - && displayId != Display.DEFAULT_DISPLAY; windowingMode = mService.mAtmService.mSupportsFreeformWindowManagement - && (mService.mIsPc || forceDesktopMode) + && (mService.mIsPc || dc.forceDesktopMode()) ? WindowConfiguration.WINDOWING_MODE_FREEFORM : WindowConfiguration.WINDOWING_MODE_FULLSCREEN; } @@ -272,7 +270,7 @@ class DisplayWindowSettings { int getWindowingModeLocked(DisplayContent dc) { final DisplayInfo displayInfo = dc.getDisplayInfo(); final Entry entry = getEntry(displayInfo); - return getWindowingModeLocked(entry, dc.getDisplayId()); + return getWindowingModeLocked(entry, dc); } void setWindowingModeLocked(DisplayContent dc, int mode) { @@ -382,7 +380,7 @@ class DisplayWindowSettings { final Entry entry = getOrCreateEntry(displayInfo); // Setting windowing mode first, because it may override overscan values later. - dc.setWindowingMode(getWindowingModeLocked(entry, dc.getDisplayId())); + dc.setWindowingMode(getWindowingModeLocked(entry, dc)); dc.getDisplayRotation().restoreSettings(entry.mUserRotationMode, entry.mUserRotation, entry.mFixedToUserRotation); diff --git a/services/core/java/com/android/server/wm/EnsureActivitiesVisibleHelper.java b/services/core/java/com/android/server/wm/EnsureActivitiesVisibleHelper.java index e2c07491db01..251c01469c6a 100644 --- a/services/core/java/com/android/server/wm/EnsureActivitiesVisibleHelper.java +++ b/services/core/java/com/android/server/wm/EnsureActivitiesVisibleHelper.java @@ -22,12 +22,9 @@ import static com.android.server.wm.Task.TAG_VISIBILITY; import android.annotation.Nullable; import android.util.Slog; -import com.android.internal.util.function.pooled.PooledConsumer; -import com.android.internal.util.function.pooled.PooledLambda; - /** Helper class to ensure activities are in the right visible state for a container. */ class EnsureActivitiesVisibleHelper { - private final Task mContiner; + private final Task mTask; private ActivityRecord mTop; private ActivityRecord mStarting; private boolean mAboveTop; @@ -38,11 +35,11 @@ class EnsureActivitiesVisibleHelper { private boolean mNotifyClients; EnsureActivitiesVisibleHelper(Task container) { - mContiner = container; + mTask = container; } /** - * Update all attributes except {@link mContiner} to use in subsequent calculations. + * Update all attributes except {@link mTask} to use in subsequent calculations. * * @param starting The activity that is being started * @param configChanges Parts of the configuration that changed for this activity for evaluating @@ -54,11 +51,11 @@ class EnsureActivitiesVisibleHelper { void reset(ActivityRecord starting, int configChanges, boolean preserveWindows, boolean notifyClients) { mStarting = starting; - mTop = mContiner.topRunningActivity(); + mTop = mTask.topRunningActivity(); // If the top activity is not fullscreen, then we need to make sure any activities under it // are now visible. mAboveTop = mTop != null; - mContainerShouldBeVisible = mContiner.shouldBeVisible(mStarting); + mContainerShouldBeVisible = mTask.shouldBeVisible(mStarting); mBehindFullscreenActivity = !mContainerShouldBeVisible; mConfigChanges = configChanges; mPreserveWindows = preserveWindows; @@ -66,7 +63,26 @@ class EnsureActivitiesVisibleHelper { } /** - * Ensure visibility with an option to also update the configuration of visible activities. + * Update visibility to activities. + * @see Task#ensureActivitiesVisible(ActivityRecord, int, boolean) + * @see RootWindowContainer#ensureActivitiesVisible(ActivityRecord, int, boolean) + * @param starting The top most activity in the task. + * The activity is either starting or resuming. + * Caller should ensure starting activity is visible. + * + */ + void processUpdate(@Nullable ActivityRecord starting) { + reset(starting, 0 /* configChanges */, false /* preserveWindows */, + false /* notifyClients */); + if (DEBUG_VISIBILITY) { + Slog.v(TAG_VISIBILITY, "ensureActivitiesVisible processUpdate behind " + mTop); + } + + mTask.forAllActivities(this::updateActivityVisibility); + } + + /** + * Commit visibility with an option to also update the configuration of visible activities. * @see Task#ensureActivitiesVisible(ActivityRecord, int, boolean) * @see RootWindowContainer#ensureActivitiesVisible(ActivityRecord, int, boolean) * @param starting The top most activity in the task. @@ -79,54 +95,84 @@ class EnsureActivitiesVisibleHelper { * @param notifyClients Flag indicating whether the configuration and visibility changes shoulc * be sent to the clients. */ - void process(@Nullable ActivityRecord starting, int configChanges, boolean preserveWindows, - boolean notifyClients) { + void processCommit(ActivityRecord starting, int configChanges, + boolean preserveWindows, boolean notifyClients) { reset(starting, configChanges, preserveWindows, notifyClients); - if (DEBUG_VISIBILITY) Slog.v(TAG_VISIBILITY, "ensureActivitiesVisible behind " + mTop - + " configChanges=0x" + Integer.toHexString(configChanges)); + if (DEBUG_VISIBILITY) { + Slog.v(TAG_VISIBILITY, "ensureActivitiesVisible processCommit behind " + mTop); + } if (mTop != null) { - mContiner.checkTranslucentActivityWaiting(mTop); + mTask.checkTranslucentActivityWaiting(mTop); } // We should not resume activities that being launched behind because these // activities are actually behind other fullscreen activities, but still required // to be visible (such as performing Recents animation). final boolean resumeTopActivity = mTop != null && !mTop.mLaunchTaskBehind - && mContiner.isTopActivityFocusable() - && (starting == null || !starting.isDescendantOf(mContiner)); - - final PooledConsumer f = PooledLambda.obtainConsumer( - EnsureActivitiesVisibleHelper::setActivityVisibilityState, this, - PooledLambda.__(ActivityRecord.class), starting, resumeTopActivity); - mContiner.forAllActivities(f); - f.recycle(); + && mTask.isTopActivityFocusable() + && (starting == null || !starting.isDescendantOf(mTask)); + + mTask.forAllActivities(a -> { + commitActivityVisibility(a, starting, resumeTopActivity); + }); } - private void setActivityVisibilityState(ActivityRecord r, ActivityRecord starting, - final boolean resumeTopActivity) { - final boolean isTop = r == mTop; + private boolean isAboveTop(boolean isTop) { if (mAboveTop && !isTop) { - return; + return true; } mAboveTop = false; + return false; + } + + private void updateActivityVisibility(ActivityRecord r) { + final boolean isTop = r == mTop; + if (isAboveTop(isTop)) { + return; + } - final boolean reallyVisible = r.shouldBeVisible( - mBehindFullscreenActivity, false /* ignoringKeyguard */); + r.updateVisibility(mBehindFullscreenActivity); // Check whether activity should be visible without Keyguard influence if (r.visibleIgnoringKeyguard) { if (r.occludesParent()) { // At this point, nothing else needs to be shown in this task. - if (DEBUG_VISIBILITY) Slog.v(TAG_VISIBILITY, "Fullscreen: at " + r - + " stackVisible=" + mContainerShouldBeVisible - + " behindFullscreen=" + mBehindFullscreenActivity); + if (DEBUG_VISIBILITY) { + Slog.v(TAG_VISIBILITY, "Fullscreen: at " + r + + " stackVisible=" + mContainerShouldBeVisible + + " behindFullscreen=" + mBehindFullscreenActivity); + } mBehindFullscreenActivity = true; } else { mBehindFullscreenActivity = false; } } + if (!mBehindFullscreenActivity && mTask.isActivityTypeHome() && r.isRootOfTask()) { + if (DEBUG_VISIBILITY) { + Slog.v(TAG_VISIBILITY, "Home task: at " + mTask + + " stackShouldBeVisible=" + mContainerShouldBeVisible + + " behindFullscreenActivity=" + mBehindFullscreenActivity); + } + // No other task in the home stack should be visible behind the home activity. + // Home activities is usually a translucent activity with the wallpaper behind + // them. However, when they don't have the wallpaper behind them, we want to + // show activities in the next application stack behind them vs. another + // task in the home stack like recents. + mBehindFullscreenActivity = true; + } + } + + private void commitActivityVisibility(ActivityRecord r, ActivityRecord starting, + final boolean resumeTopActivity) { + final boolean isTop = r == mTop; + if (isAboveTop(isTop)) { + return; + } + + final boolean reallyVisible = r.shouldBeVisibleUnchecked(); + if (reallyVisible) { if (r.finishing) { return; @@ -170,20 +216,6 @@ class EnsureActivitiesVisibleHelper { + " mLaunchTaskBehind=" + r.mLaunchTaskBehind); r.makeInvisible(); } - - final int windowingMode = mContiner.getWindowingMode(); - if (!mBehindFullscreenActivity && mContiner.isActivityTypeHome() - && r.isRootOfTask()) { - if (DEBUG_VISIBILITY) Slog.v(TAG_VISIBILITY, "Home task: at " + mContiner - + " stackShouldBeVisible=" + mContainerShouldBeVisible - + " behindFullscreenActivity=" + mBehindFullscreenActivity); - // No other task in the home stack should be visible behind the home activity. - // Home activities is usually a translucent activity with the wallpaper behind - // them. However, when they don't have the wallpaper behind them, we want to - // show activities in the next application stack behind them vs. another - // task in the home stack like recents. - mBehindFullscreenActivity = true; - } } private void makeVisibleAndRestartIfNeeded(ActivityRecord starting, int configChanges, @@ -207,7 +239,7 @@ class EnsureActivitiesVisibleHelper { r.setVisibility(true); } if (r != starting) { - mContiner.mStackSupervisor.startSpecificActivity(r, andResume, true /* checkConfig */); + mTask.mStackSupervisor.startSpecificActivity(r, andResume, true /* checkConfig */); } } } diff --git a/services/core/java/com/android/server/wm/InputMonitor.java b/services/core/java/com/android/server/wm/InputMonitor.java index 4efd687b7bb4..c493b66b6204 100644 --- a/services/core/java/com/android/server/wm/InputMonitor.java +++ b/services/core/java/com/android/server/wm/InputMonitor.java @@ -275,7 +275,7 @@ final class InputMonitor { void populateInputWindowHandle(final InputWindowHandle inputWindowHandle, final WindowState child, int flags, final int type, final boolean isVisible, - final boolean hasFocus, final boolean hasWallpaper) { + final boolean focusable, final boolean hasWallpaper) { // Add a window to our list of input windows. inputWindowHandle.name = child.toString(); flags = child.getSurfaceTouchableRegion(inputWindowHandle, flags); @@ -283,7 +283,7 @@ final class InputMonitor { inputWindowHandle.layoutParamsType = type; inputWindowHandle.dispatchingTimeoutMillis = child.getInputDispatchingTimeoutMillis(); inputWindowHandle.visible = isVisible; - inputWindowHandle.focusable = hasFocus; + inputWindowHandle.focusable = focusable; inputWindowHandle.hasWallpaper = hasWallpaper; inputWindowHandle.paused = child.mActivityRecord != null ? child.mActivityRecord.paused : false; inputWindowHandle.ownerPid = child.mSession.mPid; @@ -472,8 +472,9 @@ final class InputMonitor { resetInputConsumers(mInputTransaction); - mDisplayContent.forAllWindows(this, - true /* traverseTopToBottom */); + mDisplayContent.forAllWindows(this, true /* traverseTopToBottom */); + + updateInputFocusRequest(); if (!mUpdateInputWindowsImmediately) { mDisplayContent.getPendingTransaction().merge(mInputTransaction); @@ -483,6 +484,29 @@ final class InputMonitor { Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER); } + private void updateInputFocusRequest() { + if (mDisplayContent.mLastRequestedFocus == mDisplayContent.mCurrentFocus) { + return; + } + + final WindowState focus = mDisplayContent.mCurrentFocus; + if (focus == null || focus.mInputWindowHandle.token == null) { + mDisplayContent.mLastRequestedFocus = focus; + return; + } + + if (!focus.mWinAnimator.hasSurface()) { + ProtoLog.d(WM_DEBUG_FOCUS_LIGHT, + "Focus not requested for window=%s because it has no surface", + focus); + return; + } + + mInputTransaction.setFocusedWindow(focus.mInputWindowHandle.token, mDisplayId); + mDisplayContent.mLastRequestedFocus = focus; + ProtoLog.v(WM_DEBUG_FOCUS_LIGHT, "Focus requested for window=%s", focus); + } + @Override public void accept(WindowState w) { final InputChannel inputChannel = w.mInputChannel; @@ -510,11 +534,12 @@ final class InputMonitor { final int flags = w.mAttrs.flags; final int privateFlags = w.mAttrs.privateFlags; - final boolean hasFocus = w.isFocused(); + final boolean focusable = w.canReceiveKeys() + && (mService.mPerDisplayFocusEnabled || mDisplayContent.isOnTop()); if (mAddRecentsAnimationInputConsumerHandle && shouldApplyRecentsInputConsumer) { if (recentsAnimationController.updateInputConsumerForApp( - mRecentsAnimationInputConsumer.mWindowHandle, hasFocus)) { + mRecentsAnimationInputConsumer.mWindowHandle, focusable)) { mRecentsAnimationInputConsumer.show(mInputTransaction, w); mAddRecentsAnimationInputConsumerHandle = false; } @@ -559,7 +584,7 @@ final class InputMonitor { } populateInputWindowHandle( - inputWindowHandle, w, flags, type, isVisible, hasFocus, hasWallpaper); + inputWindowHandle, w, flags, type, isVisible, focusable, hasWallpaper); // register key interception info mService.mKeyInterceptionInfoForToken.put(inputWindowHandle.token, diff --git a/services/core/java/com/android/server/wm/InsetsStateController.java b/services/core/java/com/android/server/wm/InsetsStateController.java index ab1074ee2821..5520ad37e8ed 100644 --- a/services/core/java/com/android/server/wm/InsetsStateController.java +++ b/services/core/java/com/android/server/wm/InsetsStateController.java @@ -286,6 +286,7 @@ class InsetsStateController { } if (changed) { notifyInsetsChanged(); + mDisplayContent.updateSystemGestureExclusion(); mDisplayContent.getDisplayPolicy().updateSystemUiVisibilityLw(); } } diff --git a/services/core/java/com/android/server/wm/KeyguardController.java b/services/core/java/com/android/server/wm/KeyguardController.java index 69e8c57a489c..bad28ba333ba 100644 --- a/services/core/java/com/android/server/wm/KeyguardController.java +++ b/services/core/java/com/android/server/wm/KeyguardController.java @@ -278,6 +278,27 @@ class KeyguardController { } /** + * Checks whether {@param r} should be visible depending on Keyguard state. + * + * @return true if {@param r} is visible taken Keyguard state into account, false otherwise + */ + boolean checkKeyguardVisibility(ActivityRecord r) { + if (r.mDisplayContent.canShowWithInsecureKeyguard() && canDismissKeyguard()) { + return true; + } + + if (isKeyguardOrAodShowing(r.mDisplayContent.getDisplayId())) { + // If keyguard is showing, nothing is visible, except if we are able to dismiss Keyguard + // right away and AOD isn't visible. + return canShowActivityWhileKeyguardShowing(r, r.containsDismissKeyguardWindow()); + } else if (isKeyguardLocked()) { + return canShowWhileOccluded(r.containsDismissKeyguardWindow(), r.canShowWhenLocked()); + } else { + return true; + } + } + + /** * Makes sure to update lockscreen occluded/dismiss state if needed after completing all * visibility updates ({@link ActivityStackSupervisor#endActivityVisibilityUpdate}). */ @@ -442,6 +463,7 @@ class KeyguardController { private final int mDisplayId; private boolean mOccluded; private ActivityRecord mDismissingKeyguardActivity; + private ActivityRecord mTopTurnScreenOnActivity; private boolean mRequestDismissKeyguard; private final ActivityTaskManagerService mService; private final ActivityTaskManagerInternal.SleepTokenAcquirer mSleepTokenAcquirer; @@ -455,30 +477,38 @@ class KeyguardController { void onRemoved() { mDismissingKeyguardActivity = null; + mTopTurnScreenOnActivity = null; mSleepTokenAcquirer.release(mDisplayId); } void visibilitiesUpdated(KeyguardController controller, DisplayContent display) { final boolean lastOccluded = mOccluded; final ActivityRecord lastDismissActivity = mDismissingKeyguardActivity; + final ActivityRecord lastTurnScreenOnActivity = mTopTurnScreenOnActivity; mRequestDismissKeyguard = false; mOccluded = false; mDismissingKeyguardActivity = null; + mTopTurnScreenOnActivity = null; + // only top + focusable + visible task can control occluding. final Task stack = getStackForControllingOccluding(display); if (stack != null) { final ActivityRecord topDismissing = stack.getTopDismissingKeyguardActivity(); + final ActivityRecord topTurnScreenOn = stack.getTopTurnScreenOnActivity(); mOccluded = stack.topActivityOccludesKeyguard() || (topDismissing != null && stack.topRunningActivity() == topDismissing && controller.canShowWhileOccluded( true /* dismissKeyguard */, false /* showWhenLocked */)); - if (stack.getTopDismissingKeyguardActivity() != null) { - mDismissingKeyguardActivity = stack.getTopDismissingKeyguardActivity(); + if (topDismissing != null) { + mDismissingKeyguardActivity = topDismissing; + } + if (topTurnScreenOn != null) { + mTopTurnScreenOnActivity = topTurnScreenOn; } // FLAG_CAN_SHOW_WITH_INSECURE_KEYGUARD only apply for secondary display. - if (mDisplayId != DEFAULT_DISPLAY) { - mOccluded |= stack.canShowWithInsecureKeyguard() + if (mDisplayId != DEFAULT_DISPLAY && stack.mDisplayContent != null) { + mOccluded |= stack.mDisplayContent.canShowWithInsecureKeyguard() && controller.canDismissKeyguard(); } } @@ -488,14 +518,20 @@ class KeyguardController { .getDisplayPolicy().isShowingDreamLw(); } - if (lastOccluded != mOccluded) { - controller.handleOccludedChanged(mDisplayId); - } - if (lastDismissActivity != mDismissingKeyguardActivity && !mOccluded + mRequestDismissKeyguard = lastDismissActivity != mDismissingKeyguardActivity + && !mOccluded && mDismissingKeyguardActivity != null && controller.mWindowManager.isKeyguardSecure( - controller.mService.getCurrentUserId())) { - mRequestDismissKeyguard = true; + controller.mService.getCurrentUserId()); + + if (mTopTurnScreenOnActivity != null + && mTopTurnScreenOnActivity != lastTurnScreenOnActivity + && !mService.mWindowManager.mPowerManager.isInteractive()) { + controller.mStackSupervisor.wakeUp("handleTurnScreenOn"); + } + + if (lastOccluded != mOccluded) { + controller.handleOccludedChanged(mDisplayId); } } @@ -525,6 +561,8 @@ class KeyguardController { sb.append(" Occluded=").append(mOccluded) .append(" DismissingKeyguardActivity=") .append(mDismissingKeyguardActivity) + .append(" TurnScreenOnActivity=") + .append(mTopTurnScreenOnActivity) .append(" at display=") .append(mDisplayId); pw.println(sb.toString()); diff --git a/services/core/java/com/android/server/wm/OWNERS b/services/core/java/com/android/server/wm/OWNERS index 4be4c896cbff..1077736cebb5 100644 --- a/services/core/java/com/android/server/wm/OWNERS +++ b/services/core/java/com/android/server/wm/OWNERS @@ -11,3 +11,4 @@ erosky@google.com riddlehsu@google.com louischang@google.com winsonc@google.com +tigerhuang@google.com diff --git a/services/core/java/com/android/server/wm/RecentsAnimationController.java b/services/core/java/com/android/server/wm/RecentsAnimationController.java index 6882dc4ca151..b50cb4c34398 100644 --- a/services/core/java/com/android/server/wm/RecentsAnimationController.java +++ b/services/core/java/com/android/server/wm/RecentsAnimationController.java @@ -814,14 +814,14 @@ public class RecentsAnimationController implements DeathRecipient { } boolean updateInputConsumerForApp(InputWindowHandle inputWindowHandle, - boolean hasFocus) { + boolean focusable) { // Update the input consumer touchable region to match the target app main window final WindowState targetAppMainWindow = mTargetActivityRecord != null ? mTargetActivityRecord.findMainWindow() : null; if (targetAppMainWindow != null) { targetAppMainWindow.getBounds(mTmpRect); - inputWindowHandle.focusable = hasFocus; + inputWindowHandle.focusable = focusable; inputWindowHandle.touchableRegion.set(mTmpRect); return true; } diff --git a/services/core/java/com/android/server/wm/RootWindowContainer.java b/services/core/java/com/android/server/wm/RootWindowContainer.java index 6539e1325ec1..d149db6b676f 100644 --- a/services/core/java/com/android/server/wm/RootWindowContainer.java +++ b/services/core/java/com/android/server/wm/RootWindowContainer.java @@ -99,6 +99,7 @@ import android.annotation.Nullable; import android.annotation.UserIdInt; import android.app.ActivityManager; import android.app.ActivityOptions; +import android.app.ActivityTaskManager.RootTaskInfo; import android.app.AppGlobals; import android.app.WindowConfiguration; import android.content.ComponentName; @@ -1982,10 +1983,22 @@ class RootWindowContainer extends WindowContainer<DisplayContent> notifyClients); } } finally { - mStackSupervisor.endActivityVisibilityUpdate(); + mStackSupervisor.endActivityVisibilityUpdate(starting, configChanges, preserveWindows, + notifyClients); } } + void commitActivitiesVisible(ActivityRecord starting, int configChanges, + boolean preserveWindows, boolean notifyClients) { + forAllTaskDisplayAreas(taskDisplayArea -> { + for (int stackNdx = taskDisplayArea.getStackCount() - 1; stackNdx >= 0; --stackNdx) { + final Task task = taskDisplayArea.getStackAt(stackNdx); + task.commitActivitiesVisible(starting, configChanges, preserveWindows, + notifyClients); + } + }); + } + boolean switchUser(int userId, UserState uss) { final Task topFocusedStack = getTopDisplayFocusedStack(); final int focusStackId = topFocusedStack != null @@ -2201,7 +2214,22 @@ class RootWindowContainer extends WindowContainer<DisplayContent> ensureActivitiesVisible(null, 0, false /* preserveWindows */); resumeFocusedStacksTopActivities(); - mService.getTaskChangeNotificationController().notifyActivityPinned(r); + notifyActivityPipModeChanged(r); + } + + /** + * Notifies when an activity enters or leaves PIP mode. + * @param r indicates the activity currently in PIP, can be null to indicate no activity is + * currently in PIP mode. + */ + void notifyActivityPipModeChanged(@Nullable ActivityRecord r) { + final boolean inPip = r != null; + if (inPip) { + mService.getTaskChangeNotificationController().notifyActivityPinned(r); + } else { + mService.getTaskChangeNotificationController().notifyActivityUnpinned(); + } + mWindowManager.mPolicy.setPipVisibilityLw(inPip); } void executeAppTransitionForAllDisplay() { @@ -2423,77 +2451,73 @@ class RootWindowContainer extends WindowContainer<DisplayContent> return display.getStack(windowingMode, activityType); } - private ActivityManager.StackInfo getStackInfo(Task stack) { - final TaskDisplayArea taskDisplayArea = stack.getDisplayArea(); - ActivityManager.StackInfo info = new ActivityManager.StackInfo(); - stack.getBounds(info.bounds); - info.displayId = taskDisplayArea != null ? taskDisplayArea.getDisplayId() : INVALID_DISPLAY; - info.stackId = stack.mTaskId; - info.stackToken = stack.mRemoteToken.toWindowContainerToken(); - info.userId = stack.mCurrentUser; - info.visible = stack.shouldBeVisible(null); - // A stack might be not attached to a display. - // TODO: Can be removed since no one is using it. - info.position = taskDisplayArea != null ? taskDisplayArea.getIndexOf(stack) : 0; - info.configuration.setTo(stack.getConfiguration()); - - final int numTasks = stack.getDescendantTaskCount(); - info.taskIds = new int[numTasks]; - info.taskNames = new String[numTasks]; - info.taskBounds = new Rect[numTasks]; - info.taskUserIds = new int[numTasks]; + private RootTaskInfo getRootTaskInfo(Task task) { + final TaskDisplayArea taskDisplayArea = task.getDisplayArea(); + RootTaskInfo info = new RootTaskInfo(); + task.fillTaskInfo(info); + + // A task might be not attached to a display. + info.position = taskDisplayArea != null ? taskDisplayArea.getIndexOf(task) : 0; + info.visible = task.shouldBeVisible(null); + task.getBounds(info.bounds); + + final int numTasks = task.getDescendantTaskCount(); + info.childTaskIds = new int[numTasks]; + info.childTaskNames = new String[numTasks]; + info.childTaskBounds = new Rect[numTasks]; + info.childTaskUserIds = new int[numTasks]; final int[] currentIndex = {0}; final PooledConsumer c = PooledLambda.obtainConsumer( - RootWindowContainer::processTaskForStackInfo, PooledLambda.__(Task.class), info, + RootWindowContainer::processTaskForTaskInfo, PooledLambda.__(Task.class), info, currentIndex); - stack.forAllLeafTasks(c, false /* traverseTopToBottom */); + task.forAllLeafTasks(c, false /* traverseTopToBottom */); c.recycle(); - final ActivityRecord top = stack.topRunningActivity(); + final ActivityRecord top = task.topRunningActivity(); info.topActivity = top != null ? top.intent.getComponent() : null; return info; } - private static void processTaskForStackInfo( - Task task, ActivityManager.StackInfo info, int[] currentIndex) { + private static void processTaskForTaskInfo( + Task task, RootTaskInfo info, int[] currentIndex) { int i = currentIndex[0]; - info.taskIds[i] = task.mTaskId; - info.taskNames[i] = task.origActivity != null ? task.origActivity.flattenToString() + info.childTaskIds[i] = task.mTaskId; + info.childTaskNames[i] = task.origActivity != null ? task.origActivity.flattenToString() : task.realActivity != null ? task.realActivity.flattenToString() : task.getTopNonFinishingActivity() != null ? task.getTopNonFinishingActivity().packageName : "unknown"; - info.taskBounds[i] = task.mAtmService.getTaskBounds(task.mTaskId); - info.taskUserIds[i] = task.mUserId; + info.childTaskBounds[i] = task.mAtmService.getTaskBounds(task.mTaskId); + info.childTaskUserIds[i] = task.mUserId; currentIndex[0] = ++i; } - ActivityManager.StackInfo getStackInfo(int stackId) { - Task stack = getStack(stackId); - if (stack != null) { - return getStackInfo(stack); + RootTaskInfo getRootTaskInfo(int taskId) { + Task task = getStack(taskId); + if (task != null) { + return getRootTaskInfo(task); } return null; } - ActivityManager.StackInfo getStackInfo(int windowingMode, int activityType) { + RootTaskInfo getRootTaskInfo(int windowingMode, int activityType) { final Task stack = getStack(windowingMode, activityType); - return (stack != null) ? getStackInfo(stack) : null; + return (stack != null) ? getRootTaskInfo(stack) : null; } - ActivityManager.StackInfo getStackInfo(int windowingMode, int activityType, int displayId) { + RootTaskInfo getRootTaskInfo(int windowingMode, int activityType, int displayId) { final Task stack = getStack(windowingMode, activityType, displayId); - return (stack != null) ? getStackInfo(stack) : null; + return (stack != null) ? getRootTaskInfo(stack) : null; } - /** If displayId == INVALID_DISPLAY, this will get stack infos on all displays */ - ArrayList<ActivityManager.StackInfo> getAllStackInfos(int displayId) { - ArrayList<ActivityManager.StackInfo> list = new ArrayList<>(); + /** If displayId == INVALID_DISPLAY, this will get root task infos on all displays */ + ArrayList<RootTaskInfo> getAllRootTaskInfos(int displayId) { + ArrayList<RootTaskInfo> list = new ArrayList<>(); if (displayId == INVALID_DISPLAY) { forAllTaskDisplayAreas(taskDisplayArea -> { for (int sNdx = taskDisplayArea.getStackCount() - 1; sNdx >= 0; --sNdx) { final Task stack = taskDisplayArea.getStackAt(sNdx); - list.add(getStackInfo(stack)); + list.add(getRootTaskInfo(stack)); } }); return list; @@ -2505,7 +2529,7 @@ class RootWindowContainer extends WindowContainer<DisplayContent> display.forAllTaskDisplayAreas(taskDisplayArea -> { for (int sNdx = taskDisplayArea.getStackCount() - 1; sNdx >= 0; --sNdx) { final Task stack = taskDisplayArea.getStackAt(sNdx); - list.add(getStackInfo(stack)); + list.add(getRootTaskInfo(stack)); } }); return list; diff --git a/services/core/java/com/android/server/wm/Session.java b/services/core/java/com/android/server/wm/Session.java index 3b32a9d76258..3d6d7b72671b 100644 --- a/services/core/java/com/android/server/wm/Session.java +++ b/services/core/java/com/android/server/wm/Session.java @@ -56,6 +56,7 @@ import android.view.InsetsState; import android.view.SurfaceControl; import android.view.SurfaceSession; import android.view.WindowManager; +import android.window.ClientWindowFrames; import com.android.internal.os.logging.MetricsLoggerWrapper; import com.android.internal.protolog.common.ProtoLog; @@ -201,9 +202,7 @@ class Session extends IWindowSession.Stub implements IBinder.DeathRecipient { @Override public int relayout(IWindow window, int seq, WindowManager.LayoutParams attrs, int requestedWidth, int requestedHeight, int viewFlags, int flags, long frameNumber, - Rect outFrame, Rect outContentInsets, Rect outVisibleInsets, - Rect outStableInsets, Rect outBackdropFrame, - DisplayCutout.ParcelableWrapper cutout, MergedConfiguration mergedConfiguration, + ClientWindowFrames outFrames, MergedConfiguration mergedConfiguration, SurfaceControl outSurfaceControl, InsetsState outInsetsState, InsetsSourceControl[] outActiveControls, Point outSurfaceSize, SurfaceControl outBLASTSurfaceControl) { @@ -212,10 +211,8 @@ class Session extends IWindowSession.Stub implements IBinder.DeathRecipient { Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, mRelayoutTag); int res = mService.relayoutWindow(this, window, seq, attrs, requestedWidth, requestedHeight, viewFlags, flags, frameNumber, - outFrame, outContentInsets, outVisibleInsets, - outStableInsets, outBackdropFrame, cutout, - mergedConfiguration, outSurfaceControl, outInsetsState, outActiveControls, - outSurfaceSize, outBLASTSurfaceControl); + outFrames, mergedConfiguration, outSurfaceControl, outInsetsState, + outActiveControls, outSurfaceSize, outBLASTSurfaceControl); Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER); if (false) Slog.d(TAG_WM, "<<<<<< EXITING relayout to " + Binder.getCallingPid()); @@ -240,11 +237,6 @@ class Session extends IWindowSession.Stub implements IBinder.DeathRecipient { } @Override - public void getDisplayFrame(IWindow window, Rect outDisplayFrame) { - mService.getWindowDisplayFrame(this, window, outDisplayFrame); - } - - @Override public void finishDrawing(IWindow window, @Nullable SurfaceControl.Transaction postDrawTransaction) { if (DEBUG) Slog.v(TAG_WM, "IWindow finishDrawing called for " + window); diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java index 70fd860f21f2..c4ca4cd637e3 100644 --- a/services/core/java/com/android/server/wm/Task.java +++ b/services/core/java/com/android/server/wm/Task.java @@ -61,7 +61,6 @@ import static android.content.res.Configuration.ORIENTATION_UNDEFINED; import static android.os.Trace.TRACE_TAG_WINDOW_MANAGER; import static android.provider.Settings.Secure.USER_SETUP_COMPLETE; import static android.view.Display.DEFAULT_DISPLAY; -import static android.view.Display.FLAG_CAN_SHOW_WITH_INSECURE_KEYGUARD; import static android.view.Display.INVALID_DISPLAY; import static android.view.SurfaceControl.METADATA_TASK_ID; import static android.view.WindowManager.TRANSIT_ACTIVITY_CLOSE; @@ -197,7 +196,6 @@ import android.util.DisplayMetrics; import android.util.Log; import android.util.Slog; import android.util.proto.ProtoOutputStream; -import android.view.Display; import android.view.DisplayInfo; import android.view.RemoteAnimationAdapter; import android.view.RemoteAnimationTarget; @@ -600,6 +598,7 @@ class Task extends WindowContainer<WindowContainer> { private boolean mTopActivityOccludesKeyguard; private ActivityRecord mTopDismissingKeyguardActivity; + private ActivityRecord mTopTurnScreenOnActivity; private static final int TRANSLUCENT_TIMEOUT_MSG = FIRST_ACTIVITY_STACK_MSG + 1; @@ -1434,7 +1433,7 @@ class Task extends WindowContainer<WindowContainer> { && (newParent == null || !newParent.inPinnedWindowingMode())) { // Notify if a task from the pinned stack is being removed // (or moved depending on the mode). - mAtmService.getTaskChangeNotificationController().notifyActivityUnpinned(); + mRootWindowContainer.notifyActivityPipModeChanged(null); } } @@ -4019,7 +4018,7 @@ class Task extends WindowContainer<WindowContainer> { */ void fillTaskInfo(TaskInfo info, boolean stripExtras) { getNumRunningActivities(mReuseActivitiesReport); - info.userId = mUserId; + info.userId = isLeafTask() ? mUserId : mCurrentUser; info.stackId = getRootTaskId(); info.taskId = mTaskId; info.displayId = getDisplayId(); @@ -5102,10 +5101,11 @@ class Task extends WindowContainer<WindowContainer> { : WINDOWING_MODE_FULLSCREEN; } if (currentMode == WINDOWING_MODE_PINNED) { - mAtmService.getTaskChangeNotificationController().notifyActivityUnpinned(); + mRootWindowContainer.notifyActivityPipModeChanged(null); } if (likelyResolvedMode == WINDOWING_MODE_PINNED && taskDisplayArea.getRootPinnedTask() != null) { + // Can only have 1 pip at a time, so replace an existing pip taskDisplayArea.getRootPinnedTask().dismissPip(); } @@ -5428,6 +5428,7 @@ class Task extends WindowContainer<WindowContainer> { mAtmService.updateCpuStats(); boolean pauseImmediately = false; + boolean shouldAutoPip = false; if (resuming != null && (resuming.info.flags & FLAG_RESUME_WHILE_PAUSING) != 0) { // If the flag RESUME_WHILE_PAUSING is set, then continue to schedule the previous // activity to be paused, while at the same time resuming the new resume activity @@ -5435,26 +5436,39 @@ class Task extends WindowContainer<WindowContainer> { // activities a chance to enter Pip before resuming the next activity. final boolean lastResumedCanPip = prev != null && prev.checkEnterPictureInPictureState( "shouldResumeWhilePausing", userLeaving); - if (!lastResumedCanPip) { + if (lastResumedCanPip && prev.pictureInPictureArgs.isAutoEnterAllowed()) { + shouldAutoPip = true; + } else if (!lastResumedCanPip) { pauseImmediately = true; + } else { + // The previous activity may still enter PIP even though it did not allow auto-PIP. } } + boolean didAutoPip = false; if (prev.attachedToProcess()) { - if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Enqueueing pending pause: " + prev); - try { - EventLogTags.writeWmPauseActivity(prev.mUserId, System.identityHashCode(prev), - prev.shortComponentName, "userLeaving=" + userLeaving); - - mAtmService.getLifecycleManager().scheduleTransaction(prev.app.getThread(), - prev.appToken, PauseActivityItem.obtain(prev.finishing, userLeaving, - prev.configChangeFlags, pauseImmediately)); - } catch (Exception e) { - // Ignore exception, if process died other code will cleanup. - Slog.w(TAG, "Exception thrown during pause", e); + if (shouldAutoPip) { + if (DEBUG_PAUSE) { + Slog.d(TAG_PAUSE, "Auto-PIP allowed, entering PIP mode directly: " + prev); + } + didAutoPip = mAtmService.enterPictureInPictureMode(prev, prev.pictureInPictureArgs); mPausingActivity = null; - mLastPausedActivity = null; - mLastNoHistoryActivity = null; + } else { + if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Enqueueing pending pause: " + prev); + try { + EventLogTags.writeWmPauseActivity(prev.mUserId, System.identityHashCode(prev), + prev.shortComponentName, "userLeaving=" + userLeaving); + + mAtmService.getLifecycleManager().scheduleTransaction(prev.app.getThread(), + prev.appToken, PauseActivityItem.obtain(prev.finishing, userLeaving, + prev.configChangeFlags, pauseImmediately)); + } catch (Exception e) { + // Ignore exception, if process died other code will cleanup. + Slog.w(TAG, "Exception thrown during pause", e); + mPausingActivity = null; + mLastPausedActivity = null; + mLastNoHistoryActivity = null; + } } } else { mPausingActivity = null; @@ -5468,6 +5482,11 @@ class Task extends WindowContainer<WindowContainer> { mStackSupervisor.acquireLaunchWakelock(); } + if (didAutoPip) { + // Already entered PIP mode, no need to keep pausing. + return true; + } + if (mPausingActivity != null) { // Have the window manager pause its key dispatching until the new // activity has started. If we're pausing the activity just because @@ -5644,21 +5663,29 @@ class Task extends WindowContainer<WindowContainer> { boolean preserveWindows, boolean notifyClients) { mTopActivityOccludesKeyguard = false; mTopDismissingKeyguardActivity = null; + mTopTurnScreenOnActivity = null; mStackSupervisor.beginActivityVisibilityUpdate(); try { - mEnsureActivitiesVisibleHelper.process( - starting, configChanges, preserveWindows, notifyClients); + mEnsureActivitiesVisibleHelper.processUpdate(starting); if (mTranslucentActivityWaiting != null && mUndrawnActivitiesBelowTopTranslucent.isEmpty()) { - // Nothing is getting drawn or everything was already visible, don't wait for timeout. + // Nothing is getting drawn or everything was already visible, don't wait for + // timeout. notifyActivityDrawnLocked(null); } } finally { - mStackSupervisor.endActivityVisibilityUpdate(); + mStackSupervisor.endActivityVisibilityUpdate(starting, configChanges, preserveWindows, + notifyClients); } } + void commitActivitiesVisible(ActivityRecord starting, int configChanges, + boolean preserveWindows, boolean notifyClients) { + mEnsureActivitiesVisibleHelper.processCommit(starting, configChanges, preserveWindows, + notifyClients); + } + /** * @return true if the top visible activity wants to occlude the Keyguard, false otherwise */ @@ -5692,64 +5719,34 @@ class Task extends WindowContainer<WindowContainer> { } /** - * Checks whether {@param r} should be visible depending on Keyguard state and updates - * {@link #mTopActivityOccludesKeyguard} and {@link #mTopDismissingKeyguardActivity} if - * necessary. - * - * @return true if {@param r} is visible taken Keyguard state into account, false otherwise + * @return the top most visible activity that wants to turn screen on */ - boolean checkKeyguardVisibility(ActivityRecord r, boolean shouldBeVisible, boolean isTop) { - int displayId = getDisplayId(); - if (displayId == INVALID_DISPLAY) displayId = DEFAULT_DISPLAY; + ActivityRecord getTopTurnScreenOnActivity() { + return mTopTurnScreenOnActivity; + } - final boolean keyguardOrAodShowing = mStackSupervisor.getKeyguardController() - .isKeyguardOrAodShowing(displayId); - final boolean keyguardLocked = mStackSupervisor.getKeyguardController().isKeyguardLocked(); + /** + * Updates {@link #mTopActivityOccludesKeyguard}, {@link #mTopTurnScreenOnActivity} and + * {@link #mTopDismissingKeyguardActivity} if this task could be visible. + * + */ + void updateKeyguardVisibility(ActivityRecord r, boolean isTop) { final boolean showWhenLocked = r.canShowWhenLocked(); final boolean dismissKeyguard = r.containsDismissKeyguardWindow(); - if (shouldBeVisible) { - if (dismissKeyguard && mTopDismissingKeyguardActivity == null) { - mTopDismissingKeyguardActivity = r; - } - - // Only the top activity may control occluded, as we can't occlude the Keyguard if the - // top app doesn't want to occlude it. - if (isTop) { - mTopActivityOccludesKeyguard |= showWhenLocked; - } - - final boolean canShowWithKeyguard = canShowWithInsecureKeyguard() - && mStackSupervisor.getKeyguardController().canDismissKeyguard(); - if (canShowWithKeyguard) { - return true; - } - } - if (keyguardOrAodShowing) { - // If keyguard is showing, nothing is visible, except if we are able to dismiss Keyguard - // right away and AOD isn't visible. - return shouldBeVisible && mStackSupervisor.getKeyguardController() - .canShowActivityWhileKeyguardShowing(r, dismissKeyguard); - } else if (keyguardLocked) { - return shouldBeVisible && mStackSupervisor.getKeyguardController().canShowWhileOccluded( - dismissKeyguard, showWhenLocked); - } else { - return shouldBeVisible; + final boolean turnScreenOn = r.canTurnScreenOn(); + if (dismissKeyguard && mTopDismissingKeyguardActivity == null) { + mTopDismissingKeyguardActivity = r; } - } - /** - * Check if the display to which this stack is attached has - * {@link Display#FLAG_CAN_SHOW_WITH_INSECURE_KEYGUARD} applied. - */ - boolean canShowWithInsecureKeyguard() { - final DisplayContent displayContent = mDisplayContent; - if (displayContent == null) { - throw new IllegalStateException("Stack is not attached to any display, stackId=" - + getRootTaskId()); + if (turnScreenOn && mTopTurnScreenOnActivity == null) { + mTopTurnScreenOnActivity = r; } - final int flags = displayContent.mDisplay.getFlags(); - return (flags & FLAG_CAN_SHOW_WITH_INSECURE_KEYGUARD) != 0; + // Only the top activity may control occluded, as we can't occlude the Keyguard if the + // top app doesn't want to occlude it. + if (isTop) { + mTopActivityOccludesKeyguard |= showWhenLocked; + } } void checkTranslucentActivityWaiting(ActivityRecord top) { diff --git a/services/core/java/com/android/server/wm/TaskDisplayArea.java b/services/core/java/com/android/server/wm/TaskDisplayArea.java index 6550167683a0..2b32e40f7332 100644 --- a/services/core/java/com/android/server/wm/TaskDisplayArea.java +++ b/services/core/java/com/android/server/wm/TaskDisplayArea.java @@ -1779,7 +1779,8 @@ final class TaskDisplayArea extends DisplayArea<Task> { notifyClients); } } finally { - mAtmService.mStackSupervisor.endActivityVisibilityUpdate(); + mAtmService.mStackSupervisor.endActivityVisibilityUpdate(starting, configChanges, + preserveWindows, notifyClients); } } diff --git a/services/core/java/com/android/server/wm/TaskOrganizerController.java b/services/core/java/com/android/server/wm/TaskOrganizerController.java index 63a595e3bc17..d9290fb18f08 100644 --- a/services/core/java/com/android/server/wm/TaskOrganizerController.java +++ b/services/core/java/com/android/server/wm/TaskOrganizerController.java @@ -38,7 +38,6 @@ import android.os.Binder; import android.os.IBinder; import android.os.RemoteException; import android.util.Slog; -import android.util.SparseBooleanArray; import android.view.SurfaceControl; import android.window.ITaskOrganizer; import android.window.ITaskOrganizerController; @@ -54,7 +53,6 @@ import java.util.HashMap; import java.util.HashSet; import java.util.LinkedList; import java.util.List; -import java.util.Set; import java.util.WeakHashMap; import java.util.function.Consumer; diff --git a/services/core/java/com/android/server/wm/TaskSnapshotController.java b/services/core/java/com/android/server/wm/TaskSnapshotController.java index e3112efdead2..f39fa1b7fbc8 100644 --- a/services/core/java/com/android/server/wm/TaskSnapshotController.java +++ b/services/core/java/com/android/server/wm/TaskSnapshotController.java @@ -16,7 +16,9 @@ package com.android.server.wm; +import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED; import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER; +import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION; import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_SCREENSHOT; import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME; @@ -615,8 +617,8 @@ class TaskSnapshotController { return state.calculateInsets(frame, null /* ignoringVisibilityState */, false /* isScreenRound */, false /* alwaysConsumeSystemBars */, null /* displayCutout */, 0 /* legacySoftInputMode */, 0 /* legacyWindowFlags */, - 0 /* legacySystemUiFlags */, null /* typeSideMap */).getInsets( - WindowInsets.Type.systemBars()).toRect(); + 0 /* legacySystemUiFlags */, TYPE_APPLICATION, WINDOWING_MODE_UNDEFINED, + null /* typeSideMap */).getInsets(WindowInsets.Type.systemBars()).toRect(); } void dump(PrintWriter pw, String prefix) { diff --git a/services/core/java/com/android/server/wm/TaskSnapshotSurface.java b/services/core/java/com/android/server/wm/TaskSnapshotSurface.java index e9ada6be7e7b..100f1bff12a7 100644 --- a/services/core/java/com/android/server/wm/TaskSnapshotSurface.java +++ b/services/core/java/com/android/server/wm/TaskSnapshotSurface.java @@ -67,7 +67,6 @@ import android.os.RemoteException; import android.os.SystemClock; import android.util.MergedConfiguration; import android.util.Slog; -import android.view.DisplayCutout; import android.view.IWindowSession; import android.view.InsetsSourceControl; import android.view.InsetsState; @@ -79,6 +78,7 @@ import android.view.ViewGroup.LayoutParams; import android.view.ViewRootImpl; import android.view.WindowManager; import android.view.WindowManagerGlobal; +import android.window.ClientWindowFrames; import com.android.internal.R; import com.android.internal.annotations.VisibleForTesting; @@ -159,12 +159,8 @@ class TaskSnapshotSurface implements StartingSurface { final IWindowSession session = WindowManagerGlobal.getWindowSession(); window.setSession(session); final SurfaceControl surfaceControl = new SurfaceControl(); - final Rect tmpRect = new Rect(); - final DisplayCutout.ParcelableWrapper tmpCutout = new DisplayCutout.ParcelableWrapper(); - final Rect tmpFrame = new Rect(); + final ClientWindowFrames tmpFrames = new ClientWindowFrames(); final Rect taskBounds; - final Rect tmpContentInsets = new Rect(); - final Rect tmpStableInsets = new Rect(); final InsetsState mTmpInsetsState = new InsetsState(); final InsetsSourceControl[] mTempControls = new InsetsSourceControl[0]; final MergedConfiguration tmpMergedConfiguration = new MergedConfiguration(); @@ -254,8 +250,9 @@ class TaskSnapshotSurface implements StartingSurface { } try { final int res = session.addToDisplay(window, window.mSeq, layoutParams, - View.GONE, activity.getDisplayContent().getDisplayId(), tmpFrame, tmpRect, - tmpRect, tmpCutout, null, mTmpInsetsState, mTempControls); + View.GONE, activity.getDisplayContent().getDisplayId(), tmpFrames.frame, + tmpFrames.contentInsets, tmpFrames.stableInsets, tmpFrames.displayCutout, + null /* outInputChannel */, mTmpInsetsState, mTempControls); if (res < 0) { Slog.w(TAG, "Failed to add snapshot starting window res=" + res); return null; @@ -270,15 +267,14 @@ class TaskSnapshotSurface implements StartingSurface { window.setOuter(snapshotSurface); try { session.relayout(window, window.mSeq, layoutParams, -1, -1, View.VISIBLE, 0, -1, - tmpFrame, tmpContentInsets, tmpRect, tmpStableInsets, tmpRect, - tmpCutout, tmpMergedConfiguration, surfaceControl, mTmpInsetsState, + tmpFrames, tmpMergedConfiguration, surfaceControl, mTmpInsetsState, mTempControls, sTmpSurfaceSize, sTmpSurfaceControl); } catch (RemoteException e) { // Local call. } - final Rect systemBarInsets = getSystemBarInsets(tmpFrame, insetsState); - snapshotSurface.setFrames(tmpFrame, systemBarInsets); + final Rect systemBarInsets = getSystemBarInsets(tmpFrames.frame, insetsState); + snapshotSurface.setFrames(tmpFrames.frame, systemBarInsets); snapshotSurface.drawSnapshot(); return snapshotSurface; } @@ -528,11 +524,9 @@ class TaskSnapshotSurface implements StartingSurface { } @Override - public void resized(Rect frame, Rect contentInsets, Rect visibleInsets, - Rect stableInsets, boolean reportDraw, - MergedConfiguration mergedConfiguration, Rect backDropFrame, boolean forceLayout, - boolean alwaysConsumeSystemBars, int displayId, - DisplayCutout.ParcelableWrapper displayCutout) { + public void resized(ClientWindowFrames frames, boolean reportDraw, + MergedConfiguration mergedConfiguration, boolean forceLayout, + boolean alwaysConsumeSystemBars, int displayId) { if (mergedConfiguration != null && mOuter != null && mOuter.mOrientationOnCreation != mergedConfiguration.getMergedConfiguration().orientation) { diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java index 017747f03ca0..8eb6432e0d52 100644 --- a/services/core/java/com/android/server/wm/WindowManagerService.java +++ b/services/core/java/com/android/server/wm/WindowManagerService.java @@ -258,6 +258,7 @@ import android.view.WindowManager.RemoveContentMode; import android.view.WindowManager.TransitionType; import android.view.WindowManagerGlobal; import android.view.WindowManagerPolicyConstants.PointerEventListener; +import android.window.ClientWindowFrames; import com.android.internal.R; import com.android.internal.annotations.VisibleForTesting; @@ -2065,21 +2066,6 @@ public class WindowManagerService extends IWindowManager.Stub } } - public void getWindowDisplayFrame(Session session, IWindow client, - Rect outDisplayFrame) { - synchronized (mGlobalLock) { - WindowState win = windowForClientLocked(session, client, false); - if (win == null) { - outDisplayFrame.setEmpty(); - return; - } - outDisplayFrame.set(win.getDisplayFrame()); - if (win.inSizeCompatMode()) { - outDisplayFrame.scale(win.mInvGlobalScale); - } - } - } - public void onRectangleOnScreenRequested(IBinder token, Rect rectangle) { synchronized (mGlobalLock) { if (mAccessibilityController != null) { @@ -2115,9 +2101,7 @@ public class WindowManagerService extends IWindowManager.Stub public int relayoutWindow(Session session, IWindow client, int seq, LayoutParams attrs, int requestedWidth, int requestedHeight, int viewVisibility, int flags, - long frameNumber, Rect outFrame, Rect outContentInsets, - Rect outVisibleInsets, Rect outStableInsets, Rect outBackdropFrame, - DisplayCutout.ParcelableWrapper outCutout, MergedConfiguration mergedConfiguration, + long frameNumber, ClientWindowFrames outFrames, MergedConfiguration mergedConfiguration, SurfaceControl outSurfaceControl, InsetsState outInsetsState, InsetsSourceControl[] outActiveControls, Point outSurfaceSize, SurfaceControl outBLASTSurfaceControl) { @@ -2386,10 +2370,6 @@ public class WindowManagerService extends IWindowManager.Stub if (win.mActivityRecord != null) { win.mActivityRecord.updateReportedVisibilityLocked(); } - if (winAnimator.mReportSurfaceResized) { - winAnimator.mReportSurfaceResized = false; - result |= WindowManagerGlobal.RELAYOUT_RES_SURFACE_RESIZED; - } if (displayPolicy.areSystemBarsForcedShownLw(win)) { result |= WindowManagerGlobal.RELAYOUT_RES_CONSUME_ALWAYS_SYSTEM_BARS; } @@ -2419,18 +2399,14 @@ public class WindowManagerService extends IWindowManager.Stub // The last inset values represent the last client state win.updateLastInsetValues(); - win.getCompatFrame(outFrame); - win.getInsetsForRelayout(outContentInsets, outVisibleInsets, - outStableInsets); - outCutout.set(win.getWmDisplayCutout().getDisplayCutout()); - outBackdropFrame.set(win.getBackdropFrame(win.getFrame())); + win.fillClientWindowFrames(outFrames); outInsetsState.set(win.getInsetsState(), win.isClientLocal()); if (DEBUG) { Slog.v(TAG_WM, "Relayout given client " + client.asBinder() + ", requestedWidth=" + requestedWidth + ", requestedHeight=" + requestedHeight + ", viewVisibility=" + viewVisibility - + "\nRelayout returning frame=" + outFrame + + "\nRelayout returning frame=" + outFrames.frame + ", surface=" + outSurfaceControl); } @@ -2440,8 +2416,7 @@ public class WindowManagerService extends IWindowManager.Stub result |= mInTouchMode ? WindowManagerGlobal.RELAYOUT_RES_IN_TOUCH_MODE : 0; if (DEBUG_LAYOUT) { - Slog.v(TAG_WM, - "Relayout complete " + win + ": outFrame=" + outFrame.toShortString()); + Slog.v(TAG_WM, "Relayout complete " + win + ": outFrames=" + outFrames); } win.mInRelayout = false; @@ -5753,19 +5728,6 @@ public class WindowManagerService extends IWindowManager.Stub } @Override - public void setPipVisibility(boolean visible) { - if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.STATUS_BAR) - != PackageManager.PERMISSION_GRANTED) { - throw new SecurityException("Caller does not hold permission " - + android.Manifest.permission.STATUS_BAR); - } - - synchronized (mGlobalLock) { - mPolicy.setPipVisibilityLw(visible); - } - } - - @Override public void statusBarVisibilityChanged(int displayId, int visibility) { if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.STATUS_BAR) != PackageManager.PERMISSION_GRANTED) { diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java index 84a9c750d2d3..721f002a1b41 100644 --- a/services/core/java/com/android/server/wm/WindowState.java +++ b/services/core/java/com/android/server/wm/WindowState.java @@ -209,7 +209,6 @@ import android.util.Slog; import android.util.TimeUtils; import android.util.proto.ProtoOutputStream; import android.view.Display; -import android.view.DisplayCutout; import android.view.DisplayInfo; import android.view.Gravity; import android.view.IApplicationToken; @@ -233,6 +232,7 @@ import android.view.WindowManager; import android.view.animation.Animation; import android.view.animation.AnimationUtils; import android.view.animation.Interpolator; +import android.window.ClientWindowFrames; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.policy.KeyInterceptionInfo; @@ -388,15 +388,6 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP private final Configuration mTempConfiguration = new Configuration(); /** - * The last content insets returned to the client in relayout. We use - * these in the bounds animation to ensure we only observe inset changes - * at the same time that a client resizes it's surface so that we may use - * the geometryAppliesWithResize synchronization mechanism to keep - * the contents in place. - */ - final Rect mLastRelayoutContentInsets = new Rect(); - - /** * Set to true if we are waiting for this window to receive its * given internal insets before laying out other windows based on it. */ @@ -437,6 +428,8 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP private final WindowFrames mWindowFrames = new WindowFrames(); + private final ClientWindowFrames mClientWindowFrames = new ClientWindowFrames(); + /** The frames used to compute a temporal layout appearance. */ private WindowFrames mSimulatedWindowFrames; @@ -1299,7 +1292,10 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP return mWindowFrames.mRelFrame; } - /** Retrieves the frame of the display that this window was last laid out in. */ + /** + * Gets the frame that excludes the area of side insets according to the layout parameter from + * {@link WindowManager.LayoutParams#setFitInsetsSides}. + */ Rect getDisplayFrame() { return mWindowFrames.mDisplayFrame; } @@ -3585,6 +3581,39 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP return wpc != null && wpc.registeredForDisplayConfigChanges(); } + void fillClientWindowFrames(ClientWindowFrames outFrames) { + outFrames.frame.set(mWindowFrames.mCompatFrame); + outFrames.displayFrame.set(mWindowFrames.mDisplayFrame); + if (mInvGlobalScale != 1.0f && inSizeCompatMode()) { + outFrames.displayFrame.scale(mInvGlobalScale); + } + + final Rect backdropFrame = outFrames.backdropFrame; + // When the task is docked, we send fullscreen sized backdropFrame as soon as resizing + // start even if we haven't received the relayout window, so that the client requests + // the relayout sooner. When dragging stops, backdropFrame needs to stay fullscreen + // until the window to small size, otherwise the multithread renderer will shift last + // one or more frame to wrong offset. So here we send fullscreen backdrop if either + // isDragResizing() or isDragResizeChanged() is true. + final boolean resizing = isDragResizing() || isDragResizeChanged(); + if (!resizing || getWindowConfiguration().useWindowFrameForBackdrop()) { + // Surface position is now inherited from parent, and BackdropFrameRenderer uses + // backdrop frame to position content. Thus we just keep the size of backdrop frame, + // and remove the offset to avoid double offset from display origin. + backdropFrame.set(outFrames.frame); + backdropFrame.offsetTo(0, 0); + } else { + final DisplayInfo displayInfo = getDisplayInfo(); + backdropFrame.set(0, 0, displayInfo.logicalWidth, displayInfo.logicalHeight); + } + outFrames.displayCutout.set(mWindowFrames.mDisplayCutout.getDisplayCutout()); + + // TODO(b/149813814): Remove legacy insets. + outFrames.contentInsets.set(mWindowFrames.mLastContentInsets); + outFrames.visibleInsets.set(mWindowFrames.mLastVisibleInsets); + outFrames.stableInsets.set(mWindowFrames.mLastStableInsets); + } + void reportResized() { // If the activity is scheduled to relaunch, skip sending the resized to ViewRootImpl now // since it will be destroyed anyway. This also prevents the client from receiving @@ -3616,23 +3645,18 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP mWinAnimator.mSurfaceResized = false; mWindowFrames.resetInsetsChanged(); - final Rect frame = mWindowFrames.mCompatFrame; - final Rect contentInsets = mWindowFrames.mLastContentInsets; - final Rect visibleInsets = mWindowFrames.mLastVisibleInsets; - final Rect stableInsets = mWindowFrames.mLastStableInsets; final MergedConfiguration mergedConfiguration = mLastReportedConfiguration; final boolean reportDraw = mWinAnimator.mDrawState == DRAW_PENDING || useBLASTSync() || !mRedrawForSyncReported; final boolean forceRelayout = reportOrientation || isDragResizeChanged() || !mRedrawForSyncReported; final int displayId = getDisplayId(); - final DisplayCutout displayCutout = getWmDisplayCutout().getDisplayCutout(); + fillClientWindowFrames(mClientWindowFrames); mRedrawForSyncReported = true; try { - mClient.resized(frame, contentInsets, visibleInsets, stableInsets, reportDraw, - mergedConfiguration, getBackdropFrame(frame), forceRelayout, + mClient.resized(mClientWindowFrames, reportDraw, mergedConfiguration, forceRelayout, getDisplayContent().getDisplayPolicy().areSystemBarsForcedShownLw(this), - displayId, new DisplayCutout.ParcelableWrapper(displayCutout)); + displayId); if (mWmService.mAccessibilityController != null) { mWmService.mAccessibilityController.onSomeWindowResizedOrMovedLocked(displayId); @@ -3738,27 +3762,6 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP return (mAttrs.insetsFlags.behavior & BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE) != 0; } - Rect getBackdropFrame(Rect frame) { - // When the task is docked, we send fullscreen sized backDropFrame as soon as resizing - // start even if we haven't received the relayout window, so that the client requests - // the relayout sooner. When dragging stops, backDropFrame needs to stay fullscreen - // until the window to small size, otherwise the multithread renderer will shift last - // one or more frame to wrong offset. So here we send fullscreen backdrop if either - // isDragResizing() or isDragResizeChanged() is true. - boolean resizing = isDragResizing() || isDragResizeChanged(); - if (getWindowConfiguration().useWindowFrameForBackdrop() || !resizing) { - // Surface position is now inherited from parent, and BackdropFrameRenderer uses - // backdrop frame to position content. Thus we just keep the size of backdrop frame, and - // remove the offset to avoid double offset from display origin. - mTmpRect.set(frame); - mTmpRect.offsetTo(0, 0); - return mTmpRect; - } - final DisplayInfo displayInfo = getDisplayInfo(); - mTmpRect.set(0, 0, displayInfo.logicalWidth, displayInfo.logicalHeight); - return mTmpRect; - } - private int getRootTaskId() { final Task stack = getRootTask(); if (stack == null) { @@ -5670,18 +5673,6 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP } } - /** - * Copy the inset values over so they can be sent back to the client when a relayout occurs. - */ - void getInsetsForRelayout(Rect outContentInsets, Rect outVisibleInsets, - Rect outStableInsets) { - outContentInsets.set(mWindowFrames.mContentInsets); - outVisibleInsets.set(mWindowFrames.mVisibleInsets); - outStableInsets.set(mWindowFrames.mStableInsets); - - mLastRelayoutContentInsets.set(mWindowFrames.mContentInsets); - } - void getContentInsets(Rect outContentInsets) { outContentInsets.set(mWindowFrames.mContentInsets); } diff --git a/services/core/java/com/android/server/wm/WindowStateAnimator.java b/services/core/java/com/android/server/wm/WindowStateAnimator.java index 1bd712c3638b..5e814005a5e2 100644 --- a/services/core/java/com/android/server/wm/WindowStateAnimator.java +++ b/services/core/java/com/android/server/wm/WindowStateAnimator.java @@ -126,11 +126,7 @@ class WindowStateAnimator { * we must tell them application to resize (and thus redraw itself). */ boolean mSurfaceResized; - /** - * Whether we should inform the client on next relayoutWindow that - * the surface has been resized since last time. - */ - boolean mReportSurfaceResized; + WindowSurfaceController mSurfaceController; private WindowSurfaceController mPendingDestroySurface; @@ -872,7 +868,6 @@ class WindowStateAnimator { } if (mSurfaceResized) { - mReportSurfaceResized = true; mWin.getDisplayContent().pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER; } } diff --git a/services/core/jni/com_android_server_am_CachedAppOptimizer.cpp b/services/core/jni/com_android_server_am_CachedAppOptimizer.cpp index 7e9e11d209a6..95d4ba7c199a 100644 --- a/services/core/jni/com_android_server_am_CachedAppOptimizer.cpp +++ b/services/core/jni/com_android_server_am_CachedAppOptimizer.cpp @@ -29,6 +29,7 @@ #include <nativehelper/JNIHelp.h> #include <android_runtime/AndroidRuntime.h> +#include <binder/IPCThreadState.h> #include <jni.h> #include <processgroup/processgroup.h> @@ -90,11 +91,20 @@ static void com_android_server_am_CachedAppOptimizer_enableFreezerInternal( } } +static void com_android_server_am_CachedAppOptimizer_freezeBinder( + JNIEnv *env, jobject clazz, jint pid, jboolean freeze) { + + if (IPCThreadState::freeze(pid, freeze, 100 /* timeout [ms] */) != 0) { + jniThrowException(env, "java/lang/RuntimeException", "Unable to freeze/unfreeze binder"); + } +} + static const JNINativeMethod sMethods[] = { /* name, signature, funcPtr */ {"compactSystem", "()V", (void*)com_android_server_am_CachedAppOptimizer_compactSystem}, {"enableFreezerInternal", "(Z)V", (void*)com_android_server_am_CachedAppOptimizer_enableFreezerInternal}, + {"freezeBinder", "(IZ)V", (void*)com_android_server_am_CachedAppOptimizer_freezeBinder} }; int register_android_server_am_CachedAppOptimizer(JNIEnv* env) diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java index 80455833a3eb..b6f0f9ffe001 100644 --- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java +++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java @@ -7132,9 +7132,22 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { return (deviceOwner != null) ? deviceOwner.keepUninstalledPackages : null; } + /** + * Logs a warning when the device doesn't have {@code PackageManager.FEATURE_DEVICE_ADMIN}. + * + * @param message action that was not executed; should not end with a period because the missing + * feature will be appended to it. + */ + private void logMissingFeatureAction(String message) { + Slog.w(LOG_TAG, message + " because device does not have the " + + PackageManager.FEATURE_DEVICE_ADMIN + " feature."); + } + @Override public boolean setDeviceOwner(ComponentName admin, String ownerName, int userId) { if (!mHasFeature) { + logMissingFeatureAction("Cannot set " + ComponentName.flattenToShortString(admin) + + " as device owner for user " + userId); return false; } if (admin == null @@ -7456,6 +7469,8 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { @Override public boolean setProfileOwner(ComponentName who, String ownerName, int userHandle) { if (!mHasFeature) { + logMissingFeatureAction("Cannot set " + ComponentName.flattenToShortString(who) + + " as profile owner for user " + userHandle); return false; } if (who == null @@ -7676,6 +7691,8 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { @Override public void setUserProvisioningState(int newState, int userHandle) { if (!mHasFeature) { + logMissingFeatureAction("Cannot set provisioning state " + newState + " for user " + + userHandle); return; } @@ -7753,6 +7770,8 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { @Override public void setProfileEnabled(ComponentName who) { if (!mHasFeature) { + logMissingFeatureAction("Cannot enable profile for " + + ComponentName.flattenToShortString(who)); return; } Objects.requireNonNull(who, "ComponentName is null"); diff --git a/services/profcollect/src/com/android/server/profcollect/ProfcollectForwardingService.java b/services/profcollect/src/com/android/server/profcollect/ProfcollectForwardingService.java index 12c69eaa0f8d..ddd1f7568224 100644 --- a/services/profcollect/src/com/android/server/profcollect/ProfcollectForwardingService.java +++ b/services/profcollect/src/com/android/server/profcollect/ProfcollectForwardingService.java @@ -16,6 +16,11 @@ package com.android.server.profcollect; +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.content.Intent; import android.os.Handler; @@ -34,6 +39,7 @@ import com.android.server.wm.ActivityMetricsLaunchObserverRegistry; import com.android.server.wm.ActivityTaskManagerInternal; import java.util.concurrent.ThreadLocalRandom; +import java.util.concurrent.TimeUnit; /** * System-server-local proxy into the {@code IProfcollectd} native service. @@ -41,28 +47,43 @@ import java.util.concurrent.ThreadLocalRandom; public final class ProfcollectForwardingService extends SystemService { public static final String LOG_TAG = "ProfcollectForwardingService"; + private static final boolean DEBUG = Log.isLoggable(LOG_TAG, Log.DEBUG); + + private static final long BG_PROCESS_PERIOD = DEBUG + ? TimeUnit.MINUTES.toMillis(1) + : TimeUnit.DAYS.toMillis(1); + private IProfCollectd mIProfcollect; - private ProfcollectForwardingService mSelfService; + private static ProfcollectForwardingService sSelfService; private final Handler mHandler = new ProfcollectdHandler(IoThread.getHandler().getLooper()); public ProfcollectForwardingService(Context context) { super(context); - if (mSelfService != null) { + if (sSelfService != null) { throw new AssertionError("only one service instance allowed"); } - mSelfService = this; + sSelfService = this; } @Override public void onStart() { - Log.i(LOG_TAG, "Profcollect forwarding service start"); - connectNativeService(); - if (mIProfcollect == null) { - return; + if (DEBUG) { + Log.d(LOG_TAG, "Profcollect forwarding service start"); } - if (serviceHasSupportedTraceProvider()) { - registerObservers(); + connectNativeService(); + } + + @Override + public void onBootPhase(int phase) { + if (phase == PHASE_BOOT_COMPLETED) { + if (mIProfcollect == null) { + return; + } + if (serviceHasSupportedTraceProvider()) { + registerObservers(); + } + ProfcollectBGJobService.schedule(getContext()); } } @@ -130,6 +151,50 @@ public final class ProfcollectForwardingService extends SystemService { } } + /** + * Background trace process service. + */ + public static class ProfcollectBGJobService extends JobService { + // Unique ID in system service + private static final int JOB_IDLE_PROCESS = 260817; + private static final ComponentName JOB_SERVICE_NAME = new ComponentName( + "android", + ProfcollectBGJobService.class.getName()); + + /** + * Attach the service to the system job scheduler. + */ + public static void schedule(Context context) { + JobScheduler js = context.getSystemService(JobScheduler.class); + + js.schedule(new JobInfo.Builder(JOB_IDLE_PROCESS, JOB_SERVICE_NAME) + .setRequiresDeviceIdle(true) + .setRequiresCharging(true) + .setPeriodic(BG_PROCESS_PERIOD) + .build()); + } + + @Override + public boolean onStartJob(JobParameters params) { + if (DEBUG) { + Log.d(LOG_TAG, "Starting background process job"); + } + + try { + sSelfService.mIProfcollect.ProcessProfile(); + } catch (RemoteException e) { + Log.e(LOG_TAG, e.getMessage()); + } + return true; + } + + @Override + public boolean onStopJob(JobParameters params) { + // TODO: Handle this? + return false; + } + } + // Event observers private void registerObservers() { registerAppLaunchObserver(); @@ -155,7 +220,9 @@ public final class ProfcollectForwardingService extends SystemService { int randomNum = ThreadLocalRandom.current().nextInt(100); if (randomNum < traceFrequency) { try { - Log.i(LOG_TAG, "Tracing on app launch event: " + packageName); + if (DEBUG) { + Log.d(LOG_TAG, "Tracing on app launch event: " + packageName); + } mIProfcollect.TraceOnce("applaunch"); } catch (RemoteException e) { Log.e(LOG_TAG, e.getMessage()); diff --git a/services/tests/PackageManagerServiceTests/host/Android.bp b/services/tests/PackageManagerServiceTests/host/Android.bp index 4f636efc7c06..a941331fcec9 100644 --- a/services/tests/PackageManagerServiceTests/host/Android.bp +++ b/services/tests/PackageManagerServiceTests/host/Android.bp @@ -21,12 +21,15 @@ java_test_host { "truth-prebuilt", ], static_libs: [ + "cts-host-utils", "frameworks-base-hostutils", "PackageManagerServiceHostTestsIntentVerifyUtils", ], test_suites: ["general-tests"], java_resources: [ + ":PackageManagerTestAppDeclaresStaticLibrary", ":PackageManagerTestAppStub", + ":PackageManagerTestAppUsesStaticLibrary", ":PackageManagerTestAppVersion1", ":PackageManagerTestAppVersion2", ":PackageManagerTestAppVersion3", diff --git a/services/tests/PackageManagerServiceTests/host/src/com/android/server/pm/test/HostUtils.kt b/services/tests/PackageManagerServiceTests/host/src/com/android/server/pm/test/HostUtils.kt index 24c714c0d5f2..9399030e057c 100644 --- a/services/tests/PackageManagerServiceTests/host/src/com/android/server/pm/test/HostUtils.kt +++ b/services/tests/PackageManagerServiceTests/host/src/com/android/server/pm/test/HostUtils.kt @@ -18,6 +18,7 @@ package com.android.server.pm.test import com.android.internal.util.test.SystemPreparer import com.android.tradefed.device.ITestDevice +import com.google.common.truth.Truth import org.junit.rules.TemporaryFolder import java.io.File import java.io.FileOutputStream @@ -48,6 +49,44 @@ internal fun ITestDevice.installJavaResourceApk( internal fun ITestDevice.uninstallPackages(vararg pkgNames: String) = pkgNames.forEach { uninstallPackage(it) } +/** + * Retry [block] a total of [maxAttempts] times, waiting [millisBetweenAttempts] milliseconds + * between each iteration, until a non-null result is returned, providing that result back to the + * caller. + * + * If an [AssertionError] is thrown by the [block] and a non-null result is never returned, that + * error will be re-thrown. This allows the use of [Truth.assertThat] to indicate success while + * providing a meaningful error message in case of failure. + */ +internal fun <T> retryUntilNonNull( + maxAttempts: Int = 10, + millisBetweenAttempts: Long = 1000, + block: () -> T? +): T { + var attempt = 0 + var failure: AssertionError? = null + while (attempt++ < maxAttempts) { + val result = try { + block() + } catch (e: AssertionError) { + failure = e + null + } + + if (result != null) { + return result + } else { + Thread.sleep(millisBetweenAttempts) + } + } + + throw failure ?: AssertionError("Never succeeded") +} + +internal fun retryUntilSuccess(block: () -> Boolean) { + retryUntilNonNull { block().takeIf { it } } +} + internal object HostUtils { fun getDataDir(device: ITestDevice, pkgName: String) = @@ -78,6 +117,25 @@ internal object HostUtils { * dumpsys package and therefore device.getAppPackageInfo doesn't work immediately after reboot, * so the following methods parse the package dump directly to see if the path matches. */ + + /** + * Reads the pm dump for a package name starting from the Packages: metadata section until + * the following section. + */ + fun packageSection( + device: ITestDevice, + pkgName: String, + sectionName: String = "Packages" + ) = device.executeShellCommand("pm dump $pkgName") + .lineSequence() + .dropWhile { !it.startsWith(sectionName) } // Wait until the header + .drop(1) // Drop the header itself + .takeWhile { + // Until next top level header, a non-empty line that doesn't start with whitespace + it.isEmpty() || it.first().isWhitespace() + } + .map(String::trim) + fun getCodePaths(device: ITestDevice, pkgName: String) = device.executeShellCommand("pm dump $pkgName") .lineSequence() @@ -87,14 +145,7 @@ internal object HostUtils { .toList() private fun userIdLineSequence(device: ITestDevice, pkgName: String) = - device.executeShellCommand("pm dump $pkgName") - .lineSequence() - .dropWhile { !it.startsWith("Packages:") } - .takeWhile { - !it.startsWith("Hidden system packages:") && - !it.startsWith("Queries:") - } - .map(String::trim) + packageSection(device, pkgName) .filter { it.startsWith("User ") } fun getUserIdToPkgEnabledState(device: ITestDevice, pkgName: String) = diff --git a/services/tests/PackageManagerServiceTests/host/src/com/android/server/pm/test/SdCardEjectionTests.kt b/services/tests/PackageManagerServiceTests/host/src/com/android/server/pm/test/SdCardEjectionTests.kt new file mode 100644 index 000000000000..9f9e6a310d0b --- /dev/null +++ b/services/tests/PackageManagerServiceTests/host/src/com/android/server/pm/test/SdCardEjectionTests.kt @@ -0,0 +1,255 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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.test + +import android.cts.host.utils.DeviceJUnit4ClassRunnerWithParameters +import android.cts.host.utils.DeviceJUnit4Parameterized +import com.android.tradefed.testtype.junit4.BaseHostJUnit4Test +import com.google.common.truth.Truth.assertThat +import org.junit.After +import org.junit.Before +import org.junit.Rule +import org.junit.Test +import org.junit.rules.TemporaryFolder +import org.junit.runner.RunWith +import org.junit.runners.Parameterized +import java.io.File +import java.util.regex.Pattern + +/** + * Verifies PackageManagerService behavior when an app is moved to an adoptable storage device. + * + * Also has the effect of verifying system behavior when the PackageSetting for a package has no + * corresponding AndroidPackage which can be parsed from the APK on disk. This is done by removing + * the storage device and causing a reboot, at which point PMS will read PackageSettings from disk + * and fail to find the package path. + */ +@RunWith(DeviceJUnit4Parameterized::class) +@Parameterized.UseParametersRunnerFactory( + DeviceJUnit4ClassRunnerWithParameters.RunnerFactory::class) +class SdCardEjectionTests : BaseHostJUnit4Test() { + + companion object { + private const val VERSION_DECLARES = "PackageManagerTestAppDeclaresStaticLibrary.apk" + private const val VERSION_DECLARES_PKG_NAME = + "com.android.server.pm.test.test_app_declares_static_library" + private const val VERSION_USES = "PackageManagerTestAppUsesStaticLibrary.apk" + private const val VERSION_USES_PKG_NAME = + "com.android.server.pm.test.test_app_uses_static_library" + + // TODO(chiuwinson): Use the HostUtils constants when merged + private const val TEST_PKG_NAME = "com.android.server.pm.test.test_app" + private const val VERSION_ONE = "PackageManagerTestAppVersion1.apk" + + @Parameterized.Parameters(name = "reboot={0}") + @JvmStatic + fun parameters() = arrayOf(false, true) + + data class Volume( + val diskId: String, + val fsUuid: String + ) + } + + @Rule + @JvmField + val tempFolder = TemporaryFolder() + + @Parameterized.Parameter(0) + @JvmField + var reboot: Boolean = false + + @Before + @After + fun removePackagesAndDeleteVirtualDisk() { + device.uninstallPackages(VERSION_ONE, VERSION_USES_PKG_NAME, VERSION_DECLARES_PKG_NAME) + removeVirtualDisk() + device.reboot() + } + + @Test + fun launchActivity() { + val hostApkFile = HostUtils.copyResourceToHostFile(VERSION_ONE, tempFolder.newFile()) + assertThat(device.installPackage(hostApkFile, true)).isNull() + + val errorRegex = Pattern.compile("error", Pattern.CASE_INSENSITIVE) + fun assertStartResponse(launched: Boolean) { + val response = device.executeShellCommand("am start -n $TEST_PKG_NAME/.TestActivity") + if (launched) { + assertThat(response).doesNotContainMatch(errorRegex) + } else { + assertThat(response).containsMatch(errorRegex) + } + } + + assertStartResponse(launched = true) + + val volume = initializeVirtualDisk() + + movePackage(TEST_PKG_NAME, volume) + assertStartResponse(launched = true) + + unmount(volume, TEST_PKG_NAME) + assertStartResponse(launched = false) + + remount(volume, hostApkFile, TEST_PKG_NAME) + assertStartResponse(launched = true) + } + + @Test + fun uninstallStaticLibraryInUse() { + assertThat(device.installJavaResourceApk(tempFolder, VERSION_DECLARES)).isNull() + + val usesApkFile = HostUtils.copyResourceToHostFile(VERSION_USES, tempFolder.newFile()) + assertThat(device.installPackage(usesApkFile, true)).isNull() + + fun assertUninstallFails() = assertThat(device.uninstallPackage(VERSION_DECLARES_PKG_NAME)) + .isEqualTo("DELETE_FAILED_USED_SHARED_LIBRARY") + + assertUninstallFails() + + val volume = initializeVirtualDisk() + + movePackage(VERSION_USES_PKG_NAME, volume) + assertUninstallFails() + + unmount(volume, VERSION_USES_PKG_NAME) + assertUninstallFails() + + remount(volume, usesApkFile, VERSION_USES_PKG_NAME) + assertUninstallFails() + + // Check that install in the correct order (uses first) passes + assertThat(device.uninstallPackage(VERSION_USES_PKG_NAME)).isNull() + assertThat(device.uninstallPackage(VERSION_DECLARES_PKG_NAME)).isNull() + } + + private fun initializeVirtualDisk(): Volume { + // Rather than making any assumption about what disks/volumes exist on the device, + // save the existing disks/volumes to compare and see when a new one pops up, assuming + // it was created as the result of the calls in this test. + val existingDisks = device.executeShellCommand("sm list-disks adoptable").lines() + val existingVolumes = device.executeShellCommand("sm list-volumes private").lines() + device.executeShellCommand("sm set-virtual-disk true") + + val diskId = retryUntilNonNull { + device.executeShellCommand("sm list-disks adoptable") + .lines() + .filterNot(existingDisks::contains) + .filterNot(String::isEmpty) + .firstOrNull() + } + + device.executeShellCommand("sm partition $diskId private") + + return retrieveNewVolume(existingVolumes) + } + + private fun retrieveNewVolume(existingVolumes: List<String>): Volume { + val newVolume = retryUntilNonNull { + device.executeShellCommand("sm list-volumes private") + .lines() + .toMutableList() + .apply { removeAll(existingVolumes) } + .firstOrNull() + ?.takeIf { it.isNotEmpty() } + } + + val sections = newVolume.split(" ") + return Volume(diskId = sections.first(), fsUuid = sections.last()).also { + assertThat(it.diskId).isNotEmpty() + assertThat(it.fsUuid).isNotEmpty() + } + } + + private fun removeVirtualDisk() { + device.executeShellCommand("sm set-virtual-disk false") + retryUntilSuccess { + !device.executeShellCommand("sm list-volumes").contains("ejecting") + } + } + + private fun movePackage(pkgName: String, volume: Volume) { + // TODO(b/167241596): oat dir must exist for a move install + val codePath = HostUtils.getCodePaths(device, pkgName).first() + device.executeShellCommand("mkdir $codePath/oat") + assertThat(device.executeShellCommand( + "pm move-package $pkgName ${volume.fsUuid}").trim()) + .isEqualTo("Success") + } + + private fun unmount(volume: Volume, pkgName: String) { + assertThat(device.executeShellCommand("sm unmount ${volume.diskId}")).isEmpty() + if (reboot) { + // The system automatically mounts the virtual disk on startup, which would mean the + // app files are available to the system. To prevent this, disable the disk entirely. + // TODO: There must be a better way to prevent it from auto-mounting. + removeVirtualDisk() + device.reboot() + } else { + // Because PackageManager unmount scan is asynchronous, need to retry until the package + // has been unloaded. This only has to be done in the non-reboot case. Reboot will + // clear the data structure by its nature. + retryUntilSuccess { + // The compiler section will print the state of the physical APK + HostUtils.packageSection(device, pkgName, sectionName = "Compiler stats") + .any { it.contains("Unable to find package: $pkgName") } + } + } + } + + private fun remount(volume: Volume, hostApkFile: File, pkgName: String) { + if (reboot) { + // Because the disk was destroyed when unmounting, it now has to be rebuilt manually. + // This enables a new virtual disk, unmounts it, mutates its UUID to match the previous + // partition's, remounts it, and pushes the base.apk back onto the device. This + // simulates the same disk being re-inserted. This is very hacky. + val newVolume = initializeVirtualDisk() + val mountPoint = device.executeShellCommand("mount") + .lineSequence() + .first { it.contains(newVolume.fsUuid) } + .takeWhile { !it.isWhitespace() } + + device.executeShellCommand("sm unmount ${newVolume.diskId}") + + // Save without renamed UUID to compare and see when the renamed pops up + val existingVolumes = device.executeShellCommand("sm list-volumes private").lines() + + device.executeShellCommand("make_f2fs -U ${volume.fsUuid} $mountPoint") + device.executeShellCommand("sm mount ${newVolume.diskId}") + + val reparsedVolume = retrieveNewVolume(existingVolumes) + assertThat(reparsedVolume.fsUuid).isEqualTo(volume.fsUuid) + + val codePath = HostUtils.getCodePaths(device, pkgName).first() + device.pushFile(hostApkFile, "$codePath/base.apk") + + // Unmount so following remount will re-kick package scan + device.executeShellCommand("sm unmount ${newVolume.diskId}") + } + + device.executeShellCommand("sm mount ${volume.diskId}") + + // Because PackageManager remount scan is asynchronous, need to retry until the package + // has been loaded and added to the internal structures. Otherwise resolution will fail. + retryUntilSuccess { + // The compiler section will print the state of the physical APK + HostUtils.packageSection(device, pkgName, sectionName = "Compiler stats") + .none { it.contains("Unable to find package: $pkgName") } + } + } +} diff --git a/services/tests/PackageManagerServiceTests/host/test-apps/Android.bp b/services/tests/PackageManagerServiceTests/host/test-apps/Generic/Android.bp index 4a3076e4736a..4a3076e4736a 100644 --- a/services/tests/PackageManagerServiceTests/host/test-apps/Android.bp +++ b/services/tests/PackageManagerServiceTests/host/test-apps/Generic/Android.bp diff --git a/services/tests/PackageManagerServiceTests/host/test-apps/AndroidManifestOriginalOverride.xml b/services/tests/PackageManagerServiceTests/host/test-apps/Generic/AndroidManifestOriginalOverride.xml index cba580e44065..cba580e44065 100644 --- a/services/tests/PackageManagerServiceTests/host/test-apps/AndroidManifestOriginalOverride.xml +++ b/services/tests/PackageManagerServiceTests/host/test-apps/Generic/AndroidManifestOriginalOverride.xml diff --git a/services/tests/PackageManagerServiceTests/host/test-apps/AndroidManifestVersion1.xml b/services/tests/PackageManagerServiceTests/host/test-apps/Generic/AndroidManifestVersion1.xml index efc7372a177c..05b6248e761e 100644 --- a/services/tests/PackageManagerServiceTests/host/test-apps/AndroidManifestVersion1.xml +++ b/services/tests/PackageManagerServiceTests/host/test-apps/Generic/AndroidManifestVersion1.xml @@ -25,4 +25,9 @@ android:protectionLevel="normal" /> + <application> + <activity android:name="com.android.server.pm.test.test_app.TestActivity" + android:label="PackageManagerTestApp" /> + </application> + </manifest> diff --git a/services/tests/PackageManagerServiceTests/host/test-apps/AndroidManifestVersion2.xml b/services/tests/PackageManagerServiceTests/host/test-apps/Generic/AndroidManifestVersion2.xml index 620054c5dd57..d6eb3e02f7f0 100644 --- a/services/tests/PackageManagerServiceTests/host/test-apps/AndroidManifestVersion2.xml +++ b/services/tests/PackageManagerServiceTests/host/test-apps/Generic/AndroidManifestVersion2.xml @@ -25,4 +25,6 @@ android:protectionLevel="normal" /> + <application/> + </manifest> diff --git a/services/tests/PackageManagerServiceTests/host/test-apps/AndroidManifestVersion3.xml b/services/tests/PackageManagerServiceTests/host/test-apps/Generic/AndroidManifestVersion3.xml index 1997771783dd..90317cb6cec9 100644 --- a/services/tests/PackageManagerServiceTests/host/test-apps/AndroidManifestVersion3.xml +++ b/services/tests/PackageManagerServiceTests/host/test-apps/Generic/AndroidManifestVersion3.xml @@ -25,4 +25,6 @@ android:protectionLevel="normal" /> + <application/> + </manifest> diff --git a/services/tests/PackageManagerServiceTests/host/test-apps/AndroidManifestVersion4.xml b/services/tests/PackageManagerServiceTests/host/test-apps/Generic/AndroidManifestVersion4.xml index d6ade0304189..795c3c105951 100644 --- a/services/tests/PackageManagerServiceTests/host/test-apps/AndroidManifestVersion4.xml +++ b/services/tests/PackageManagerServiceTests/host/test-apps/Generic/AndroidManifestVersion4.xml @@ -25,4 +25,6 @@ android:protectionLevel="normal" /> + <application/> + </manifest> diff --git a/services/tests/PackageManagerServiceTests/host/test-apps/Generic/src/com/android/server/pm/test/test_app/TestActivity.kt b/services/tests/PackageManagerServiceTests/host/test-apps/Generic/src/com/android/server/pm/test/test_app/TestActivity.kt new file mode 100644 index 000000000000..0c9b8d481fa5 --- /dev/null +++ b/services/tests/PackageManagerServiceTests/host/test-apps/Generic/src/com/android/server/pm/test/test_app/TestActivity.kt @@ -0,0 +1,21 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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.test.test_app + +import android.app.Activity + +class TestActivity : Activity() diff --git a/services/tests/PackageManagerServiceTests/host/test-apps/UsesStaticLibrary/Android.bp b/services/tests/PackageManagerServiceTests/host/test-apps/UsesStaticLibrary/Android.bp new file mode 100644 index 000000000000..58f17f253a24 --- /dev/null +++ b/services/tests/PackageManagerServiceTests/host/test-apps/UsesStaticLibrary/Android.bp @@ -0,0 +1,24 @@ +// Copyright (C) 2020 The Android Open Source Project +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +android_test_helper_app { + name: "PackageManagerTestAppDeclaresStaticLibrary", + manifest: "AndroidManifestDeclaresStaticLibrary.xml", + certificate: ":FrameworksCoreTests_keyset_A_cert", +} + +android_test_helper_app { + name: "PackageManagerTestAppUsesStaticLibrary", + manifest: "AndroidManifestUsesStaticLibrary.xml", +} diff --git a/services/tests/PackageManagerServiceTests/host/test-apps/UsesStaticLibrary/AndroidManifestDeclaresStaticLibrary.xml b/services/tests/PackageManagerServiceTests/host/test-apps/UsesStaticLibrary/AndroidManifestDeclaresStaticLibrary.xml new file mode 100644 index 000000000000..8a6c01ab2ba0 --- /dev/null +++ b/services/tests/PackageManagerServiceTests/host/test-apps/UsesStaticLibrary/AndroidManifestDeclaresStaticLibrary.xml @@ -0,0 +1,24 @@ +<?xml version="1.0" encoding="utf-8"?><!-- + ~ Copyright (C) 2020 The Android Open Source Project + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT 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.server.pm.test.test_app_declares_static_library"> + + <application> + <static-library android:name="com.android.server.pm.test.static_library" + android:version="1" /> + </application> + +</manifest> diff --git a/services/tests/PackageManagerServiceTests/host/test-apps/UsesStaticLibrary/AndroidManifestUsesStaticLibrary.xml b/services/tests/PackageManagerServiceTests/host/test-apps/UsesStaticLibrary/AndroidManifestUsesStaticLibrary.xml new file mode 100644 index 000000000000..82d9ac46d7d7 --- /dev/null +++ b/services/tests/PackageManagerServiceTests/host/test-apps/UsesStaticLibrary/AndroidManifestUsesStaticLibrary.xml @@ -0,0 +1,34 @@ +<?xml version="1.0" encoding="utf-8"?><!-- + ~ Copyright (C) 2020 The Android Open Source Project + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT 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.server.pm.test.test_app_uses_static_library"> + + <application> + <activity android:name="com.android.server.pm.test.static_library.TestActivity" + android:label="TestActivity" + android:exported="true"> + <intent-filter> + <action android:name="android.intent.action.MAIN" /> + <category android:name="android.intent.category.LAUNCHER" /> + </intent-filter> + </activity> + + <uses-static-library android:name="com.android.server.pm.test.static_library" + android:certDigest="1F:BE:5F:FB:B0:AD:DC:0C:CD:BF:22:B9:8A:2F:5A:58:A5:C8:29:80:E1:30:2F:65:0E:6B:CA:ED:03:82:BF:CF" + android:version="1" /> + </application> + +</manifest> diff --git a/services/tests/PackageManagerServiceTests/host/test-apps/UsesStaticLibrary/src/com/android/server/pm/test/static_library/TestActivity.kt b/services/tests/PackageManagerServiceTests/host/test-apps/UsesStaticLibrary/src/com/android/server/pm/test/static_library/TestActivity.kt new file mode 100644 index 000000000000..fa85258cd95b --- /dev/null +++ b/services/tests/PackageManagerServiceTests/host/test-apps/UsesStaticLibrary/src/com/android/server/pm/test/static_library/TestActivity.kt @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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.test.static_library + +import android.app.Activity +import android.graphics.Color +import android.os.Bundle +import android.view.ViewGroup +import android.widget.FrameLayout + +class TestActivity : Activity() { + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + setContentView(FrameLayout(this).apply { + setBackgroundColor(Color.BLUE) + }, ViewGroup.LayoutParams( + ViewGroup.LayoutParams.MATCH_PARENT, + ViewGroup.LayoutParams.MATCH_PARENT + )) + } +} diff --git a/services/tests/mockingservicestests/src/com/android/server/DeviceIdleControllerTest.java b/services/tests/mockingservicestests/src/com/android/server/DeviceIdleControllerTest.java index 6cd083e11754..f4c6918c0e96 100644 --- a/services/tests/mockingservicestests/src/com/android/server/DeviceIdleControllerTest.java +++ b/services/tests/mockingservicestests/src/com/android/server/DeviceIdleControllerTest.java @@ -67,7 +67,6 @@ import static org.mockito.Mockito.verify; import android.app.ActivityManagerInternal; import android.app.AlarmManager; import android.app.IActivityManager; -import android.content.ContentResolver; import android.content.Context; import android.content.Intent; import android.hardware.Sensor; @@ -87,6 +86,7 @@ import android.os.PowerManager; import android.os.PowerManagerInternal; import android.os.PowerSaveState; import android.os.SystemClock; +import android.provider.DeviceConfig; import androidx.test.runner.AndroidJUnit4; @@ -99,6 +99,7 @@ import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.ArgumentCaptor; +import org.mockito.ArgumentMatchers; import org.mockito.InOrder; import org.mockito.Mock; import org.mockito.MockitoSession; @@ -106,6 +107,8 @@ import org.mockito.invocation.InvocationOnMock; import org.mockito.quality.Strictness; import org.mockito.stubbing.Answer; +import java.util.concurrent.Executor; + /** * Tests for {@link com.android.server.DeviceIdleController}. */ @@ -124,8 +127,6 @@ public class DeviceIdleControllerTest { @Mock private ConnectivityManager mConnectivityManager; @Mock - private ContentResolver mContentResolver; - @Mock private IActivityManager mIActivityManager; @Mock private LocationManager mLocationManager; @@ -294,6 +295,7 @@ public class DeviceIdleControllerTest { mMockingSession = mockitoSession() .initMocks(this) .strictness(Strictness.LENIENT) + .spyStatic(DeviceConfig.class) .spyStatic(LocalServices.class) .startMocking(); spyOn(getContext()); @@ -310,6 +312,14 @@ public class DeviceIdleControllerTest { .thenReturn(mock(PowerSaveState.class)); doReturn(mock(NetworkPolicyManagerInternal.class)) .when(() -> LocalServices.getService(NetworkPolicyManagerInternal.class)); + doAnswer((Answer<Void>) invocationOnMock -> null) + .when(() -> DeviceConfig.addOnPropertiesChangedListener( + anyString(), any(Executor.class), + any(DeviceConfig.OnPropertiesChangedListener.class))); + doAnswer((Answer<DeviceConfig.Properties>) invocationOnMock + -> mock(DeviceConfig.Properties.class)) + .when(() -> DeviceConfig.getProperties( + anyString(), ArgumentMatchers.<String>any())); when(mPowerManager.newWakeLock(anyInt(), anyString())).thenReturn(mWakeLock); doNothing().when(mWakeLock).acquire(); doNothing().when(mAlarmManager).set(anyInt(), anyLong(), anyString(), any(), any()); @@ -319,7 +329,6 @@ public class DeviceIdleControllerTest { mAppStateTracker = new AppStateTrackerForTest(getContext(), Looper.getMainLooper()); mAnyMotionDetector = new AnyMotionDetectorForTest(); mInjector = new InjectorForTest(getContext()); - doNothing().when(mContentResolver).registerContentObserver(any(), anyBoolean(), any()); mDeviceIdleController = new DeviceIdleController(getContext(), mInjector); spyOn(mDeviceIdleController); @@ -330,8 +339,7 @@ public class DeviceIdleControllerTest { mDeviceIdleController.setLightEnabledForTest(true); // Get the same Constants object that mDeviceIdleController got. - mConstants = mInjector.getConstants(mDeviceIdleController, - mInjector.getHandler(mDeviceIdleController), mContentResolver); + mConstants = mInjector.getConstants(mDeviceIdleController); } @After diff --git a/services/tests/servicestests/src/com/android/server/accessibility/magnification/FullScreenMagnificationControllerTest.java b/services/tests/servicestests/src/com/android/server/accessibility/magnification/FullScreenMagnificationControllerTest.java index 57bfbf33d680..6acd9b6b3803 100644 --- a/services/tests/servicestests/src/com/android/server/accessibility/magnification/FullScreenMagnificationControllerTest.java +++ b/services/tests/servicestests/src/com/android/server/accessibility/magnification/FullScreenMagnificationControllerTest.java @@ -44,6 +44,7 @@ import android.graphics.Rect; import android.graphics.Region; import android.os.Looper; import android.view.MagnificationSpec; +import android.view.accessibility.MagnificationAnimationCallback; import androidx.test.InstrumentationRegistry; import androidx.test.runner.AndroidJUnit4; @@ -99,12 +100,12 @@ public class FullScreenMagnificationControllerTest { ValueAnimator.AnimatorListener mStateListener; FullScreenMagnificationController mFullScreenMagnificationController; - Runnable mEndCallback; + MagnificationAnimationCallback mAnimationCallback; @Before public void setUp() { Looper looper = InstrumentationRegistry.getContext().getMainLooper(); - mEndCallback = Mockito.mock(Runnable.class); + mAnimationCallback = Mockito.mock(MagnificationAnimationCallback.class); // Pretending ID of the Thread associated with looper as main thread ID in controller when(mMockContext.getMainLooper()).thenReturn(looper); when(mMockControllerCtx.getContext()).thenReturn(mMockContext); @@ -323,7 +324,6 @@ public class FullScreenMagnificationControllerTest { for (int i = 0; i < DISPLAY_COUNT; i++) { setScaleAndCenter_animated_stateChangesAndAnimationHappens(i); resetMockWindowManager(); - Mockito.reset(mEndCallback); } } @@ -336,7 +336,7 @@ public class FullScreenMagnificationControllerTest { MagnificationSpec endSpec = getMagnificationSpec(scale, offsets); assertTrue(mFullScreenMagnificationController.setScaleAndCenter(displayId, scale, - newCenter.x, newCenter.y, mEndCallback, SERVICE_ID_1)); + newCenter.x, newCenter.y, mAnimationCallback, SERVICE_ID_1)); mMessageCapturingHandler.sendAllMessages(); assertEquals(newCenter.x, mFullScreenMagnificationController.getCenterX(displayId), 0.5); @@ -365,18 +365,17 @@ public class FullScreenMagnificationControllerTest { mTargetAnimationListener.onAnimationUpdate(mMockValueAnimator); mStateListener.onAnimationEnd(mMockValueAnimator); verify(mMockWindowManager).setMagnificationSpec(eq(displayId), argThat(closeTo(endSpec))); - verify(mEndCallback).run(); + verify(mAnimationCallback).onResult(true); } @Test public void testSetScaleAndCenterWithAnimation_sameSpec_noAnimationButInvokeEndCallback() { for (int i = 0; i < DISPLAY_COUNT; i++) { - setScaleAndCenter_sameSpec_noAnimationButInvokeEndCallback(i); - Mockito.reset(mEndCallback); + setScaleAndCenter_sameSpec_noAnimationButInvokeCallbacks(i); } } - private void setScaleAndCenter_sameSpec_noAnimationButInvokeEndCallback(int displayId) { + private void setScaleAndCenter_sameSpec_noAnimationButInvokeCallbacks(int displayId) { register(displayId); final PointF center = INITIAL_BOUNDS_LOWER_RIGHT_2X_CENTER; final float targetScale = 2.0f; @@ -385,11 +384,11 @@ public class FullScreenMagnificationControllerTest { mMessageCapturingHandler.sendAllMessages(); assertFalse(mFullScreenMagnificationController.setScaleAndCenter(displayId, - targetScale, center.x, center.y, mEndCallback, SERVICE_ID_1)); + targetScale, center.x, center.y, mAnimationCallback, SERVICE_ID_1)); mMessageCapturingHandler.sendAllMessages(); verify(mMockValueAnimator, never()).start(); - verify(mEndCallback).run(); + verify(mAnimationCallback).onResult(true); } @Test @@ -673,38 +672,38 @@ public class FullScreenMagnificationControllerTest { public void testReset_notMagnifying_noStateChangeButInvokeCallback() { for (int i = 0; i < DISPLAY_COUNT; i++) { reset_notMagnifying_noStateChangeButInvokeCallback(i); - Mockito.reset(mEndCallback); } } private void reset_notMagnifying_noStateChangeButInvokeCallback(int displayId) { register(displayId); - assertFalse(mFullScreenMagnificationController.reset(displayId, mEndCallback)); + assertFalse(mFullScreenMagnificationController.reset(displayId, mAnimationCallback)); mMessageCapturingHandler.sendAllMessages(); verify(mMockAms, never()).notifyMagnificationChanged(eq(displayId), any(Region.class), anyFloat(), anyFloat(), anyFloat()); - verify(mEndCallback).run(); + verify(mAnimationCallback).onResult(true); } @Test - public void testReset_Magnifying_resetsMagnificationAndInvokeLastEndCallback() { + public void testReset_Magnifying_resetsMagnificationAndInvokeCallbacks() { for (int i = 0; i < DISPLAY_COUNT; i++) { - reset_Magnifying_resetsMagnificationAndInvokeLastEndCallback(i); + reset_Magnifying_resetsMagnificationAndInvokeCallbacks(i); } } - private void reset_Magnifying_resetsMagnificationAndInvokeLastEndCallback(int displayId) { + private void reset_Magnifying_resetsMagnificationAndInvokeCallbacks(int displayId) { register(displayId); float scale = 2.5f; PointF firstCenter = INITIAL_BOUNDS_LOWER_RIGHT_2X_CENTER; assertTrue(mFullScreenMagnificationController.setScaleAndCenter(displayId, - scale, firstCenter.x, firstCenter.y, mEndCallback, SERVICE_ID_1)); + scale, firstCenter.x, firstCenter.y, mAnimationCallback, SERVICE_ID_1)); mMessageCapturingHandler.sendAllMessages(); Mockito.reset(mMockValueAnimator); // Stubs the logic after the animation is started. doAnswer(invocation -> { + mStateListener.onAnimationCancel(mMockValueAnimator); mStateListener.onAnimationEnd(mMockValueAnimator); return null; }).when(mMockValueAnimator).cancel(); @@ -713,13 +712,14 @@ public class FullScreenMagnificationControllerTest { float fraction = 0.33f; when(mMockValueAnimator.getAnimatedFraction()).thenReturn(fraction); mTargetAnimationListener.onAnimationUpdate(mMockValueAnimator); - Runnable lastEndCallback = Mockito.mock(Runnable.class); + MagnificationAnimationCallback lastAnimationCallback = Mockito.mock( + MagnificationAnimationCallback.class); - assertTrue(mFullScreenMagnificationController.reset(displayId, lastEndCallback)); + assertTrue(mFullScreenMagnificationController.reset(displayId, lastAnimationCallback)); mMessageCapturingHandler.sendAllMessages(); // Verify expected actions. - verify(mEndCallback, never()).run(); + verify(mAnimationCallback).onResult(false); verify(mMockValueAnimator).start(); verify(mMockValueAnimator).cancel(); @@ -729,7 +729,7 @@ public class FullScreenMagnificationControllerTest { mStateListener.onAnimationEnd(mMockValueAnimator); assertFalse(mFullScreenMagnificationController.isMagnifying(DISPLAY_0)); - verify(lastEndCallback).run(); + verify(lastAnimationCallback).onResult(true); } @Test @@ -1142,6 +1142,7 @@ public class FullScreenMagnificationControllerTest { verify(mMockValueAnimator).addListener(animatorListenerArgumentCaptor.capture()); mStateListener = animatorListenerArgumentCaptor.getValue(); Mockito.reset(mMockValueAnimator); // Ignore other initialization + Mockito.reset(mAnimationCallback); } private void zoomIn2xToMiddle(int displayId) { diff --git a/services/tests/servicestests/src/com/android/server/audio/NoOpAudioSystemAdapter.java b/services/tests/servicestests/src/com/android/server/audio/NoOpAudioSystemAdapter.java index 609af8d5bf4d..8d706cb960e9 100644 --- a/services/tests/servicestests/src/com/android/server/audio/NoOpAudioSystemAdapter.java +++ b/services/tests/servicestests/src/com/android/server/audio/NoOpAudioSystemAdapter.java @@ -79,6 +79,23 @@ public class NoOpAudioSystemAdapter extends AudioSystemAdapter { } @Override + public int setDevicesRoleForCapturePreset(int capturePreset, int role, + @NonNull List<AudioDeviceAttributes> devices) { + return AudioSystem.AUDIO_STATUS_OK; + } + + @Override + public int removeDevicesRoleForCapturePreset( + int capturePreset, int role, @NonNull List<AudioDeviceAttributes> devicesToRemove) { + return AudioSystem.AUDIO_STATUS_OK; + } + + @Override + public int clearDevicesRoleForCapturePreset(int capturePreset, int role) { + return AudioSystem.AUDIO_STATUS_OK; + } + + @Override public int setParameters(String keyValuePairs) { return AudioSystem.AUDIO_STATUS_OK; } diff --git a/services/tests/servicestests/src/com/android/server/display/BrightnessTrackerTest.java b/services/tests/servicestests/src/com/android/server/display/BrightnessTrackerTest.java index 1d04c8397ffa..e02a46af3849 100644 --- a/services/tests/servicestests/src/com/android/server/display/BrightnessTrackerTest.java +++ b/services/tests/servicestests/src/com/android/server/display/BrightnessTrackerTest.java @@ -24,7 +24,7 @@ import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; -import android.app.ActivityManager; +import android.app.ActivityTaskManager.RootTaskInfo; import android.content.BroadcastReceiver; import android.content.ComponentName; import android.content.ContentResolver; @@ -984,8 +984,8 @@ public class BrightnessTrackerTest { } @Override - public ActivityManager.StackInfo getFocusedStack() throws RemoteException { - ActivityManager.StackInfo focusedStack = new ActivityManager.StackInfo(); + public RootTaskInfo getFocusedStack() throws RemoteException { + RootTaskInfo focusedStack = new RootTaskInfo(); focusedStack.userId = 0; focusedStack.topActivity = new ComponentName("a.package", "a.class"); return focusedStack; diff --git a/services/tests/servicestests/src/com/android/server/om/OverlayActorEnforcerTests.kt b/services/tests/servicestests/src/com/android/server/om/OverlayActorEnforcerTests.kt index 08392737350a..154d42ce3f8d 100644 --- a/services/tests/servicestests/src/com/android/server/om/OverlayActorEnforcerTests.kt +++ b/services/tests/servicestests/src/com/android/server/om/OverlayActorEnforcerTests.kt @@ -21,172 +21,387 @@ import android.content.om.OverlayableInfo import android.content.pm.ApplicationInfo import android.content.pm.PackageInfo import android.os.Process -import org.junit.Rule +import com.android.server.om.OverlayActorEnforcer.ActorState +import com.android.server.testutils.mockThrowOnUnmocked +import com.android.server.testutils.whenever +import com.google.common.truth.Truth.assertThat +import org.junit.BeforeClass import org.junit.Test -import org.junit.rules.ExpectedException -import java.lang.UnsupportedOperationException +import org.junit.runner.RunWith +import org.junit.runners.Parameterized +import org.mockito.Mockito.spy +import java.io.IOException +@RunWith(Parameterized::class) class OverlayActorEnforcerTests { + companion object { - private const val NAMESPACE = "testnamespace" - private const val ACTOR_NAME = "testactor" - private const val ACTOR_PKG_NAME = "com.test.actor.one" + private const val TARGET_PKG = "com.test.target" + private const val OVERLAY_PKG = "com.test.overlay" + + private const val VALID_NAMESPACE = "testNamespaceValid" + private const val INVALID_NAMESPACE = "testNamespaceInvalid" + private const val VALID_ACTOR_NAME = "testActorOne" + private const val INVALID_ACTOR_NAME = "testActorTwo" + private const val VALID_ACTOR_PKG = "com.test.actor.valid" + private const val INVALID_ACTOR_PKG = "com.test.actor.invalid" private const val OVERLAYABLE_NAME = "TestOverlayable" - private const val UID = 3536 + private const val NULL_UID = 3536 + private const val EMPTY_UID = NULL_UID + 1 + private const val INVALID_ACTOR_UID = NULL_UID + 2 + private const val VALID_ACTOR_UID = NULL_UID + 3 + private const val TARGET_UID = NULL_UID + 4 private const val USER_ID = 55 - } - @get:Rule - val expectedException = ExpectedException.none()!! + @JvmStatic + @Parameterized.Parameters(name = "{0}") + fun parameters() = CASES.mapIndexed { caseIndex, testCase -> + fun param(pair: Pair<String, TestState.() -> Unit>, type: Params.Type): Params { + val expectedState = testCase.state.takeUnless { type == Params.Type.ALLOWED } + ?: ActorState.ALLOWED + val (caseName, case) = pair + val testName = makeTestName(testCase, caseName, type) + return Params(caseIndex, expectedState, testName, type, case) + } - @Test - fun isRoot() { - verify(callingUid = Process.ROOT_UID) - } + testCase.failures.map { param(it, Params.Type.FAILURE) } + + testCase.allowed.map { param(it, Params.Type.ALLOWED) } + }.flatten() - @Test(expected = SecurityException::class) - fun isShell() { - verify(callingUid = Process.SHELL_UID) - } + @BeforeClass + @JvmStatic + fun checkAllCasesHandled() { + // Assert that all states have been tested at least once. + assertThat(CASES.map { it.state }.distinct()).containsAllIn(ActorState.values()) + } - @Test - fun isSystem() { - verify(callingUid = Process.SYSTEM_UID) - } + @BeforeClass + @JvmStatic + fun checkAllCasesUniquelyNamed() { + val duplicateCaseNames = CASES.mapIndexed { caseIndex, testCase -> + testCase.failures.map { + makeTestName(testCase, it.first, Params.Type.FAILURE) + } + testCase.allowed.map { + makeTestName(testCase, it.first, Params.Type.ALLOWED) + } + } + .flatten() + .groupingBy { it } + .eachCount() + .filterValues { it > 1 } + .keys - @Test(expected = SecurityException::class) - fun noOverlayable_noTarget() { - verify(targetOverlayableName = null) - } + assertThat(duplicateCaseNames).isEmpty() + } - @Test - fun noOverlayable_noTarget_withPermission() { - verify(targetOverlayableName = null, hasPermission = true) - } + /* + The pattern in this block is a result of the incredible number of branches in + enforcement logic. It serves to verify failures with the assumption that all errors + are checked in order. The idea is to emulate the if-else branches from code, but using + actual test data instead of if statements. - @Test(expected = SecurityException::class) - fun noOverlayable_withTarget() { - verify(targetOverlayableName = OVERLAYABLE_NAME) - } + Each state is verified by providing a failure or exclusive set of failures which cause + a failure state to be returned. Each state also provides a success case which will + "skip" the state. This allows subsequent failure cases to cascade from the first case + by calling all the skip branches for preceding states and then choosing only 1 of + the failures to test. - @Test(expected = SecurityException::class) - fun withOverlayable_noTarget() { - verify( - targetOverlayableName = null, - overlayableInfo = OverlayableInfo(OVERLAYABLE_NAME, null) - ) - } + Given the failure states A, B, and C: testA calls A.failure + assert, testB calls + A.skip + B.failure + assert, testC calls A.skip + B.skip + C.failure + assert, etc. - @Test(expected = SecurityException::class) - fun withOverlayable_noActor() { - verify( - overlayableInfo = OverlayableInfo(OVERLAYABLE_NAME, null) - ) - } + Calling `allowed` is a special case for when there is a combination of parameters that + skips the remaining checks and immediately allows the actor through. For these cases, + the first failure branch will be run, assert that it's not allowed, and the + allowed branch will run, asserting that it now results in ALLOWED, skipping all + remaining functions. - @Test - fun withOverlayable_noActor_withPermission() { - verify( - hasPermission = true, - overlayableInfo = OverlayableInfo(OVERLAYABLE_NAME, null) - ) - } + This is an ordered list of TestCase objects, with the possibility to repeat failure + states if any can occur multiple times in the logic tree. - @Test(expected = SecurityException::class) - fun withOverlayable_withActor_notActor() { - verify( - isActor = false, - overlayableInfo = OverlayableInfo(OVERLAYABLE_NAME, - "overlay://$NAMESPACE/$ACTOR_NAME") + Each failure must be handled at least once. + */ + private val CASES = listOf( + ActorState.TARGET_NOT_FOUND withCases { + failure("nullPkgInfo") { targetPkgInfo = null } + allowed("debuggable") { + targetPkgInfo = pkgInfo(TARGET_PKG).apply { + applicationInfo.flags = ApplicationInfo.FLAG_DEBUGGABLE + } + } + skip { targetPkgInfo = pkgInfo(TARGET_PKG) } + }, + ActorState.NO_PACKAGES_FOR_UID withCases { + failure("empty") { callingUid = EMPTY_UID } + failure("null") { callingUid = NULL_UID } + failure("shell") { callingUid = Process.SHELL_UID } + allowed("targetUid") { callingUid = TARGET_UID } + allowed("rootUid") { callingUid = Process.ROOT_UID } + allowed("systemUid") { callingUid = Process.SYSTEM_UID } + skip { callingUid = INVALID_ACTOR_UID } + }, + ActorState.MISSING_TARGET_OVERLAYABLE_NAME withCases { + failure("nullTargetOverlayableName") { + overlayInfoParams.targetOverlayableName = null + targetOverlayableInfo = OverlayableInfo(OVERLAYABLE_NAME, + "overlay://$VALID_NAMESPACE/$VALID_ACTOR_NAME") + } + skip { overlayInfoParams.targetOverlayableName = OVERLAYABLE_NAME } + }, + ActorState.MISSING_LEGACY_PERMISSION withCases { + failure("noPermission") { + overlayInfoParams.targetOverlayableName = null + targetOverlayableInfo = null + hasPermission = false + } + allowed("hasPermission") { hasPermission = true } + skip { overlayInfoParams.targetOverlayableName = OVERLAYABLE_NAME } + }, + ActorState.ERROR_READING_OVERLAYABLE withCases { + failure("doesTargetDefineOverlayableIOException") { + overlayInfoParams.targetOverlayableName = null + whenever(doesTargetDefineOverlayable(TARGET_PKG, USER_ID)) + .thenThrow(IOException::class.java) + } + skip { overlayInfoParams.targetOverlayableName = OVERLAYABLE_NAME } + }, + ActorState.UNABLE_TO_GET_TARGET_OVERLAYABLE withCases { + failure("getOverlayableForTargetIOException") { + whenever(getOverlayableForTarget(TARGET_PKG, OVERLAYABLE_NAME, + USER_ID)).thenThrow(IOException::class.java) + } + }, + ActorState.MISSING_OVERLAYABLE withCases { + failure("nullTargetOverlayableInfo") { targetOverlayableInfo = null } + skip { + targetOverlayableInfo = OverlayableInfo(OVERLAYABLE_NAME, + "overlay://$VALID_NAMESPACE/$VALID_ACTOR_NAME") + } + }, + ActorState.MISSING_LEGACY_PERMISSION withCases { + failure("noPermissionNullActor") { + targetOverlayableInfo = OverlayableInfo(OVERLAYABLE_NAME, null) + hasPermission = false + } + failure("noPermissionEmptyActor") { + targetOverlayableInfo = OverlayableInfo(OVERLAYABLE_NAME, "") + hasPermission = false + } + allowed("hasPermissionNullActor") { + hasPermission = true + } + skip { + targetOverlayableInfo = OverlayableInfo(OVERLAYABLE_NAME, + "overlay://$VALID_NAMESPACE/$VALID_ACTOR_NAME") + } + }, + ActorState.INVALID_OVERLAYABLE_ACTOR_NAME withCases { + fun TestState.mockActor(actorUri: String) { + targetOverlayableInfo = OverlayableInfo(OVERLAYABLE_NAME, actorUri) + } + failure("wrongScheme") { + mockActor("notoverlay://$VALID_NAMESPACE/$VALID_ACTOR_NAME") + } + failure("extraPath") { + mockActor("overlay://$VALID_NAMESPACE/$VALID_ACTOR_NAME/extraPath") + } + failure("missingPath") { mockActor("overlay://$VALID_NAMESPACE") } + failure("missingAuthority") { mockActor("overlay://") } + skip { mockActor("overlay://$VALID_NAMESPACE/$VALID_ACTOR_NAME") } + }, + ActorState.NO_NAMED_ACTORS withCases { + failure("empty") { namedActorsMap = emptyMap() } + skip { + namedActorsMap = mapOf(INVALID_NAMESPACE to + mapOf(INVALID_ACTOR_NAME to VALID_ACTOR_PKG)) + } + }, + ActorState.MISSING_NAMESPACE withCases { + failure("invalidNamespace") { + namedActorsMap = mapOf(INVALID_NAMESPACE to + mapOf(INVALID_ACTOR_NAME to VALID_ACTOR_PKG)) + } + skip { + namedActorsMap = mapOf(VALID_NAMESPACE to + mapOf(INVALID_ACTOR_NAME to VALID_ACTOR_PKG)) + } + }, + ActorState.MISSING_ACTOR_NAME withCases { + failure("invalidActorName") { + namedActorsMap = mapOf(VALID_NAMESPACE to + mapOf(INVALID_ACTOR_NAME to VALID_ACTOR_PKG)) + } + skip { + namedActorsMap = mapOf(VALID_NAMESPACE to + mapOf(VALID_ACTOR_NAME to VALID_ACTOR_PKG)) + } + }, + ActorState.MISSING_APP_INFO withCases { + failure("nullActorPkgInfo") { actorPkgInfo = null } + failure("nullActorAppInfo") { + actorPkgInfo = PackageInfo().apply { applicationInfo = null } + } + skip { actorPkgInfo = pkgInfo(VALID_ACTOR_PKG) } + }, + ActorState.ACTOR_NOT_PREINSTALLED withCases { + failure("notSystem") { + actorPkgInfo = pkgInfo(VALID_ACTOR_PKG).apply { + applicationInfo.flags = 0 + } + } + skip { + actorPkgInfo = pkgInfo(VALID_ACTOR_PKG).apply { + applicationInfo.flags = ApplicationInfo.FLAG_SYSTEM + } + } + }, + ActorState.INVALID_ACTOR withCases { + failure("invalidUid") { callingUid = INVALID_ACTOR_UID } + skip { callingUid = VALID_ACTOR_UID } + }, + ActorState.ALLOWED withCases { + // No point making an exception for this case in all of the test code, so + // just pretend this is a failure that results in a success result code. + failure("allowed") { /* Do nothing */ } + } ) - } - @Test(expected = SecurityException::class) - fun withOverlayable_withActor_isActor_notPreInstalled() { - verify( - isActor = true, - isPreInstalled = false, - overlayableInfo = OverlayableInfo(OVERLAYABLE_NAME, - "overlay://$NAMESPACE/$ACTOR_NAME") - ) + data class OverlayInfoParams( + var targetPackageName: String = TARGET_PKG, + var targetOverlayableName: String? = null + ) { + fun toOverlayInfo() = OverlayInfo( + OVERLAY_PKG, + targetPackageName, + targetOverlayableName, + null, + "/path", + OverlayInfo.STATE_UNKNOWN, 0, + 0, false) + } + + private infix fun ActorState.withCases(block: TestCase.() -> Unit) = + TestCase(this).apply(block) + + private fun pkgInfo(pkgName: String): PackageInfo = mockThrowOnUnmocked { + this.packageName = pkgName + this.applicationInfo = ApplicationInfo().apply { + this.packageName = pkgName + } + } + + private fun makeTestName(testCase: TestCase, caseName: String, type: Params.Type): String { + val resultSuffix = if (type == Params.Type.ALLOWED) "allowed" else "failed" + return "${testCase.state}_${resultSuffix}_$caseName" + } } + @Parameterized.Parameter(0) + lateinit var params: Params + @Test - fun withOverlayable_withActor_isActor_isPreInstalled() { - verify( - isActor = true, - isPreInstalled = true, - overlayableInfo = OverlayableInfo(OVERLAYABLE_NAME, - "overlay://$NAMESPACE/$ACTOR_NAME") - ) - } + fun verify() { + // Apply all the skip states before the failure to be verified + val testState = CASES.take(params.index) + .fold(TestState.create()) { testState, case -> + testState.apply(case.skip) + } - @Test(expected = SecurityException::class) - fun withOverlayable_invalidActor() { - verify( - isActor = true, - isPreInstalled = true, - overlayableInfo = OverlayableInfo(OVERLAYABLE_NAME, "notValidActor") - ) + // If testing an allowed branch, first apply a failure to ensure it fails + if (params.type == Params.Type.ALLOWED) { + CASES[params.index].failures.firstOrNull()?.second?.run(testState::apply) + assertThat(testState.toResult()).isNotEqualTo(ActorState.ALLOWED) + } + + // Apply the test case in the params to the collected state + testState.apply(params.function) + + // Assert the result matches the expected state + assertThat(testState.toResult()).isEqualTo(params.expectedState) } - private fun verify( - isActor: Boolean = false, - isPreInstalled: Boolean = false, - hasPermission: Boolean = false, - overlayableInfo: OverlayableInfo? = null, - callingUid: Int = UID, - targetOverlayableName: String? = OVERLAYABLE_NAME + private fun TestState.toResult() = OverlayActorEnforcer(this) + .isAllowedActor("test", overlayInfoParams.toOverlayInfo(), callingUid, USER_ID) + + data class Params( + var index: Int, + var expectedState: ActorState, + val testName: String, + val type: Type, + val function: TestState.() -> Unit ) { - val callback = MockCallback( - isActor = isActor, - isPreInstalled = isPreInstalled, - hasPermission = hasPermission, - overlayableInfo = overlayableInfo - ) + override fun toString() = testName - val overlayInfo = overlayInfo(targetOverlayableName) - OverlayActorEnforcer(callback) - .enforceActor(overlayInfo, "test", callingUid, USER_ID) + enum class Type { + FAILURE, + ALLOWED + } } - private fun overlayInfo(targetOverlayableName: String?) = OverlayInfo("com.test.overlay", - "com.test.target", targetOverlayableName, null, "/path", OverlayInfo.STATE_UNKNOWN, 0, - 0, false) + data class TestCase( + val state: ActorState, + val failures: MutableList<Pair<String, TestState.() -> Unit>> = mutableListOf(), + var allowed: MutableList<Pair<String, TestState.() -> Unit>> = mutableListOf(), + var skip: (TestState.() -> Unit) = {} + ) { + fun failure(caseName: String, block: TestState.() -> Unit) { + failures.add(caseName to block) + } - private class MockCallback( - private val isActor: Boolean = false, - private val isPreInstalled: Boolean = false, - private val hasPermission: Boolean = false, - private val overlayableInfo: OverlayableInfo? = null, - private vararg val packageNames: String = arrayOf("com.test.actor.one") + fun allowed(caseName: String, block: TestState.() -> Unit) { + allowed.add(caseName to block) + } + + fun skip(block: TestState.() -> Unit) { + this.skip = block + } + } + + open class TestState private constructor( + var callingUid: Int = NULL_UID, + val overlayInfoParams: OverlayInfoParams = OverlayInfoParams(), + var namedActorsMap: Map<String, Map<String, String>> = emptyMap(), + var hasPermission: Boolean = false, + var targetOverlayableInfo: OverlayableInfo? = null, + var targetPkgInfo: PackageInfo? = null, + var actorPkgInfo: PackageInfo? = null, + vararg val packageNames: String = arrayOf("com.test.actor.one") ) : PackageManagerHelper { - override fun getNamedActors() = if (isActor) { - mapOf(NAMESPACE to mapOf(ACTOR_NAME to ACTOR_PKG_NAME)) - } else { - emptyMap() + companion object { + // Enforce that new instances are spied + fun create() = spy(TestState())!! } + override fun getNamedActors() = namedActorsMap + + @Throws(IOException::class) override fun getOverlayableForTarget( packageName: String, targetOverlayableName: String, userId: Int - ) = overlayableInfo + ) = targetOverlayableInfo?.takeIf { + // Protect against this method being called with the wrong package name + targetPkgInfo == null || targetPkgInfo?.packageName == packageName + } override fun getPackagesForUid(uid: Int) = when (uid) { - UID -> packageNames + EMPTY_UID -> emptyArray() + INVALID_ACTOR_UID -> arrayOf(INVALID_ACTOR_PKG) + VALID_ACTOR_UID -> arrayOf(VALID_ACTOR_PKG) + TARGET_UID -> arrayOf(TARGET_PKG) + NULL_UID -> null else -> null } - override fun getPackageInfo(packageName: String, userId: Int) = PackageInfo().apply { - applicationInfo = ApplicationInfo().apply { - flags = if (isPreInstalled) ApplicationInfo.FLAG_SYSTEM else 0 - } - } + override fun getPackageInfo(packageName: String, userId: Int) = + listOfNotNull(targetPkgInfo, actorPkgInfo).find { it.packageName == packageName } + @Throws(IOException::class) // Mockito requires this checked exception to be declared override fun doesTargetDefineOverlayable(targetPackageName: String?, userId: Int): Boolean { - return overlayableInfo != null + return targetOverlayableInfo?.takeIf { + // Protect against this method being called with the wrong package name + targetPkgInfo == null || targetPkgInfo?.packageName == targetPackageName + } != null } override fun enforcePermission(permission: String?, message: String?) { diff --git a/services/tests/servicestests/src/com/android/server/pm/PackageManagerSettingsTests.java b/services/tests/servicestests/src/com/android/server/pm/PackageManagerSettingsTests.java index 0bf06bb4dda7..dac05424e01f 100644 --- a/services/tests/servicestests/src/com/android/server/pm/PackageManagerSettingsTests.java +++ b/services/tests/servicestests/src/com/android/server/pm/PackageManagerSettingsTests.java @@ -45,6 +45,7 @@ import android.content.pm.SuspendDialogInfo; import android.content.pm.UserInfo; import android.os.BaseBundle; import android.os.PersistableBundle; +import android.os.Process; import android.os.UserHandle; import android.os.UserManagerInternal; import android.util.ArrayMap; @@ -59,8 +60,12 @@ import androidx.test.runner.AndroidJUnit4; import com.android.permission.persistence.RuntimePermissionsPersistence; import com.android.server.LocalServices; +import com.android.server.pm.parsing.pkg.PackageImpl; +import com.android.server.pm.parsing.pkg.ParsedPackage; import com.android.server.pm.permission.PermissionSettings; +import com.google.common.truth.Truth; + import org.junit.After; import org.junit.Before; import org.junit.Test; @@ -380,6 +385,74 @@ public class PackageManagerSettingsTests { } @Test + public void testWriteReadUsesStaticLibraries() { + final Context context = InstrumentationRegistry.getTargetContext(); + final Object lock = new Object(); + final Settings settingsUnderTest = new Settings(context.getFilesDir(), mPermissionSettings, + mRuntimePermissionsPersistence, lock); + final PackageSetting ps1 = createPackageSetting(PACKAGE_NAME_1); + ps1.appId = Process.FIRST_APPLICATION_UID; + ps1.pkg = ((ParsedPackage) PackageImpl.forTesting(PACKAGE_NAME_1).hideAsParsed()) + .setUid(ps1.appId) + .setSystem(true) + .hideAsFinal(); + final PackageSetting ps2 = createPackageSetting(PACKAGE_NAME_2); + ps2.appId = Process.FIRST_APPLICATION_UID + 1; + ps2.pkg = ((ParsedPackage) PackageImpl.forTesting(PACKAGE_NAME_2).hideAsParsed()) + .setUid(ps2.appId) + .hideAsFinal(); + + ps1.usesStaticLibraries = new String[] { "com.example.shared.one" }; + ps1.usesStaticLibrariesVersions = new long[] { 12 }; + ps1.setFlags(ps1.pkgFlags | ApplicationInfo.FLAG_SYSTEM); + settingsUnderTest.mPackages.put(PACKAGE_NAME_1, ps1); + assertThat(settingsUnderTest.disableSystemPackageLPw(PACKAGE_NAME_1, false), is(true)); + + ps2.usesStaticLibraries = new String[] { "com.example.shared.two" }; + ps2.usesStaticLibrariesVersions = new long[] { 34 }; + settingsUnderTest.mPackages.put(PACKAGE_NAME_2, ps2); + + settingsUnderTest.writeLPr(); + + settingsUnderTest.mPackages.clear(); + settingsUnderTest.mDisabledSysPackages.clear(); + + assertThat(settingsUnderTest.readLPw(createFakeUsers()), is(true)); + + PackageSetting readPs1 = settingsUnderTest.getPackageLPr(PACKAGE_NAME_1); + PackageSetting readPs2 = settingsUnderTest.getPackageLPr(PACKAGE_NAME_2); + + Truth.assertThat(readPs1).isNotNull(); + Truth.assertThat(readPs1.usesStaticLibraries).isNotNull(); + Truth.assertThat(readPs1.usesStaticLibrariesVersions).isNotNull(); + Truth.assertThat(readPs2).isNotNull(); + Truth.assertThat(readPs2.usesStaticLibraries).isNotNull(); + Truth.assertThat(readPs2.usesStaticLibrariesVersions).isNotNull(); + + List<Long> ps1VersionsAsList = new ArrayList<>(); + for (long version : ps1.usesStaticLibrariesVersions) { + ps1VersionsAsList.add(version); + } + + List<Long> ps2VersionsAsList = new ArrayList<>(); + for (long version : ps2.usesStaticLibrariesVersions) { + ps2VersionsAsList.add(version); + } + + Truth.assertThat(readPs1.usesStaticLibraries).asList() + .containsExactlyElementsIn(ps1.usesStaticLibraries).inOrder(); + + Truth.assertThat(readPs1.usesStaticLibrariesVersions).asList() + .containsExactlyElementsIn(ps1VersionsAsList).inOrder(); + + Truth.assertThat(readPs2.usesStaticLibraries).asList() + .containsExactlyElementsIn(ps2.usesStaticLibraries).inOrder(); + + Truth.assertThat(readPs2.usesStaticLibrariesVersions).asList() + .containsExactlyElementsIn(ps2VersionsAsList).inOrder(); + } + + @Test public void testPackageRestrictionsDistractionFlagsDefault() { final PackageSetting defaultSetting = createPackageSetting(PACKAGE_NAME_1); assertThat(defaultSetting.getDistractionFlags(0), is(PackageManager.RESTRICTION_NONE)); @@ -617,7 +690,7 @@ public class PackageManagerSettingsTests { null /*usesStaticLibraries*/, null /*usesStaticLibrariesVersions*/, null /*mimeGroups*/); - assertThat(testPkgSetting01.getCodePath(), is(UPDATED_CODE_PATH)); + assertThat(testPkgSetting01.getPath(), is(UPDATED_CODE_PATH)); assertThat(testPkgSetting01.name, is(PACKAGE_NAME)); assertThat(testPkgSetting01.pkgFlags, is(ApplicationInfo.FLAG_SYSTEM)); assertThat(testPkgSetting01.pkgPrivateFlags, is(ApplicationInfo.PRIVATE_FLAG_PRIVILEGED)); @@ -656,7 +729,7 @@ public class PackageManagerSettingsTests { null /*usesStaticLibrariesVersions*/, null /*mimeGroups*/); assertThat(testPkgSetting01.appId, is(0)); - assertThat(testPkgSetting01.getCodePath(), is(INITIAL_CODE_PATH)); + assertThat(testPkgSetting01.getPath(), is(INITIAL_CODE_PATH)); assertThat(testPkgSetting01.name, is(PACKAGE_NAME)); assertThat(testPkgSetting01.pkgFlags, is(0)); assertThat(testPkgSetting01.pkgPrivateFlags, is(0)); @@ -700,7 +773,7 @@ public class PackageManagerSettingsTests { null /*usesStaticLibrariesVersions*/, null /*mimeGroups*/); assertThat(testPkgSetting01.appId, is(10064)); - assertThat(testPkgSetting01.getCodePath(), is(INITIAL_CODE_PATH)); + assertThat(testPkgSetting01.getPath(), is(INITIAL_CODE_PATH)); assertThat(testPkgSetting01.name, is(PACKAGE_NAME)); assertThat(testPkgSetting01.pkgFlags, is(0)); assertThat(testPkgSetting01.pkgPrivateFlags, is(0)); @@ -741,7 +814,7 @@ public class PackageManagerSettingsTests { null /*usesStaticLibrariesVersions*/, null /*mimeGroups*/); assertThat(testPkgSetting01.appId, is(10064)); - assertThat(testPkgSetting01.getCodePath(), is(UPDATED_CODE_PATH)); + assertThat(testPkgSetting01.getPath(), is(UPDATED_CODE_PATH)); assertThat(testPkgSetting01.name, is(PACKAGE_NAME)); assertThat(testPkgSetting01.pkgFlags, is(0)); assertThat(testPkgSetting01.pkgPrivateFlags, is(0)); @@ -792,10 +865,10 @@ public class PackageManagerSettingsTests { private void verifySettingCopy(PackageSetting origPkgSetting, PackageSetting testPkgSetting) { assertThat(origPkgSetting, is(not(testPkgSetting))); assertThat(origPkgSetting.appId, is(testPkgSetting.appId)); - assertSame(origPkgSetting.getCodePath(), testPkgSetting.getCodePath()); - assertThat(origPkgSetting.getCodePath(), is(testPkgSetting.getCodePath())); - assertSame(origPkgSetting.getCodePathString(), testPkgSetting.getCodePathString()); - assertThat(origPkgSetting.getCodePathString(), is(testPkgSetting.getCodePathString())); + assertSame(origPkgSetting.getPath(), testPkgSetting.getPath()); + assertThat(origPkgSetting.getPath(), is(testPkgSetting.getPath())); + assertSame(origPkgSetting.getPathString(), testPkgSetting.getPathString()); + assertThat(origPkgSetting.getPathString(), is(testPkgSetting.getPathString())); assertSame(origPkgSetting.cpuAbiOverrideString, testPkgSetting.cpuAbiOverrideString); assertThat(origPkgSetting.cpuAbiOverrideString, is(testPkgSetting.cpuAbiOverrideString)); assertThat(origPkgSetting.firstInstallTime, is(testPkgSetting.firstInstallTime)); 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 2651cfa5449b..1d384e961dc3 100644 --- a/services/tests/servicestests/src/com/android/server/pm/PackageParserTest.java +++ b/services/tests/servicestests/src/com/android/server/pm/PackageParserTest.java @@ -312,7 +312,7 @@ public class PackageParserTest { private static PackageSetting mockPkgSetting(AndroidPackage pkg) { return new PackageSetting(pkg.getPackageName(), pkg.getRealPackage(), - new File(pkg.getCodePath()), null, pkg.getPrimaryCpuAbi(), pkg.getSecondaryCpuAbi(), + new File(pkg.getPath()), null, pkg.getPrimaryCpuAbi(), pkg.getSecondaryCpuAbi(), null, pkg.getVersionCode(), PackageInfoUtils.appInfoFlags(pkg, null), PackageInfoUtils.appInfoPrivateFlags(pkg, null), @@ -335,8 +335,8 @@ public class PackageParserTest { assertEquals(a.getPackageName(), b.getPackageName()); assertArrayEquals(a.getSplitNames(), b.getSplitNames()); assertEquals(a.getVolumeUuid(), b.getVolumeUuid()); - assertEquals(a.getCodePath(), b.getCodePath()); - assertEquals(a.getBaseCodePath(), b.getBaseCodePath()); + assertEquals(a.getPath(), b.getPath()); + assertEquals(a.getBaseApkPath(), b.getBaseApkPath()); assertArrayEquals(a.getSplitCodePaths(), b.getSplitCodePaths()); assertArrayEquals(a.getSplitRevisionCodes(), b.getSplitRevisionCodes()); assertArrayEquals(a.getSplitFlags(), b.getSplitFlags()); diff --git a/services/tests/servicestests/src/com/android/server/pm/ScanTests.java b/services/tests/servicestests/src/com/android/server/pm/ScanTests.java index 56dddb0a8112..4d8cc4647271 100644 --- a/services/tests/servicestests/src/com/android/server/pm/ScanTests.java +++ b/services/tests/servicestests/src/com/android/server/pm/ScanTests.java @@ -533,7 +533,7 @@ public class ScanTests { arrayContaining("some.static.library", "some.other.static.library")); assertThat(pkgSetting.usesStaticLibrariesVersions, is(new long[]{234L, 456L})); assertThat(pkgSetting.pkg, is(scanResult.request.parsedPackage)); - assertThat(pkgSetting.getCodePath(), is(new File(createCodePath(packageName)))); + assertThat(pkgSetting.getPath(), is(new File(createCodePath(packageName)))); assertThat(pkgSetting.versionCode, is(PackageInfo.composeLongVersionCode(1, 2345))); } diff --git a/services/tests/servicestests/src/com/android/server/pm/dex/DexMetadataHelperTest.java b/services/tests/servicestests/src/com/android/server/pm/dex/DexMetadataHelperTest.java index caa8ae5e0e39..3ce7a7d73d4a 100644 --- a/services/tests/servicestests/src/com/android/server/pm/dex/DexMetadataHelperTest.java +++ b/services/tests/servicestests/src/com/android/server/pm/dex/DexMetadataHelperTest.java @@ -29,12 +29,10 @@ import android.content.pm.PackageParser.PackageLite; import android.content.pm.PackageParser.PackageParserException; import android.content.pm.dex.DexMetadataHelper; import android.content.pm.parsing.ApkLiteParseUtils; -import android.content.pm.parsing.result.ParseInput; import android.content.pm.parsing.result.ParseResult; import android.content.pm.parsing.result.ParseTypeImpl; import android.os.FileUtils; -import androidx.annotation.NonNull; import androidx.test.InstrumentationRegistry; import androidx.test.filters.SmallTest; import androidx.test.runner.AndroidJUnit4; @@ -106,9 +104,9 @@ public class DexMetadataHelperTest { Map<String, String> packageDexMetadata = AndroidPackageUtils.getPackageDexMetadata(pkg); assertEquals(1, packageDexMetadata.size()); - String baseDexMetadata = packageDexMetadata.get(pkg.getBaseCodePath()); + String baseDexMetadata = packageDexMetadata.get(pkg.getBaseApkPath()); assertNotNull(baseDexMetadata); - assertTrue(isDexMetadataForApk(baseDexMetadata, pkg.getBaseCodePath())); + assertTrue(isDexMetadataForApk(baseDexMetadata, pkg.getBaseApkPath())); } @Test @@ -122,9 +120,9 @@ public class DexMetadataHelperTest { Map<String, String> packageDexMetadata = AndroidPackageUtils.getPackageDexMetadata(pkg); assertEquals(2, packageDexMetadata.size()); - String baseDexMetadata = packageDexMetadata.get(pkg.getBaseCodePath()); + String baseDexMetadata = packageDexMetadata.get(pkg.getBaseApkPath()); assertNotNull(baseDexMetadata); - assertTrue(isDexMetadataForApk(baseDexMetadata, pkg.getBaseCodePath())); + assertTrue(isDexMetadataForApk(baseDexMetadata, pkg.getBaseApkPath())); String splitDexMetadata = packageDexMetadata.get(pkg.getSplitCodePaths()[0]); assertNotNull(splitDexMetadata); diff --git a/services/tests/servicestests/src/com/android/server/timezonedetector/TestState.java b/services/tests/servicestests/src/com/android/server/timezonedetector/TestState.java new file mode 100644 index 000000000000..7049efa1cc2f --- /dev/null +++ b/services/tests/servicestests/src/com/android/server/timezonedetector/TestState.java @@ -0,0 +1,92 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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.timezonedetector; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +import java.util.ArrayList; + +/** + * A test support class used for tracking a piece of state in test objects like fakes and mocks. + * State can optionally be initialized using {@link #init}, which sets the value to an initial + * value, but is not treated as a change. Calls to {@link #set} are tracked and can be checked for + * during tests. The change-tracking can be cleared by calling {@link #commitLatest}, which puts the + * object into an unchanged state and sets the initial value to the latest value passed to + * {@link #set}. + */ +public class TestState<T> { + private T mInitialValue; + private final ArrayList<T> mValues = new ArrayList<>(5); + + /** Sets the initial value for the state. */ + public void init(T value) { + mValues.clear(); + mInitialValue = value; + } + + /** Sets the latest value for the state. */ + public void set(T value) { + mValues.add(value); + } + + /** Returns {@code true} if {@link #set} has been called. */ + public boolean hasBeenSet() { + return mValues.size() > 0; + } + + /** Fails if {@link #set} has been called. */ + public void assertHasNotBeenSet() { + assertFalse(hasBeenSet()); + } + + /** Fails if {@link #set} has not been called. */ + public void assertHasBeenSet() { + assertTrue(hasBeenSet()); + } + + /** + * Clears tracked changes and re-initializes using the latest set value as the initial value. + */ + public void commitLatest() { + if (hasBeenSet()) { + mInitialValue = mValues.get(mValues.size() - 1); + mValues.clear(); + } + } + + /** Asserts the latest value passed to {@link #set} equals {@code expected}. */ + public void assertLatestEquals(T expected) { + assertEquals(expected, getLatest()); + } + + /** Asserts the number of times {@link #set} has been called. */ + public void assertChangeCount(int expectedCount) { + assertEquals(expectedCount, mValues.size()); + } + + /** + * Returns the latest value passed to {@link #set}. If {@link #set} hasn't been called then the + * initial value is returned. + */ + public T getLatest() { + if (hasBeenSet()) { + return mValues.get(mValues.size() - 1); + } + return mInitialValue; + } +} diff --git a/services/tests/servicestests/src/com/android/server/timezonedetector/TimeZoneDetectorStrategyImplTest.java b/services/tests/servicestests/src/com/android/server/timezonedetector/TimeZoneDetectorStrategyImplTest.java index 2bee5e5e7295..1cdf19319209 100644 --- a/services/tests/servicestests/src/com/android/server/timezonedetector/TimeZoneDetectorStrategyImplTest.java +++ b/services/tests/servicestests/src/com/android/server/timezonedetector/TimeZoneDetectorStrategyImplTest.java @@ -54,7 +54,6 @@ import org.junit.Test; import java.io.StringWriter; import java.util.Arrays; import java.util.Collections; -import java.util.LinkedList; import java.util.List; import java.util.concurrent.atomic.AtomicBoolean; @@ -994,55 +993,6 @@ public class TimeZoneDetectorStrategyImplTest { } } - /** Some piece of state that tests want to track. */ - private static class TestState<T> { - private T mInitialValue; - private LinkedList<T> mValues = new LinkedList<>(); - - void init(T value) { - mValues.clear(); - mInitialValue = value; - } - - void set(T value) { - mValues.addFirst(value); - } - - boolean hasBeenSet() { - return mValues.size() > 0; - } - - void assertHasNotBeenSet() { - assertFalse(hasBeenSet()); - } - - void assertHasBeenSet() { - assertTrue(hasBeenSet()); - } - - void commitLatest() { - if (hasBeenSet()) { - mInitialValue = mValues.getLast(); - mValues.clear(); - } - } - - void assertLatestEquals(T expected) { - assertEquals(expected, getLatest()); - } - - void assertChangeCount(int expectedCount) { - assertEquals(expectedCount, mValues.size()); - } - - public T getLatest() { - if (hasBeenSet()) { - return mValues.getFirst(); - } - return mInitialValue; - } - } - /** * A "fluent" class allows reuse of code in tests: initialization, simulation and verification * logic. diff --git a/services/tests/servicestests/src/com/android/server/usage/AppStandbyControllerTests.java b/services/tests/servicestests/src/com/android/server/usage/AppStandbyControllerTests.java index 7c7b1a296673..2aeab209162a 100644 --- a/services/tests/servicestests/src/com/android/server/usage/AppStandbyControllerTests.java +++ b/services/tests/servicestests/src/com/android/server/usage/AppStandbyControllerTests.java @@ -139,10 +139,13 @@ public class AppStandbyControllerTests { private AppStandbyController mController; private CountDownLatch mStateChangedLatch = new CountDownLatch(1); + private String mLatchPkgName = null; private AppIdleStateChangeListener mListener = new AppIdleStateChangeListener() { @Override public void onAppIdleStateChanged(String packageName, int userId, boolean idle, int bucket, int reason) { + // Ignore events not related to mLatchPkgName, if set. + if (mLatchPkgName != null && !mLatchPkgName.equals(packageName)) return; mStateChangedLatch.countDown(); } }; @@ -374,6 +377,7 @@ public class AppStandbyControllerTests { mInjector.mElapsedRealtime, false)); controller.addListener(mListener); + mLatchPkgName = null; return controller; } @@ -1377,7 +1381,7 @@ public class AppStandbyControllerTests { @Test public void testUnexemptedSyncScheduled() throws Exception { - mStateChangedLatch = new CountDownLatch(1); + rearmLatch(PACKAGE_1); mController.addListener(mListener); assertEquals("Test package did not start in the Never bucket", STANDBY_BUCKET_NEVER, getStandbyBucket(mController, PACKAGE_1)); @@ -1389,7 +1393,7 @@ public class AppStandbyControllerTests { setAndAssertBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_RARE, REASON_MAIN_FORCED_BY_SYSTEM); - mStateChangedLatch = new CountDownLatch(1); + rearmLatch(PACKAGE_1); mController.postReportSyncScheduled(PACKAGE_1, USER_ID, false); mStateChangedLatch.await(1000, TimeUnit.MILLISECONDS); assertEquals("Unexempted sync scheduled should not elevate a non Never bucket", @@ -1400,7 +1404,7 @@ public class AppStandbyControllerTests { public void testExemptedSyncScheduled() throws Exception { setAndAssertBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_RARE, REASON_MAIN_FORCED_BY_SYSTEM); mInjector.mDeviceIdleMode = true; - mStateChangedLatch = new CountDownLatch(1); + rearmLatch(PACKAGE_1); mController.postReportSyncScheduled(PACKAGE_1, USER_ID, true); mStateChangedLatch.await(1000, TimeUnit.MILLISECONDS); assertEquals("Exempted sync scheduled in doze should set bucket to working set", @@ -1408,7 +1412,7 @@ public class AppStandbyControllerTests { setAndAssertBucket(PACKAGE_1, USER_ID, STANDBY_BUCKET_RARE, REASON_MAIN_FORCED_BY_SYSTEM); mInjector.mDeviceIdleMode = false; - mStateChangedLatch = new CountDownLatch(1); + rearmLatch(PACKAGE_1); mController.postReportSyncScheduled(PACKAGE_1, USER_ID, true); mStateChangedLatch.await(1000, TimeUnit.MILLISECONDS); assertEquals("Exempted sync scheduled while not in doze should set bucket to active", @@ -1558,10 +1562,19 @@ public class AppStandbyControllerTests { } private void setAndAssertBucket(String pkg, int user, int bucket, int reason) throws Exception { - mStateChangedLatch = new CountDownLatch(1); + rearmLatch(pkg); mController.setAppStandbyBucket(pkg, user, bucket, reason); mStateChangedLatch.await(100, TimeUnit.MILLISECONDS); assertEquals("Failed to set package bucket", bucket, getStandbyBucket(mController, PACKAGE_1)); } + + private void rearmLatch(String pkgName) { + mLatchPkgName = pkgName; + mStateChangedLatch = new CountDownLatch(1); + } + + private void rearmLatch() { + rearmLatch(null); + } } diff --git a/services/tests/servicestests/utils-mockito/com/android/server/testutils/MockitoUtils.kt b/services/tests/servicestests/utils-mockito/com/android/server/testutils/MockitoUtils.kt index 056fa886f640..59cbd1ce1d7b 100644 --- a/services/tests/servicestests/utils-mockito/com/android/server/testutils/MockitoUtils.kt +++ b/services/tests/servicestests/utils-mockito/com/android/server/testutils/MockitoUtils.kt @@ -22,8 +22,6 @@ import org.mockito.invocation.InvocationOnMock import org.mockito.stubbing.Answer import org.mockito.stubbing.Stubber -// TODO(chiuwinson): Move this entire file to a shared utility module -// TODO(b/135203078): De-dupe utils added for overlays vs package refactor object MockitoUtils { val ANSWER_THROWS = Answer<Any?> { when (val name = it.method.name) { @@ -64,7 +62,7 @@ fun <Type : Any?> whenever(mock: Type, block: InvocationOnMock.() -> Any?) = fun whenever(mock: Unit) = Mockito.`when`(mock).thenAnswer { } -inline fun <reified T> spyThrowOnUnmocked(value: T?, block: T.() -> Unit): T { +inline fun <reified T> spyThrowOnUnmocked(value: T?, block: T.() -> Unit = {}): T { val swappingAnswer = object : Answer<Any?> { var delegate: Answer<*> = Answers.RETURNS_DEFAULTS @@ -81,4 +79,5 @@ inline fun <reified T> spyThrowOnUnmocked(value: T?, block: T.() -> Unit): T { } } -inline fun <reified T> mockThrowOnUnmocked(block: T.() -> Unit) = spyThrowOnUnmocked<T>(null, block) +inline fun <reified T> mockThrowOnUnmocked(block: T.() -> Unit = {}) = + spyThrowOnUnmocked<T>(null, block) diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java index 86447192a441..9e7226e7cacf 100755 --- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java +++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java @@ -1086,12 +1086,18 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { } /** - * Confirm the system user on automotive devices can use car categories + * Confirm an application with the SEND_CATEGORY_CAR_NOTIFICATIONS permission on automotive + * devices can use car categories. */ @Test - public void testEnqueuedRestrictedNotifications_asSystem() throws Exception { + public void testEnqueuedRestrictedNotifications_hasPermission() throws Exception { when(mPackageManager.hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE, 0)) .thenReturn(true); + // SEND_CATEGORY_CAR_NOTIFICATIONS is a system-level permission that this test cannot + // obtain. Mocking out enforce permission call to ensure notifications can be created when + // permitted. + doNothing().when(mContext).enforceCallingPermission( + eq("android.permission.SEND_CATEGORY_CAR_NOTIFICATIONS"), anyString()); List<String> categories = Arrays.asList(Notification.CATEGORY_CAR_EMERGENCY, Notification.CATEGORY_CAR_WARNING, Notification.CATEGORY_CAR_INFORMATION); @@ -1114,7 +1120,6 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { */ @Test public void testEnqueuedRestrictedNotifications_notAutomotive() throws Exception { - mService.isSystemUid = false; when(mPackageManager.hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE, 0)) .thenReturn(false); List<String> categories = Arrays.asList(Notification.CATEGORY_CAR_EMERGENCY, @@ -1134,12 +1139,11 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { } /** - * Confirm if a non-system user tries to use the car categories on a automotive device that - * they will get a security exception + * Confirm if an application tries to use the car categories on a automotive device without the + * SEND_CATEGORY_CAR_NOTIFICATIONS permission that a security exception will be thrown. */ @Test - public void testEnqueuedRestrictedNotifications_badUser() throws Exception { - mService.isSystemUid = false; + public void testEnqueuedRestrictedNotifications_noPermission() throws Exception { when(mPackageManager.hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE, 0)) .thenReturn(true); List<String> categories = Arrays.asList(Notification.CATEGORY_CAR_EMERGENCY, diff --git a/services/tests/uiservicestests/src/com/android/server/slice/PackageMatchingCacheTest.java b/services/tests/uiservicestests/src/com/android/server/slice/PackageMatchingCacheTest.java new file mode 100644 index 000000000000..f6c854e23494 --- /dev/null +++ b/services/tests/uiservicestests/src/com/android/server/slice/PackageMatchingCacheTest.java @@ -0,0 +1,76 @@ +/* + * 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.slice; + +import static org.junit.Assert.assertTrue; +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.testing.AndroidTestingRunner; +import android.testing.TestableLooper.RunWithLooper; + +import androidx.test.filters.SmallTest; + +import com.android.server.UiServiceTestCase; +import com.android.server.slice.SliceManagerService.PackageMatchingCache; + +import org.junit.Test; +import org.junit.runner.RunWith; + +import java.util.function.Supplier; + +@SmallTest +@RunWith(AndroidTestingRunner.class) +@RunWithLooper +public class PackageMatchingCacheTest extends UiServiceTestCase { + + private final Supplier<String> supplier = mock(Supplier.class); + private final PackageMatchingCache cache = new PackageMatchingCache(supplier); + + @Test + public void testNulls() { + // Doesn't get for a null input + cache.matches(null); + verify(supplier, never()).get(); + + // Gets once valid input in sent. + cache.matches(""); + verify(supplier).get(); + } + + @Test + public void testCaching() { + when(supplier.get()).thenReturn("ret.pkg"); + + assertTrue(cache.matches("ret.pkg")); + assertTrue(cache.matches("ret.pkg")); + assertTrue(cache.matches("ret.pkg")); + + verify(supplier, times(1)).get(); + } + + @Test + public void testGetOnFailure() { + when(supplier.get()).thenReturn("ret.pkg"); + assertTrue(cache.matches("ret.pkg")); + + when(supplier.get()).thenReturn("other.pkg"); + assertTrue(cache.matches("other.pkg")); + verify(supplier, times(2)).get(); + } +} diff --git a/services/tests/uiservicestests/src/com/android/server/slice/SliceManagerServiceTest.java b/services/tests/uiservicestests/src/com/android/server/slice/SliceManagerServiceTest.java index cf1c36c0d243..a4436951f48b 100644 --- a/services/tests/uiservicestests/src/com/android/server/slice/SliceManagerServiceTest.java +++ b/services/tests/uiservicestests/src/com/android/server/slice/SliceManagerServiceTest.java @@ -90,6 +90,8 @@ public class SliceManagerServiceTest extends UiServiceTestCase { @Test public void testAddPinCreatesPinned() throws RemoteException { + doReturn("pkg").when(mService).getDefaultHome(anyInt()); + mService.pinSlice("pkg", TEST_URI, EMPTY_SPECS, mToken); mService.pinSlice("pkg", TEST_URI, EMPTY_SPECS, mToken); verify(mService, times(1)).createPinnedSlice(eq(maybeAddUserId(TEST_URI, 0)), anyString()); @@ -97,6 +99,8 @@ public class SliceManagerServiceTest extends UiServiceTestCase { @Test public void testRemovePinDestroysPinned() throws RemoteException { + doReturn("pkg").when(mService).getDefaultHome(anyInt()); + mService.pinSlice("pkg", TEST_URI, EMPTY_SPECS, mToken); when(mCreatedSliceState.unpin(eq("pkg"), eq(mToken))).thenReturn(false); 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 1eb45d587d33..cf07183a007d 100644 --- a/services/tests/wmtests/src/com/android/server/wm/ActivityDisplayTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/ActivityDisplayTests.java @@ -67,7 +67,7 @@ public class ActivityDisplayTests extends WindowTestsBase { final TaskDisplayArea taskDisplayAreas = mRootWindowContainer.getDefaultDisplay().getDefaultTaskDisplayArea(); final Task stack = - new StackBuilder(mRootWindowContainer).setOnTop(!ON_TOP).build(); + new TaskBuilder(mSupervisor).setOnTop(!ON_TOP).setCreateActivity(true).build(); final Task prevFocusedStack = taskDisplayAreas.getFocusedStack(); stack.moveToFront("moveStackToFront"); @@ -90,7 +90,7 @@ public class ActivityDisplayTests extends WindowTestsBase { final Task pinnedStack = mRootWindowContainer.getDefaultTaskDisplayArea() .createStack(WINDOWING_MODE_PINNED, ACTIVITY_TYPE_STANDARD, ON_TOP); final Task pinnedTask = new TaskBuilder(mAtm.mStackSupervisor) - .setStack(pinnedStack).build(); + .setParentTask(pinnedStack).build(); new ActivityBuilder(mAtm).setActivityFlags(FLAG_ALWAYS_FOCUSABLE) .setTask(pinnedTask).build(); pinnedStack.moveToFront("movePinnedStackToFront"); @@ -144,7 +144,7 @@ public class ActivityDisplayTests extends WindowTestsBase { doReturn(false).when(display).shouldDestroyContentOnRemove(); // Put home stack on the display. - final Task homeStack = new StackBuilder(mRootWindowContainer) + final Task homeStack = new TaskBuilder(mSupervisor) .setDisplay(display).setActivityType(ACTIVITY_TYPE_HOME).build(); // Put a finishing standard activity which will be reparented. @@ -163,7 +163,7 @@ public class ActivityDisplayTests extends WindowTestsBase { final Task fullscreenStack = display.getDefaultTaskDisplayArea().createStack( WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, ON_TOP); final Task fullscreenTask = new TaskBuilder(mAtm.mStackSupervisor) - .setStack(fullscreenStack).build(); + .setParentTask(fullscreenStack).build(); new ActivityBuilder(mAtm).setTask(fullscreenTask).build(); return fullscreenStack; } @@ -175,12 +175,11 @@ public class ActivityDisplayTests extends WindowTestsBase { public void testTopRunningActivity() { final DisplayContent display = mRootWindowContainer.getDefaultDisplay(); final KeyguardController keyguard = mSupervisor.getKeyguardController(); - final Task stack = new StackBuilder(mRootWindowContainer).build(); + final Task stack = new TaskBuilder(mSupervisor).setCreateActivity(true).build(); final ActivityRecord activity = stack.getTopNonFinishingActivity(); // Create empty stack on top. - final Task emptyStack = - new StackBuilder(mRootWindowContainer).setCreateActivity(false).build(); + final Task emptyStack = new TaskBuilder(mSupervisor).build(); // Make sure the top running activity is not affected when keyguard is not locked. assertTopRunningActivity(activity, display); @@ -322,10 +321,10 @@ public class ActivityDisplayTests extends WindowTestsBase { ACTIVITY_TYPE_STANDARD, ON_TOP); final Task stack4 = taskDisplayArea.createStack(WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, ON_TOP); - final Task task1 = new TaskBuilder(mAtm.mStackSupervisor).setStack(stack1).build(); - final Task task2 = new TaskBuilder(mAtm.mStackSupervisor).setStack(stack2).build(); - final Task task3 = new TaskBuilder(mAtm.mStackSupervisor).setStack(stack3).build(); - final Task task4 = new TaskBuilder(mAtm.mStackSupervisor).setStack(stack4).build(); + final Task task1 = new TaskBuilder(mAtm.mStackSupervisor).setParentTask(stack1).build(); + final Task task2 = new TaskBuilder(mAtm.mStackSupervisor).setParentTask(stack2).build(); + final Task task3 = new TaskBuilder(mAtm.mStackSupervisor).setParentTask(stack3).build(); + final Task task4 = new TaskBuilder(mAtm.mStackSupervisor).setParentTask(stack4).build(); // Reordering stacks while removing stacks. doAnswer(invocation -> { 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 eb78172cd562..e860f2508983 100644 --- a/services/tests/wmtests/src/com/android/server/wm/ActivityMetricsLaunchObserverTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/ActivityMetricsLaunchObserverTests.java @@ -341,9 +341,8 @@ public class ActivityMetricsLaunchObserverTests extends WindowTestsBase { public void testConsecutiveLaunchOnDifferentDisplay() { onActivityLaunched(mTopActivity); - final Task stack = new StackBuilder(mRootWindowContainer) + final Task stack = new TaskBuilder(mSupervisor) .setDisplay(addNewDisplayContentAt(DisplayContent.POSITION_BOTTOM)) - .setCreateActivity(false) .build(); final ActivityRecord activityOnNewDisplay = new ActivityBuilder(mAtm) .setStack(stack) 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 bca990c659ae..89a0c7c4885e 100644 --- a/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java @@ -73,7 +73,6 @@ import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.ArgumentMatchers.anyString; -import static org.mockito.ArgumentMatchers.same; import static org.mockito.Mockito.clearInvocations; import static org.mockito.Mockito.never; @@ -131,7 +130,7 @@ public class ActivityRecordTests extends WindowTestsBase { @Before public void setUp() throws Exception { - mStack = new StackBuilder(mRootWindowContainer).build(); + mStack = new TaskBuilder(mSupervisor).setCreateActivity(true).build(); mTask = mStack.getBottomMostTask(); mActivity = mTask.getTopNonFinishingActivity(); @@ -172,7 +171,7 @@ public class ActivityRecordTests extends WindowTestsBase { @Test public void testNoCleanupMovingActivityInSameStack() { - final Task newTask = new TaskBuilder(mAtm.mStackSupervisor).setStack(mStack).build(); + final Task newTask = new TaskBuilder(mAtm.mStackSupervisor).setParentTask(mStack).build(); mActivity.reparent(newTask, 0, null /*reason*/); verify(mStack, times(0)).cleanUpActivityReferences(any()); } @@ -262,7 +261,7 @@ public class ActivityRecordTests extends WindowTestsBase { // Set options for two ActivityRecords in separate Tasks. Apply one ActivityRecord options. // Pending options should be cleared for only ActivityRecord that was applied - Task task2 = new TaskBuilder(mAtm.mStackSupervisor).setStack(mStack).build(); + Task task2 = new TaskBuilder(mAtm.mStackSupervisor).setParentTask(mStack).build(); activity2 = new ActivityBuilder(mAtm).setTask(task2).build(); activity2.updateOptionsLocked(activityOptions); mActivity.updateOptionsLocked(activityOptions); @@ -548,7 +547,7 @@ public class ActivityRecordTests extends WindowTestsBase { .build(); mActivity.setState(Task.ActivityState.STOPPED, "Testing"); - final Task stack = new StackBuilder(mRootWindowContainer).build(); + final Task stack = new TaskBuilder(mSupervisor).setCreateActivity(true).build(); try { doReturn(false).when(stack).isTranslucent(any()); assertFalse(mStack.shouldBeVisible(null /* starting */)); @@ -756,14 +755,14 @@ public class ActivityRecordTests extends WindowTestsBase { @Test public void testFinishActivityIfPossible_adjustStackOrder() { // Prepare the stacks with order (top to bottom): mStack, stack1, stack2. - final Task stack1 = new StackBuilder(mRootWindowContainer).build(); + final Task stack1 = new TaskBuilder(mSupervisor).setCreateActivity(true).build(); mStack.moveToFront("test"); // The stack2 is needed here for moving back to simulate the // {@link DisplayContent#mPreferredTopFocusableStack} is cleared, so // {@link DisplayContent#getFocusedStack} will rely on the order of focusable-and-visible // stacks. Then when mActivity is finishing, its stack will be invisible (no running // activities in the stack) that is the key condition to verify. - final Task stack2 = new StackBuilder(mRootWindowContainer).build(); + final Task stack2 = new TaskBuilder(mSupervisor).setCreateActivity(true).build(); stack2.moveToBack("test", stack2.getBottomMostTask()); assertTrue(mStack.isTopStackInDisplayArea()); @@ -973,7 +972,7 @@ public class ActivityRecordTests extends WindowTestsBase { // Simulates that {@code currentTop} starts an existing activity from background (so its // state is stopped) and the starting flow just goes to place it at top. - final Task nextStack = new StackBuilder(mRootWindowContainer).build(); + final Task nextStack = new TaskBuilder(mSupervisor).setCreateActivity(true).build(); final ActivityRecord nextTop = nextStack.getTopNonFinishingActivity(); nextTop.setState(STOPPED, "test"); @@ -1095,7 +1094,7 @@ public class ActivityRecordTests extends WindowTestsBase { // Add another stack to become focused and make the activity there visible. This way it // simulates finishing in non-focused stack in split-screen. - final Task stack = new StackBuilder(mRootWindowContainer).build(); + final Task stack = new TaskBuilder(mSupervisor).setCreateActivity(true).build(); final ActivityRecord focusedActivity = stack.getTopMostActivity(); focusedActivity.nowVisible = true; focusedActivity.mVisibleRequested = true; @@ -1581,7 +1580,7 @@ public class ActivityRecordTests extends WindowTestsBase { // Create a new task with custom config to reparent the activity to. final Task newTask = - new TaskBuilder(mSupervisor).setStack(initialTask.getRootTask()).build(); + new TaskBuilder(mSupervisor).setParentTask(initialTask.getRootTask()).build(); final Configuration newConfig = newTask.getConfiguration(); newConfig.densityDpi += 100; newTask.onRequestedOverrideConfigurationChanged(newConfig); @@ -1613,7 +1612,7 @@ public class ActivityRecordTests extends WindowTestsBase { // Create a new task with custom config to reparent the second activity to. final Task newTask = - new TaskBuilder(mSupervisor).setStack(initialTask.getRootTask()).build(); + new TaskBuilder(mSupervisor).setParentTask(initialTask.getRootTask()).build(); final Configuration newConfig = newTask.getConfiguration(); newConfig.densityDpi += 100; newTask.onRequestedOverrideConfigurationChanged(newConfig); @@ -1671,8 +1670,6 @@ public class ActivityRecordTests extends WindowTestsBase { @Test public void testCanTurnScreenOn() { mStack.setWindowingMode(WINDOWING_MODE_FULLSCREEN); - doReturn(true).when(mStack).checkKeyguardVisibility( - same(mActivity), eq(true) /* shouldBeVisible */, anyBoolean()); doReturn(true).when(mActivity).getTurnScreenOnFlag(); assertTrue(mActivity.canTurnScreenOn()); @@ -1681,8 +1678,6 @@ public class ActivityRecordTests extends WindowTestsBase { @Test public void testFreeformWindowCantTurnScreenOn() { mStack.setWindowingMode(WINDOWING_MODE_FREEFORM); - doReturn(true).when(mStack).checkKeyguardVisibility( - same(mActivity), eq(true) /* shouldBeVisible */, anyBoolean()); doReturn(true).when(mActivity).getTurnScreenOnFlag(); assertFalse(mActivity.canTurnScreenOn()); @@ -1750,7 +1745,7 @@ public class ActivityRecordTests extends WindowTestsBase { } final Task stack = display.getDefaultTaskDisplayArea() .createStack(WINDOWING_MODE_UNDEFINED, ACTIVITY_TYPE_STANDARD, true /* onTop */); - final Task task = new TaskBuilder(mSupervisor).setStack(stack).build(); + final Task task = new TaskBuilder(mSupervisor).setParentTask(stack).build(); return new ActivityBuilder(mAtm).setTask(task).setUseProcess(process).build(); } } 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 27e2d1370fae..f9ad49bb5034 100644 --- a/services/tests/wmtests/src/com/android/server/wm/ActivityStackSupervisorTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/ActivityStackSupervisorTests.java @@ -115,8 +115,8 @@ public class ActivityStackSupervisorTests extends WindowTestsBase { public void testHandleNonResizableTaskOnSecondaryDisplay() { // Create an unresizable task on secondary display. final DisplayContent newDisplay = addNewDisplayContentAt(DisplayContent.POSITION_TOP); - final Task stack = new StackBuilder(mRootWindowContainer) - .setDisplay(newDisplay).build(); + final Task stack = new TaskBuilder(mSupervisor) + .setDisplay(newDisplay).setCreateActivity(true).build(); final ActivityRecord unresizableActivity = stack.getTopNonFinishingActivity(); final Task task = unresizableActivity.getTask(); unresizableActivity.info.resizeMode = ActivityInfo.RESIZE_MODE_UNRESIZEABLE; 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 524f32deb864..a60f93a3b14a 100644 --- a/services/tests/wmtests/src/com/android/server/wm/ActivityStackTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/ActivityStackTests.java @@ -100,7 +100,7 @@ public class ActivityStackTests extends WindowTestsBase { mStack = mDefaultTaskDisplayArea.createStack(WINDOWING_MODE_UNDEFINED, ACTIVITY_TYPE_STANDARD, true /* onTop */); spyOn(mStack); - mTask = new TaskBuilder(mSupervisor).setStack(mStack).build(); + mTask = new TaskBuilder(mSupervisor).setParentTask(mStack).build(); } @Test @@ -330,7 +330,7 @@ public class ActivityStackTests extends WindowTestsBase { targetActivity); final ComponentName alias = new ComponentName(DEFAULT_COMPONENT_PACKAGE_NAME, aliasActivity); - final Task task = new TaskBuilder(mAtm.mStackSupervisor).setStack(mStack).build(); + final Task task = new TaskBuilder(mAtm.mStackSupervisor).setParentTask(mStack).build(); task.origActivity = alias; task.realActivity = target; new ActivityBuilder(mAtm).setComponent(target).setTask(task).setTargetActivity( @@ -995,7 +995,7 @@ public class ActivityStackTests extends WindowTestsBase { mDefaultTaskDisplayArea.positionChildAt(onTop ? POSITION_TOP : POSITION_BOTTOM, task, false /* includingParents */); } else { - task = new StackBuilder(mRootWindowContainer) + task = new TaskBuilder(mSupervisor) .setTaskDisplayArea(taskDisplayArea) .setWindowingMode(windowingMode) .setActivityType(activityType) @@ -1410,7 +1410,7 @@ public class ActivityStackTests extends WindowTestsBase { new ActivityBuilder(mAtm).setTask(mTask).build(); new ActivityBuilder(mAtm).setTask(mTask).build(); doReturn(false).when(nonTopVisibleActivity).attachedToProcess(); - doReturn(true).when(nonTopVisibleActivity).shouldBeVisible(anyBoolean(), anyBoolean()); + doReturn(true).when(nonTopVisibleActivity).shouldBeVisibleUnchecked(); doNothing().when(mSupervisor).startSpecificActivity(any(), anyBoolean(), anyBoolean()); 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 e537b7c204cc..076047b35604 100644 --- a/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java @@ -217,7 +217,10 @@ public class ActivityStarterTests extends WindowTestsBase { // Create source token final ActivityBuilder builder = new ActivityBuilder(service).setTask( - new TaskBuilder(service.mStackSupervisor).setVoiceSession(voiceSession).build()); + new TaskBuilder(service.mStackSupervisor) + .setVoiceSession(voiceSession) + .setCreateParentTask(true) + .build()); if (aInfo != null) { aInfo.applicationInfo = new ApplicationInfo(); @@ -706,7 +709,9 @@ public class ActivityStarterTests extends WindowTestsBase { @Test public void testBringTaskToFrontWhenFocusedStackIsFinising() { // Put 2 tasks in the same stack (simulate the behavior of home stack). + final Task rootTask = new TaskBuilder(mSupervisor).build(); final ActivityRecord activity = new ActivityBuilder(mAtm) + .setStack(rootTask) .setCreateTask(true).build(); new ActivityBuilder(mAtm) .setStack(activity.getRootTask()) @@ -792,7 +797,7 @@ public class ActivityStarterTests extends WindowTestsBase { // Create another activity on top of the secondary display. final Task topStack = secondaryTaskContainer.createStack(WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, true /* onTop */); - final Task topTask = new TaskBuilder(mSupervisor).setStack(topStack).build(); + final Task topTask = new TaskBuilder(mSupervisor).setParentTask(topStack).build(); new ActivityBuilder(mAtm).setTask(topTask).build(); // Start activity with the same intent as {@code singleTaskActivity} on secondary display. @@ -851,7 +856,7 @@ public class ActivityStarterTests extends WindowTestsBase { DEFAULT_COMPONENT_PACKAGE_NAME + ".SingleTaskActivity"); final Task task = new TaskBuilder(mSupervisor) .setComponent(componentName) - .setStack(stack) + .setParentTask(stack) .build(); return new ActivityBuilder(mAtm) .setComponent(componentName) @@ -987,7 +992,7 @@ public class ActivityStarterTests extends WindowTestsBase { final ActivityStarter starter = prepareStarter(0 /* flags */); starter.mStartActivity = new ActivityBuilder(mAtm).build(); final Task task = new TaskBuilder(mAtm.mStackSupervisor) - .setStack(mAtm.mRootWindowContainer.getDefaultTaskDisplayArea().createStack( + .setParentTask(mAtm.mRootWindowContainer.getDefaultTaskDisplayArea().createStack( WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, true /* onTop */)) .setUserId(10) .build(); diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityTaskManagerServiceTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityTaskManagerServiceTests.java index 567610018fc1..031165727207 100644 --- a/services/tests/wmtests/src/com/android/server/wm/ActivityTaskManagerServiceTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/ActivityTaskManagerServiceTests.java @@ -73,7 +73,7 @@ public class ActivityTaskManagerServiceTests extends WindowTestsBase { /** Verify that activity is finished correctly upon request. */ @Test public void testActivityFinish() { - final Task stack = new StackBuilder(mRootWindowContainer).build(); + final Task stack = new TaskBuilder(mSupervisor).setCreateActivity(true).build(); final ActivityRecord activity = stack.getBottomMostTask().getTopNonFinishingActivity(); assertTrue("Activity must be finished", mAtm.finishActivity(activity.appToken, 0 /* resultCode */, null /* resultData */, @@ -87,7 +87,7 @@ public class ActivityTaskManagerServiceTests extends WindowTestsBase { @Test public void testOnPictureInPictureRequested() throws RemoteException { - final Task stack = new StackBuilder(mRootWindowContainer).build(); + final Task stack = new TaskBuilder(mSupervisor).setCreateActivity(true).build(); final ActivityRecord activity = stack.getBottomMostTask().getTopNonFinishingActivity(); final ClientLifecycleManager mockLifecycleManager = mock(ClientLifecycleManager.class); doReturn(mockLifecycleManager).when(mAtm).getLifecycleManager(); @@ -106,7 +106,7 @@ public class ActivityTaskManagerServiceTests extends WindowTestsBase { @Test(expected = IllegalStateException.class) public void testOnPictureInPictureRequested_cannotEnterPip() throws RemoteException { - final Task stack = new StackBuilder(mRootWindowContainer).build(); + final Task stack = new TaskBuilder(mSupervisor).setCreateActivity(true).build(); final ActivityRecord activity = stack.getBottomMostTask().getTopNonFinishingActivity(); ClientLifecycleManager lifecycleManager = mAtm.getLifecycleManager(); doReturn(false).when(activity).inPinnedWindowingMode(); @@ -120,7 +120,7 @@ public class ActivityTaskManagerServiceTests extends WindowTestsBase { @Test(expected = IllegalStateException.class) public void testOnPictureInPictureRequested_alreadyInPIPMode() throws RemoteException { - final Task stack = new StackBuilder(mRootWindowContainer).build(); + final Task stack = new TaskBuilder(mSupervisor).setCreateActivity(true).build(); final ActivityRecord activity = stack.getBottomMostTask().getTopNonFinishingActivity(); ClientLifecycleManager lifecycleManager = mAtm.getLifecycleManager(); doReturn(true).when(activity).inPinnedWindowingMode(); diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java b/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java index f8baf8497069..89a34cfc77f3 100644 --- a/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java @@ -24,10 +24,10 @@ import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED; import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE; import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_PORTRAIT; import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED; -import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_USER; import static android.os.Build.VERSION_CODES.P; import static android.os.Build.VERSION_CODES.Q; import static android.view.Display.DEFAULT_DISPLAY; +import static android.view.Display.FLAG_PRIVATE; import static android.view.DisplayCutout.BOUNDS_POSITION_LEFT; import static android.view.DisplayCutout.BOUNDS_POSITION_TOP; import static android.view.DisplayCutout.fromBoundingRect; @@ -95,6 +95,7 @@ import android.os.SystemClock; import android.platform.test.annotations.Presubmit; import android.util.DisplayMetrics; import android.view.DisplayCutout; +import android.view.DisplayInfo; import android.view.Gravity; import android.view.IDisplayWindowRotationCallback; import android.view.IDisplayWindowRotationController; @@ -760,13 +761,14 @@ public class DisplayContentTests extends WindowTestsBase { window.mAttrs.screenOrientation, dc.getOrientation()); // ---------------------------- - // Test close-to-square display + // Test close-to-square display - should be handled in the same way // ---------------------------- dc.mBaseDisplayHeight = dc.mBaseDisplayWidth; dc.configureDisplayPolicy(); - assertEquals("Screen orientation must be SCREEN_ORIENTATION_USER.", - SCREEN_ORIENTATION_USER, dc.getOrientation()); + assertEquals( + "Screen orientation must be defined by the window even on close-to-square display.", + window.mAttrs.screenOrientation, dc.getOrientation()); } @Test @@ -821,7 +823,14 @@ public class DisplayContentTests extends WindowTestsBase { final DisplayContent newDisplay = createNewDisplay(); final WindowState appWin = createWindow(null, TYPE_APPLICATION, mDisplayContent, "appWin"); + final Task stack = mDisplayContent.getTopStack(); + final ActivityRecord activity = stack.topRunningActivity(); + doReturn(true).when(activity).shouldBeVisibleUnchecked(); + final WindowState appWin1 = createWindow(null, TYPE_APPLICATION, newDisplay, "appWin1"); + final Task stack1 = newDisplay.getTopStack(); + final ActivityRecord activity1 = stack1.topRunningActivity(); + doReturn(true).when(activity1).shouldBeVisibleUnchecked(); appWin.setHasSurface(true); appWin1.setHasSurface(true); @@ -847,17 +856,17 @@ public class DisplayContentTests extends WindowTestsBase { dc.getDisplayRotation().setFixedToUserRotation( IWindowManager.FIXED_TO_USER_ROTATION_DISABLED); - final Task stack = - new StackBuilder(mWm.mAtmService.mRootWindowContainer) - .setDisplay(dc) - .build(); + final Task stack = new TaskBuilder(mSupervisor) + .setDisplay(dc) + .setCreateActivity(true) + .build(); doReturn(true).when(stack).isVisible(); - final Task freeformStack = - new StackBuilder(mWm.mAtmService.mRootWindowContainer) - .setDisplay(dc) - .setWindowingMode(WINDOWING_MODE_FREEFORM) - .build(); + final Task freeformStack = new TaskBuilder(mSupervisor) + .setDisplay(dc) + .setCreateActivity(true) + .setWindowingMode(WINDOWING_MODE_FREEFORM) + .build(); doReturn(true).when(freeformStack).isVisible(); freeformStack.getTopChild().setBounds(100, 100, 300, 400); @@ -879,8 +888,8 @@ public class DisplayContentTests extends WindowTestsBase { IWindowManager.FIXED_TO_USER_ROTATION_DISABLED); final int newOrientation = getRotatedOrientation(dc); - final Task stack = new StackBuilder(mWm.mAtmService.mRootWindowContainer) - .setDisplay(dc).build(); + final Task stack = new TaskBuilder(mSupervisor) + .setDisplay(dc).setCreateActivity(true).build(); final ActivityRecord activity = stack.getTopMostTask().getTopNonFinishingActivity(); activity.setRequestedOrientation(newOrientation); @@ -898,8 +907,8 @@ public class DisplayContentTests extends WindowTestsBase { IWindowManager.FIXED_TO_USER_ROTATION_ENABLED); final int newOrientation = getRotatedOrientation(dc); - final Task stack = new StackBuilder(mWm.mAtmService.mRootWindowContainer) - .setDisplay(dc).build(); + final Task stack = new TaskBuilder(mSupervisor) + .setDisplay(dc).setCreateActivity(true).build(); final ActivityRecord activity = stack.getTopMostTask().getTopNonFinishingActivity(); activity.setRequestedOrientation(newOrientation); @@ -1209,8 +1218,8 @@ public class DisplayContentTests extends WindowTestsBase { verify(t, never()).setPosition(any(), eq(0), eq(0)); // Launch another activity before the transition is finished. - final ActivityRecord app2 = new StackBuilder(mWm.mRoot) - .setDisplay(mDisplayContent).build().getTopMostActivity(); + final ActivityRecord app2 = new TaskBuilder(mSupervisor) + .setDisplay(mDisplayContent).setCreateActivity(true).build().getTopMostActivity(); app2.setVisible(false); mDisplayContent.mOpeningApps.add(app2); app2.setRequestedOrientation(newOrientation); @@ -1508,7 +1517,7 @@ public class DisplayContentTests extends WindowTestsBase { @Test public void testSetWindowingModeAtomicallyUpdatesWindoingModeAndDisplayWindowingMode() { final DisplayContent dc = createNewDisplay(); - final Task stack = new StackBuilder(mWm.mAtmService.mRootWindowContainer) + final Task stack = new TaskBuilder(mSupervisor) .setDisplay(dc) .build(); doAnswer(invocation -> { @@ -1522,6 +1531,28 @@ public class DisplayContentTests extends WindowTestsBase { dc.setWindowingMode(WINDOWING_MODE_FULLSCREEN); } + @Test + public void testForceDesktopMode() { + mWm.mForceDesktopModeOnExternalDisplays = true; + // Not applicable for default display + assertFalse(mDefaultDisplay.forceDesktopMode()); + + // Not applicable for private secondary display. + final DisplayInfo displayInfo = new DisplayInfo(); + displayInfo.copyFrom(mDisplayInfo); + displayInfo.flags = FLAG_PRIVATE; + final DisplayContent privateDc = createNewDisplay(displayInfo); + assertFalse(privateDc.forceDesktopMode()); + + // Applicable for public secondary display. + final DisplayContent publicDc = createNewDisplay(); + assertTrue(publicDc.forceDesktopMode()); + + // Make sure forceDesktopMode() is false when the force config is disabled. + mWm.mForceDesktopModeOnExternalDisplays = false; + assertFalse(publicDc.forceDesktopMode()); + } + private boolean isOptionsPanelAtRight(int displayId) { return (mWm.getPreferredOptionsPanelGravity(displayId) & Gravity.RIGHT) == Gravity.RIGHT; } diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyTests.java b/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyTests.java index b50530ed3059..b77d21c0f711 100644 --- a/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyTests.java @@ -27,11 +27,9 @@ import static android.view.WindowInsetsController.BEHAVIOR_SHOW_BARS_BY_TOUCH; import static android.view.WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM; import static android.view.WindowManager.LayoutParams.FLAG_DIM_BEHIND; import static android.view.WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS; -import static android.view.WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON; import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR; import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN; import static android.view.WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE; -import static android.view.WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE; import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED; import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_FORCE_DRAW_BAR_BACKGROUNDS; import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_STATUS_FORCE_SHOW_NAVIGATION; @@ -39,7 +37,6 @@ import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION; import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION; import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD; import static android.view.WindowManager.LayoutParams.TYPE_NAVIGATION_BAR; -import static android.view.WindowManager.LayoutParams.TYPE_TOAST; import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn; import static com.android.server.policy.WindowManagerPolicy.NAV_BAR_BOTTOM; @@ -47,7 +44,6 @@ import static com.android.server.policy.WindowManagerPolicy.NAV_BAR_RIGHT; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNotEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; @@ -235,18 +231,6 @@ public class DisplayPolicyTests extends WindowTestsBase { assertEquals(mAppWindow, policy.getTopFullscreenOpaqueWindow()); } - @Test - public void testShouldShowToastWhenScreenLocked() { - final DisplayPolicy policy = mDisplayContent.getDisplayPolicy(); - final WindowState activity = createApplicationWindow(); - final WindowState toast = createToastWindow(); - - policy.adjustWindowParamsLw(toast, toast.mAttrs, 0 /* callingPid */, 0 /* callingUid */); - - assertTrue(policy.canToastShowWhenLocked(0 /* callingUid */)); - assertNotEquals(0, toast.getAttrs().flags & FLAG_SHOW_WHEN_LOCKED); - } - @Test(expected = RuntimeException.class) public void testMainAppWindowDisallowFitSystemWindowTypes() { final DisplayPolicy policy = mDisplayContent.getDisplayPolicy(); @@ -257,16 +241,6 @@ public class DisplayPolicyTests extends WindowTestsBase { 0 /* callingUid */); } - private WindowState createToastWindow() { - final WindowState win = createWindow(null, TYPE_TOAST, "Toast"); - final WindowManager.LayoutParams attrs = win.mAttrs; - attrs.width = WRAP_CONTENT; - attrs.height = WRAP_CONTENT; - attrs.flags = FLAG_KEEP_SCREEN_ON | FLAG_NOT_FOCUSABLE | FLAG_NOT_TOUCHABLE; - attrs.format = PixelFormat.TRANSLUCENT; - return win; - } - private WindowState createApplicationWindow() { final WindowState win = createWindow(null, TYPE_APPLICATION, "Application"); final WindowManager.LayoutParams attrs = win.mAttrs; 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 18a2d1337d4b..d701a9df7cb8 100644 --- a/services/tests/wmtests/src/com/android/server/wm/LaunchParamsPersisterTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/LaunchParamsPersisterTests.java @@ -116,7 +116,7 @@ public class LaunchParamsPersisterTests extends WindowTestsBase { Task stack = mTestDisplay.getDefaultTaskDisplayArea() .createStack(TEST_WINDOWING_MODE, ACTIVITY_TYPE_STANDARD, /* onTop */ true); - mTestTask = new TaskBuilder(mSupervisor).setComponent(TEST_COMPONENT).setStack(stack) + mTestTask = new TaskBuilder(mSupervisor).setComponent(TEST_COMPONENT).setParentTask(stack) .build(); mTestTask.mUserId = TEST_USER_ID; mTestTask.mLastNonFullscreenBounds = TEST_BOUNDS; @@ -342,7 +342,7 @@ public class LaunchParamsPersisterTests extends WindowTestsBase { final Task anotherTaskOfTheSameUser = new TaskBuilder(mSupervisor) .setComponent(ALTERNATIVE_COMPONENT) .setUserId(TEST_USER_ID) - .setStack(stack) + .setParentTask(stack) .build(); anotherTaskOfTheSameUser.setWindowingMode(WINDOWING_MODE_FREEFORM); anotherTaskOfTheSameUser.setBounds(200, 300, 400, 500); @@ -354,7 +354,7 @@ public class LaunchParamsPersisterTests extends WindowTestsBase { final Task anotherTaskOfDifferentUser = new TaskBuilder(mSupervisor) .setComponent(TEST_COMPONENT) .setUserId(ALTERNATIVE_USER_ID) - .setStack(stack) + .setParentTask(stack) .build(); anotherTaskOfDifferentUser.setWindowingMode(WINDOWING_MODE_FREEFORM); anotherTaskOfDifferentUser.setBounds(300, 400, 500, 600); diff --git a/services/tests/wmtests/src/com/android/server/wm/RecentTasksTest.java b/services/tests/wmtests/src/com/android/server/wm/RecentTasksTest.java index 9954f484f0a6..58d994c6cae3 100644 --- a/services/tests/wmtests/src/com/android/server/wm/RecentTasksTest.java +++ b/services/tests/wmtests/src/com/android/server/wm/RecentTasksTest.java @@ -44,6 +44,7 @@ import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; +import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyBoolean; import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.ArgumentMatchers.anyString; @@ -291,7 +292,8 @@ public class RecentTasksTest extends WindowTestsBase { mRecentTasks.add(mTasks.get(1)); invocation.callRealMethod(); return null; - }).when(mSupervisor).endActivityVisibilityUpdate(); + }).when(mSupervisor).endActivityVisibilityUpdate(any(), anyInt(), anyBoolean(), + anyBoolean()); mTaskContainer.ensureActivitiesVisible(null /* starting */, 0 /* configChanges */, false /* preserveWindows */, false /* notifyClients */); @@ -333,10 +335,10 @@ public class RecentTasksTest extends WindowTestsBase { // other task Task task1 = createTaskBuilder(".Task1") .setFlags(FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_MULTIPLE_TASK) - .setStack(mTaskContainer.getRootHomeTask()).build(); + .setParentTask(mTaskContainer.getRootHomeTask()).build(); Task task2 = createTaskBuilder(".Task1") .setFlags(FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_MULTIPLE_TASK) - .setStack(mStack).build(); + .setParentTask(mStack).build(); mRecentTasks.add(task1); mRecentTasks.add(task2); assertThat(mCallbacksRecorder.mAdded).hasSize(2); @@ -352,7 +354,7 @@ public class RecentTasksTest extends WindowTestsBase { // and we want to ensure that a new task will match a restored task Task task1 = createTaskBuilder(".Task1") .setFlags(FLAG_ACTIVITY_NEW_TASK) - .setStack(mStack) + .setParentTask(mStack) .build(); setTaskActivityType(task1, ACTIVITY_TYPE_UNDEFINED); assertThat(task1.getActivityType()).isEqualTo(ACTIVITY_TYPE_UNDEFINED); @@ -361,7 +363,7 @@ public class RecentTasksTest extends WindowTestsBase { Task task2 = createTaskBuilder(".Task1") .setFlags(FLAG_ACTIVITY_NEW_TASK) - .setStack(mStack) + .setParentTask(mStack) .build(); assertEquals(ACTIVITY_TYPE_STANDARD, task2.getActivityType()); mRecentTasks.add(task2); @@ -376,7 +378,7 @@ public class RecentTasksTest extends WindowTestsBase { public void testAddTaskCompatibleActivityTypeDifferentUser_expectNoRemove() { Task task1 = createTaskBuilder(".Task1") .setFlags(FLAG_ACTIVITY_NEW_TASK) - .setStack(mStack) + .setParentTask(mStack) .setUserId(TEST_USER_0_ID) .build(); setTaskActivityType(task1, ACTIVITY_TYPE_UNDEFINED); @@ -386,7 +388,7 @@ public class RecentTasksTest extends WindowTestsBase { Task task2 = createTaskBuilder(".Task1") .setFlags(FLAG_ACTIVITY_NEW_TASK) - .setStack(mStack) + .setParentTask(mStack) .setUserId(TEST_USER_1_ID) .build(); assertEquals(ACTIVITY_TYPE_STANDARD, task2.getActivityType()); @@ -401,7 +403,7 @@ public class RecentTasksTest extends WindowTestsBase { public void testAddTaskCompatibleWindowingMode_expectRemove() { Task task1 = createTaskBuilder(".Task1") .setFlags(FLAG_ACTIVITY_NEW_TASK) - .setStack(mStack) + .setParentTask(mStack) .build(); setTaskWindowingMode(task1, WINDOWING_MODE_UNDEFINED); assertEquals(WINDOWING_MODE_UNDEFINED, task1.getWindowingMode()); @@ -410,7 +412,7 @@ public class RecentTasksTest extends WindowTestsBase { Task task2 = createTaskBuilder(".Task1") .setFlags(FLAG_ACTIVITY_NEW_TASK) - .setStack(mStack) + .setParentTask(mStack) .build(); setTaskWindowingMode(task2, WINDOWING_MODE_FULLSCREEN); assertEquals(WINDOWING_MODE_FULLSCREEN, task2.getWindowingMode()); @@ -427,7 +429,7 @@ public class RecentTasksTest extends WindowTestsBase { public void testAddTaskIncompatibleWindowingMode_expectNoRemove() { Task task1 = createTaskBuilder(".Task1") .setFlags(FLAG_ACTIVITY_NEW_TASK) - .setStack(mStack) + .setParentTask(mStack) .build(); setTaskWindowingMode(task1, WINDOWING_MODE_FULLSCREEN); assertEquals(WINDOWING_MODE_FULLSCREEN, task1.getWindowingMode()); @@ -435,7 +437,7 @@ public class RecentTasksTest extends WindowTestsBase { Task task2 = createTaskBuilder(".Task1") .setFlags(FLAG_ACTIVITY_NEW_TASK) - .setStack(mStack) + .setParentTask(mStack) .build(); setTaskWindowingMode(task2, WINDOWING_MODE_PINNED); assertEquals(WINDOWING_MODE_PINNED, task2.getWindowingMode()); @@ -453,19 +455,19 @@ public class RecentTasksTest extends WindowTestsBase { // Add task to recents final String taskAffinity = "affinity"; final int uid = 10123; - final Task task1 = createTaskBuilder(".Task1").setStack(mStack).build(); + final Task task1 = createTaskBuilder(".Task1").setParentTask(mStack).build(); task1.affinity = ActivityRecord.computeTaskAffinity(taskAffinity, uid, LAUNCH_MULTIPLE); mRecentTasks.add(task1); // Add another task to recents, and make sure the previous task was removed. - final Task task2 = createTaskBuilder(".Task2").setStack(mStack).build(); + final Task task2 = createTaskBuilder(".Task2").setParentTask(mStack).build(); task2.affinity = ActivityRecord.computeTaskAffinity(taskAffinity, uid, LAUNCH_MULTIPLE); mRecentTasks.add(task2); assertEquals(1, mRecentTasks.getRecentTasks(MAX_VALUE, 0 /* flags */, true /* getTasksAllowed */, TEST_USER_0_ID, 0).getList().size()); // Add another single-instance task to recents, and make sure no task is removed. - final Task task3 = createTaskBuilder(".Task3").setStack(mStack).build(); + final Task task3 = createTaskBuilder(".Task3").setParentTask(mStack).build(); task3.affinity = ActivityRecord.computeTaskAffinity(taskAffinity, uid, LAUNCH_SINGLE_INSTANCE); mRecentTasks.add(task3); @@ -497,7 +499,7 @@ public class RecentTasksTest extends WindowTestsBase { // tasks because their intents are identical. mRecentTasks.add(task1); // Go home to trigger the removal of untracked tasks. - mRecentTasks.add(createTaskBuilder(".Home").setStack(mTaskContainer.getRootHomeTask()) + mRecentTasks.add(createTaskBuilder(".Home").setParentTask(mTaskContainer.getRootHomeTask()) .build()); // The task was added into recents again so it is not hidden and shouldn't be removed. @@ -883,10 +885,10 @@ public class RecentTasksTest extends WindowTestsBase { // Add a number of tasks (beyond the max) but ensure that nothing is trimmed because all // the tasks belong in stacks above the home stack - mRecentTasks.add(createTaskBuilder(".HomeTask1").setStack(homeStack).build()); - mRecentTasks.add(createTaskBuilder(".Task1").setStack(aboveHomeStack).build()); - mRecentTasks.add(createTaskBuilder(".Task2").setStack(aboveHomeStack).build()); - mRecentTasks.add(createTaskBuilder(".Task3").setStack(aboveHomeStack).build()); + mRecentTasks.add(createTaskBuilder(".HomeTask1").setParentTask(homeStack).build()); + mRecentTasks.add(createTaskBuilder(".Task1").setParentTask(aboveHomeStack).build()); + mRecentTasks.add(createTaskBuilder(".Task2").setParentTask(aboveHomeStack).build()); + mRecentTasks.add(createTaskBuilder(".Task3").setParentTask(aboveHomeStack).build()); assertNoTasksTrimmed(); } @@ -904,11 +906,11 @@ public class RecentTasksTest extends WindowTestsBase { // Add a number of tasks (beyond the max) but ensure that only the task in the stack behind // the home stack is trimmed once a new task is added final Task behindHomeTask = createTaskBuilder(".Task1") - .setStack(behindHomeStack) + .setParentTask(behindHomeStack) .build(); mRecentTasks.add(behindHomeTask); - mRecentTasks.add(createTaskBuilder(".HomeTask1").setStack(homeStack).build()); - mRecentTasks.add(createTaskBuilder(".Task2").setStack(aboveHomeStack).build()); + mRecentTasks.add(createTaskBuilder(".HomeTask1").setParentTask(homeStack).build()); + mRecentTasks.add(createTaskBuilder(".Task2").setParentTask(aboveHomeStack).build()); assertTrimmed(behindHomeTask); } @@ -924,10 +926,10 @@ public class RecentTasksTest extends WindowTestsBase { // Add a number of tasks (beyond the max) on each display, ensure that the tasks are not // removed - mRecentTasks.add(createTaskBuilder(".HomeTask1").setStack(homeStack).build()); - mRecentTasks.add(createTaskBuilder(".Task1").setStack(otherDisplayStack).build()); - mRecentTasks.add(createTaskBuilder(".Task2").setStack(otherDisplayStack).build()); - mRecentTasks.add(createTaskBuilder(".HomeTask2").setStack(homeStack).build()); + mRecentTasks.add(createTaskBuilder(".HomeTask1").setParentTask(homeStack).build()); + mRecentTasks.add(createTaskBuilder(".Task1").setParentTask(otherDisplayStack).build()); + mRecentTasks.add(createTaskBuilder(".Task2").setParentTask(otherDisplayStack).build()); + mRecentTasks.add(createTaskBuilder(".HomeTask2").setParentTask(homeStack).build()); assertNoTasksTrimmed(); } @@ -1170,12 +1172,12 @@ public class RecentTasksTest extends WindowTestsBase { () -> mAtm.setTaskWindowingModeSplitScreenPrimary(0, true)); assertSecurityException(expectCallable, () -> mAtm.moveTopActivityToPinnedStack(INVALID_STACK_ID, new Rect())); - assertSecurityException(expectCallable, () -> mAtm.getAllStackInfos()); + assertSecurityException(expectCallable, () -> mAtm.getAllRootTaskInfos()); assertSecurityException(expectCallable, - () -> mAtm.getStackInfo(WINDOWING_MODE_UNDEFINED, ACTIVITY_TYPE_UNDEFINED)); + () -> mAtm.getRootTaskInfo(WINDOWING_MODE_UNDEFINED, ACTIVITY_TYPE_UNDEFINED)); assertSecurityException(expectCallable, () -> { try { - mAtm.getFocusedStackInfo(); + mAtm.getFocusedRootTaskInfo(); } catch (RemoteException e) { // Ignore } @@ -1214,7 +1216,7 @@ public class RecentTasksTest extends WindowTestsBase { private TaskBuilder createTaskBuilder(String packageName, String className) { return new TaskBuilder(mAtm.mStackSupervisor) .setComponent(new ComponentName(packageName, className)) - .setStack(mStack) + .setParentTask(mStack) .setUserId(TEST_USER_0_ID); } 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 26b0bfb1dd7c..901ed36254ea 100644 --- a/services/tests/wmtests/src/com/android/server/wm/RootActivityContainerTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/RootActivityContainerTests.java @@ -195,8 +195,7 @@ public class RootActivityContainerTests extends WindowTestsBase { public void testApplySleepTokens() { final DisplayContent display = mRootWindowContainer.getDefaultDisplay(); final KeyguardController keyguard = mSupervisor.getKeyguardController(); - final Task stack = new StackBuilder(mRootWindowContainer) - .setCreateActivity(false) + final Task stack = new TaskBuilder(mSupervisor) .setDisplay(display) .setOnTop(false) .build(); @@ -384,7 +383,7 @@ public class RootActivityContainerTests extends WindowTestsBase { final Task primaryStack = mRootWindowContainer.getDefaultTaskDisplayArea() .createStack(WINDOWING_MODE_SPLIT_SCREEN_PRIMARY, ACTIVITY_TYPE_STANDARD, true /* onTop */); - final Task task = new TaskBuilder(mSupervisor).setStack(primaryStack).build(); + final Task task = new TaskBuilder(mSupervisor).setParentTask(primaryStack).build(); final ActivityRecord r = new ActivityBuilder(mAtm).setTask(task).build(); // Find a launch stack for the top activity in split-screen primary, while requesting @@ -404,14 +403,17 @@ public class RootActivityContainerTests extends WindowTestsBase { @Test public void testFindTaskToMoveToFrontWhenRecentsOnTop() { // Create stack/task on default display. - final Task targetStack = new StackBuilder(mRootWindowContainer) + final Task targetStack = new TaskBuilder(mSupervisor) + .setCreateActivity(true) .setOnTop(false) .build(); final Task targetTask = targetStack.getBottomMostTask(); // Create Recents on top of the display. - final Task stack = new StackBuilder(mRootWindowContainer).setActivityType( - ACTIVITY_TYPE_RECENTS).build(); + final Task stack = new TaskBuilder(mSupervisor) + .setCreateActivity(true) + .setActivityType(ACTIVITY_TYPE_RECENTS) + .build(); final String reason = "findTaskToMoveToFront"; mSupervisor.findTaskToMoveToFront(targetTask, 0, ActivityOptions.makeBasic(), reason, @@ -431,14 +433,14 @@ public class RootActivityContainerTests extends WindowTestsBase { final TaskDisplayArea taskDisplayArea = mRootWindowContainer.getDefaultTaskDisplayArea(); final Task targetStack = taskDisplayArea.createStack(WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, false /* onTop */); - final Task targetTask = new TaskBuilder(mSupervisor).setStack(targetStack).build(); + final Task targetTask = new TaskBuilder(mSupervisor).setParentTask(targetStack).build(); // Create Recents on secondary display. final TestDisplayContent secondDisplay = addNewDisplayContentAt( DisplayContent.POSITION_TOP); final Task stack = secondDisplay.getDefaultTaskDisplayArea() .createStack(WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_RECENTS, true /* onTop */); - final Task task = new TaskBuilder(mSupervisor).setStack(stack).build(); + final Task task = new TaskBuilder(mSupervisor).setParentTask(stack).build(); new ActivityBuilder(mAtm).setTask(task).build(); final String reason = "findTaskToMoveToFront"; @@ -458,7 +460,7 @@ public class RootActivityContainerTests extends WindowTestsBase { final TaskDisplayArea taskDisplayArea = mRootWindowContainer.getDefaultTaskDisplayArea(); final Task targetStack = spy(taskDisplayArea.createStack(WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, false /* onTop */)); - final Task task = new TaskBuilder(mSupervisor).setStack(targetStack).build(); + final Task task = new TaskBuilder(mSupervisor).setParentTask(targetStack).build(); final ActivityRecord activity = new ActivityBuilder(mAtm).setTask(task).build(); taskDisplayArea.positionChildAt(POSITION_BOTTOM, targetStack, false /*includingParents*/); @@ -514,7 +516,7 @@ public class RootActivityContainerTests extends WindowTestsBase { DisplayContent.POSITION_TOP); final Task stack = secondDisplay.getDefaultTaskDisplayArea() .createStack(WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, true /* onTop */); - final Task task = new TaskBuilder(mSupervisor).setStack(stack).build(); + final Task task = new TaskBuilder(mSupervisor).setParentTask(stack).build(); new ActivityBuilder(mAtm).setTask(task).build(); doReturn(true).when(mRootWindowContainer).resumeHomeActivity(any(), any(), any()); @@ -538,7 +540,7 @@ public class RootActivityContainerTests extends WindowTestsBase { final TaskDisplayArea taskDisplayArea = mRootWindowContainer.getDefaultTaskDisplayArea(); final Task targetStack = spy(taskDisplayArea.createStack(WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, false /* onTop */)); - final Task task = new TaskBuilder(mSupervisor).setStack(targetStack).build(); + final Task task = new TaskBuilder(mSupervisor).setParentTask(targetStack).build(); final ActivityRecord activity = new ActivityBuilder(mAtm).setTask(task).build(); activity.setState(ActivityState.RESUMED, "test"); @@ -558,7 +560,7 @@ public class RootActivityContainerTests extends WindowTestsBase { final TaskDisplayArea taskDisplayArea = mRootWindowContainer.getDefaultTaskDisplayArea(); final Task targetStack = spy(taskDisplayArea.createStack(WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, false /* onTop */)); - final Task task = new TaskBuilder(mSupervisor).setStack(targetStack).build(); + final Task task = new TaskBuilder(mSupervisor).setParentTask(targetStack).build(); final ActivityRecord activity = new ActivityBuilder(mAtm).setTask(task).build(); activity.setState(ActivityState.RESUMED, "test"); taskDisplayArea.positionChildAt(POSITION_BOTTOM, targetStack, false /*includingParents*/); @@ -884,7 +886,7 @@ public class RootActivityContainerTests extends WindowTestsBase { // Create a root task with an activity on secondary display. final TestDisplayContent secondaryDisplay = new TestDisplayContent.Builder(mAtm, 300, 600).build(); - final Task task = new StackBuilder(mRootWindowContainer) + final Task task = new TaskBuilder(mSupervisor) .setDisplay(secondaryDisplay).build(); final ActivityRecord activity = new ActivityBuilder(mAtm).setTask(task).build(); diff --git a/services/tests/wmtests/src/com/android/server/wm/RootWindowContainerTests.java b/services/tests/wmtests/src/com/android/server/wm/RootWindowContainerTests.java index 191c33c61aca..3053fe6ec55f 100644 --- a/services/tests/wmtests/src/com/android/server/wm/RootWindowContainerTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/RootWindowContainerTests.java @@ -174,7 +174,7 @@ public class RootWindowContainerTests extends WindowTestsBase { @Test public void testForceStopPackage() { - final Task task = new StackBuilder(mWm.mRoot).build(); + final Task task = new TaskBuilder(mSupervisor).setCreateActivity(true).build(); final ActivityRecord activity = task.getTopMostActivity(); final WindowProcessController wpc = activity.app; final ActivityRecord[] activities = { 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 341509310e26..8a5b13c0bdce 100644 --- a/services/tests/wmtests/src/com/android/server/wm/RunningTasksTest.java +++ b/services/tests/wmtests/src/com/android/server/wm/RunningTasksTest.java @@ -62,8 +62,7 @@ public class RunningTasksTest extends WindowTestsBase { final int numStacks = 2; for (int stackIndex = 0; stackIndex < numStacks; stackIndex++) { - final Task stack = new StackBuilder(mRootWindowContainer) - .setCreateActivity(false) + final Task stack = new TaskBuilder(mSupervisor) .setDisplay(display) .setOnTop(false) .build(); @@ -104,8 +103,7 @@ public class RunningTasksTest extends WindowTestsBase { final DisplayContent display = new TestDisplayContent.Builder(mAtm, 1000, 2500).build(); final int numTasks = 10; for (int i = 0; i < numTasks; i++) { - final Task stack = new StackBuilder(mRootWindowContainer) - .setCreateActivity(false) + final Task stack = new TaskBuilder(mSupervisor) .setDisplay(display) .setOnTop(true) .build(); @@ -135,7 +133,7 @@ public class RunningTasksTest extends WindowTestsBase { final Task task = new TaskBuilder(mAtm.mStackSupervisor) .setComponent(new ComponentName(mContext.getPackageName(), className)) .setTaskId(taskId) - .setStack(stack) + .setParentTask(stack) .build(); task.lastActiveTime = lastActiveTime; final ActivityRecord activity = new ActivityBuilder(mAtm) diff --git a/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java b/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java index 468b2c35ffc2..edcf0d4f5501 100644 --- a/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java @@ -72,7 +72,7 @@ public class SizeCompatTests extends WindowTestsBase { private ActivityRecord mActivity; private void setUpApp(DisplayContent display) { - mStack = new StackBuilder(mRootWindowContainer).setDisplay(display).build(); + mStack = new TaskBuilder(mSupervisor).setDisplay(display).setCreateActivity(true).build(); mTask = mStack.getBottomMostTask(); mActivity = mTask.getTopNonFinishingActivity(); } @@ -138,8 +138,6 @@ public class SizeCompatTests extends WindowTestsBase { public void testFixedAspectRatioBoundsWithDecorInSquareDisplay() { final int notchHeight = 100; setUpApp(new TestDisplayContent.Builder(mAtm, 600, 800).setNotch(notchHeight).build()); - // Rotation is ignored so because the display size is close to square (700/600<1.333). - assertTrue(mActivity.mDisplayContent.ignoreRotationForApps()); final Rect displayBounds = mActivity.mDisplayContent.getWindowConfiguration().getBounds(); final float aspectRatio = 1.2f; @@ -163,23 +161,14 @@ public class SizeCompatTests extends WindowTestsBase { mActivity.setRequestedOrientation(SCREEN_ORIENTATION_LANDSCAPE); assertFitted(); - // After the orientation of activity is changed, even display is not rotated, the aspect - // ratio should be the same (bounds=[0, 0 - 600, 600], appBounds=[0, 100 - 600, 600]). + // After the orientation of activity is changed, the display is rotated, the aspect + // ratio should be the same (bounds=[100, 0 - 800, 583], appBounds=[100, 0 - 800, 583]). assertEquals(appBounds.width(), appBounds.height() * aspectRatio, 0.5f /* delta */); - // The notch is still on top. - assertEquals(mActivity.getBounds().height(), appBounds.height() + notchHeight); + // The notch is no longer on top. + assertEquals(appBounds, mActivity.getBounds()); mActivity.setRequestedOrientation(SCREEN_ORIENTATION_PORTRAIT); assertFitted(); - - // Close-to-square display can rotate without being restricted by the requested orientation. - // The notch becomes on the left side. The activity is horizontal centered in 100 ~ 800. - // So the bounds and appBounds will be [200, 0 - 700, 600] (500x600) that is still fitted. - // Left = 100 + (800 - 100 - 500) / 2 = 200. - rotateDisplay(mActivity.mDisplayContent, ROTATION_90); - assertFitted(); - assertEquals(appBounds.left, - notchHeight + (displayBounds.width() - notchHeight - appBounds.width()) / 2); } @Test diff --git a/services/tests/wmtests/src/com/android/server/wm/SystemServicesTestRule.java b/services/tests/wmtests/src/com/android/server/wm/SystemServicesTestRule.java index eb7d9c2d3c32..6a29c5b5424a 100644 --- a/services/tests/wmtests/src/com/android/server/wm/SystemServicesTestRule.java +++ b/services/tests/wmtests/src/com/android/server/wm/SystemServicesTestRule.java @@ -534,11 +534,14 @@ public class SystemServicesTestRule implements TestRule { doNothing().when(this).scheduleIdleTimeout(any()); // unit test version does not handle launch wake lock doNothing().when(this).acquireLaunchWakelock(); - doReturn(mock(KeyguardController.class)).when(this).getKeyguardController(); mLaunchingActivityWakeLock = mock(PowerManager.WakeLock.class); initialize(); + + final KeyguardController controller = getKeyguardController(); + spyOn(controller); + doReturn(true).when(controller).checkKeyguardVisibility(any()); } } diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskDisplayAreaTests.java b/services/tests/wmtests/src/com/android/server/wm/TaskDisplayAreaTests.java index 260f1e9a9259..bc3b3a4d7ad1 100644 --- a/services/tests/wmtests/src/com/android/server/wm/TaskDisplayAreaTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/TaskDisplayAreaTests.java @@ -218,7 +218,7 @@ public class TaskDisplayAreaTests extends WindowTestsBase { final Task rootHomeTask = defaultTaskDisplayArea.getRootHomeTask(); rootHomeTask.mResizeMode = RESIZE_MODE_UNRESIZEABLE; - final Task primarySplitTask = new StackBuilder(rootWindowContainer) + final Task primarySplitTask = new TaskBuilder(mSupervisor) .setTaskDisplayArea(defaultTaskDisplayArea) .setWindowingMode(WINDOWING_MODE_SPLIT_SCREEN_PRIMARY) .setActivityType(ACTIVITY_TYPE_STANDARD) 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 42de5e6b429d..1d32e17dd5e1 100644 --- a/services/tests/wmtests/src/com/android/server/wm/TaskLaunchParamsModifierTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/TaskLaunchParamsModifierTests.java @@ -1358,7 +1358,7 @@ public class TaskLaunchParamsModifierTests extends WindowTestsBase { final Task stack = display.getDefaultTaskDisplayArea() .createStack(display.getWindowingMode(), ACTIVITY_TYPE_STANDARD, true); stack.setWindowingMode(WINDOWING_MODE_FREEFORM); - final Task task = new TaskBuilder(mSupervisor).setStack(stack).build(); + final Task task = new TaskBuilder(mSupervisor).setParentTask(stack).build(); // Just work around the unnecessary adjustments for bounds. task.getWindowConfiguration().setBounds(bounds); } 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 08537a4ea9c1..a908bfef98de 100644 --- a/services/tests/wmtests/src/com/android/server/wm/TaskRecordTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/TaskRecordTests.java @@ -176,7 +176,7 @@ public class TaskRecordTests extends WindowTestsBase { TaskDisplayArea taskDisplayArea = mAtm.mRootWindowContainer.getDefaultTaskDisplayArea(); Task stack = taskDisplayArea.createStack(WINDOWING_MODE_FREEFORM, ACTIVITY_TYPE_STANDARD, true /* onTop */); - Task task = new TaskBuilder(mSupervisor).setStack(stack).build(); + Task task = new TaskBuilder(mSupervisor).setParentTask(stack).build(); final Configuration parentConfig = stack.getConfiguration(); parentConfig.windowConfiguration.setBounds(parentBounds); parentConfig.densityDpi = DisplayMetrics.DENSITY_DEFAULT; @@ -212,7 +212,7 @@ public class TaskRecordTests extends WindowTestsBase { @Test public void testBoundsOnModeChangeFreeformToFullscreen() { DisplayContent display = mAtm.mRootWindowContainer.getDefaultDisplay(); - Task stack = new StackBuilder(mRootWindowContainer).setDisplay(display) + Task stack = new TaskBuilder(mSupervisor).setDisplay(display).setCreateActivity(true) .setWindowingMode(WINDOWING_MODE_FREEFORM).build(); Task task = stack.getBottomMostTask(); task.getRootActivity().setOrientation(SCREEN_ORIENTATION_UNSPECIFIED); @@ -253,7 +253,7 @@ public class TaskRecordTests extends WindowTestsBase { dr.setFixedToUserRotation(FIXED_TO_USER_ROTATION_ENABLED); dr.setUserRotation(USER_ROTATION_FREE, ROTATION_0); - final Task stack = new StackBuilder(mRootWindowContainer) + final Task stack = new TaskBuilder(mSupervisor).setCreateActivity(true) .setWindowingMode(WINDOWING_MODE_FULLSCREEN).setDisplay(display).build(); final Task task = stack.getBottomMostTask(); final ActivityRecord root = task.getTopNonFinishingActivity(); @@ -317,7 +317,7 @@ public class TaskRecordTests extends WindowTestsBase { dr.setFixedToUserRotation(FIXED_TO_USER_ROTATION_ENABLED); dr.setUserRotation(USER_ROTATION_FREE, ROTATION_0); - final Task stack = new StackBuilder(mRootWindowContainer) + final Task stack = new TaskBuilder(mSupervisor).setCreateActivity(true) .setWindowingMode(WINDOWING_MODE_FULLSCREEN).setDisplay(display).build(); final Task task = stack.getBottomMostTask(); ActivityRecord root = task.getTopNonFinishingActivity(); @@ -341,7 +341,7 @@ public class TaskRecordTests extends WindowTestsBase { Configuration.ORIENTATION_LANDSCAPE; display.onRequestedOverrideConfigurationChanged( display.getRequestedOverrideConfiguration()); - Task stack = new StackBuilder(mRootWindowContainer) + Task stack = new TaskBuilder(mSupervisor).setCreateActivity(true) .setWindowingMode(WINDOWING_MODE_FULLSCREEN).setDisplay(display).build(); Task task = stack.getBottomMostTask(); ActivityRecord root = task.getTopNonFinishingActivity(); @@ -497,7 +497,7 @@ public class TaskRecordTests extends WindowTestsBase { DisplayInfo displayInfo = new DisplayInfo(); mAtm.mContext.getDisplay().getDisplayInfo(displayInfo); final int displayHeight = displayInfo.logicalHeight; - final Task task = new TaskBuilder(mSupervisor).setStack(stack).build(); + final Task task = new TaskBuilder(mSupervisor).setParentTask(stack).build(); final Configuration inOutConfig = new Configuration(); final Configuration parentConfig = new Configuration(); final int longSide = 1200; @@ -1029,7 +1029,7 @@ public class TaskRecordTests extends WindowTestsBase { } private Task getTestTask() { - final Task stack = new StackBuilder(mRootWindowContainer).build(); + final Task stack = new TaskBuilder(mSupervisor).setCreateActivity(true).build(); return stack.getBottomMostTask(); } @@ -1039,7 +1039,7 @@ public class TaskRecordTests extends WindowTestsBase { TaskDisplayArea taskDisplayArea = mAtm.mRootWindowContainer.getDefaultTaskDisplayArea(); Task stack = taskDisplayArea.createStack(windowingMode, ACTIVITY_TYPE_STANDARD, true /* onTop */); - Task task = new TaskBuilder(mSupervisor).setStack(stack).build(); + Task task = new TaskBuilder(mSupervisor).setParentTask(stack).build(); final Configuration parentConfig = stack.getConfiguration(); parentConfig.windowConfiguration.setAppBounds(parentBounds); diff --git a/services/tests/wmtests/src/com/android/server/wm/TestIWindow.java b/services/tests/wmtests/src/com/android/server/wm/TestIWindow.java index e39b4bcd2eb0..d37f3f402c30 100644 --- a/services/tests/wmtests/src/com/android/server/wm/TestIWindow.java +++ b/services/tests/wmtests/src/com/android/server/wm/TestIWindow.java @@ -17,17 +17,16 @@ package com.android.server.wm; import android.graphics.Point; -import android.graphics.Rect; import android.os.Bundle; import android.os.ParcelFileDescriptor; import android.os.RemoteException; import android.util.MergedConfiguration; -import android.view.DisplayCutout; import android.view.DragEvent; import android.view.IScrollCaptureController; import android.view.IWindow; import android.view.InsetsSourceControl; import android.view.InsetsState; +import android.window.ClientWindowFrames; import com.android.internal.os.IResultReceiver; @@ -38,10 +37,9 @@ public class TestIWindow extends IWindow.Stub { } @Override - public void resized(Rect frame, Rect contentInsets, Rect visibleInsets, - Rect stableInsets, boolean reportDraw, MergedConfiguration mergedConfig, - Rect backDropFrame, boolean forceLayout, boolean alwaysConsumeSystemBars, int displayId, - DisplayCutout.ParcelableWrapper displayCutout) throws RemoteException { + public void resized(ClientWindowFrames frames, boolean reportDraw, + MergedConfiguration mergedConfig, boolean forceLayout, boolean alwaysConsumeSystemBars, + int displayId) throws RemoteException { } @Override diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowContainerTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowContainerTests.java index 4163a9a546a0..36f3a21e38f1 100644 --- a/services/tests/wmtests/src/com/android/server/wm/WindowContainerTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/WindowContainerTests.java @@ -829,7 +829,7 @@ public class WindowContainerTests extends WindowTestsBase { final DisplayContent displayContent = createNewDisplay(); // Do not reparent activity to default display when removing the display. doReturn(true).when(displayContent).shouldDestroyContentOnRemove(); - final ActivityRecord r = new StackBuilder(mWm.mRoot) + final ActivityRecord r = new TaskBuilder(mSupervisor).setCreateActivity(true) .setDisplay(displayContent).build().getTopMostActivity(); // Add a window and make the activity animating so the removal of activity is deferred. createWindow(null, TYPE_BASE_APPLICATION, r, "win"); diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowOrganizerTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowOrganizerTests.java index 46a6a82faba5..5d8a2a11dce8 100644 --- a/services/tests/wmtests/src/com/android/server/wm/WindowOrganizerTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/WindowOrganizerTests.java @@ -52,7 +52,7 @@ import static org.mockito.ArgumentMatchers.anyInt; import android.app.ActivityManager; import android.app.ActivityManager.RunningTaskInfo; -import android.app.ActivityManager.StackInfo; +import android.app.ActivityTaskManager.RootTaskInfo; import android.app.PictureInPictureParams; import android.content.pm.ActivityInfo; import android.content.res.Configuration; @@ -290,7 +290,7 @@ public class WindowOrganizerTests extends WindowTestsBase { @Test public void testTaskTransaction() { removeGlobalMinSizeRestriction(); - final Task stack = new StackBuilder(mWm.mRoot) + final Task stack = new TaskBuilder(mSupervisor) .setWindowingMode(WINDOWING_MODE_FREEFORM).build(); final Task task = stack.getTopMostTask(); testTransaction(task); @@ -299,11 +299,11 @@ public class WindowOrganizerTests extends WindowTestsBase { @Test public void testStackTransaction() { removeGlobalMinSizeRestriction(); - final Task stack = new StackBuilder(mWm.mRoot) + final Task stack = new TaskBuilder(mSupervisor) .setWindowingMode(WINDOWING_MODE_FREEFORM).build(); - StackInfo info = - mWm.mAtmService.getStackInfo(WINDOWING_MODE_FREEFORM, ACTIVITY_TYPE_STANDARD); - assertEquals(stack.mRemoteToken.toWindowContainerToken(), info.stackToken); + RootTaskInfo info = + mWm.mAtmService.getRootTaskInfo(WINDOWING_MODE_FREEFORM, ACTIVITY_TYPE_STANDARD); + assertEquals(stack.mRemoteToken.toWindowContainerToken(), info.token); testTransaction(stack); } @@ -324,7 +324,7 @@ public class WindowOrganizerTests extends WindowTestsBase { @Test public void testSetWindowingMode() { - final Task stack = new StackBuilder(mWm.mRoot) + final Task stack = new TaskBuilder(mSupervisor) .setWindowingMode(WINDOWING_MODE_FREEFORM).build(); testSetWindowingMode(stack); @@ -358,7 +358,7 @@ public class WindowOrganizerTests extends WindowTestsBase { @Test public void testContainerFocusableChanges() { removeGlobalMinSizeRestriction(); - final Task stack = new StackBuilder(mWm.mRoot) + final Task stack = new TaskBuilder(mSupervisor) .setWindowingMode(WINDOWING_MODE_FREEFORM).build(); final Task task = stack.getTopMostTask(); WindowContainerTransaction t = new WindowContainerTransaction(); @@ -374,7 +374,7 @@ public class WindowOrganizerTests extends WindowTestsBase { @Test public void testContainerHiddenChanges() { removeGlobalMinSizeRestriction(); - final Task stack = new StackBuilder(mWm.mRoot) + final Task stack = new TaskBuilder(mSupervisor).setCreateActivity(true) .setWindowingMode(WINDOWING_MODE_FREEFORM).build(); WindowContainerTransaction t = new WindowContainerTransaction(); assertTrue(stack.shouldBeVisible(null)); @@ -389,7 +389,7 @@ public class WindowOrganizerTests extends WindowTestsBase { @Test public void testOverrideConfigSize() { removeGlobalMinSizeRestriction(); - final Task stack = new StackBuilder(mWm.mRoot) + final Task stack = new TaskBuilder(mSupervisor) .setWindowingMode(WINDOWING_MODE_FREEFORM).build(); final Task task = stack.getTopMostTask(); WindowContainerTransaction t = new WindowContainerTransaction(); diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java index 3106ca26c8a1..c18043fcc4b9 100644 --- a/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java @@ -581,12 +581,10 @@ public class WindowStateTests extends WindowTestsBase { mWm.mResizingWindows.remove(win); spyOn(win.mClient); try { - doThrow(new RemoteException("test")).when(win.mClient).resized(any() /* frame */, - any() /* contentInsets */, any() /* visibleInsets */, any() /* stableInsets */, + doThrow(new RemoteException("test")).when(win.mClient).resized(any() /* frames */, anyBoolean() /* reportDraw */, any() /* mergedConfig */, - any() /* backDropFrame */, anyBoolean() /* forceLayout */, - anyBoolean() /* alwaysConsumeSystemBars */, anyInt() /* displayId */, - any() /* displayCutout */); + anyBoolean() /* forceLayout */, anyBoolean() /* alwaysConsumeSystemBars */, + anyInt() /* displayId */); } catch (RemoteException ignored) { } win.reportResized(); 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 38c4e0a7de02..7daddd8720ab 100644 --- a/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java +++ b/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java @@ -90,6 +90,7 @@ import com.android.server.AttributeCache; import org.junit.Before; import org.junit.BeforeClass; import org.junit.runner.Description; +import org.mockito.Mockito; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; @@ -398,22 +399,20 @@ class WindowTestsBase extends SystemServiceTestsBase { } Task createTaskStackOnDisplay(int windowingMode, int activityType, DisplayContent dc) { - return new StackBuilder(dc.mWmService.mRoot) + return new TaskBuilder(dc.mAtmService.mStackSupervisor) .setDisplay(dc) .setWindowingMode(windowingMode) .setActivityType(activityType) - .setCreateActivity(false) .setIntent(new Intent()) .build(); } Task createTaskStackOnTaskDisplayArea(int windowingMode, int activityType, TaskDisplayArea tda) { - return new StackBuilder(tda.mWmService.mRoot) + return new TaskBuilder(tda.mDisplayContent.mAtmService.mStackSupervisor) .setTaskDisplayArea(tda) .setWindowingMode(windowingMode) .setActivityType(activityType) - .setCreateActivity(false) .setIntent(new Intent()) .build(); } @@ -422,7 +421,7 @@ class WindowTestsBase extends SystemServiceTestsBase { Task createTaskInStack(Task stack, int userId) { final Task task = new TaskBuilder(stack.mStackSupervisor) .setUserId(userId) - .setStack(stack) + .setParentTask(stack) .build(); return task; } @@ -733,7 +732,7 @@ class WindowTestsBase extends SystemServiceTestsBase { if (mCreateTask) { mTask = new TaskBuilder(mService.mStackSupervisor) .setComponent(mComponent) - .setStack(mStack).build(); + .setParentTask(mStack).build(); } else if (mTask == null && mStack != null && DisplayContent.alwaysCreateStack( mStack.getWindowingMode(), mStack.getActivityType())) { // The stack can be the task root. @@ -813,43 +812,51 @@ class WindowTestsBase extends SystemServiceTestsBase { protected static class TaskBuilder { private final ActivityStackSupervisor mSupervisor; + private TaskDisplayArea mTaskDisplayArea; private ComponentName mComponent; private String mPackage; private int mFlags = 0; - // Task id 0 is reserved in ARC for the home app. - private int mTaskId = SystemServicesTestRule.sNextTaskId++; + private int mTaskId = -1; private int mUserId = 0; + private int mWindowingMode = WINDOWING_MODE_UNDEFINED; + private int mActivityType = ACTIVITY_TYPE_STANDARD; + private ActivityInfo mActivityInfo; + private Intent mIntent; + private boolean mOnTop = true; private IVoiceInteractionSession mVoiceSession; - private boolean mCreateStack = true; - private Task mStack; - private TaskDisplayArea mTaskDisplayArea; + private boolean mCreateParentTask = false; + private Task mParentTask; + + private boolean mCreateActivity = false; TaskBuilder(ActivityStackSupervisor supervisor) { mSupervisor = supervisor; + mTaskDisplayArea = mSupervisor.mRootWindowContainer.getDefaultTaskDisplayArea(); } - TaskBuilder setComponent(ComponentName component) { - mComponent = component; + /** + * Set the parent {@link DisplayContent} and use the default task display area. Overrides + * the task display area, if was set before. + */ + TaskBuilder setDisplay(DisplayContent display) { + mTaskDisplayArea = display.getDefaultTaskDisplayArea(); return this; } - TaskBuilder setPackage(String packageName) { - mPackage = packageName; + /** Set the parent {@link TaskDisplayArea}. Overrides the display, if was set before. */ + TaskBuilder setTaskDisplayArea(TaskDisplayArea taskDisplayArea) { + mTaskDisplayArea = taskDisplayArea; return this; } - /** - * Set to {@code true} by default, set to {@code false} to prevent the task from - * automatically creating a parent stack. - */ - TaskBuilder setCreateStack(boolean createStack) { - mCreateStack = createStack; + TaskBuilder setComponent(ComponentName component) { + mComponent = component; return this; } - TaskBuilder setVoiceSession(IVoiceInteractionSession session) { - mVoiceSession = session; + TaskBuilder setPackage(String packageName) { + mPackage = packageName; return this; } @@ -868,156 +875,117 @@ class WindowTestsBase extends SystemServiceTestsBase { return this; } - TaskBuilder setStack(Task stack) { - mStack = stack; - return this; - } - - TaskBuilder setDisplay(DisplayContent display) { - mTaskDisplayArea = display.getDefaultTaskDisplayArea(); - return this; - } - - Task build() { - SystemServicesTestRule.checkHoldsLock(mSupervisor.mService.mGlobalLock); - - if (mStack == null && mCreateStack) { - TaskDisplayArea displayArea = mTaskDisplayArea != null ? mTaskDisplayArea - : mSupervisor.mRootWindowContainer.getDefaultTaskDisplayArea(); - mStack = displayArea.createStack( - WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, true /* onTop */); - spyOn(mStack); - } - - final ActivityInfo aInfo = new ActivityInfo(); - aInfo.applicationInfo = new ApplicationInfo(); - aInfo.applicationInfo.packageName = mPackage; - - Intent intent = new Intent(); - if (mComponent == null) { - mComponent = ComponentName.createRelative(DEFAULT_COMPONENT_PACKAGE_NAME, - DEFAULT_COMPONENT_CLASS_NAME); - } - - intent.setComponent(mComponent); - intent.setFlags(mFlags); - - final Task task = new Task(mSupervisor.mService, mTaskId, aInfo, - intent /*intent*/, mVoiceSession, null /*_voiceInteractor*/, - null /*taskDescription*/, mStack); - spyOn(task); - task.mUserId = mUserId; - - if (mStack != null) { - mStack.moveToFront("test"); - mStack.addChild(task, true, true); - } - - return task; - } - } - - static class StackBuilder { - private final RootWindowContainer mRootWindowContainer; - private DisplayContent mDisplay; - private TaskDisplayArea mTaskDisplayArea; - private int mStackId = -1; - private int mWindowingMode = WINDOWING_MODE_UNDEFINED; - private int mActivityType = ACTIVITY_TYPE_STANDARD; - private boolean mOnTop = true; - private boolean mCreateActivity = true; - private ActivityInfo mInfo; - private Intent mIntent; - - StackBuilder(RootWindowContainer root) { - mRootWindowContainer = root; - mDisplay = mRootWindowContainer.getDefaultDisplay(); - mTaskDisplayArea = mDisplay.getDefaultTaskDisplayArea(); - } - - StackBuilder setWindowingMode(int windowingMode) { + TaskBuilder setWindowingMode(int windowingMode) { mWindowingMode = windowingMode; return this; } - StackBuilder setActivityType(int activityType) { + TaskBuilder setActivityType(int activityType) { mActivityType = activityType; return this; } - StackBuilder setStackId(int stackId) { - mStackId = stackId; + TaskBuilder setActivityInfo(ActivityInfo info) { + mActivityInfo = info; return this; } - /** - * Set the parent {@link DisplayContent} and use the default task display area. Overrides - * the task display area, if was set before. - */ - StackBuilder setDisplay(DisplayContent display) { - mDisplay = display; - mTaskDisplayArea = mDisplay.getDefaultTaskDisplayArea(); + TaskBuilder setIntent(Intent intent) { + mIntent = intent; return this; } - /** Set the parent {@link TaskDisplayArea}. Overrides the display, if was set before. */ - StackBuilder setTaskDisplayArea(TaskDisplayArea taskDisplayArea) { - mTaskDisplayArea = taskDisplayArea; - mDisplay = mTaskDisplayArea.mDisplayContent; + TaskBuilder setOnTop(boolean onTop) { + mOnTop = onTop; return this; } - StackBuilder setOnTop(boolean onTop) { - mOnTop = onTop; + TaskBuilder setVoiceSession(IVoiceInteractionSession session) { + mVoiceSession = session; return this; } - StackBuilder setCreateActivity(boolean createActivity) { - mCreateActivity = createActivity; + TaskBuilder setCreateParentTask(boolean createParentTask) { + mCreateParentTask = createParentTask; return this; } - StackBuilder setActivityInfo(ActivityInfo info) { - mInfo = info; + TaskBuilder setParentTask(Task parentTask) { + mParentTask = parentTask; return this; } - StackBuilder setIntent(Intent intent) { - mIntent = intent; + TaskBuilder setCreateActivity(boolean createActivity) { + mCreateActivity = createActivity; return this; } Task build() { - SystemServicesTestRule.checkHoldsLock(mRootWindowContainer.mWmService.mGlobalLock); + SystemServicesTestRule.checkHoldsLock(mSupervisor.mService.mGlobalLock); + + // Create parent task. + if (mParentTask == null && mCreateParentTask) { + mParentTask = mTaskDisplayArea.createStack( + WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, true /* onTop */); + } + if (mParentTask != null && !Mockito.mockingDetails(mParentTask).isSpy()) { + spyOn(mParentTask); + } + + // Create task. + if (mActivityInfo == null) { + mActivityInfo = new ActivityInfo(); + mActivityInfo.applicationInfo = new ApplicationInfo(); + mActivityInfo.applicationInfo.packageName = mPackage; + } - final int stackId = mStackId >= 0 ? mStackId : mTaskDisplayArea.getNextStackId(); - final Task stack = mTaskDisplayArea.createStackUnchecked( - mWindowingMode, mActivityType, stackId, mOnTop, mInfo, mIntent, - false /* createdByOrganizer */); - final ActivityStackSupervisor supervisor = mRootWindowContainer.mStackSupervisor; + if (mIntent == null) { + mIntent = new Intent(); + if (mComponent == null) { + mComponent = ComponentName.createRelative(DEFAULT_COMPONENT_PACKAGE_NAME, + DEFAULT_COMPONENT_CLASS_NAME); + } + mIntent.setComponent(mComponent); + mIntent.setFlags(mFlags); + } + Task task; + final int taskId = mTaskId >= 0 ? mTaskId : mTaskDisplayArea.getNextStackId(); + if (mParentTask == null) { + task = mTaskDisplayArea.createStackUnchecked( + mWindowingMode, mActivityType, taskId, mOnTop, mActivityInfo, + mIntent, false /* createdByOrganizer */); + } else { + task = new Task(mSupervisor.mService, taskId, mActivityInfo, + mIntent /*intent*/, mVoiceSession, null /*_voiceInteractor*/, + null /*taskDescription*/, mParentTask); + mParentTask.moveToFront("build-task"); + mParentTask.addChild(task, true, true); + } + spyOn(task); + task.mUserId = mUserId; + Task rootTask = task.getRootTask(); + doNothing().when(rootTask).startActivityLocked( + any(), any(), anyBoolean(), anyBoolean(), any()); + + // Create child task with activity. if (mCreateActivity) { - new ActivityBuilder(supervisor.mService) + new ActivityBuilder(mSupervisor.mService) .setCreateTask(true) - .setStack(stack) + .setStack(task) .build(); if (mOnTop) { // We move the task to front again in order to regain focus after activity - // added to the stack. Or {@link DisplayContent#mPreferredTopFocusableStack} + // added to the stack. Or {@link TaskDisplayArea#mPreferredTopFocusableStack} // could be other stacks (e.g. home stack). - stack.moveToFront("createActivityStack"); + task.moveToFront("createActivityTask"); } else { - stack.moveToBack("createActivityStack", null); + task.moveToBack("createActivityTask", null); } } - spyOn(stack); - - doNothing().when(stack).startActivityLocked( - any(), any(), anyBoolean(), anyBoolean(), any()); - return stack; + return task; } - } static class TestSplitOrganizer extends ITaskOrganizer.Stub { diff --git a/telecomm/OWNERS b/telecomm/OWNERS index 673a0a9b558e..9969ee965fbd 100644 --- a/telecomm/OWNERS +++ b/telecomm/OWNERS @@ -1,7 +1,8 @@ set noparent -tgunn@google.com breadley@google.com hallliu@google.com +tgunn@google.com +xiaotonj@google.com +shuoq@google.com rgreenwalt@google.com -paulye@google.com diff --git a/telecomm/java/android/telecom/Logging/SessionManager.java b/telecomm/java/android/telecom/Logging/SessionManager.java index 67e5eabf54eb..9d17219c1ae4 100644 --- a/telecomm/java/android/telecom/Logging/SessionManager.java +++ b/telecomm/java/android/telecom/Logging/SessionManager.java @@ -17,6 +17,7 @@ package android.telecom.Logging; import android.annotation.Nullable; +import android.content.ContentResolver; import android.content.Context; import android.os.Handler; import android.os.Looper; @@ -453,7 +454,9 @@ public class SessionManager { * perform a sweep to check and make sure that the session is still not incomplete (stale). */ private long getCleanupTimeout(Context context) { - return Settings.Secure.getLong(context.getContentResolver(), TIMEOUTS_PREFIX + - "stale_session_cleanup_timeout_millis", DEFAULT_SESSION_TIMEOUT_MS); + final ContentResolver cr = context.getContentResolver(); + return Settings.Secure.getLongForUser(cr, TIMEOUTS_PREFIX + + "stale_session_cleanup_timeout_millis", DEFAULT_SESSION_TIMEOUT_MS, + cr.getUserId()); } } diff --git a/telecomm/java/com/android/internal/telecom/IDeviceIdleControllerAdapter.aidl b/telecomm/java/com/android/internal/telecom/IDeviceIdleControllerAdapter.aidl new file mode 100644 index 000000000000..50bbf4c41284 --- /dev/null +++ b/telecomm/java/com/android/internal/telecom/IDeviceIdleControllerAdapter.aidl @@ -0,0 +1,26 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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.telecom; + +/* + * Adapter interface for using DeviceIdleController, since the PowerWhitelistManager is not + * directly accessible in the SYSTEM process. + */ +interface IDeviceIdleControllerAdapter { + void exemptAppTemporarilyForEvent(String packageName, long duration, int userHandle, + String reason); +}
\ No newline at end of file diff --git a/telecomm/java/com/android/internal/telecom/IInternalServiceRetriever.aidl b/telecomm/java/com/android/internal/telecom/IInternalServiceRetriever.aidl new file mode 100644 index 000000000000..b56010696361 --- /dev/null +++ b/telecomm/java/com/android/internal/telecom/IInternalServiceRetriever.aidl @@ -0,0 +1,27 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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.telecom; + +import com.android.internal.telecom.IDeviceIdleControllerAdapter; + +/* + * Interface used to retrieve services that are only accessible via LocalService in the SYSTEM + * process. + */ +interface IInternalServiceRetriever { + IDeviceIdleControllerAdapter getDeviceIdleController(); +} diff --git a/telecomm/java/com/android/internal/telecom/ITelecomLoader.aidl b/telecomm/java/com/android/internal/telecom/ITelecomLoader.aidl new file mode 100644 index 000000000000..eda0f5b24958 --- /dev/null +++ b/telecomm/java/com/android/internal/telecom/ITelecomLoader.aidl @@ -0,0 +1,28 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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.telecom; + +import com.android.internal.telecom.ITelecomService; +import com.android.internal.telecom.IInternalServiceRetriever; + +/* + * Internal interface for getting an instance of the ITelecomService for external publication. + * Allows the TelecomLoaderService to pass additional dependencies required for creation. + */ +interface ITelecomLoader { + ITelecomService createTelecomService(IInternalServiceRetriever retriever); +} diff --git a/telephony/api/system-current.txt b/telephony/api/system-current.txt index 944edd542e40..72e11c867a2b 100644 --- a/telephony/api/system-current.txt +++ b/telephony/api/system-current.txt @@ -291,6 +291,22 @@ package android.telephony { method public static boolean isVoiceMailNumber(@NonNull android.content.Context, int, @Nullable String); } + public final class PhysicalChannelConfig implements android.os.Parcelable { + method public int describeContents(); + method public int getCellBandwidthDownlink(); + method public int getChannelNumber(); + method public int getConnectionStatus(); + method public int getNetworkType(); + method @IntRange(from=0, to=1007) public int getPhysicalCellId(); + method public void writeToParcel(@NonNull android.os.Parcel, int); + field public static final int CHANNEL_NUMBER_UNKNOWN = -1; // 0xffffffff + field public static final int CONNECTION_PRIMARY_SERVING = 1; // 0x1 + field public static final int CONNECTION_SECONDARY_SERVING = 2; // 0x2 + field public static final int CONNECTION_UNKNOWN = -1; // 0xffffffff + field @NonNull public static final android.os.Parcelable.Creator<android.telephony.PhysicalChannelConfig> CREATOR; + field public static final int PHYSICAL_CELL_ID_UNKNOWN = -1; // 0xffffffff + } + public final class PreciseCallState implements android.os.Parcelable { ctor public PreciseCallState(int, int, int, int, int); method public int describeContents(); diff --git a/telephony/java/android/telephony/PhysicalChannelConfig.java b/telephony/java/android/telephony/PhysicalChannelConfig.java index af62ba4b93a1..8d49e15da934 100644 --- a/telephony/java/android/telephony/PhysicalChannelConfig.java +++ b/telephony/java/android/telephony/PhysicalChannelConfig.java @@ -17,6 +17,9 @@ package android.telephony; import android.annotation.IntDef; +import android.annotation.IntRange; +import android.annotation.NonNull; +import android.annotation.SystemApi; import android.os.Parcel; import android.os.Parcelable; import android.telephony.Annotation.NetworkType; @@ -29,9 +32,11 @@ import java.util.Objects; /** * @hide */ +@SystemApi public final class PhysicalChannelConfig implements Parcelable { // TODO(b/72993578) consolidate these enums in a central location. + /** @hide */ @Retention(RetentionPolicy.SOURCE) @IntDef({CONNECTION_PRIMARY_SERVING, CONNECTION_SECONDARY_SERVING, CONNECTION_UNKNOWN}) public @interface ConnectionStatus {} @@ -47,7 +52,13 @@ public final class PhysicalChannelConfig implements Parcelable { public static final int CONNECTION_SECONDARY_SERVING = 2; /** Connection status is unknown. */ - public static final int CONNECTION_UNKNOWN = Integer.MAX_VALUE; + public static final int CONNECTION_UNKNOWN = -1; + + /** Channel number is unknown. */ + public static final int CHANNEL_NUMBER_UNKNOWN = -1; + + /** Physical Cell Id is unknown. */ + public static final int PHYSICAL_CELL_ID_UNKNOWN = -1; /** * Connection status of the cell. @@ -75,7 +86,7 @@ public final class PhysicalChannelConfig implements Parcelable { private int mFrequencyRange; /** - * The absolute radio frequency channel number, {@link Integer#MAX_VALUE} if unknown. + * The absolute radio frequency channel number, {@link CHANNEL_NUMBER_UNKNOWN} if unknown. */ private int mChannelNumber; @@ -86,7 +97,8 @@ public final class PhysicalChannelConfig implements Parcelable { private int[] mContextIds; /** - * The physical cell identifier for this cell - PCI, PSC, {@link Integer#MAX_VALUE} if known. + * The physical cell identifier for this cell - PCI, PSC, {@link PHYSICAL_CELL_ID_UNKNOWN} + * if unknown. */ private int mPhysicalCellId; @@ -96,7 +108,7 @@ public final class PhysicalChannelConfig implements Parcelable { } @Override - public void writeToParcel(Parcel dest, int flags) { + public void writeToParcel(@NonNull Parcel dest, int flags) { dest.writeInt(mCellConnectionStatus); dest.writeInt(mCellBandwidthDownlinkKhz); dest.writeInt(mRat); @@ -120,6 +132,7 @@ public final class PhysicalChannelConfig implements Parcelable { * physical channel has no data call mapped to it. * * @return an integer list indicates the data call ids. + * @hide */ public int[] getContextIds() { return mContextIds; @@ -131,6 +144,7 @@ public final class PhysicalChannelConfig implements Parcelable { * @see {@link ServiceState#FREQUENCY_RANGE_MID} * @see {@link ServiceState#FREQUENCY_RANGE_HIGH} * @see {@link ServiceState#FREQUENCY_RANGE_MMWAVE} + * @hide */ @ServiceState.FrequencyRange public int getFrequencyRange() { @@ -139,7 +153,7 @@ public final class PhysicalChannelConfig implements Parcelable { /** * @return the absolute radio frequency channel number for this physical channel, - * {@link Integer#MAX_VALUE} if unknown. + * {@link CHANNEL_NUMBER_UNKNOWN} if unknown. */ public int getChannelNumber() { return mChannelNumber; @@ -152,18 +166,20 @@ public final class PhysicalChannelConfig implements Parcelable { * In EUTRAN, this value is physical layer cell identity. The range is [0, 503]. * Reference: 3GPP TS 36.211 section 6.11. * - * In 5G RAN, this value is physical layer cell identity. The range is [0, 1008]. + * In 5G RAN, this value is physical layer cell identity. The range is [0, 1007]. * Reference: 3GPP TS 38.211 section 7.4.2.1. * - * @return the physical cell identifier for this cell, {@link Integer#MAX_VALUE} if unknown. + * @return the physical cell identifier for this cell, {@link PHYSICAL_CELL_ID_UNKNOWN} + * if {@link android.telephony.CellInfo#UNAVAILABLE}. */ + @IntRange(from = 0, to = 1007) public int getPhysicalCellId() { return mPhysicalCellId; } /**The radio technology for this physical channel. */ @NetworkType - public int getRat() { + public int getNetworkType() { return mRat; } @@ -181,7 +197,10 @@ public final class PhysicalChannelConfig implements Parcelable { return mCellConnectionStatus; } - /** @return String representation of the connection status */ + /** + * @return String representation of the connection status + * @hide + */ private String getConnectionStatusString() { switch(mCellConnectionStatus) { case CONNECTION_PRIMARY_SERVING: @@ -254,6 +273,12 @@ public final class PhysicalChannelConfig implements Parcelable { .toString(); } + /** @hide */ + public PhysicalChannelConfig(int status, int bandwidth) { + mCellConnectionStatus = status; + mCellBandwidthDownlinkKhz = bandwidth; + } + private PhysicalChannelConfig(Parcel in) { mCellConnectionStatus = in.readInt(); mCellBandwidthDownlinkKhz = in.readInt(); @@ -274,7 +299,10 @@ public final class PhysicalChannelConfig implements Parcelable { mPhysicalCellId = builder.mPhysicalCellId; } - /** The builder of {@code PhysicalChannelConfig}. */ + /** + * The builder of {@code PhysicalChannelConfig}. + * @hide + */ public static final class Builder { private int mRat; private int mFrequencyRange; @@ -284,60 +312,51 @@ public final class PhysicalChannelConfig implements Parcelable { private int[] mContextIds; private int mPhysicalCellId; - /** @hide */ public Builder() { mRat = ServiceState.RIL_RADIO_TECHNOLOGY_UNKNOWN; mFrequencyRange = ServiceState.FREQUENCY_RANGE_UNKNOWN; - mChannelNumber = Integer.MAX_VALUE; + mChannelNumber = CHANNEL_NUMBER_UNKNOWN; mCellBandwidthDownlinkKhz = 0; mCellConnectionStatus = CONNECTION_UNKNOWN; mContextIds = new int[0]; - mPhysicalCellId = Integer.MAX_VALUE; + mPhysicalCellId = PHYSICAL_CELL_ID_UNKNOWN; } - /** @hide */ public PhysicalChannelConfig build() { return new PhysicalChannelConfig(this); } - /** @hide */ public Builder setRat(int rat) { this.mRat = rat; return this; } - /** @hide */ public Builder setFrequencyRange(int frequencyRange) { this.mFrequencyRange = frequencyRange; return this; } - /** @hide */ public Builder setChannelNumber(int channelNumber) { this.mChannelNumber = channelNumber; return this; } - /** @hide */ public Builder setCellBandwidthDownlinkKhz(int cellBandwidthDownlinkKhz) { this.mCellBandwidthDownlinkKhz = cellBandwidthDownlinkKhz; return this; } - /** @hide */ public Builder setCellConnectionStatus(int connectionStatus) { this.mCellConnectionStatus = connectionStatus; return this; } - /** @hide */ public Builder setContextIds(int[] contextIds) { if (contextIds != null) Arrays.sort(contextIds); this.mContextIds = contextIds; return this; } - /** @hide */ public Builder setPhysicalCellId(int physicalCellId) { this.mPhysicalCellId = physicalCellId; return this; diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java index 7a7792242c12..969016b1c017 100644 --- a/telephony/java/android/telephony/TelephonyManager.java +++ b/telephony/java/android/telephony/TelephonyManager.java @@ -5555,8 +5555,49 @@ public class TelephonyManager { * @param events The telephony state(s) of interest to the listener, * as a bitwise-OR combination of {@link PhoneStateListener} * LISTEN_ flags. + * @deprecated use {@link #listen(long, PhoneStateListener) instead due to the event number + * limit increased to 64. */ + @Deprecated public void listen(PhoneStateListener listener, int events) { + listen(events, listener); + } + + /** + * Registers a listener object to receive notification of changes + * in specified telephony states. + * <p> + * To register a listener, pass a {@link PhoneStateListener} and specify at least one telephony + * state of interest in the events argument. + * + * At registration, and when a specified telephony state changes, the telephony manager invokes + * the appropriate callback method on the listener object and passes the current (updated) + * values. + * <p> + * To un-register a listener, pass the listener object and set the events argument to + * {@link PhoneStateListener#LISTEN_NONE LISTEN_NONE} (0). + * + * If this TelephonyManager object has been created with {@link #createForSubscriptionId}, + * applies to the given subId. Otherwise, applies to + * {@link SubscriptionManager#getDefaultSubscriptionId()}. To listen events for multiple subIds, + * pass a separate listener object to each TelephonyManager object created with + * {@link #createForSubscriptionId}. + * + * Note: if you call this method while in the middle of a binder transaction, you <b>must</b> + * call {@link android.os.Binder#clearCallingIdentity()} before calling this method. A + * {@link SecurityException} will be thrown otherwise. + * + * This API should be used sparingly -- large numbers of listeners will cause system + * instability. If a process has registered too many listeners without unregistering them, it + * may encounter an {@link IllegalStateException} when trying to register more listeners. + * + * @param events The telephony state(s) of interest to the listener, + * as a bitwise-OR combination of {@link PhoneStateListener} + * LISTEN_ flags. + * @param listener The {@link PhoneStateListener} object to register + * (or unregister) + */ + public void listen(long events, @NonNull PhoneStateListener listener) { if (mContext == null) return; boolean notifyNow = (getITelephony() != null); TelephonyRegistryManager telephonyRegistry = diff --git a/tests/FlickerTests/Android.bp b/tests/FlickerTests/Android.bp index 943d78398879..a53ea16ba7c4 100644 --- a/tests/FlickerTests/Android.bp +++ b/tests/FlickerTests/Android.bp @@ -28,7 +28,6 @@ android_test { "flickertestapplib", "flickerlib", "truth-prebuilt", - "app-helpers-core", "launcher-helper-lib", "launcher-aosp-tapl" ], diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/CommonAssertions.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/CommonAssertions.kt index c1a3ed695096..69b11872e123 100644 --- a/tests/FlickerTests/src/com/android/server/wm/flicker/CommonAssertions.kt +++ b/tests/FlickerTests/src/com/android/server/wm/flicker/CommonAssertions.kt @@ -109,7 +109,7 @@ fun LayersAssertion.navBarLayerRotatesAndScales( } if (startingPos == endingPos) { - all("navBarLayerRotatesAndScales", enabled, bugId) { + all("navBarLayerRotatesAndScales", enabled = false, bugId = 167747321) { this.hasVisibleRegion(FlickerTestBase.NAVIGATION_BAR_WINDOW_TITLE, startingPos) } } diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/ImeAppHelper.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/ImeAppHelper.kt index c1b765790ce5..f4de36e99952 100644 --- a/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/ImeAppHelper.kt +++ b/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/ImeAppHelper.kt @@ -30,7 +30,7 @@ open class ImeAppHelper( launcherStrategy: ILauncherStrategy = LauncherStrategyFactory .getInstance(instr) .launcherStrategy -) : FlickerAppHelper(instr, launcherName, launcherStrategy) { +) : StandardAppHelper(instr, launcherName, launcherStrategy) { open fun openIME(device: UiDevice) { val editText = device.wait( Until.findObject(By.res(getPackage(), "plain_text_input")), diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/PipAppHelper.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/PipAppHelper.kt index d10bb1ef3ee7..0572a7813819 100644 --- a/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/PipAppHelper.kt +++ b/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/PipAppHelper.kt @@ -28,7 +28,7 @@ class PipAppHelper( launcherStrategy: ILauncherStrategy = LauncherStrategyFactory .getInstance(instr) .launcherStrategy -) : FlickerAppHelper(instr, "PipApp", launcherStrategy) { +) : StandardAppHelper(instr, "PipApp", launcherStrategy) { fun clickEnterPipButton(device: UiDevice) { val enterPipButton = device.findObject(By.res(getPackage(), "enter_pip")) Assert.assertNotNull("Pip button not found, this usually happens when the device " + diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppColdTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppColdTest.kt index 254209aee450..17590723da8d 100644 --- a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppColdTest.kt +++ b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppColdTest.kt @@ -80,7 +80,7 @@ class OpenAppColdTest( noUncoveredRegions(Surface.ROTATION_0, rotation, bugId = 141361128) navBarLayerRotatesAndScales(Surface.ROTATION_0, rotation) statusBarLayerRotatesScales(Surface.ROTATION_0, rotation) - navBarLayerIsAlwaysVisible() + navBarLayerIsAlwaysVisible(enabled = rotation == Surface.ROTATION_0) statusBarLayerIsAlwaysVisible(enabled = false) wallpaperLayerBecomesInvisible() } diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppTestBase.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppTestBase.kt index 7d70812a22f2..98e05d526bed 100644 --- a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppTestBase.kt +++ b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppTestBase.kt @@ -17,7 +17,7 @@ package com.android.server.wm.flicker.launch import com.android.server.wm.flicker.NonRotationTestBase -import com.android.server.wm.flicker.StandardAppHelper +import com.android.server.wm.flicker.helpers.StandardAppHelper import com.android.server.wm.flicker.dsl.LayersAssertion import com.android.server.wm.flicker.dsl.WmAssertion diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppWarmTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppWarmTest.kt index dda41a3021a0..acd141a8d74f 100644 --- a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppWarmTest.kt +++ b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppWarmTest.kt @@ -18,7 +18,7 @@ package com.android.server.wm.flicker.launch import android.view.Surface import androidx.test.filters.RequiresDevice -import com.android.server.wm.flicker.StandardAppHelper +import com.android.server.wm.flicker.helpers.StandardAppHelper import com.android.server.wm.flicker.dsl.flicker import com.android.server.wm.flicker.focusChanges import com.android.server.wm.flicker.helpers.wakeUpAndGoToHomeScreen @@ -88,7 +88,7 @@ class OpenAppWarmTest( noUncoveredRegions(Surface.ROTATION_0, rotation, bugId = 141361128) navBarLayerRotatesAndScales(Surface.ROTATION_0, rotation) statusBarLayerRotatesScales(Surface.ROTATION_0, rotation) - navBarLayerIsAlwaysVisible(bugId = 140855415) + navBarLayerIsAlwaysVisible(enabled = rotation == Surface.ROTATION_0) statusBarLayerIsAlwaysVisible(enabled = false) wallpaperLayerBecomesInvisible() } diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/rotation/ChangeAppRotationTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/rotation/ChangeAppRotationTest.kt index 0ca150892f36..99218c2c586d 100644 --- a/tests/FlickerTests/src/com/android/server/wm/flicker/rotation/ChangeAppRotationTest.kt +++ b/tests/FlickerTests/src/com/android/server/wm/flicker/rotation/ChangeAppRotationTest.kt @@ -20,7 +20,7 @@ import androidx.test.filters.RequiresDevice import android.view.Surface import com.android.server.wm.flicker.NonRotationTestBase.Companion.SCREENSHOT_LAYER import com.android.server.wm.flicker.RotationTestBase -import com.android.server.wm.flicker.StandardAppHelper +import com.android.server.wm.flicker.helpers.StandardAppHelper import com.android.server.wm.flicker.dsl.flicker import com.android.server.wm.flicker.focusDoesNotChange import com.android.server.wm.flicker.helpers.WindowUtils diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/splitscreen/OpenAppToSplitScreenTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/splitscreen/OpenAppToSplitScreenTest.kt index c5e48d966155..3b5e6694ef0f 100644 --- a/tests/FlickerTests/src/com/android/server/wm/flicker/splitscreen/OpenAppToSplitScreenTest.kt +++ b/tests/FlickerTests/src/com/android/server/wm/flicker/splitscreen/OpenAppToSplitScreenTest.kt @@ -19,7 +19,7 @@ package com.android.server.wm.flicker.splitscreen import android.view.Surface import androidx.test.filters.RequiresDevice import com.android.server.wm.flicker.NonRotationTestBase -import com.android.server.wm.flicker.StandardAppHelper +import com.android.server.wm.flicker.helpers.StandardAppHelper import com.android.server.wm.flicker.dsl.flicker import com.android.server.wm.flicker.focusChanges import com.android.server.wm.flicker.helpers.exitSplitScreen diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/splitscreen/ResizeSplitScreenTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/splitscreen/ResizeSplitScreenTest.kt index 91211cabf45c..abf41a1fd408 100644 --- a/tests/FlickerTests/src/com/android/server/wm/flicker/splitscreen/ResizeSplitScreenTest.kt +++ b/tests/FlickerTests/src/com/android/server/wm/flicker/splitscreen/ResizeSplitScreenTest.kt @@ -24,7 +24,7 @@ import androidx.test.filters.FlakyTest import androidx.test.filters.RequiresDevice import androidx.test.uiautomator.By import com.android.server.wm.flicker.FlickerTestBase -import com.android.server.wm.flicker.StandardAppHelper +import com.android.server.wm.flicker.helpers.StandardAppHelper import com.android.server.wm.flicker.dsl.flicker import com.android.server.wm.flicker.focusDoesNotChange import com.android.server.wm.flicker.helpers.ImeAppHelper diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/splitscreen/SplitScreenToLauncherTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/splitscreen/SplitScreenToLauncherTest.kt index 5c7dcd901a41..87c863338edb 100644 --- a/tests/FlickerTests/src/com/android/server/wm/flicker/splitscreen/SplitScreenToLauncherTest.kt +++ b/tests/FlickerTests/src/com/android/server/wm/flicker/splitscreen/SplitScreenToLauncherTest.kt @@ -19,7 +19,7 @@ package com.android.server.wm.flicker.splitscreen import android.view.Surface import androidx.test.filters.RequiresDevice import com.android.server.wm.flicker.NonRotationTestBase -import com.android.server.wm.flicker.StandardAppHelper +import com.android.server.wm.flicker.helpers.StandardAppHelper import com.android.server.wm.flicker.dsl.flicker import com.android.server.wm.flicker.focusDoesNotChange import com.android.server.wm.flicker.helpers.exitSplitScreen diff --git a/tests/SilkFX/res/layout/activity_glass.xml b/tests/SilkFX/res/layout/activity_glass.xml index 85dab9315197..a7b76bdeba09 100644 --- a/tests/SilkFX/res/layout/activity_glass.xml +++ b/tests/SilkFX/res/layout/activity_glass.xml @@ -68,6 +68,21 @@ app:layout_constraintStart_toStartOf="parent" /> <SeekBar + android:id="@+id/zoom" + android:layout_width="0dp" + android:layout_height="wrap_content" + android:layout_marginBottom="16dp" + android:layout_marginEnd="12dp" + android:layout_marginStart="12dp" + android:min="-100" + android:max="100" + android:progress="-15" + app:layout_constraintBottom_toTopOf="@+id/blurRadiusTitle" + app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintHorizontal_bias="1.0" + app:layout_constraintStart_toStartOf="parent" /> + + <SeekBar android:id="@+id/blurRadius" android:layout_width="0dp" android:layout_height="wrap_content" @@ -75,7 +90,7 @@ android:layout_marginEnd="12dp" android:layout_marginStart="12dp" android:max="150" - android:progress="50" + android:progress="20" app:layout_constraintBottom_toTopOf="@+id/materialOpacityTitle" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintHorizontal_bias="1.0" @@ -132,6 +147,17 @@ app:layout_constraintStart_toStartOf="parent" /> <TextView + android:id="@+id/zoomTitle" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_marginStart="24dp" + android:layout_marginBottom="8dp" + android:text="Zoom" + android:textColor="@android:color/white" + app:layout_constraintBottom_toTopOf="@+id/zoom" + app:layout_constraintStart_toStartOf="parent" /> + + <TextView android:id="@+id/blurRadiusTitle" android:layout_width="wrap_content" android:layout_height="wrap_content" @@ -200,7 +226,7 @@ android:layout_marginStart="24dp" android:layout_marginBottom="8dp" android:text="Light Material" - app:layout_constraintBottom_toTopOf="@+id/blurRadiusTitle" + app:layout_constraintBottom_toTopOf="@+id/zoomTitle" app:layout_constraintStart_toStartOf="parent" /> <TextView @@ -213,6 +239,15 @@ app:layout_constraintStart_toEndOf="@+id/blurRadiusTitle" /> <TextView + android:id="@+id/zoomValue" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:text="TextView" + android:layout_marginLeft="8dp" + app:layout_constraintBottom_toBottomOf="@+id/zoomTitle" + app:layout_constraintStart_toEndOf="@+id/zoomTitle" /> + + <TextView android:id="@+id/materialOpacityValue" android:layout_width="wrap_content" android:layout_height="wrap_content" diff --git a/tests/SilkFX/src/com/android/test/silkfx/materials/GlassActivity.kt b/tests/SilkFX/src/com/android/test/silkfx/materials/GlassActivity.kt index 6f5ddacb2733..72b342c54d19 100644 --- a/tests/SilkFX/src/com/android/test/silkfx/materials/GlassActivity.kt +++ b/tests/SilkFX/src/com/android/test/silkfx/materials/GlassActivity.kt @@ -39,11 +39,13 @@ class GlassActivity : Activity(), SeekBar.OnSeekBarChangeListener { lateinit var noiseOpacitySeekBar: SeekBar lateinit var materialOpacitySeekBar: SeekBar lateinit var scrimOpacitySeekBar: SeekBar + lateinit var zoomSeekBar: SeekBar lateinit var blurRadiusSeekBar: SeekBar lateinit var noiseOpacityValue: TextView lateinit var materialOpacityValue: TextView lateinit var scrimOpacityValue: TextView lateinit var blurRadiusValue: TextView + lateinit var zoomValue: TextView lateinit var background: Bitmap @@ -58,12 +60,14 @@ class GlassActivity : Activity(), SeekBar.OnSeekBarChangeListener { materialView = requireViewById(R.id.materialView) materialOpacitySeekBar = requireViewById(R.id.materialOpacity) blurRadiusSeekBar = requireViewById(R.id.blurRadius) + zoomSeekBar = requireViewById(R.id.zoom) noiseOpacitySeekBar = requireViewById(R.id.noiseOpacity) scrimOpacitySeekBar = requireViewById(R.id.scrimOpacity) noiseOpacityValue = requireViewById(R.id.noiseOpacityValue) materialOpacityValue = requireViewById(R.id.materialOpacityValue) scrimOpacityValue = requireViewById(R.id.scrimOpacityValue) blurRadiusValue = requireViewById(R.id.blurRadiusValue) + zoomValue = requireViewById(R.id.zoomValue) background = BitmapFactory.decodeResource(resources, R.drawable.background1) backgroundView.setImageBitmap(background) @@ -75,7 +79,7 @@ class GlassActivity : Activity(), SeekBar.OnSeekBarChangeListener { scrimOpacitySeekBar.setOnSeekBarChangeListener(this) arrayOf(blurRadiusSeekBar, materialOpacitySeekBar, noiseOpacitySeekBar, - scrimOpacitySeekBar).forEach { + scrimOpacitySeekBar, zoomSeekBar).forEach { it.setOnSeekBarChangeListener(this) onProgressChanged(it, it.progress, fromUser = false) } @@ -104,6 +108,10 @@ class GlassActivity : Activity(), SeekBar.OnSeekBarChangeListener { materialView.scrimOpacity = progress / seekBar.max.toFloat() scrimOpacityValue.text = progress.toString() } + zoomSeekBar -> { + materialView.zoom = progress / seekBar.max.toFloat() + zoomValue.text = progress.toString() + } else -> throw IllegalArgumentException("Unknown seek bar") } } diff --git a/tests/SilkFX/src/com/android/test/silkfx/materials/GlassView.kt b/tests/SilkFX/src/com/android/test/silkfx/materials/GlassView.kt index e100959908c3..60797680b79e 100644 --- a/tests/SilkFX/src/com/android/test/silkfx/materials/GlassView.kt +++ b/tests/SilkFX/src/com/android/test/silkfx/materials/GlassView.kt @@ -70,6 +70,12 @@ class GlassView(context: Context, attributeSet: AttributeSet) : View(context, at invalidate() } + var zoom = 0.0f + set(value) { + field = value + invalidate() + } + var color = Color.BLACK set(value) { field = value @@ -107,7 +113,12 @@ class GlassView(context: Context, attributeSet: AttributeSet) : View(context, at } override fun onDraw(canvas: Canvas?) { - src.set(left, top, right, bottom) + src.set(-width/2, -height/2, width/2, height/2) + src.scale(1.0f + zoom) + val centerX = left + width / 2 + val centerY = top + height / 2 + src.set(src.left + centerX, src.top + centerY, src.right + centerX, src.bottom + centerY) + dst.set(0, 0, width, height) canvas?.drawBitmap(backgroundBitmap, src, dst, blurPaint) canvas?.drawRect(dst, materialPaint) diff --git a/tools/validatekeymaps/Main.cpp b/tools/validatekeymaps/Main.cpp index 0aca13e95a52..7c150f9c8db9 100644 --- a/tools/validatekeymaps/Main.cpp +++ b/tools/validatekeymaps/Main.cpp @@ -16,8 +16,8 @@ #include <input/KeyCharacterMap.h> #include <input/KeyLayoutMap.h> +#include <input/PropertyMap.h> #include <input/VirtualKeyMap.h> -#include <utils/PropertyMap.h> #include <stdarg.h> #include <stdio.h> diff --git a/wifi/Android.bp b/wifi/Android.bp index 941ff61b3ba5..3040041038cb 100644 --- a/wifi/Android.bp +++ b/wifi/Android.bp @@ -129,12 +129,8 @@ java_sdk_library { }, hostdex: true, // for hiddenapi check - // Allow access to the stubs from anywhere. - visibility: ["//visibility:public"], - // Restrict access to implementation library. impl_library_visibility: [ - "//visibility:override", // Ignore the visibility property. "//frameworks/opt/net/wifi/service:__subpackages__", ] + test_access_hidden_api_whitelist, diff --git a/wifi/api/current.txt b/wifi/api/current.txt index b104decab73c..3f5c673eeb81 100644 --- a/wifi/api/current.txt +++ b/wifi/api/current.txt @@ -144,6 +144,7 @@ package android.net.wifi { @Deprecated public static class WifiConfiguration.GroupCipher { field @Deprecated public static final int CCMP = 3; // 0x3 + field @Deprecated public static final int GCMP_128 = 7; // 0x7 field @Deprecated public static final int GCMP_256 = 5; // 0x5 field @Deprecated public static final int SMS4 = 6; // 0x6 field @Deprecated public static final int TKIP = 2; // 0x2 @@ -173,6 +174,7 @@ package android.net.wifi { @Deprecated public static class WifiConfiguration.PairwiseCipher { field @Deprecated public static final int CCMP = 2; // 0x2 + field @Deprecated public static final int GCMP_128 = 5; // 0x5 field @Deprecated public static final int GCMP_256 = 3; // 0x3 field @Deprecated public static final int NONE = 0; // 0x0 field @Deprecated public static final int SMS4 = 4; // 0x4 @@ -579,6 +581,7 @@ package android.net.wifi.aware { method public void onPublishStarted(@NonNull android.net.wifi.aware.PublishDiscoverySession); method public void onServiceDiscovered(android.net.wifi.aware.PeerHandle, byte[], java.util.List<byte[]>); method public void onServiceDiscoveredWithinRange(android.net.wifi.aware.PeerHandle, byte[], java.util.List<byte[]>, int); + method public void onServiceLost(@NonNull android.net.wifi.aware.PeerHandle); method public void onSessionConfigFailed(); method public void onSessionConfigUpdated(); method public void onSessionTerminated(); @@ -654,6 +657,7 @@ package android.net.wifi.aware { method public void attach(@NonNull android.net.wifi.aware.AttachCallback, @NonNull android.net.wifi.aware.IdentityChangedListener, @Nullable android.os.Handler); method public android.net.wifi.aware.Characteristics getCharacteristics(); method public boolean isAvailable(); + method public boolean isDeviceAttached(); field public static final String ACTION_WIFI_AWARE_STATE_CHANGED = "android.net.wifi.aware.action.WIFI_AWARE_STATE_CHANGED"; field public static final int WIFI_AWARE_DATA_PATH_ROLE_INITIATOR = 0; // 0x0 field public static final int WIFI_AWARE_DATA_PATH_ROLE_RESPONDER = 1; // 0x1 diff --git a/wifi/api/system-current.txt b/wifi/api/system-current.txt index eff64a31367a..c3e573c311c2 100644 --- a/wifi/api/system-current.txt +++ b/wifi/api/system-current.txt @@ -449,6 +449,7 @@ package android.net.wifi { method @Deprecated @Nullable @RequiresPermission(android.Manifest.permission.ACCESS_WIFI_STATE) public android.net.wifi.WifiConfiguration getWifiApConfiguration(); method @RequiresPermission(android.Manifest.permission.ACCESS_WIFI_STATE) public int getWifiApState(); method @NonNull @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.NETWORK_SETUP_WIZARD}) public java.util.List<android.net.wifi.WifiConfiguration> getWifiConfigForMatchedNetworkSuggestionsSharedWithUser(@NonNull java.util.List<android.net.wifi.ScanResult>); + method public boolean is60GHzBandSupported(); method public boolean isApMacRandomizationSupported(); method public boolean isConnectedMacRandomizationSupported(); method @Deprecated public boolean isDeviceToDeviceRttSupported(); @@ -651,6 +652,7 @@ package android.net.wifi { field public static final int WIFI_BAND_5_GHZ = 2; // 0x2 field public static final int WIFI_BAND_5_GHZ_DFS_ONLY = 4; // 0x4 field public static final int WIFI_BAND_5_GHZ_WITH_DFS = 6; // 0x6 + field public static final int WIFI_BAND_60_GHZ = 16; // 0x10 field public static final int WIFI_BAND_6_GHZ = 8; // 0x8 field public static final int WIFI_BAND_BOTH = 3; // 0x3 field public static final int WIFI_BAND_BOTH_WITH_DFS = 7; // 0x7 diff --git a/wifi/java/android/net/wifi/IWifiManager.aidl b/wifi/java/android/net/wifi/IWifiManager.aidl index e4937892e2f7..b3ed8ac09034 100644 --- a/wifi/java/android/net/wifi/IWifiManager.aidl +++ b/wifi/java/android/net/wifi/IWifiManager.aidl @@ -118,6 +118,8 @@ interface IWifiManager boolean is6GHzBandSupported(); + boolean is60GHzBandSupported(); + boolean isWifiStandardSupported(int standard); DhcpInfo getDhcpInfo(); diff --git a/wifi/java/android/net/wifi/ScanResult.java b/wifi/java/android/net/wifi/ScanResult.java index 9302f78b7fca..54ec1e1c7c0b 100644 --- a/wifi/java/android/net/wifi/ScanResult.java +++ b/wifi/java/android/net/wifi/ScanResult.java @@ -595,6 +595,27 @@ public final class ScanResult implements Parcelable { public static final int BAND_6_GHZ_END_FREQ_MHZ = 7105; /** + * 60 GHz band first channel number + * @hide + */ + public static final int BAND_60_GHZ_FIRST_CH_NUM = 1; + /** + * 60 GHz band last channel number + * @hide + */ + public static final int BAND_60_GHZ_LAST_CH_NUM = 6; + /** + * 60 GHz band frequency of first channel in MHz + * @hide + */ + public static final int BAND_60_GHZ_START_FREQ_MHZ = 58320; + /** + * 60 GHz band frequency of last channel in MHz + * @hide + */ + public static final int BAND_60_GHZ_END_FREQ_MHZ = 70200; + + /** * Utility function to check if a frequency within 2.4 GHz band * @param freqMhz frequency in MHz * @return true if within 2.4GHz, false otherwise @@ -628,6 +649,17 @@ public final class ScanResult implements Parcelable { } /** + * Utility function to check if a frequency within 60 GHz band + * @param freqMhz + * @return true if within 60GHz, false otherwise + * + * @hide + */ + public static boolean is60GHz(int freqMhz) { + return freqMhz >= BAND_60_GHZ_START_FREQ_MHZ && freqMhz <= BAND_60_GHZ_END_FREQ_MHZ; + } + + /** * Utility function to convert channel number/band to frequency in MHz * @param channel number to convert * @param band of channel to convert @@ -707,6 +739,13 @@ public final class ScanResult implements Parcelable { } /** + * @hide + */ + public boolean is60GHz() { + return ScanResult.is60GHz(frequency); + } + + /** * @hide * anqp lines from supplicant BSS response */ diff --git a/wifi/java/android/net/wifi/SoftApCapability.java b/wifi/java/android/net/wifi/SoftApCapability.java index 99c4eac7977b..cf54f26fc5e4 100644 --- a/wifi/java/android/net/wifi/SoftApCapability.java +++ b/wifi/java/android/net/wifi/SoftApCapability.java @@ -21,7 +21,7 @@ import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.SystemApi; import android.net.wifi.SoftApConfiguration.BandType; -import android.os.Build; +import android.net.wifi.util.SdkLevelUtil; import android.os.Parcel; import android.os.Parcelable; @@ -176,7 +176,7 @@ public final class SoftApCapability implements Parcelable { */ @NonNull public int[] getSupportedChannelList(@BandType int band) { - if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.R) { + if (!SdkLevelUtil.isAtLeastS()) { throw new UnsupportedOperationException(); } switch (band) { diff --git a/wifi/java/android/net/wifi/SoftApConfiguration.java b/wifi/java/android/net/wifi/SoftApConfiguration.java index 393fe8d3ab9a..bc837b3c344d 100644 --- a/wifi/java/android/net/wifi/SoftApConfiguration.java +++ b/wifi/java/android/net/wifi/SoftApConfiguration.java @@ -22,7 +22,7 @@ import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.SystemApi; import android.net.MacAddress; -import android.os.Build; +import android.net.wifi.util.SdkLevelUtil; import android.os.Parcel; import android.os.Parcelable; import android.text.TextUtils; @@ -551,7 +551,7 @@ public final class SoftApConfiguration implements Parcelable { @SystemApi @MacRandomizationSetting public int getMacRandomizationSetting() { - if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.R) { + if (!SdkLevelUtil.isAtLeastS()) { throw new UnsupportedOperationException(); } return mMacRandomizationSetting; @@ -1046,7 +1046,7 @@ public final class SoftApConfiguration implements Parcelable { @NonNull public Builder setMacRandomizationSetting( @MacRandomizationSetting int macRandomizationSetting) { - if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.R) { + if (!SdkLevelUtil.isAtLeastS()) { throw new UnsupportedOperationException(); } mMacRandomizationSetting = macRandomizationSetting; diff --git a/wifi/java/android/net/wifi/SoftApInfo.java b/wifi/java/android/net/wifi/SoftApInfo.java index 4791275cdce5..40981f7b0fb1 100644 --- a/wifi/java/android/net/wifi/SoftApInfo.java +++ b/wifi/java/android/net/wifi/SoftApInfo.java @@ -20,7 +20,7 @@ import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.SystemApi; import android.net.MacAddress; -import android.os.Build; +import android.net.wifi.util.SdkLevelUtil; import android.os.Parcel; import android.os.Parcelable; @@ -138,7 +138,7 @@ public final class SoftApInfo implements Parcelable { */ @Nullable public MacAddress getBssid() { - if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.R) { + if (!SdkLevelUtil.isAtLeastS()) { throw new UnsupportedOperationException(); } return mBssid; diff --git a/wifi/java/android/net/wifi/WifiConfiguration.java b/wifi/java/android/net/wifi/WifiConfiguration.java index 1588bf72c969..02b7a42d3878 100644 --- a/wifi/java/android/net/wifi/WifiConfiguration.java +++ b/wifi/java/android/net/wifi/WifiConfiguration.java @@ -301,9 +301,16 @@ public class WifiConfiguration implements Parcelable { */ public static final int SMS4 = 4; + /** + * AES in Galois/Counter Mode with a 128-bit integrity key + */ + public static final int GCMP_128 = 5; + + public static final String varName = "pairwise"; - public static final String[] strings = { "NONE", "TKIP", "CCMP", "GCMP_256", "SMS4" }; + public static final String[] strings = { "NONE", "TKIP", "CCMP", "GCMP_256", "SMS4", + "GCMP_128" }; } /** @@ -345,13 +352,17 @@ public class WifiConfiguration implements Parcelable { * SMS4 cipher for WAPI */ public static final int SMS4 = 6; + /** + * AES in Galois/Counter Mode with a 128-bit integrity key + */ + public static final int GCMP_128 = 7; public static final String varName = "group"; public static final String[] strings = { /* deprecated */ "WEP40", /* deprecated */ "WEP104", "TKIP", "CCMP", "GTK_NOT_USED", "GCMP_256", - "SMS4" }; + "SMS4", "GCMP_128" }; } /** @@ -498,8 +509,10 @@ public class WifiConfiguration implements Parcelable { allowedProtocols.set(WifiConfiguration.Protocol.RSN); allowedKeyManagement.set(WifiConfiguration.KeyMgmt.SAE); allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.CCMP); + allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.GCMP_128); allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.GCMP_256); allowedGroupCiphers.set(WifiConfiguration.GroupCipher.CCMP); + allowedGroupCiphers.set(WifiConfiguration.GroupCipher.GCMP_128); allowedGroupCiphers.set(WifiConfiguration.GroupCipher.GCMP_256); requirePmf = true; break; @@ -508,7 +521,9 @@ public class WifiConfiguration implements Parcelable { allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_EAP); allowedKeyManagement.set(WifiConfiguration.KeyMgmt.IEEE8021X); allowedKeyManagement.set(WifiConfiguration.KeyMgmt.SUITE_B_192); + allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.GCMP_128); allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.GCMP_256); + allowedGroupCiphers.set(WifiConfiguration.GroupCipher.GCMP_128); allowedGroupCiphers.set(WifiConfiguration.GroupCipher.GCMP_256); allowedGroupManagementCiphers.set(WifiConfiguration.GroupMgmtCipher.BIP_GMAC_256); // Note: allowedSuiteBCiphers bitset will be set by the service once the @@ -519,8 +534,10 @@ public class WifiConfiguration implements Parcelable { allowedProtocols.set(WifiConfiguration.Protocol.RSN); allowedKeyManagement.set(WifiConfiguration.KeyMgmt.OWE); allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.CCMP); + allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.GCMP_128); allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.GCMP_256); allowedGroupCiphers.set(WifiConfiguration.GroupCipher.CCMP); + allowedGroupCiphers.set(WifiConfiguration.GroupCipher.GCMP_128); allowedGroupCiphers.set(WifiConfiguration.GroupCipher.GCMP_256); requirePmf = true; break; @@ -596,6 +613,12 @@ public class WifiConfiguration implements Parcelable { public static final int AP_BAND_5GHZ = 1; /** + * 60GHz band + * @hide + */ + public static final int AP_BAND_60GHZ = 2; + + /** * Device is allowed to choose the optimal band (2Ghz or 5Ghz) based on device capability, * operating country code and current radio conditions. * @hide @@ -2509,7 +2532,18 @@ public class WifiConfiguration implements Parcelable { @KeyMgmt.KeyMgmtScheme public int getAuthType() { if (allowedKeyManagement.cardinality() > 1) { - throw new IllegalStateException("More than one auth type set"); + if (allowedKeyManagement.get(KeyMgmt.WPA_EAP)) { + if (allowedKeyManagement.cardinality() == 2 + && allowedKeyManagement.get(KeyMgmt.IEEE8021X)) { + return KeyMgmt.WPA_EAP; + } + if (allowedKeyManagement.cardinality() == 3 + && allowedKeyManagement.get(KeyMgmt.IEEE8021X) + && allowedKeyManagement.get(KeyMgmt.SUITE_B_192)) { + return KeyMgmt.SUITE_B_192; + } + } + throw new IllegalStateException("Invalid auth type set: " + allowedKeyManagement); } if (allowedKeyManagement.get(KeyMgmt.WPA_PSK)) { return KeyMgmt.WPA_PSK; diff --git a/wifi/java/android/net/wifi/WifiEnterpriseConfig.java b/wifi/java/android/net/wifi/WifiEnterpriseConfig.java index 77fa673f1960..90edc4523b7b 100644 --- a/wifi/java/android/net/wifi/WifiEnterpriseConfig.java +++ b/wifi/java/android/net/wifi/WifiEnterpriseConfig.java @@ -30,6 +30,9 @@ import java.lang.annotation.RetentionPolicy; import java.nio.charset.StandardCharsets; import java.security.PrivateKey; import java.security.cert.X509Certificate; +import java.security.interfaces.ECPublicKey; +import java.security.interfaces.RSAPublicKey; +import java.security.spec.ECParameterSpec; import java.util.Arrays; import java.util.HashMap; import java.util.List; @@ -1442,4 +1445,50 @@ public class WifiEnterpriseConfig implements Parcelable { } return TextUtils.isEmpty(getCaPath()); } + + /** + * Check if a given certificate Get the Suite-B cipher from the certificate + * + * @param x509Certificate Certificate to process + * @return true if the certificate OID matches the Suite-B requirements for RSA or ECDSA + * certificates, or false otherwise. + * @hide + */ + public static boolean isSuiteBCipherCert(@Nullable X509Certificate x509Certificate) { + if (x509Certificate == null) { + return false; + } + final String sigAlgOid = x509Certificate.getSigAlgOID(); + + // Wi-Fi alliance requires the use of both ECDSA secp384r1 and RSA 3072 certificates + // in WPA3-Enterprise 192-bit security networks, which are also known as Suite-B-192 + // networks, even though NSA Suite-B-192 mandates ECDSA only. The use of the term + // Suite-B was already coined in the IEEE 802.11-2016 specification for + // AKM 00-0F-AC but the test plan for WPA3-Enterprise 192-bit for APs mandates + // support for both RSA and ECDSA, and for STAs it mandates ECDSA and optionally + // RSA. In order to be compatible with all WPA3-Enterprise 192-bit deployments, + // we are supporting both types here. + if (sigAlgOid.equals("1.2.840.113549.1.1.12")) { + // sha384WithRSAEncryption + if (x509Certificate.getPublicKey() instanceof RSAPublicKey) { + final RSAPublicKey rsaPublicKey = (RSAPublicKey) x509Certificate.getPublicKey(); + if (rsaPublicKey.getModulus() != null + && rsaPublicKey.getModulus().bitLength() >= 3072) { + return true; + } + } + } else if (sigAlgOid.equals("1.2.840.10045.4.3.3")) { + // ecdsa-with-SHA384 + if (x509Certificate.getPublicKey() instanceof ECPublicKey) { + final ECPublicKey ecPublicKey = (ECPublicKey) x509Certificate.getPublicKey(); + final ECParameterSpec ecParameterSpec = ecPublicKey.getParams(); + + if (ecParameterSpec != null && ecParameterSpec.getOrder() != null + && ecParameterSpec.getOrder().bitLength() >= 384) { + return true; + } + } + } + return false; + } } diff --git a/wifi/java/android/net/wifi/WifiManager.java b/wifi/java/android/net/wifi/WifiManager.java index b28b902910bf..c76f4a63a777 100644 --- a/wifi/java/android/net/wifi/WifiManager.java +++ b/wifi/java/android/net/wifi/WifiManager.java @@ -2407,6 +2407,8 @@ public class WifiManager { public static final long WIFI_FEATURE_OCE = 0x1000000000L; // OCE Support /** @hide */ public static final long WIFI_FEATURE_WAPI = 0x2000000000L; // WAPI + /** @hide */ + public static final long WIFI_FEATURE_INFRA_60G = 0x4000000000L; // 60 GHz Band Support /** @hide */ public static final long WIFI_FEATURE_FILS_SHA256 = 0x4000000000L; // FILS-SHA256 @@ -2569,6 +2571,21 @@ public class WifiManager { } /** + * Check if the chipset supports the 60GHz frequency band. + * + * @return {@code true} if supported, {@code false} otherwise. + * @hide + */ + @SystemApi + public boolean is60GHzBandSupported() { + try { + return mService.is60GHzBandSupported(); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + /** * Check if the chipset supports 6GHz band. * @return {@code true} if supported, {@code false} otherwise. */ diff --git a/wifi/java/android/net/wifi/WifiNetworkSpecifier.java b/wifi/java/android/net/wifi/WifiNetworkSpecifier.java index b0213b0ef502..e12bb9178235 100644 --- a/wifi/java/android/net/wifi/WifiNetworkSpecifier.java +++ b/wifi/java/android/net/wifi/WifiNetworkSpecifier.java @@ -78,12 +78,12 @@ public final class WifiNetworkSpecifier extends NetworkSpecifier implements Parc private @Nullable String mWpa3SaePassphrase; /** * The enterprise configuration details specifying the EAP method, - * certificates and other settings associated with the WPA-EAP networks. + * certificates and other settings associated with the WPA/WPA2-Enterprise networks. */ private @Nullable WifiEnterpriseConfig mWpa2EnterpriseConfig; /** * The enterprise configuration details specifying the EAP method, - * certificates and other settings associated with the SuiteB networks. + * certificates and other settings associated with the WPA3-Enterprise networks. */ private @Nullable WifiEnterpriseConfig mWpa3EnterpriseConfig; /** @@ -243,7 +243,11 @@ public final class WifiNetworkSpecifier extends NetworkSpecifier implements Parc /** * Set the associated enterprise configuration for this network. Needed for authenticating - * to WPA3-SuiteB networks. See {@link WifiEnterpriseConfig} for description. + * to WPA3-Enterprise networks (standard and 192-bit security). See + * {@link WifiEnterpriseConfig} for description. For 192-bit security networks, both the + * client and CA certificates must be provided, and must be of type of either + * sha384WithRSAEncryption (OID 1.2.840.113549.1.1.12) or ecdsa-with-SHA384 + * (OID 1.2.840.10045.4.3.3). * * @param enterpriseConfig Instance of {@link WifiEnterpriseConfig}. * @return Instance of {@link Builder} to enable chaining of the builder method. @@ -284,8 +288,25 @@ public final class WifiNetworkSpecifier extends NetworkSpecifier implements Parc } else if (mWpa2EnterpriseConfig != null) { // WPA-EAP network configuration.setSecurityParams(WifiConfiguration.SECURITY_TYPE_EAP); configuration.enterpriseConfig = mWpa2EnterpriseConfig; - } else if (mWpa3EnterpriseConfig != null) { // WPA3-SuiteB network - configuration.setSecurityParams(WifiConfiguration.SECURITY_TYPE_EAP_SUITE_B); + } else if (mWpa3EnterpriseConfig != null) { // WPA3-Enterprise + if (mWpa3EnterpriseConfig.getEapMethod() == WifiEnterpriseConfig.Eap.TLS + && WifiEnterpriseConfig.isSuiteBCipherCert( + mWpa3EnterpriseConfig.getClientCertificate()) + && WifiEnterpriseConfig.isSuiteBCipherCert( + mWpa3EnterpriseConfig.getCaCertificate())) { + // WPA3-Enterprise in 192-bit security mode (Suite-B) + configuration.setSecurityParams(WifiConfiguration.SECURITY_TYPE_EAP_SUITE_B); + } else { + // WPA3-Enterprise + configuration.setSecurityParams(WifiConfiguration.SECURITY_TYPE_EAP); + configuration.allowedProtocols.set(WifiConfiguration.Protocol.RSN); + configuration.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.CCMP); + configuration.allowedPairwiseCiphers.set( + WifiConfiguration.PairwiseCipher.GCMP_256); + configuration.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.CCMP); + configuration.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.GCMP_256); + configuration.requirePmf = true; + } configuration.enterpriseConfig = mWpa3EnterpriseConfig; } else if (mIsEnhancedOpen) { // OWE network configuration.setSecurityParams(WifiConfiguration.SECURITY_TYPE_OWE); diff --git a/wifi/java/android/net/wifi/WifiNetworkSuggestion.java b/wifi/java/android/net/wifi/WifiNetworkSuggestion.java index e4e900ffe12a..aa699634dac4 100644 --- a/wifi/java/android/net/wifi/WifiNetworkSuggestion.java +++ b/wifi/java/android/net/wifi/WifiNetworkSuggestion.java @@ -72,12 +72,12 @@ public final class WifiNetworkSuggestion implements Parcelable { private @Nullable String mWpa3SaePassphrase; /** * The enterprise configuration details specifying the EAP method, - * certificates and other settings associated with the WPA-EAP networks. + * certificates and other settings associated with the WPA/WPA2-Enterprise networks. */ private @Nullable WifiEnterpriseConfig mWpa2EnterpriseConfig; /** * The enterprise configuration details specifying the EAP method, - * certificates and other settings associated with the SuiteB networks. + * certificates and other settings associated with the WPA3-Enterprise networks. */ private @Nullable WifiEnterpriseConfig mWpa3EnterpriseConfig; /** @@ -288,7 +288,11 @@ public final class WifiNetworkSuggestion implements Parcelable { /** * Set the associated enterprise configuration for this network. Needed for authenticating - * to WPA3 enterprise networks. See {@link WifiEnterpriseConfig} for description. + * to WPA3-Enterprise networks (standard and 192-bit security). See + * {@link WifiEnterpriseConfig} for description. For 192-bit security networks, both the + * client and CA certificates must be provided, and must be of type of either + * sha384WithRSAEncryption (OID 1.2.840.113549.1.1.12) or ecdsa-with-SHA384 + * (OID 1.2.840.10045.4.3.3). * * @param enterpriseConfig Instance of {@link WifiEnterpriseConfig}. * @return Instance of {@link Builder} to enable chaining of the builder method. @@ -570,8 +574,25 @@ public final class WifiNetworkSuggestion implements Parcelable { } else if (mWpa2EnterpriseConfig != null) { // WPA-EAP network configuration.setSecurityParams(WifiConfiguration.SECURITY_TYPE_EAP); configuration.enterpriseConfig = mWpa2EnterpriseConfig; - } else if (mWpa3EnterpriseConfig != null) { // WPA3-SuiteB network - configuration.setSecurityParams(WifiConfiguration.SECURITY_TYPE_EAP_SUITE_B); + } else if (mWpa3EnterpriseConfig != null) { // WPA3-Enterprise + if (mWpa3EnterpriseConfig.getEapMethod() == WifiEnterpriseConfig.Eap.TLS + && WifiEnterpriseConfig.isSuiteBCipherCert( + mWpa3EnterpriseConfig.getClientCertificate()) + && WifiEnterpriseConfig.isSuiteBCipherCert( + mWpa3EnterpriseConfig.getCaCertificate())) { + // WPA3-Enterprise in 192-bit security mode (Suite-B) + configuration.setSecurityParams(WifiConfiguration.SECURITY_TYPE_EAP_SUITE_B); + } else { + // WPA3-Enterprise + configuration.setSecurityParams(WifiConfiguration.SECURITY_TYPE_EAP); + configuration.allowedProtocols.set(WifiConfiguration.Protocol.RSN); + configuration.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.CCMP); + configuration.allowedPairwiseCiphers.set( + WifiConfiguration.PairwiseCipher.GCMP_256); + configuration.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.CCMP); + configuration.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.GCMP_256); + configuration.requirePmf = true; + } configuration.enterpriseConfig = mWpa3EnterpriseConfig; } else if (mIsEnhancedOpen) { // OWE network configuration.setSecurityParams(WifiConfiguration.SECURITY_TYPE_OWE); diff --git a/wifi/java/android/net/wifi/WifiScanner.java b/wifi/java/android/net/wifi/WifiScanner.java index 94771ac4ad78..a68d7e260b6a 100644 --- a/wifi/java/android/net/wifi/WifiScanner.java +++ b/wifi/java/android/net/wifi/WifiScanner.java @@ -68,7 +68,9 @@ public class WifiScanner { /** @hide */ public static final int WIFI_BAND_INDEX_6_GHZ = 3; /** @hide */ - public static final int WIFI_BAND_COUNT = 4; + public static final int WIFI_BAND_INDEX_60_GHZ = 4; + /** @hide */ + public static final int WIFI_BAND_COUNT = 5; /** @hide */ @Retention(RetentionPolicy.SOURCE) @@ -76,7 +78,8 @@ public class WifiScanner { WIFI_BAND_INDEX_24_GHZ, WIFI_BAND_INDEX_5_GHZ, WIFI_BAND_INDEX_5_GHZ_DFS_ONLY, - WIFI_BAND_INDEX_6_GHZ}) + WIFI_BAND_INDEX_6_GHZ, + WIFI_BAND_INDEX_60_GHZ}) public @interface WifiBandIndex {} /** no band specified; use channel list instead */ @@ -89,6 +92,8 @@ public class WifiScanner { public static final int WIFI_BAND_5_GHZ_DFS_ONLY = 1 << WIFI_BAND_INDEX_5_GHZ_DFS_ONLY; /** 6 GHz band */ public static final int WIFI_BAND_6_GHZ = 1 << WIFI_BAND_INDEX_6_GHZ; + /** 60 GHz band */ + public static final int WIFI_BAND_60_GHZ = 1 << WIFI_BAND_INDEX_60_GHZ; /** * Combination of bands @@ -113,6 +118,12 @@ public class WifiScanner { /** 2.4 GHz band and 5 GHz band; with DFS channels and 6 GHz */ public static final int WIFI_BAND_24_5_WITH_DFS_6_GHZ = WIFI_BAND_BOTH_WITH_DFS | WIFI_BAND_6_GHZ; + /** @hide */ + public static final int WIFI_BAND_24_5_6_60_GHZ = + WIFI_BAND_24_5_6_GHZ | WIFI_BAND_60_GHZ; + /** @hide */ + public static final int WIFI_BAND_24_5_WITH_DFS_6_60_GHZ = + WIFI_BAND_24_5_6_60_GHZ | WIFI_BAND_5_GHZ_DFS_ONLY; /** @hide */ @Retention(RetentionPolicy.SOURCE) @@ -127,7 +138,10 @@ public class WifiScanner { WIFI_BAND_BOTH_WITH_DFS, WIFI_BAND_6_GHZ, WIFI_BAND_24_5_6_GHZ, - WIFI_BAND_24_5_WITH_DFS_6_GHZ}) + WIFI_BAND_24_5_WITH_DFS_6_GHZ, + WIFI_BAND_60_GHZ, + WIFI_BAND_24_5_6_60_GHZ, + WIFI_BAND_24_5_WITH_DFS_6_60_GHZ}) public @interface WifiBand {} /** @@ -179,7 +193,10 @@ public class WifiScanner { * @hide */ public static boolean isFullBandScan(@WifiBand int bandScanned, boolean excludeDfs) { - return (bandScanned | WIFI_BAND_6_GHZ | (excludeDfs ? WIFI_BAND_5_GHZ_DFS_ONLY : 0)) + // 5GHz DFS channel is part of 5GHz, mark 5GHz scanned as well. + if ((bandScanned & WIFI_BAND_5_GHZ_DFS_ONLY) != 0) bandScanned |= WIFI_BAND_5_GHZ; + return (bandScanned | WIFI_BAND_6_GHZ | WIFI_BAND_60_GHZ + | (excludeDfs ? WIFI_BAND_5_GHZ_DFS_ONLY : 0)) == WIFI_BAND_ALL; } @@ -571,6 +588,19 @@ public class WifiScanner { } } + /** {@hide} */ + public void addResults(@NonNull ScanData s) { + mBandScanned |= s.mBandScanned; + mFlags |= s.mFlags; + addResults(s.getResults()); + } + + /** {@hide} */ + public boolean isFullBandScanResults() { + return (mBandScanned & WifiScanner.WIFI_BAND_24_GHZ) != 0 + && (mBandScanned & WifiScanner.WIFI_BAND_5_GHZ) != 0; + } + /** Implement the Parcelable interface {@hide} */ public int describeContents() { return 0; diff --git a/wifi/java/android/net/wifi/aware/DiscoverySessionCallback.java b/wifi/java/android/net/wifi/aware/DiscoverySessionCallback.java index bfb0462952b1..e3800ad6ef36 100644 --- a/wifi/java/android/net/wifi/aware/DiscoverySessionCallback.java +++ b/wifi/java/android/net/wifi/aware/DiscoverySessionCallback.java @@ -189,4 +189,16 @@ public class DiscoverySessionCallback { public void onMessageReceived(PeerHandle peerHandle, byte[] message) { /* empty */ } + + /** + * Called when the discovered peer is no longer visible. All further operations on this + * discovery session will fail. If the peer is visible again, + * {@link #onServiceDiscovered(PeerHandle, byte[], List)} or + * {@link #onServiceDiscoveredWithinRange(PeerHandle, byte[], List, int)} will be called. + * + * @param peerHandle An opaque handle to the peer matching our discovery operation. + */ + public void onServiceLost(@NonNull PeerHandle peerHandle) { + /* empty */ + } } diff --git a/wifi/java/android/net/wifi/aware/IWifiAwareDiscoverySessionCallback.aidl b/wifi/java/android/net/wifi/aware/IWifiAwareDiscoverySessionCallback.aidl index 421a8af2073e..e3e7c8e6c747 100644 --- a/wifi/java/android/net/wifi/aware/IWifiAwareDiscoverySessionCallback.aidl +++ b/wifi/java/android/net/wifi/aware/IWifiAwareDiscoverySessionCallback.aidl @@ -35,4 +35,5 @@ oneway interface IWifiAwareDiscoverySessionCallback void onMessageSendSuccess(int messageId); void onMessageSendFail(int messageId, int reason); void onMessageReceived(int peerId, in byte[] message); + void onMatchExpired(int peerId); } diff --git a/wifi/java/android/net/wifi/aware/IWifiAwareManager.aidl b/wifi/java/android/net/wifi/aware/IWifiAwareManager.aidl index 88f95ad4d495..f5b1edce1d69 100644 --- a/wifi/java/android/net/wifi/aware/IWifiAwareManager.aidl +++ b/wifi/java/android/net/wifi/aware/IWifiAwareManager.aidl @@ -36,6 +36,7 @@ interface IWifiAwareManager // Aware API boolean isUsageEnabled(); Characteristics getCharacteristics(); + boolean isDeviceAttached(); // client API void connect(in IBinder binder, in String callingPackage, in String callingFeatureId, diff --git a/wifi/java/android/net/wifi/aware/WifiAwareManager.java b/wifi/java/android/net/wifi/aware/WifiAwareManager.java index c2ae17c4bdeb..d6e46fd52caf 100644 --- a/wifi/java/android/net/wifi/aware/WifiAwareManager.java +++ b/wifi/java/android/net/wifi/aware/WifiAwareManager.java @@ -179,6 +179,22 @@ public class WifiAwareManager { } /** + * Return the current status of the Aware service: whether ot not the device is already attached + * to an Aware cluster. To attach to an Aware cluster, please use + * {@link #attach(AttachCallback, Handler)} or + * {@link #attach(AttachCallback, IdentityChangedListener, Handler)}. + * @return A boolean indicating whether the device is attached to a cluster at this time (true) + * or not (false). + */ + public boolean isDeviceAttached() { + try { + return mService.isDeviceAttached(); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + /** * Returns the characteristics of the Wi-Fi Aware interface: a set of parameters which specify * limitations on configurations, e.g. the maximum service name length. * @@ -587,6 +603,7 @@ public class WifiAwareManager { private static final int CALLBACK_MESSAGE_SEND_FAIL = 6; private static final int CALLBACK_MESSAGE_RECEIVED = 7; private static final int CALLBACK_MATCH_WITH_DISTANCE = 8; + private static final int CALLBACK_MATCH_EXPIRED = 9; private static final String MESSAGE_BUNDLE_KEY_MESSAGE = "message"; private static final String MESSAGE_BUNDLE_KEY_MESSAGE2 = "message2"; @@ -676,6 +693,9 @@ public class WifiAwareManager { mOriginalCallback.onMessageReceived(new PeerHandle(msg.arg1), (byte[]) msg.obj); break; + case CALLBACK_MATCH_EXPIRED: + mOriginalCallback + .onServiceLost(new PeerHandle(msg.arg1)); } } }; @@ -746,6 +766,15 @@ public class WifiAwareManager { onMatchCommon(CALLBACK_MATCH_WITH_DISTANCE, peerId, serviceSpecificInfo, matchFilter, distanceMm); } + @Override + public void onMatchExpired(int peerId) { + if (VDBG) { + Log.v(TAG, "onMatchExpired: peerId=" + peerId); + } + Message msg = mHandler.obtainMessage(CALLBACK_MATCH_EXPIRED); + msg.arg1 = peerId; + mHandler.sendMessage(msg); + } @Override public void onMessageSendSuccess(int messageId) { diff --git a/wifi/java/android/net/wifi/nl80211/NativeScanResult.java b/wifi/java/android/net/wifi/nl80211/NativeScanResult.java index a8e999973fe8..35cf45fe36ed 100644 --- a/wifi/java/android/net/wifi/nl80211/NativeScanResult.java +++ b/wifi/java/android/net/wifi/nl80211/NativeScanResult.java @@ -225,6 +225,15 @@ public final class NativeScanResult implements Parcelable { * BSS capability bit (see IEEE Std 802.11: 9.4.1.4): Immediate Block Ack. */ public static final int BSS_CAPABILITY_IMMEDIATE_BLOCK_ACK = 0x1 << 15; + /** + * BSS capability bit (see IEEE Std 802.11: 9.4.1.4): DMG ESS. + * In DMG bits 0 and 1 are parsed together, where ESS=0x3 and IBSS=0x1 + */ + public static final int BSS_CAPABILITY_DMG_ESS = 0x3; + /** + * BSS capability bit (see IEEE Std 802.11: 9.4.1.4): DMG IBSS. + */ + public static final int BSS_CAPABILITY_DMG_IBSS = 0x1; /** * Returns the capabilities of the AP repseresented by this scan result as advertised in the diff --git a/wifi/java/android/net/wifi/nl80211/WifiNl80211Manager.java b/wifi/java/android/net/wifi/nl80211/WifiNl80211Manager.java index 4116234c4c8d..3175e456693d 100644 --- a/wifi/java/android/net/wifi/nl80211/WifiNl80211Manager.java +++ b/wifi/java/android/net/wifi/nl80211/WifiNl80211Manager.java @@ -223,7 +223,11 @@ public class WifiNl80211Manager { /** * Callbacks for SoftAp interface registered using * {@link #registerApCallback(String, Executor, SoftApCallback)}. + * + * @deprecated The usage is replaced by vendor HAL + * {@code android.hardware.wifi.hostapd.V1_3.IHostapdCallback}. */ + @Deprecated public interface SoftApCallback { /** * Invoked when there is a fatal failure and the SoftAp is shutdown. @@ -1121,7 +1125,11 @@ public class WifiNl80211Manager { * @param callback Callback for AP events. * @return true on success, false on failure (e.g. when called on an interface which has not * been set up). + * + * @deprecated The usage is replaced by vendor HAL + * {@code android.hardware.wifi.hostapd.V1_3.IHostapdCallback}. */ + @Deprecated public boolean registerApCallback(@NonNull String ifaceName, @NonNull @CallbackExecutor Executor executor, @NonNull SoftApCallback callback) { diff --git a/wifi/java/android/net/wifi/util/SdkLevelUtil.java b/wifi/java/android/net/wifi/util/SdkLevelUtil.java new file mode 100644 index 000000000000..042634c7125c --- /dev/null +++ b/wifi/java/android/net/wifi/util/SdkLevelUtil.java @@ -0,0 +1,68 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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.wifi.util; + +import android.os.Build; + +/** + * Utility to check the SDK version of the device that the code is running on. + * + * This can be used to disable new Wifi APIs added in Mainline updates on older SDK versions. + * + * @hide + */ +public class SdkLevelUtil { + + /** This class is instantiable to allow easy mocking. */ + public SdkLevelUtil() { } + + /** See {@link #isAtLeastS()}. This version is non-static to allow easy mocking. */ + public boolean isAtLeastSMockable() { + return isAtLeastS(); + } + + /** Returns true if the Android platform SDK is at least "S", false otherwise. */ + public static boolean isAtLeastS() { + // TODO(b/167575586): after S SDK finalization, this method should just be + // `return Build.VERSION.SDK_INT >= Build.VERSION_CODES.S;` + + // at least S: return true + // this condition only evaluates to true after S SDK finalization when VERSION_CODES.S + // is set to something like "31", before SDK finalization the value is "10000" + // Note that Build.VERSION_CODES.S is inlined at compile time. If it's inlined to 10000, + // this condition never evaluates to true. + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { + return true; + } + + // Assume for now that S = R + 1 + if (Build.VERSION.SDK_INT > Build.VERSION_CODES.R) { + return true; + } + + // R: check CODENAME + // Before S SDK finalization, SDK_INT = R = 30 i.e. remains on the previous version + if (Build.VERSION.SDK_INT == Build.VERSION_CODES.R) { + // CODENAME = "REL" on R release builds + // CODENAME = "S" on S development builds + return "S".equals(Build.VERSION.CODENAME); + } + + // older than R: return false + return false; + } +} diff --git a/wifi/tests/src/android/net/wifi/FakeKeys.java b/wifi/tests/src/android/net/wifi/FakeKeys.java index 641b891a1f4d..8aa6add4a4e4 100644 --- a/wifi/tests/src/android/net/wifi/FakeKeys.java +++ b/wifi/tests/src/android/net/wifi/FakeKeys.java @@ -212,7 +212,57 @@ public class FakeKeys { (byte) 0xbc, (byte) 0xa7, (byte) 0x92, (byte) 0x90, (byte) 0xdd, (byte) 0xa1, (byte) 0x9c, (byte) 0xce, (byte) 0xa1, (byte) 0x87, (byte) 0x11, (byte) 0x51 }; - public static final PrivateKey RSA_KEY1 = loadPrivateRSAKey(FAKE_RSA_KEY_1); + public static final PrivateKey RSA_KEY1 = loadPrivateKey("RSA", FAKE_RSA_KEY_1); + + private static final String CA_SUITE_B_RSA3072_CERT_STRING = + "-----BEGIN CERTIFICATE-----\n" + + "MIIEnTCCAwWgAwIBAgIUD87Y8fFLzLr1HQ/64aEnjNq2R/4wDQYJKoZIhvcNAQEM\n" + + "BQAwXjELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAkNBMQwwCgYDVQQHDANNVFYxEDAO\n" + + "BgNVBAoMB0FuZHJvaWQxDjAMBgNVBAsMBVdpLUZpMRIwEAYDVQQDDAl1bml0ZXN0\n" + + "Q0EwHhcNMjAwNzIxMDIxNzU0WhcNMzAwNTMwMDIxNzU0WjBeMQswCQYDVQQGEwJV\n" + + "UzELMAkGA1UECAwCQ0ExDDAKBgNVBAcMA01UVjEQMA4GA1UECgwHQW5kcm9pZDEO\n" + + "MAwGA1UECwwFV2ktRmkxEjAQBgNVBAMMCXVuaXRlc3RDQTCCAaIwDQYJKoZIhvcN\n" + + "AQEBBQADggGPADCCAYoCggGBAMtrsT0otlxh0QS079KpRRbU1PQjCihSoltXnrxF\n" + + "sTWZs2weVEeYVyYU5LaauCDDgISCMtjtfbfylMBeYjpWB5hYzYQOiTzo0anWhMyb\n" + + "Ngb7gpMVZuIl6lwMYRyVRKwHWnTo2EUg1ZzW5rGe5fs/KHj6//hoNFm+3Oju0TQd\n" + + "nraQULpoERPF5B7p85Cssk8uNbviBfZXvtCuJ4N6w7PNceOY/9bbwc1mC+pPZmzV\n" + + "SOAg0vvbIQRzChm63C3jBC3xmxSOOZVrKN4zKDG2s8P0oCNGt0NlgRMrgbPRekzg\n" + + "4avkbA0vTuc2AyriTEYkdea/Mt4EpRg9XuOb43U/GJ/d/vQv2/9fsxhXmsZrn8kr\n" + + "Qo5MMHJFUd96GgHmvYSU3Mf/5r8gF626lvqHioGuTAuHUSnr02ri1WUxZ15LDRgY\n" + + "quMjDCFZfucjJPDAdtiHcFSej/4SLJlN39z8oKKNPn3aL9Gv49oAKs9S8tfDVzMk\n" + + "fDLROQFHFuW715GnnMgEAoOpRwIDAQABo1MwUTAdBgNVHQ4EFgQUeVuGmSVN4ARs\n" + + "mesUMWSJ2qWLbxUwHwYDVR0jBBgwFoAUeVuGmSVN4ARsmesUMWSJ2qWLbxUwDwYD\n" + + "VR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQwFAAOCAYEAit1Lo/hegZpPuT9dlWZJ\n" + + "bC8JvAf95O8lnn6LFb69pgYOHCLgCIlvYXu9rdBUJgZo+V1MzJJljiO6RxWRfKbQ\n" + + "8WBYkoqR1EqriR3Kn8q/SjIZCdFSaznTyU1wQMveBQ6RJWXSUhYVfE9RjyFTp7B4\n" + + "UyH2uCluR/0T06HQNGfH5XpIYQqCk1Zgng5lmEmheLDPoJpa92lKeQFJMC6eYz9g\n" + + "lF1GHxPxkPfbMJ6ZDp5X6Yopu6Q6uEXhVKM/iQVcgzRkx9rid+xTYl+nOKyK/XfC\n" + + "z8P0/TFIoPTW02DLge5wKagdoCpy1B7HdrAXyUjoH4B8MsUkq3kYPFSjPzScuTtV\n" + + "kUuDw5ipCNeXCRnhbYqRDk6PX5GUu2cmN9jtaH3tbgm3fKNOsd/BO1fLIl7qjXlR\n" + + "27HHbC0JXjNvlm2DLp23v4NTxS7WZGYsxyUj5DZrxBxqCsTXu/01w1BrQKWKh9FM\n" + + "aVrlA8omfVODK2CSuw+KhEMHepRv/AUgsLl4L4+RMoa+\n" + + "-----END CERTIFICATE-----\n"; + public static final X509Certificate CA_SUITE_B_RSA3072_CERT = + loadCertificate(CA_SUITE_B_RSA3072_CERT_STRING); + + private static final String CA_SUITE_B_ECDSA_CERT_STRING = + "-----BEGIN CERTIFICATE-----\n" + + "MIICTzCCAdSgAwIBAgIUdnLttwNPnQzFufplGOr9bTrGCqMwCgYIKoZIzj0EAwMw\n" + + "XjELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAkNBMQwwCgYDVQQHDANNVFYxEDAOBgNV\n" + + "BAoMB0FuZHJvaWQxDjAMBgNVBAsMBVdpLUZpMRIwEAYDVQQDDAl1bml0ZXN0Q0Ew\n" + + "HhcNMjAwNzIxMDIyNDA1WhcNMzAwNTMwMDIyNDA1WjBeMQswCQYDVQQGEwJVUzEL\n" + + "MAkGA1UECAwCQ0ExDDAKBgNVBAcMA01UVjEQMA4GA1UECgwHQW5kcm9pZDEOMAwG\n" + + "A1UECwwFV2ktRmkxEjAQBgNVBAMMCXVuaXRlc3RDQTB2MBAGByqGSM49AgEGBSuB\n" + + "BAAiA2IABFmntXwk9icqhDQFUP1xy04WyEpaGW4q6Q+8pujlSl/X3iotPZ++GZfp\n" + + "Mfv3YDHDBl6sELPQ2BEjyPXmpsKjOUdiUe69e88oGEdeqT2xXiQ6uzpTfJD4170i\n" + + "O/TwLrQGKKNTMFEwHQYDVR0OBBYEFCjptsX3g4g5W0L4oEP6N3gfyiZXMB8GA1Ud\n" + + "IwQYMBaAFCjptsX3g4g5W0L4oEP6N3gfyiZXMA8GA1UdEwEB/wQFMAMBAf8wCgYI\n" + + "KoZIzj0EAwMDaQAwZgIxAK61brUYRbLmQKiaEboZgrHtnPAcGo7Yzx3MwHecx3Dm\n" + + "5soIeLVYc8bPYN1pbhXW1gIxALdEe2sh03nBHyQH4adYoZungoCwt8mp/7sJFxou\n" + + "9UnRegyBgGzf74ROWdpZHzh+Pg==\n" + + "-----END CERTIFICATE-----\n"; + public static final X509Certificate CA_SUITE_B_ECDSA_CERT = + loadCertificate(CA_SUITE_B_ECDSA_CERT_STRING); private static final String CLIENT_SUITE_B_RSA3072_CERT_STRING = "-----BEGIN CERTIFICATE-----\n" @@ -243,6 +293,363 @@ public class FakeKeys { public static final X509Certificate CLIENT_SUITE_B_RSA3072_CERT = loadCertificate(CLIENT_SUITE_B_RSA3072_CERT_STRING); + private static final byte[] CLIENT_SUITE_B_RSA3072_KEY_DATA = new byte[]{ + (byte) 0x30, (byte) 0x82, (byte) 0x06, (byte) 0xfe, (byte) 0x02, (byte) 0x01, + (byte) 0x00, (byte) 0x30, (byte) 0x0d, (byte) 0x06, (byte) 0x09, (byte) 0x2a, + (byte) 0x86, (byte) 0x48, (byte) 0x86, (byte) 0xf7, (byte) 0x0d, (byte) 0x01, + (byte) 0x01, (byte) 0x01, (byte) 0x05, (byte) 0x00, (byte) 0x04, (byte) 0x82, + (byte) 0x06, (byte) 0xe8, (byte) 0x30, (byte) 0x82, (byte) 0x06, (byte) 0xe4, + (byte) 0x02, (byte) 0x01, (byte) 0x00, (byte) 0x02, (byte) 0x82, (byte) 0x01, + (byte) 0x81, (byte) 0x00, (byte) 0xc1, (byte) 0x22, (byte) 0xb7, (byte) 0x0b, + (byte) 0x92, (byte) 0xb9, (byte) 0xb9, (byte) 0xdb, (byte) 0x42, (byte) 0x29, + (byte) 0x39, (byte) 0xc4, (byte) 0xd7, (byte) 0x87, (byte) 0xbc, (byte) 0xcf, + (byte) 0x67, (byte) 0x19, (byte) 0xbf, (byte) 0x09, (byte) 0x81, (byte) 0xe1, + (byte) 0x77, (byte) 0xbe, (byte) 0x6b, (byte) 0xcf, (byte) 0xbb, (byte) 0x40, + (byte) 0xbb, (byte) 0x9d, (byte) 0x1e, (byte) 0x8a, (byte) 0x1c, (byte) 0xfe, + (byte) 0x54, (byte) 0x33, (byte) 0x0a, (byte) 0x58, (byte) 0x0a, (byte) 0xe0, + (byte) 0xc6, (byte) 0xd5, (byte) 0x50, (byte) 0x2d, (byte) 0x03, (byte) 0xdc, + (byte) 0x51, (byte) 0x3e, (byte) 0x53, (byte) 0x7d, (byte) 0x82, (byte) 0xef, + (byte) 0xc4, (byte) 0xb1, (byte) 0x2a, (byte) 0x84, (byte) 0xda, (byte) 0x45, + (byte) 0x6b, (byte) 0x6f, (byte) 0x3e, (byte) 0x63, (byte) 0x66, (byte) 0xf9, + (byte) 0x46, (byte) 0x85, (byte) 0x4f, (byte) 0xc2, (byte) 0xa4, (byte) 0xc3, + (byte) 0x25, (byte) 0x27, (byte) 0xa3, (byte) 0xf7, (byte) 0x6f, (byte) 0xfb, + (byte) 0x65, (byte) 0xc3, (byte) 0xa5, (byte) 0xdf, (byte) 0xf3, (byte) 0x01, + (byte) 0x14, (byte) 0x3e, (byte) 0xdc, (byte) 0x5c, (byte) 0x00, (byte) 0x7d, + (byte) 0x6a, (byte) 0x29, (byte) 0x02, (byte) 0x11, (byte) 0x32, (byte) 0x09, + (byte) 0x54, (byte) 0xb1, (byte) 0xc2, (byte) 0xc0, (byte) 0x9a, (byte) 0xfa, + (byte) 0xc9, (byte) 0x50, (byte) 0xe2, (byte) 0x3b, (byte) 0x91, (byte) 0x20, + (byte) 0xc2, (byte) 0x2e, (byte) 0x50, (byte) 0x2d, (byte) 0x4c, (byte) 0x9b, + (byte) 0x43, (byte) 0x5a, (byte) 0xa6, (byte) 0xd6, (byte) 0x72, (byte) 0x33, + (byte) 0x74, (byte) 0xe3, (byte) 0xfc, (byte) 0x80, (byte) 0x90, (byte) 0x11, + (byte) 0xfa, (byte) 0x64, (byte) 0xa3, (byte) 0xda, (byte) 0x95, (byte) 0x21, + (byte) 0xb8, (byte) 0x8a, (byte) 0xe9, (byte) 0xea, (byte) 0x09, (byte) 0x31, + (byte) 0x39, (byte) 0x18, (byte) 0xf0, (byte) 0x45, (byte) 0x9f, (byte) 0x02, + (byte) 0x7e, (byte) 0xd1, (byte) 0x4c, (byte) 0x57, (byte) 0x5f, (byte) 0x47, + (byte) 0x53, (byte) 0x8b, (byte) 0xb8, (byte) 0xed, (byte) 0x26, (byte) 0x54, + (byte) 0xe8, (byte) 0xe0, (byte) 0x2d, (byte) 0x6f, (byte) 0x7f, (byte) 0xfa, + (byte) 0xea, (byte) 0x58, (byte) 0xbf, (byte) 0xa8, (byte) 0x59, (byte) 0xd7, + (byte) 0xd9, (byte) 0xc0, (byte) 0x30, (byte) 0x0c, (byte) 0x70, (byte) 0xe1, + (byte) 0x04, (byte) 0xc9, (byte) 0xc7, (byte) 0xb9, (byte) 0x4b, (byte) 0xc0, + (byte) 0x02, (byte) 0xd7, (byte) 0xec, (byte) 0x1f, (byte) 0xad, (byte) 0x0d, + (byte) 0x83, (byte) 0x44, (byte) 0x64, (byte) 0x70, (byte) 0xea, (byte) 0x60, + (byte) 0xbd, (byte) 0xb3, (byte) 0xca, (byte) 0xf4, (byte) 0x16, (byte) 0x02, + (byte) 0x3d, (byte) 0x87, (byte) 0x0a, (byte) 0x57, (byte) 0xab, (byte) 0x7b, + (byte) 0xc4, (byte) 0x18, (byte) 0x20, (byte) 0xbc, (byte) 0x64, (byte) 0xbe, + (byte) 0x4b, (byte) 0x60, (byte) 0x06, (byte) 0x0d, (byte) 0x9c, (byte) 0xac, + (byte) 0x42, (byte) 0x49, (byte) 0x7b, (byte) 0x85, (byte) 0xdb, (byte) 0x0c, + (byte) 0x7e, (byte) 0xcb, (byte) 0x03, (byte) 0x7a, (byte) 0xeb, (byte) 0x5e, + (byte) 0x6b, (byte) 0x22, (byte) 0xa9, (byte) 0xfd, (byte) 0x59, (byte) 0x6d, + (byte) 0xf1, (byte) 0x45, (byte) 0x13, (byte) 0x32, (byte) 0xbd, (byte) 0x34, + (byte) 0x5a, (byte) 0xa8, (byte) 0xbc, (byte) 0xbf, (byte) 0xaa, (byte) 0x1a, + (byte) 0x1f, (byte) 0xb3, (byte) 0x20, (byte) 0xff, (byte) 0xb9, (byte) 0xf3, + (byte) 0xc4, (byte) 0xa1, (byte) 0x24, (byte) 0x53, (byte) 0xbd, (byte) 0x1f, + (byte) 0xf4, (byte) 0x43, (byte) 0x9c, (byte) 0x3a, (byte) 0x62, (byte) 0x4e, + (byte) 0x70, (byte) 0x05, (byte) 0x4d, (byte) 0x65, (byte) 0xd0, (byte) 0x75, + (byte) 0x3c, (byte) 0x20, (byte) 0xb3, (byte) 0x34, (byte) 0x92, (byte) 0xd1, + (byte) 0x5c, (byte) 0x36, (byte) 0x3c, (byte) 0x1f, (byte) 0x89, (byte) 0xa8, + (byte) 0x40, (byte) 0x01, (byte) 0x01, (byte) 0xaf, (byte) 0x43, (byte) 0x78, + (byte) 0xcb, (byte) 0xd7, (byte) 0x4f, (byte) 0x53, (byte) 0xb2, (byte) 0xf8, + (byte) 0xd6, (byte) 0x37, (byte) 0x22, (byte) 0xd3, (byte) 0xc7, (byte) 0xcb, + (byte) 0x2e, (byte) 0xb7, (byte) 0x9d, (byte) 0x06, (byte) 0x55, (byte) 0x23, + (byte) 0x6a, (byte) 0xd7, (byte) 0x00, (byte) 0xdc, (byte) 0x38, (byte) 0x36, + (byte) 0x1c, (byte) 0x12, (byte) 0xd1, (byte) 0x9e, (byte) 0x83, (byte) 0x17, + (byte) 0xe4, (byte) 0x2c, (byte) 0x4c, (byte) 0xda, (byte) 0xe3, (byte) 0xf8, + (byte) 0x65, (byte) 0x3b, (byte) 0x7b, (byte) 0x84, (byte) 0x86, (byte) 0xfc, + (byte) 0x41, (byte) 0x91, (byte) 0xf1, (byte) 0x2b, (byte) 0xe5, (byte) 0x76, + (byte) 0x36, (byte) 0x1f, (byte) 0x41, (byte) 0x35, (byte) 0x85, (byte) 0x2e, + (byte) 0x0d, (byte) 0x65, (byte) 0xfd, (byte) 0x44, (byte) 0xf5, (byte) 0x84, + (byte) 0xe3, (byte) 0xa4, (byte) 0x41, (byte) 0x9c, (byte) 0x1d, (byte) 0xb1, + (byte) 0xa5, (byte) 0xb5, (byte) 0xce, (byte) 0x02, (byte) 0xb2, (byte) 0x7a, + (byte) 0xe8, (byte) 0x85, (byte) 0x07, (byte) 0x62, (byte) 0x9d, (byte) 0x32, + (byte) 0x66, (byte) 0xc0, (byte) 0x4a, (byte) 0xaf, (byte) 0x94, (byte) 0xc7, + (byte) 0x52, (byte) 0xf5, (byte) 0x28, (byte) 0x80, (byte) 0xa8, (byte) 0xd0, + (byte) 0x88, (byte) 0x25, (byte) 0xc1, (byte) 0x67, (byte) 0x01, (byte) 0xff, + (byte) 0xc9, (byte) 0xe7, (byte) 0x02, (byte) 0x03, (byte) 0x01, (byte) 0x00, + (byte) 0x01, (byte) 0x02, (byte) 0x82, (byte) 0x01, (byte) 0x80, (byte) 0x04, + (byte) 0xb1, (byte) 0xcc, (byte) 0x53, (byte) 0x3a, (byte) 0xb0, (byte) 0xcb, + (byte) 0x04, (byte) 0xba, (byte) 0x59, (byte) 0xf8, (byte) 0x2e, (byte) 0x81, + (byte) 0xb2, (byte) 0xa9, (byte) 0xf3, (byte) 0x3c, (byte) 0xa5, (byte) 0x52, + (byte) 0x90, (byte) 0x6f, (byte) 0x98, (byte) 0xc4, (byte) 0x69, (byte) 0x5b, + (byte) 0x83, (byte) 0x84, (byte) 0x20, (byte) 0xb1, (byte) 0xae, (byte) 0xc3, + (byte) 0x04, (byte) 0x46, (byte) 0x6a, (byte) 0x24, (byte) 0x2f, (byte) 0xcd, + (byte) 0x6b, (byte) 0x90, (byte) 0x70, (byte) 0x20, (byte) 0x45, (byte) 0x25, + (byte) 0x1a, (byte) 0xc3, (byte) 0x02, (byte) 0x42, (byte) 0xf3, (byte) 0x49, + (byte) 0xe2, (byte) 0x3e, (byte) 0x21, (byte) 0x87, (byte) 0xdd, (byte) 0x6a, + (byte) 0x94, (byte) 0x2a, (byte) 0x1e, (byte) 0x0f, (byte) 0xdb, (byte) 0x77, + (byte) 0x5f, (byte) 0xc1, (byte) 0x2c, (byte) 0x03, (byte) 0xfb, (byte) 0xcf, + (byte) 0x91, (byte) 0x82, (byte) 0xa1, (byte) 0xbf, (byte) 0xb0, (byte) 0x73, + (byte) 0xfa, (byte) 0xda, (byte) 0xbc, (byte) 0xf8, (byte) 0x9f, (byte) 0x45, + (byte) 0xd3, (byte) 0xe8, (byte) 0xbb, (byte) 0x38, (byte) 0xfb, (byte) 0xc2, + (byte) 0x2d, (byte) 0x76, (byte) 0x51, (byte) 0x96, (byte) 0x18, (byte) 0x03, + (byte) 0x15, (byte) 0xd9, (byte) 0xea, (byte) 0x82, (byte) 0x25, (byte) 0x83, + (byte) 0xff, (byte) 0x5c, (byte) 0x85, (byte) 0x06, (byte) 0x09, (byte) 0xb2, + (byte) 0x46, (byte) 0x12, (byte) 0x64, (byte) 0x02, (byte) 0x74, (byte) 0x4f, + (byte) 0xbc, (byte) 0x9a, (byte) 0x25, (byte) 0x18, (byte) 0x01, (byte) 0x07, + (byte) 0x17, (byte) 0x25, (byte) 0x55, (byte) 0x7c, (byte) 0xdc, (byte) 0xe1, + (byte) 0xd1, (byte) 0x5a, (byte) 0x2f, (byte) 0x25, (byte) 0xaf, (byte) 0xf6, + (byte) 0x8f, (byte) 0xa4, (byte) 0x9a, (byte) 0x5a, (byte) 0x3a, (byte) 0xfe, + (byte) 0x2e, (byte) 0x93, (byte) 0x24, (byte) 0xa0, (byte) 0x27, (byte) 0xac, + (byte) 0x07, (byte) 0x75, (byte) 0x33, (byte) 0x01, (byte) 0x54, (byte) 0x23, + (byte) 0x0f, (byte) 0xe8, (byte) 0x9f, (byte) 0xfa, (byte) 0x36, (byte) 0xe6, + (byte) 0x3a, (byte) 0xd5, (byte) 0x78, (byte) 0xb0, (byte) 0xe4, (byte) 0x6a, + (byte) 0x16, (byte) 0x50, (byte) 0xbd, (byte) 0x0f, (byte) 0x9f, (byte) 0x32, + (byte) 0xa1, (byte) 0x6b, (byte) 0xf5, (byte) 0xa4, (byte) 0x34, (byte) 0x58, + (byte) 0xb6, (byte) 0xa4, (byte) 0xb3, (byte) 0xc3, (byte) 0x83, (byte) 0x08, + (byte) 0x18, (byte) 0xc7, (byte) 0xef, (byte) 0x95, (byte) 0xe2, (byte) 0x1b, + (byte) 0xba, (byte) 0x35, (byte) 0x61, (byte) 0xa3, (byte) 0xb4, (byte) 0x30, + (byte) 0xe0, (byte) 0xd1, (byte) 0xc1, (byte) 0xa2, (byte) 0x3a, (byte) 0xc6, + (byte) 0xb4, (byte) 0xd2, (byte) 0x80, (byte) 0x5a, (byte) 0xaf, (byte) 0xa4, + (byte) 0x54, (byte) 0x3c, (byte) 0x66, (byte) 0x5a, (byte) 0x1c, (byte) 0x4d, + (byte) 0xe1, (byte) 0xd9, (byte) 0x98, (byte) 0x44, (byte) 0x01, (byte) 0x1b, + (byte) 0x8c, (byte) 0xe9, (byte) 0x80, (byte) 0x54, (byte) 0x83, (byte) 0x3d, + (byte) 0x96, (byte) 0x25, (byte) 0x41, (byte) 0x1c, (byte) 0xad, (byte) 0xae, + (byte) 0x3b, (byte) 0x7a, (byte) 0xd7, (byte) 0x9d, (byte) 0x10, (byte) 0x7c, + (byte) 0xd1, (byte) 0xa7, (byte) 0x96, (byte) 0x39, (byte) 0xa5, (byte) 0x2f, + (byte) 0xbe, (byte) 0xc3, (byte) 0x2c, (byte) 0x64, (byte) 0x01, (byte) 0xfe, + (byte) 0xa2, (byte) 0xd1, (byte) 0x6a, (byte) 0xcf, (byte) 0x4c, (byte) 0x76, + (byte) 0x3b, (byte) 0xc8, (byte) 0x35, (byte) 0x21, (byte) 0xda, (byte) 0x98, + (byte) 0xcf, (byte) 0xf9, (byte) 0x29, (byte) 0xff, (byte) 0x30, (byte) 0x59, + (byte) 0x36, (byte) 0x53, (byte) 0x0b, (byte) 0xbb, (byte) 0xfa, (byte) 0xba, + (byte) 0xc4, (byte) 0x03, (byte) 0x23, (byte) 0xe0, (byte) 0xd3, (byte) 0x33, + (byte) 0xff, (byte) 0x32, (byte) 0xdb, (byte) 0x30, (byte) 0x64, (byte) 0xc7, + (byte) 0x56, (byte) 0xca, (byte) 0x55, (byte) 0x14, (byte) 0xee, (byte) 0x58, + (byte) 0xfe, (byte) 0x96, (byte) 0x7e, (byte) 0x1c, (byte) 0x34, (byte) 0x16, + (byte) 0xeb, (byte) 0x76, (byte) 0x26, (byte) 0x48, (byte) 0xe2, (byte) 0xe5, + (byte) 0x5c, (byte) 0xd5, (byte) 0x83, (byte) 0x37, (byte) 0xd9, (byte) 0x09, + (byte) 0x71, (byte) 0xbc, (byte) 0x54, (byte) 0x25, (byte) 0xca, (byte) 0x2e, + (byte) 0xdb, (byte) 0x36, (byte) 0x39, (byte) 0xcc, (byte) 0x3a, (byte) 0x81, + (byte) 0x95, (byte) 0x9e, (byte) 0xf4, (byte) 0x01, (byte) 0xa7, (byte) 0xc0, + (byte) 0x20, (byte) 0xce, (byte) 0x70, (byte) 0x55, (byte) 0x2c, (byte) 0xe0, + (byte) 0x93, (byte) 0x72, (byte) 0xa6, (byte) 0x25, (byte) 0xda, (byte) 0x64, + (byte) 0x19, (byte) 0x18, (byte) 0xd2, (byte) 0x31, (byte) 0xe2, (byte) 0x7c, + (byte) 0xf2, (byte) 0x30, (byte) 0x9e, (byte) 0x8d, (byte) 0xc6, (byte) 0x14, + (byte) 0x8a, (byte) 0x38, (byte) 0xf0, (byte) 0x94, (byte) 0xeb, (byte) 0xf4, + (byte) 0x64, (byte) 0x92, (byte) 0x3d, (byte) 0x67, (byte) 0xa6, (byte) 0x2c, + (byte) 0x52, (byte) 0xfc, (byte) 0x60, (byte) 0xca, (byte) 0x2a, (byte) 0xcf, + (byte) 0x24, (byte) 0xd5, (byte) 0x42, (byte) 0x5f, (byte) 0xc7, (byte) 0x9f, + (byte) 0xf3, (byte) 0xb4, (byte) 0xdf, (byte) 0x76, (byte) 0x6e, (byte) 0x53, + (byte) 0xa1, (byte) 0x7b, (byte) 0xae, (byte) 0xa5, (byte) 0x84, (byte) 0x1f, + (byte) 0xfa, (byte) 0xc0, (byte) 0xb4, (byte) 0x6c, (byte) 0xc9, (byte) 0x02, + (byte) 0x81, (byte) 0xc1, (byte) 0x00, (byte) 0xf3, (byte) 0x17, (byte) 0xd9, + (byte) 0x48, (byte) 0x17, (byte) 0x87, (byte) 0x84, (byte) 0x16, (byte) 0xea, + (byte) 0x2d, (byte) 0x31, (byte) 0x1b, (byte) 0xce, (byte) 0xec, (byte) 0xaf, + (byte) 0xdc, (byte) 0x6b, (byte) 0xaf, (byte) 0xc8, (byte) 0xf1, (byte) 0x40, + (byte) 0xa7, (byte) 0x4f, (byte) 0xef, (byte) 0x48, (byte) 0x08, (byte) 0x5e, + (byte) 0x9a, (byte) 0xd1, (byte) 0xc0, (byte) 0xb1, (byte) 0xfe, (byte) 0xe7, + (byte) 0x03, (byte) 0xd5, (byte) 0x96, (byte) 0x01, (byte) 0xe8, (byte) 0x40, + (byte) 0xca, (byte) 0x78, (byte) 0xcb, (byte) 0xb3, (byte) 0x28, (byte) 0x1a, + (byte) 0xf0, (byte) 0xe5, (byte) 0xf6, (byte) 0x46, (byte) 0xef, (byte) 0xcd, + (byte) 0x1a, (byte) 0x0f, (byte) 0x13, (byte) 0x2d, (byte) 0x38, (byte) 0xf8, + (byte) 0xf7, (byte) 0x88, (byte) 0x21, (byte) 0x15, (byte) 0xce, (byte) 0x48, + (byte) 0xf4, (byte) 0x92, (byte) 0x7e, (byte) 0x9b, (byte) 0x2e, (byte) 0x2f, + (byte) 0x22, (byte) 0x3e, (byte) 0x5c, (byte) 0x67, (byte) 0xd7, (byte) 0x58, + (byte) 0xf6, (byte) 0xef, (byte) 0x1f, (byte) 0xb4, (byte) 0x04, (byte) 0xc7, + (byte) 0xfd, (byte) 0x8c, (byte) 0x4e, (byte) 0x27, (byte) 0x9e, (byte) 0xb9, + (byte) 0xef, (byte) 0x0f, (byte) 0xf7, (byte) 0x4a, (byte) 0xc2, (byte) 0xf4, + (byte) 0x64, (byte) 0x6b, (byte) 0xe0, (byte) 0xfb, (byte) 0xe3, (byte) 0x45, + (byte) 0xd5, (byte) 0x37, (byte) 0xa0, (byte) 0x2a, (byte) 0xc6, (byte) 0xf3, + (byte) 0xf6, (byte) 0xcc, (byte) 0xb5, (byte) 0x94, (byte) 0xbf, (byte) 0x56, + (byte) 0xa0, (byte) 0x61, (byte) 0x36, (byte) 0x88, (byte) 0x35, (byte) 0xd5, + (byte) 0xa5, (byte) 0xad, (byte) 0x20, (byte) 0x48, (byte) 0xda, (byte) 0x70, + (byte) 0x35, (byte) 0xd9, (byte) 0x75, (byte) 0x66, (byte) 0xa5, (byte) 0xac, + (byte) 0x86, (byte) 0x7a, (byte) 0x75, (byte) 0x49, (byte) 0x88, (byte) 0x40, + (byte) 0xce, (byte) 0xb0, (byte) 0x6f, (byte) 0x57, (byte) 0x15, (byte) 0x54, + (byte) 0xd3, (byte) 0x2f, (byte) 0x11, (byte) 0x9b, (byte) 0xe3, (byte) 0x87, + (byte) 0xc8, (byte) 0x8d, (byte) 0x98, (byte) 0xc6, (byte) 0xe0, (byte) 0xbc, + (byte) 0x85, (byte) 0xb9, (byte) 0x04, (byte) 0x43, (byte) 0xa9, (byte) 0x41, + (byte) 0xce, (byte) 0x42, (byte) 0x1a, (byte) 0x57, (byte) 0x10, (byte) 0xd8, + (byte) 0xe4, (byte) 0x6a, (byte) 0x51, (byte) 0x10, (byte) 0x0a, (byte) 0xec, + (byte) 0xe4, (byte) 0x57, (byte) 0xc7, (byte) 0xee, (byte) 0xe9, (byte) 0xd6, + (byte) 0xcb, (byte) 0x3e, (byte) 0xba, (byte) 0xfa, (byte) 0xe9, (byte) 0x0e, + (byte) 0xed, (byte) 0x87, (byte) 0x04, (byte) 0x9a, (byte) 0x48, (byte) 0xba, + (byte) 0xaf, (byte) 0x08, (byte) 0xf5, (byte) 0x02, (byte) 0x81, (byte) 0xc1, + (byte) 0x00, (byte) 0xcb, (byte) 0x63, (byte) 0xd6, (byte) 0x54, (byte) 0xb6, + (byte) 0xf3, (byte) 0xf3, (byte) 0x8c, (byte) 0xf8, (byte) 0xd0, (byte) 0xd2, + (byte) 0x84, (byte) 0xc1, (byte) 0xf5, (byte) 0x12, (byte) 0xe0, (byte) 0x02, + (byte) 0x80, (byte) 0x42, (byte) 0x92, (byte) 0x4e, (byte) 0xa4, (byte) 0x5c, + (byte) 0xa5, (byte) 0x64, (byte) 0xec, (byte) 0xb7, (byte) 0xdc, (byte) 0xe0, + (byte) 0x2d, (byte) 0x5d, (byte) 0xac, (byte) 0x0e, (byte) 0x24, (byte) 0x48, + (byte) 0x13, (byte) 0x05, (byte) 0xe8, (byte) 0xff, (byte) 0x96, (byte) 0x93, + (byte) 0xba, (byte) 0x3c, (byte) 0x88, (byte) 0xcc, (byte) 0x80, (byte) 0xf9, + (byte) 0xdb, (byte) 0xa8, (byte) 0x4d, (byte) 0x86, (byte) 0x47, (byte) 0xc8, + (byte) 0xbf, (byte) 0x34, (byte) 0x2d, (byte) 0xda, (byte) 0xb6, (byte) 0x28, + (byte) 0xf0, (byte) 0x1e, (byte) 0xd2, (byte) 0x46, (byte) 0x0d, (byte) 0x6f, + (byte) 0x36, (byte) 0x8e, (byte) 0x84, (byte) 0xd8, (byte) 0xaf, (byte) 0xf7, + (byte) 0x69, (byte) 0x23, (byte) 0x77, (byte) 0xfb, (byte) 0xc5, (byte) 0x04, + (byte) 0x08, (byte) 0x18, (byte) 0xac, (byte) 0x85, (byte) 0x80, (byte) 0x87, + (byte) 0x1c, (byte) 0xfe, (byte) 0x8e, (byte) 0x5d, (byte) 0x00, (byte) 0x7f, + (byte) 0x5b, (byte) 0x33, (byte) 0xf5, (byte) 0xdf, (byte) 0x70, (byte) 0x81, + (byte) 0xad, (byte) 0x81, (byte) 0xf4, (byte) 0x5a, (byte) 0x37, (byte) 0x8a, + (byte) 0x79, (byte) 0x09, (byte) 0xc5, (byte) 0x55, (byte) 0xab, (byte) 0x58, + (byte) 0x7c, (byte) 0x47, (byte) 0xca, (byte) 0xa5, (byte) 0x80, (byte) 0x49, + (byte) 0x5f, (byte) 0x71, (byte) 0x83, (byte) 0xfb, (byte) 0x3b, (byte) 0x06, + (byte) 0xec, (byte) 0x75, (byte) 0x23, (byte) 0xc4, (byte) 0x32, (byte) 0xc7, + (byte) 0x18, (byte) 0xf6, (byte) 0x82, (byte) 0x95, (byte) 0x98, (byte) 0x39, + (byte) 0xf7, (byte) 0x92, (byte) 0x31, (byte) 0xc0, (byte) 0x89, (byte) 0xba, + (byte) 0xd4, (byte) 0xd4, (byte) 0x58, (byte) 0x4e, (byte) 0x38, (byte) 0x35, + (byte) 0x10, (byte) 0xb9, (byte) 0xf1, (byte) 0x27, (byte) 0xdc, (byte) 0xff, + (byte) 0xc7, (byte) 0xb2, (byte) 0xba, (byte) 0x1f, (byte) 0x27, (byte) 0xaf, + (byte) 0x99, (byte) 0xd5, (byte) 0xb0, (byte) 0x39, (byte) 0xe7, (byte) 0x43, + (byte) 0x88, (byte) 0xd3, (byte) 0xce, (byte) 0x38, (byte) 0xc2, (byte) 0x99, + (byte) 0x43, (byte) 0xfc, (byte) 0x8a, (byte) 0xe3, (byte) 0x60, (byte) 0x0d, + (byte) 0x0a, (byte) 0xb8, (byte) 0xc4, (byte) 0x29, (byte) 0xca, (byte) 0x0d, + (byte) 0x30, (byte) 0xaf, (byte) 0xca, (byte) 0xd0, (byte) 0xaa, (byte) 0x67, + (byte) 0xb1, (byte) 0xdd, (byte) 0xdb, (byte) 0x7a, (byte) 0x11, (byte) 0xad, + (byte) 0xeb, (byte) 0x02, (byte) 0x81, (byte) 0xc0, (byte) 0x71, (byte) 0xb8, + (byte) 0xcf, (byte) 0x72, (byte) 0x35, (byte) 0x67, (byte) 0xb5, (byte) 0x38, + (byte) 0x8f, (byte) 0x16, (byte) 0xd3, (byte) 0x29, (byte) 0x82, (byte) 0x35, + (byte) 0x21, (byte) 0xd4, (byte) 0x49, (byte) 0x20, (byte) 0x74, (byte) 0x2d, + (byte) 0xc0, (byte) 0xa4, (byte) 0x44, (byte) 0xf5, (byte) 0xd8, (byte) 0xc9, + (byte) 0xe9, (byte) 0x90, (byte) 0x1d, (byte) 0xde, (byte) 0x3a, (byte) 0xa6, + (byte) 0xd7, (byte) 0xe5, (byte) 0xe8, (byte) 0x4e, (byte) 0x83, (byte) 0xd7, + (byte) 0xe6, (byte) 0x2f, (byte) 0x92, (byte) 0x31, (byte) 0x21, (byte) 0x3f, + (byte) 0xfa, (byte) 0xd2, (byte) 0x85, (byte) 0x92, (byte) 0x1f, (byte) 0xff, + (byte) 0x61, (byte) 0x00, (byte) 0xf6, (byte) 0xda, (byte) 0x6e, (byte) 0xc6, + (byte) 0x7f, (byte) 0x5a, (byte) 0x35, (byte) 0x79, (byte) 0xdc, (byte) 0xdc, + (byte) 0xa3, (byte) 0x2e, (byte) 0x9f, (byte) 0x35, (byte) 0xd1, (byte) 0x5c, + (byte) 0xda, (byte) 0xb9, (byte) 0xf7, (byte) 0x58, (byte) 0x7d, (byte) 0x4f, + (byte) 0xb6, (byte) 0x13, (byte) 0xd7, (byte) 0x2c, (byte) 0x0a, (byte) 0xa8, + (byte) 0x4d, (byte) 0xf2, (byte) 0xe4, (byte) 0x67, (byte) 0x4f, (byte) 0x8b, + (byte) 0xa6, (byte) 0xca, (byte) 0x1a, (byte) 0xbb, (byte) 0x02, (byte) 0x63, + (byte) 0x8f, (byte) 0xb7, (byte) 0x46, (byte) 0xec, (byte) 0x7a, (byte) 0x8a, + (byte) 0x09, (byte) 0x0a, (byte) 0x45, (byte) 0x3a, (byte) 0x8d, (byte) 0xa8, + (byte) 0x83, (byte) 0x4b, (byte) 0x0a, (byte) 0xdb, (byte) 0x4b, (byte) 0x99, + (byte) 0xf3, (byte) 0x69, (byte) 0x95, (byte) 0xf0, (byte) 0xcf, (byte) 0xe9, + (byte) 0xf7, (byte) 0x67, (byte) 0xc9, (byte) 0x45, (byte) 0x18, (byte) 0x2f, + (byte) 0xf0, (byte) 0x5c, (byte) 0x90, (byte) 0xbd, (byte) 0xa6, (byte) 0x66, + (byte) 0x8c, (byte) 0xfe, (byte) 0x60, (byte) 0x5d, (byte) 0x6c, (byte) 0x27, + (byte) 0xec, (byte) 0xc1, (byte) 0x84, (byte) 0xb2, (byte) 0xa1, (byte) 0x97, + (byte) 0x9e, (byte) 0x16, (byte) 0x29, (byte) 0xa7, (byte) 0xe0, (byte) 0x38, + (byte) 0xa2, (byte) 0x36, (byte) 0x05, (byte) 0x5f, (byte) 0xda, (byte) 0x72, + (byte) 0x1a, (byte) 0x5f, (byte) 0xa8, (byte) 0x7d, (byte) 0x41, (byte) 0x35, + (byte) 0xf6, (byte) 0x4e, (byte) 0x0a, (byte) 0x88, (byte) 0x8e, (byte) 0x00, + (byte) 0x98, (byte) 0xa6, (byte) 0xca, (byte) 0xc1, (byte) 0xdf, (byte) 0x72, + (byte) 0x6c, (byte) 0xfe, (byte) 0x29, (byte) 0xbe, (byte) 0xa3, (byte) 0x9b, + (byte) 0x0b, (byte) 0x5c, (byte) 0x0b, (byte) 0x9d, (byte) 0xa7, (byte) 0x71, + (byte) 0xce, (byte) 0x04, (byte) 0xfa, (byte) 0xac, (byte) 0x01, (byte) 0x8d, + (byte) 0x52, (byte) 0xa0, (byte) 0x3d, (byte) 0xdd, (byte) 0x02, (byte) 0x81, + (byte) 0xc1, (byte) 0x00, (byte) 0xc1, (byte) 0xc0, (byte) 0x2e, (byte) 0xa9, + (byte) 0xee, (byte) 0xca, (byte) 0xff, (byte) 0xe4, (byte) 0xf8, (byte) 0x15, + (byte) 0xfd, (byte) 0xa5, (byte) 0x68, (byte) 0x1b, (byte) 0x2d, (byte) 0x4a, + (byte) 0xe6, (byte) 0x37, (byte) 0x06, (byte) 0xb3, (byte) 0xd7, (byte) 0x64, + (byte) 0xad, (byte) 0xb9, (byte) 0x05, (byte) 0x26, (byte) 0x97, (byte) 0x94, + (byte) 0x3a, (byte) 0x9e, (byte) 0x1c, (byte) 0xd0, (byte) 0xcd, (byte) 0x7b, + (byte) 0xf4, (byte) 0x88, (byte) 0xe2, (byte) 0xa5, (byte) 0x6d, (byte) 0xed, + (byte) 0x24, (byte) 0x77, (byte) 0x52, (byte) 0x39, (byte) 0x43, (byte) 0x0f, + (byte) 0x4e, (byte) 0x75, (byte) 0xd8, (byte) 0xa3, (byte) 0x59, (byte) 0x5a, + (byte) 0xc2, (byte) 0xba, (byte) 0x9a, (byte) 0x5b, (byte) 0x60, (byte) 0x31, + (byte) 0x0d, (byte) 0x58, (byte) 0x89, (byte) 0x13, (byte) 0xe8, (byte) 0x95, + (byte) 0xdd, (byte) 0xae, (byte) 0xcc, (byte) 0x1f, (byte) 0x73, (byte) 0x48, + (byte) 0x55, (byte) 0xd8, (byte) 0xfb, (byte) 0x67, (byte) 0xce, (byte) 0x18, + (byte) 0x85, (byte) 0x59, (byte) 0xad, (byte) 0x1f, (byte) 0x93, (byte) 0xe1, + (byte) 0xb7, (byte) 0x54, (byte) 0x80, (byte) 0x8e, (byte) 0x5f, (byte) 0xbc, + (byte) 0x1c, (byte) 0x96, (byte) 0x66, (byte) 0x2e, (byte) 0x40, (byte) 0x17, + (byte) 0x2e, (byte) 0x01, (byte) 0x7a, (byte) 0x7d, (byte) 0xaa, (byte) 0xff, + (byte) 0xa3, (byte) 0xd2, (byte) 0xdf, (byte) 0xe2, (byte) 0xf3, (byte) 0x54, + (byte) 0x51, (byte) 0xeb, (byte) 0xba, (byte) 0x7c, (byte) 0x2a, (byte) 0x22, + (byte) 0xc6, (byte) 0x42, (byte) 0xbc, (byte) 0xa1, (byte) 0x6c, (byte) 0xcf, + (byte) 0x73, (byte) 0x2e, (byte) 0x07, (byte) 0xfc, (byte) 0xf5, (byte) 0x67, + (byte) 0x25, (byte) 0xd0, (byte) 0xfa, (byte) 0xeb, (byte) 0xb4, (byte) 0xd4, + (byte) 0x19, (byte) 0xcc, (byte) 0x64, (byte) 0xa1, (byte) 0x2e, (byte) 0x78, + (byte) 0x45, (byte) 0xd9, (byte) 0x7f, (byte) 0x1b, (byte) 0x4c, (byte) 0x10, + (byte) 0x31, (byte) 0x44, (byte) 0xe8, (byte) 0xcc, (byte) 0xf9, (byte) 0x1b, + (byte) 0x87, (byte) 0x31, (byte) 0xd6, (byte) 0x69, (byte) 0x85, (byte) 0x4a, + (byte) 0x49, (byte) 0xf6, (byte) 0xb2, (byte) 0xe0, (byte) 0xb8, (byte) 0x98, + (byte) 0x3c, (byte) 0xf6, (byte) 0x78, (byte) 0x46, (byte) 0xc8, (byte) 0x3d, + (byte) 0x60, (byte) 0xc1, (byte) 0xaa, (byte) 0x2f, (byte) 0x28, (byte) 0xa1, + (byte) 0x14, (byte) 0x6b, (byte) 0x75, (byte) 0x4d, (byte) 0xb1, (byte) 0x3d, + (byte) 0x80, (byte) 0x49, (byte) 0x33, (byte) 0xfd, (byte) 0x71, (byte) 0xc0, + (byte) 0x13, (byte) 0x1e, (byte) 0x16, (byte) 0x69, (byte) 0x80, (byte) 0xa4, + (byte) 0x9c, (byte) 0xd7, (byte) 0x02, (byte) 0x81, (byte) 0xc1, (byte) 0x00, + (byte) 0x8c, (byte) 0x33, (byte) 0x2d, (byte) 0xd9, (byte) 0xf3, (byte) 0x42, + (byte) 0x4d, (byte) 0xca, (byte) 0x5e, (byte) 0x60, (byte) 0x14, (byte) 0x10, + (byte) 0xf6, (byte) 0xf3, (byte) 0x71, (byte) 0x15, (byte) 0x88, (byte) 0x54, + (byte) 0x84, (byte) 0x21, (byte) 0x04, (byte) 0xb1, (byte) 0xaf, (byte) 0x02, + (byte) 0x11, (byte) 0x7f, (byte) 0x42, (byte) 0x3e, (byte) 0x86, (byte) 0xcb, + (byte) 0x6c, (byte) 0xf5, (byte) 0x57, (byte) 0x78, (byte) 0x4a, (byte) 0x03, + (byte) 0x9b, (byte) 0x80, (byte) 0xc2, (byte) 0x04, (byte) 0x3a, (byte) 0x6b, + (byte) 0xb3, (byte) 0x30, (byte) 0x31, (byte) 0x7e, (byte) 0xc3, (byte) 0x89, + (byte) 0x09, (byte) 0x4e, (byte) 0x86, (byte) 0x59, (byte) 0x41, (byte) 0xb5, + (byte) 0xae, (byte) 0xd5, (byte) 0xc6, (byte) 0x38, (byte) 0xbc, (byte) 0xd7, + (byte) 0xd7, (byte) 0x8e, (byte) 0xa3, (byte) 0x1a, (byte) 0xde, (byte) 0x32, + (byte) 0xad, (byte) 0x8d, (byte) 0x15, (byte) 0x81, (byte) 0xfe, (byte) 0xac, + (byte) 0xbd, (byte) 0xd0, (byte) 0xca, (byte) 0xbc, (byte) 0xd8, (byte) 0x6a, + (byte) 0xe1, (byte) 0xfe, (byte) 0xda, (byte) 0xc4, (byte) 0xd8, (byte) 0x62, + (byte) 0x71, (byte) 0x20, (byte) 0xa3, (byte) 0xd3, (byte) 0x06, (byte) 0x11, + (byte) 0xa9, (byte) 0x53, (byte) 0x7a, (byte) 0x44, (byte) 0x89, (byte) 0x3d, + (byte) 0x28, (byte) 0x5e, (byte) 0x7d, (byte) 0xf0, (byte) 0x60, (byte) 0xeb, + (byte) 0xb5, (byte) 0xdf, (byte) 0xed, (byte) 0x4f, (byte) 0x6d, (byte) 0x05, + (byte) 0x59, (byte) 0x06, (byte) 0xb0, (byte) 0x62, (byte) 0x50, (byte) 0x1c, + (byte) 0xb7, (byte) 0x2c, (byte) 0x44, (byte) 0xa4, (byte) 0x49, (byte) 0xf8, + (byte) 0x4f, (byte) 0x4b, (byte) 0xab, (byte) 0x71, (byte) 0x5b, (byte) 0xcb, + (byte) 0x31, (byte) 0x10, (byte) 0x41, (byte) 0xe0, (byte) 0x1a, (byte) 0x15, + (byte) 0xdc, (byte) 0x4c, (byte) 0x5d, (byte) 0x4f, (byte) 0x62, (byte) 0x83, + (byte) 0xa4, (byte) 0x80, (byte) 0x06, (byte) 0x36, (byte) 0xba, (byte) 0xc9, + (byte) 0xe2, (byte) 0xa4, (byte) 0x11, (byte) 0x98, (byte) 0x6b, (byte) 0x4c, + (byte) 0xe9, (byte) 0x90, (byte) 0x55, (byte) 0x18, (byte) 0xde, (byte) 0xe1, + (byte) 0x42, (byte) 0x38, (byte) 0x28, (byte) 0xa3, (byte) 0x54, (byte) 0x56, + (byte) 0x31, (byte) 0xaf, (byte) 0x5a, (byte) 0xd6, (byte) 0xf0, (byte) 0x26, + (byte) 0xe0, (byte) 0x7a, (byte) 0xd9, (byte) 0x6c, (byte) 0x64, (byte) 0xca, + (byte) 0x5d, (byte) 0x6d, (byte) 0x3d, (byte) 0x9a, (byte) 0xfe, (byte) 0x36, + (byte) 0x93, (byte) 0x9e, (byte) 0x62, (byte) 0x94, (byte) 0xc6, (byte) 0x07, + (byte) 0x83, (byte) 0x96, (byte) 0xd6, (byte) 0x27, (byte) 0xa6, (byte) 0xd8 + }; + public static final PrivateKey CLIENT_SUITE_B_RSA3072_KEY = + loadPrivateKey("RSA", CLIENT_SUITE_B_RSA3072_KEY_DATA); + + private static final String CLIENT_SUITE_B_ECDSA_CERT_STRING = + "-----BEGIN CERTIFICATE-----\n" + + "MIIB9zCCAX4CFDpfSZh3AH07BEfGWuMDa7Ynz6y+MAoGCCqGSM49BAMDMF4xCzAJ\n" + + "BgNVBAYTAlVTMQswCQYDVQQIDAJDQTEMMAoGA1UEBwwDTVRWMRAwDgYDVQQKDAdB\n" + + "bmRyb2lkMQ4wDAYDVQQLDAVXaS1GaTESMBAGA1UEAwwJdW5pdGVzdENBMB4XDTIw\n" + + "MDcyMTAyMjk1MFoXDTMwMDUzMDAyMjk1MFowYjELMAkGA1UEBhMCVVMxCzAJBgNV\n" + + "BAgMAkNBMQwwCgYDVQQHDANNVFYxEDAOBgNVBAoMB0FuZHJvaWQxDjAMBgNVBAsM\n" + + "BVdpLUZpMRYwFAYDVQQDDA11bml0ZXN0Q2xpZW50MHYwEAYHKoZIzj0CAQYFK4EE\n" + + "ACIDYgAEhxhVJ7dcSqrto0X+dgRxtd8BWG8cWmPjBji3MIxDLfpcMDoIB84ae1Ew\n" + + "gJn4YUYHrWsUDiVNihv8j7a/Ol1qcIY2ybH7tbezefLmagqA4vXEUXZXoUyL4ZNC\n" + + "DWcdw6LrMAoGCCqGSM49BAMDA2cAMGQCMH4aP73HrriRUJRguiuRic+X4Cqj/7YQ\n" + + "ueJmP87KF92/thhoQ9OrRo8uJITPmNDswwIwP2Q1AZCSL4BI9dYrqu07Ar+pSkXE\n" + + "R7oOqGdZR+d/MvXcFSrbIaLKEoHXmQamIHLe\n" + + "-----END CERTIFICATE-----\n"; + public static final X509Certificate CLIENT_SUITE_B_ECDSA_CERT = + loadCertificate(CLIENT_SUITE_B_ECDSA_CERT_STRING); + + private static final byte[] CLIENT_SUITE_B_ECC_KEY_DATA = new byte[]{ + (byte) 0x30, (byte) 0x81, (byte) 0xb6, (byte) 0x02, (byte) 0x01, (byte) 0x00, + (byte) 0x30, (byte) 0x10, (byte) 0x06, (byte) 0x07, (byte) 0x2a, (byte) 0x86, + (byte) 0x48, (byte) 0xce, (byte) 0x3d, (byte) 0x02, (byte) 0x01, (byte) 0x06, + (byte) 0x05, (byte) 0x2b, (byte) 0x81, (byte) 0x04, (byte) 0x00, (byte) 0x22, + (byte) 0x04, (byte) 0x81, (byte) 0x9e, (byte) 0x30, (byte) 0x81, (byte) 0x9b, + (byte) 0x02, (byte) 0x01, (byte) 0x01, (byte) 0x04, (byte) 0x30, (byte) 0xea, + (byte) 0x6c, (byte) 0x4b, (byte) 0x6d, (byte) 0x43, (byte) 0xf9, (byte) 0x6c, + (byte) 0x91, (byte) 0xdc, (byte) 0x2d, (byte) 0x6e, (byte) 0x87, (byte) 0x4f, + (byte) 0x0a, (byte) 0x0b, (byte) 0x97, (byte) 0x25, (byte) 0x1c, (byte) 0x79, + (byte) 0xa2, (byte) 0x07, (byte) 0xdc, (byte) 0x94, (byte) 0xc2, (byte) 0xee, + (byte) 0x64, (byte) 0x51, (byte) 0x6d, (byte) 0x4e, (byte) 0x35, (byte) 0x1c, + (byte) 0x22, (byte) 0x2f, (byte) 0xc0, (byte) 0xea, (byte) 0x09, (byte) 0x47, + (byte) 0x3e, (byte) 0xb9, (byte) 0xb6, (byte) 0xb8, (byte) 0x83, (byte) 0x9e, + (byte) 0xed, (byte) 0x59, (byte) 0xe5, (byte) 0xe7, (byte) 0x0f, (byte) 0xa1, + (byte) 0x64, (byte) 0x03, (byte) 0x62, (byte) 0x00, (byte) 0x04, (byte) 0x87, + (byte) 0x18, (byte) 0x55, (byte) 0x27, (byte) 0xb7, (byte) 0x5c, (byte) 0x4a, + (byte) 0xaa, (byte) 0xed, (byte) 0xa3, (byte) 0x45, (byte) 0xfe, (byte) 0x76, + (byte) 0x04, (byte) 0x71, (byte) 0xb5, (byte) 0xdf, (byte) 0x01, (byte) 0x58, + (byte) 0x6f, (byte) 0x1c, (byte) 0x5a, (byte) 0x63, (byte) 0xe3, (byte) 0x06, + (byte) 0x38, (byte) 0xb7, (byte) 0x30, (byte) 0x8c, (byte) 0x43, (byte) 0x2d, + (byte) 0xfa, (byte) 0x5c, (byte) 0x30, (byte) 0x3a, (byte) 0x08, (byte) 0x07, + (byte) 0xce, (byte) 0x1a, (byte) 0x7b, (byte) 0x51, (byte) 0x30, (byte) 0x80, + (byte) 0x99, (byte) 0xf8, (byte) 0x61, (byte) 0x46, (byte) 0x07, (byte) 0xad, + (byte) 0x6b, (byte) 0x14, (byte) 0x0e, (byte) 0x25, (byte) 0x4d, (byte) 0x8a, + (byte) 0x1b, (byte) 0xfc, (byte) 0x8f, (byte) 0xb6, (byte) 0xbf, (byte) 0x3a, + (byte) 0x5d, (byte) 0x6a, (byte) 0x70, (byte) 0x86, (byte) 0x36, (byte) 0xc9, + (byte) 0xb1, (byte) 0xfb, (byte) 0xb5, (byte) 0xb7, (byte) 0xb3, (byte) 0x79, + (byte) 0xf2, (byte) 0xe6, (byte) 0x6a, (byte) 0x0a, (byte) 0x80, (byte) 0xe2, + (byte) 0xf5, (byte) 0xc4, (byte) 0x51, (byte) 0x76, (byte) 0x57, (byte) 0xa1, + (byte) 0x4c, (byte) 0x8b, (byte) 0xe1, (byte) 0x93, (byte) 0x42, (byte) 0x0d, + (byte) 0x67, (byte) 0x1d, (byte) 0xc3, (byte) 0xa2, (byte) 0xeb + }; + public static final PrivateKey CLIENT_SUITE_B_ECC_KEY = + loadPrivateKey("EC", CLIENT_SUITE_B_ECC_KEY_DATA); + private static X509Certificate loadCertificate(String blob) { try { final CertificateFactory certFactory = CertificateFactory.getInstance("X.509"); @@ -255,9 +662,9 @@ public class FakeKeys { } } - private static PrivateKey loadPrivateRSAKey(byte[] fakeKey) { + private static PrivateKey loadPrivateKey(String algorithm, byte[] fakeKey) { try { - KeyFactory kf = KeyFactory.getInstance("RSA"); + KeyFactory kf = KeyFactory.getInstance(algorithm); return kf.generatePrivate(new PKCS8EncodedKeySpec(fakeKey)); } catch (InvalidKeySpecException | NoSuchAlgorithmException e) { return null; diff --git a/wifi/tests/src/android/net/wifi/WifiConfigurationTest.java b/wifi/tests/src/android/net/wifi/WifiConfigurationTest.java index a7b6765e886a..62220a6237b1 100644 --- a/wifi/tests/src/android/net/wifi/WifiConfigurationTest.java +++ b/wifi/tests/src/android/net/wifi/WifiConfigurationTest.java @@ -22,6 +22,7 @@ import static android.net.wifi.WifiConfiguration.SECURITY_TYPE_OPEN; import static android.net.wifi.WifiConfiguration.SECURITY_TYPE_OWE; import static android.net.wifi.WifiConfiguration.SECURITY_TYPE_PSK; import static android.net.wifi.WifiConfiguration.SECURITY_TYPE_SAE; +import static android.net.wifi.WifiConfiguration.SECURITY_TYPE_WAPI_CERT; import static android.net.wifi.WifiConfiguration.SECURITY_TYPE_WAPI_PSK; import static org.junit.Assert.assertArrayEquals; @@ -537,4 +538,52 @@ public class WifiConfigurationTest { configuration.setSecurityParams(SECURITY_TYPE_EAP_SUITE_B); assertFalse(configuration.needsPreSharedKey()); } + + @Test + public void testGetAuthType() throws Exception { + WifiConfiguration configuration = new WifiConfiguration(); + + configuration.setSecurityParams(SECURITY_TYPE_PSK); + assertEquals(KeyMgmt.WPA_PSK, configuration.getAuthType()); + + configuration.setSecurityParams(SECURITY_TYPE_SAE); + assertEquals(KeyMgmt.SAE, configuration.getAuthType()); + + configuration.setSecurityParams(SECURITY_TYPE_WAPI_PSK); + assertEquals(KeyMgmt.WAPI_PSK, configuration.getAuthType()); + + configuration.setSecurityParams(SECURITY_TYPE_OPEN); + assertEquals(KeyMgmt.NONE, configuration.getAuthType()); + + configuration.setSecurityParams(SECURITY_TYPE_OWE); + assertEquals(KeyMgmt.OWE, configuration.getAuthType()); + + configuration.setSecurityParams(SECURITY_TYPE_EAP); + assertEquals(KeyMgmt.WPA_EAP, configuration.getAuthType()); + + configuration.setSecurityParams(SECURITY_TYPE_EAP_SUITE_B); + assertEquals(KeyMgmt.SUITE_B_192, configuration.getAuthType()); + + configuration.setSecurityParams(SECURITY_TYPE_WAPI_CERT); + assertEquals(KeyMgmt.WAPI_CERT, configuration.getAuthType()); + } + + @Test (expected = IllegalStateException.class) + public void testGetAuthTypeFailure1() throws Exception { + WifiConfiguration configuration = new WifiConfiguration(); + + configuration.setSecurityParams(SECURITY_TYPE_PSK); + configuration.allowedKeyManagement.set(KeyMgmt.IEEE8021X); + configuration.getAuthType(); + } + + @Test (expected = IllegalStateException.class) + public void testGetAuthTypeFailure2() throws Exception { + WifiConfiguration configuration = new WifiConfiguration(); + + configuration.allowedKeyManagement.set(KeyMgmt.IEEE8021X); + configuration.allowedKeyManagement.set(KeyMgmt.WPA_EAP); + configuration.allowedKeyManagement.set(KeyMgmt.SAE); + configuration.getAuthType(); + } } diff --git a/wifi/tests/src/android/net/wifi/WifiNetworkSpecifierTest.java b/wifi/tests/src/android/net/wifi/WifiNetworkSpecifierTest.java index fc0ef469ad80..6f47f3da710f 100644 --- a/wifi/tests/src/android/net/wifi/WifiNetworkSpecifierTest.java +++ b/wifi/tests/src/android/net/wifi/WifiNetworkSpecifierTest.java @@ -22,6 +22,8 @@ import static android.os.PatternMatcher.PATTERN_SIMPLE_GLOB; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; import android.net.MacAddress; @@ -35,6 +37,8 @@ import androidx.test.filters.SmallTest; import org.junit.Test; +import java.security.cert.X509Certificate; + /** * Unit tests for {@link android.net.wifi.WifiNetworkSpecifier}. */ @@ -45,6 +49,7 @@ public class WifiNetworkSpecifierTest { private static final String TEST_BSSID_OUI_MASK = "ff:ff:ff:00:00:00"; private static final String TEST_BSSID = "12:12:12:12:12:12"; private static final String TEST_PRESHARED_KEY = "\"Test123\""; + private static final String TEST_DOMAIN_SUFFIX_MATCH = "domainSuffixMatch"; /** * Validate correctness of WifiNetworkSpecifier object created by @@ -135,6 +140,106 @@ public class WifiNetworkSpecifierTest { wifiNetworkSpecifier.wifiConfiguration.enterpriseConfig.getPhase2Method()); } + /** + * Validate correctness of WifiNetworkSuggestion object created by + * {@link WifiNetworkSuggestion.Builder#build()} for WPA3-Enterprise network. + */ + @Test + public void testWifiNetworkSuggestionBuilderForWpa3EapNetwork() { + WifiEnterpriseConfig enterpriseConfig = new WifiEnterpriseConfig(); + enterpriseConfig.setEapMethod(WifiEnterpriseConfig.Eap.TLS); + enterpriseConfig.setCaCertificate(FakeKeys.CA_CERT0); + enterpriseConfig.setDomainSuffixMatch(TEST_DOMAIN_SUFFIX_MATCH); + + NetworkSpecifier specifier = new WifiNetworkSpecifier.Builder() + .setSsid(TEST_SSID) + .setWpa3EnterpriseConfig(enterpriseConfig) + .build(); + + assertTrue(specifier instanceof WifiNetworkSpecifier); + WifiNetworkSpecifier wifiNetworkSpecifier = (WifiNetworkSpecifier) specifier; + + assertEquals("\"" + TEST_SSID + "\"", wifiNetworkSpecifier.wifiConfiguration.SSID); + assertTrue(wifiNetworkSpecifier.wifiConfiguration.allowedKeyManagement + .get(WifiConfiguration.KeyMgmt.IEEE8021X)); + assertTrue(wifiNetworkSpecifier.wifiConfiguration.allowedKeyManagement + .get(WifiConfiguration.KeyMgmt.WPA_EAP)); + assertFalse(wifiNetworkSpecifier.wifiConfiguration.allowedKeyManagement + .get(WifiConfiguration.KeyMgmt.SUITE_B_192)); + assertTrue(wifiNetworkSpecifier.wifiConfiguration.allowedGroupCiphers + .get(WifiConfiguration.GroupCipher.CCMP)); + assertTrue(wifiNetworkSpecifier.wifiConfiguration.requirePmf); + assertNull(wifiNetworkSpecifier.wifiConfiguration.preSharedKey); + assertNotNull(wifiNetworkSpecifier.wifiConfiguration.enterpriseConfig); + } + + /** + * Validate correctness of WifiNetworkSuggestion object created by + * {@link WifiNetworkSuggestion.Builder#build()} for WPA3-Enterprise 192-bit RSA SuiteB network. + */ + @Test + public void testWifiNetworkSuggestionBuilderForWpa3SuiteBRsaEapNetwork() { + WifiEnterpriseConfig enterpriseConfig = new WifiEnterpriseConfig(); + enterpriseConfig.setEapMethod(WifiEnterpriseConfig.Eap.TLS); + enterpriseConfig.setCaCertificate(FakeKeys.CA_SUITE_B_RSA3072_CERT); + enterpriseConfig.setClientKeyEntryWithCertificateChain(FakeKeys.CLIENT_SUITE_B_RSA3072_KEY, + new X509Certificate[] {FakeKeys.CLIENT_SUITE_B_RSA3072_CERT}); + + enterpriseConfig.setDomainSuffixMatch(TEST_DOMAIN_SUFFIX_MATCH); + + NetworkSpecifier specifier = new WifiNetworkSpecifier.Builder() + .setSsid(TEST_SSID) + .setWpa3EnterpriseConfig(enterpriseConfig) + .build(); + + assertTrue(specifier instanceof WifiNetworkSpecifier); + WifiNetworkSpecifier wifiNetworkSpecifier = (WifiNetworkSpecifier) specifier; + + assertEquals("\"" + TEST_SSID + "\"", wifiNetworkSpecifier.wifiConfiguration.SSID); + assertTrue(wifiNetworkSpecifier.wifiConfiguration.allowedKeyManagement + .get(WifiConfiguration.KeyMgmt.SUITE_B_192)); + assertTrue(wifiNetworkSpecifier.wifiConfiguration.allowedGroupCiphers + .get(WifiConfiguration.GroupCipher.GCMP_256)); + assertTrue(wifiNetworkSpecifier.wifiConfiguration.allowedGroupManagementCiphers + .get(WifiConfiguration.GroupMgmtCipher.BIP_GMAC_256)); + assertTrue(wifiNetworkSpecifier.wifiConfiguration.requirePmf); + assertNull(wifiNetworkSpecifier.wifiConfiguration.preSharedKey); + assertNotNull(wifiNetworkSpecifier.wifiConfiguration.enterpriseConfig); + } + + /** + * Validate correctness of WifiNetworkSuggestion object created by + * {@link WifiNetworkSuggestion.Builder#build()} for WPA3-Enterprise 192-bit ECC SuiteB network. + */ + @Test + public void testWifiNetworkSuggestionBuilderForWpa3SuiteBEccEapNetwork() { + WifiEnterpriseConfig enterpriseConfig = new WifiEnterpriseConfig(); + enterpriseConfig.setEapMethod(WifiEnterpriseConfig.Eap.TLS); + enterpriseConfig.setCaCertificate(FakeKeys.CA_SUITE_B_ECDSA_CERT); + enterpriseConfig.setClientKeyEntryWithCertificateChain(FakeKeys.CLIENT_SUITE_B_ECC_KEY, + new X509Certificate[] {FakeKeys.CLIENT_SUITE_B_ECDSA_CERT}); + + enterpriseConfig.setDomainSuffixMatch(TEST_DOMAIN_SUFFIX_MATCH); + + NetworkSpecifier specifier = new WifiNetworkSpecifier.Builder() + .setSsid(TEST_SSID) + .setWpa3EnterpriseConfig(enterpriseConfig) + .build(); + + assertTrue(specifier instanceof WifiNetworkSpecifier); + WifiNetworkSpecifier wifiNetworkSpecifier = (WifiNetworkSpecifier) specifier; + + assertEquals("\"" + TEST_SSID + "\"", wifiNetworkSpecifier.wifiConfiguration.SSID); + assertTrue(wifiNetworkSpecifier.wifiConfiguration.allowedKeyManagement + .get(WifiConfiguration.KeyMgmt.SUITE_B_192)); + assertTrue(wifiNetworkSpecifier.wifiConfiguration.allowedGroupCiphers + .get(WifiConfiguration.GroupCipher.GCMP_256)); + assertTrue(wifiNetworkSpecifier.wifiConfiguration.allowedGroupManagementCiphers + .get(WifiConfiguration.GroupMgmtCipher.BIP_GMAC_256)); + assertTrue(wifiNetworkSpecifier.wifiConfiguration.requirePmf); + assertNull(wifiNetworkSpecifier.wifiConfiguration.preSharedKey); + assertNotNull(wifiNetworkSpecifier.wifiConfiguration.enterpriseConfig); + } /** * Ensure {@link WifiNetworkSpecifier.Builder#setSsid(String)} throws an exception diff --git a/wifi/tests/src/android/net/wifi/WifiNetworkSuggestionTest.java b/wifi/tests/src/android/net/wifi/WifiNetworkSuggestionTest.java index 7d5a45216fc4..abb9ce676262 100644 --- a/wifi/tests/src/android/net/wifi/WifiNetworkSuggestionTest.java +++ b/wifi/tests/src/android/net/wifi/WifiNetworkSuggestionTest.java @@ -32,6 +32,8 @@ import androidx.test.filters.SmallTest; import org.junit.Test; +import java.security.cert.X509Certificate; + /** * Unit tests for {@link android.net.wifi.WifiNetworkSuggestion}. */ @@ -212,16 +214,14 @@ public class WifiNetworkSuggestionTest { assertNull(suggestion.getEnterpriseConfig()); } - /** * Validate correctness of WifiNetworkSuggestion object created by - * {@link WifiNetworkSuggestion.Builder#build()} for SuiteB network. + * {@link WifiNetworkSuggestion.Builder#build()} for WPA3-Enterprise network. */ @Test public void testWifiNetworkSuggestionBuilderForWpa3EapNetwork() { WifiEnterpriseConfig enterpriseConfig = new WifiEnterpriseConfig(); enterpriseConfig.setEapMethod(WifiEnterpriseConfig.Eap.TLS); - enterpriseConfig.setPhase2Method(WifiEnterpriseConfig.Phase2.GTC); enterpriseConfig.setCaCertificate(FakeKeys.CA_CERT0); enterpriseConfig.setDomainSuffixMatch(TEST_DOMAIN_SUFFIX_MATCH); @@ -232,6 +232,78 @@ public class WifiNetworkSuggestionTest { assertEquals("\"" + TEST_SSID + "\"", suggestion.wifiConfiguration.SSID); assertTrue(suggestion.wifiConfiguration.allowedKeyManagement + .get(WifiConfiguration.KeyMgmt.IEEE8021X)); + assertTrue(suggestion.wifiConfiguration.allowedKeyManagement + .get(WifiConfiguration.KeyMgmt.WPA_EAP)); + assertFalse(suggestion.wifiConfiguration.allowedKeyManagement + .get(WifiConfiguration.KeyMgmt.SUITE_B_192)); + assertTrue(suggestion.wifiConfiguration.allowedGroupCiphers + .get(WifiConfiguration.GroupCipher.CCMP)); + assertTrue(suggestion.wifiConfiguration.requirePmf); + assertNull(suggestion.wifiConfiguration.preSharedKey); + // allowedSuiteBCiphers are set according to the loaded certificate and cannot be tested + // here. + assertTrue(suggestion.isUserAllowedToManuallyConnect); + assertTrue(suggestion.isInitialAutoJoinEnabled); + assertNotNull(suggestion.getEnterpriseConfig()); + } + + /** + * Validate correctness of WifiNetworkSuggestion object created by + * {@link WifiNetworkSuggestion.Builder#build()} for WPA3-Enterprise 192-bit RSA SuiteB network. + */ + @Test + public void testWifiNetworkSuggestionBuilderForWpa3SuiteBRsaEapNetwork() { + WifiEnterpriseConfig enterpriseConfig = new WifiEnterpriseConfig(); + enterpriseConfig.setEapMethod(WifiEnterpriseConfig.Eap.TLS); + enterpriseConfig.setCaCertificate(FakeKeys.CA_SUITE_B_RSA3072_CERT); + enterpriseConfig.setClientKeyEntryWithCertificateChain(FakeKeys.CLIENT_SUITE_B_RSA3072_KEY, + new X509Certificate[] {FakeKeys.CLIENT_SUITE_B_RSA3072_CERT}); + + enterpriseConfig.setDomainSuffixMatch(TEST_DOMAIN_SUFFIX_MATCH); + + WifiNetworkSuggestion suggestion = new WifiNetworkSuggestion.Builder() + .setSsid(TEST_SSID) + .setWpa3EnterpriseConfig(enterpriseConfig) + .build(); + + assertEquals("\"" + TEST_SSID + "\"", suggestion.wifiConfiguration.SSID); + assertTrue(suggestion.wifiConfiguration.allowedKeyManagement + .get(WifiConfiguration.KeyMgmt.SUITE_B_192)); + assertTrue(suggestion.wifiConfiguration.allowedGroupCiphers + .get(WifiConfiguration.GroupCipher.GCMP_256)); + assertTrue(suggestion.wifiConfiguration.allowedGroupManagementCiphers + .get(WifiConfiguration.GroupMgmtCipher.BIP_GMAC_256)); + assertTrue(suggestion.wifiConfiguration.requirePmf); + assertNull(suggestion.wifiConfiguration.preSharedKey); + // allowedSuiteBCiphers are set according to the loaded certificate and cannot be tested + // here. + assertTrue(suggestion.isUserAllowedToManuallyConnect); + assertTrue(suggestion.isInitialAutoJoinEnabled); + assertNotNull(suggestion.getEnterpriseConfig()); + } + + /** + * Validate correctness of WifiNetworkSuggestion object created by + * {@link WifiNetworkSuggestion.Builder#build()} for WPA3-Enterprise 192-bit ECC SuiteB network. + */ + @Test + public void testWifiNetworkSuggestionBuilderForWpa3SuiteBEccEapNetwork() { + WifiEnterpriseConfig enterpriseConfig = new WifiEnterpriseConfig(); + enterpriseConfig.setEapMethod(WifiEnterpriseConfig.Eap.TLS); + enterpriseConfig.setCaCertificate(FakeKeys.CA_SUITE_B_ECDSA_CERT); + enterpriseConfig.setClientKeyEntryWithCertificateChain(FakeKeys.CLIENT_SUITE_B_ECC_KEY, + new X509Certificate[] {FakeKeys.CLIENT_SUITE_B_ECDSA_CERT}); + + enterpriseConfig.setDomainSuffixMatch(TEST_DOMAIN_SUFFIX_MATCH); + + WifiNetworkSuggestion suggestion = new WifiNetworkSuggestion.Builder() + .setSsid(TEST_SSID) + .setWpa3EnterpriseConfig(enterpriseConfig) + .build(); + + assertEquals("\"" + TEST_SSID + "\"", suggestion.wifiConfiguration.SSID); + assertTrue(suggestion.wifiConfiguration.allowedKeyManagement .get(WifiConfiguration.KeyMgmt.SUITE_B_192)); assertTrue(suggestion.wifiConfiguration.allowedGroupCiphers .get(WifiConfiguration.GroupCipher.GCMP_256)); diff --git a/wifi/tests/src/android/net/wifi/aware/WifiAwareManagerTest.java b/wifi/tests/src/android/net/wifi/aware/WifiAwareManagerTest.java index 43d728bf593e..5fe0cb42073d 100644 --- a/wifi/tests/src/android/net/wifi/aware/WifiAwareManagerTest.java +++ b/wifi/tests/src/android/net/wifi/aware/WifiAwareManagerTest.java @@ -146,6 +146,15 @@ public class WifiAwareManagerTest { verify(mockAwareService).getCharacteristics(); } + /** + * Validate pass-through of isDeviceAttached() API. + */ + @Test + public void testIsAttached() throws Exception { + mDut.isDeviceAttached(); + verify(mockAwareService).isDeviceAttached(); + } + /* * WifiAwareEventCallbackProxy Tests */ @@ -360,12 +369,18 @@ public class WifiAwareManagerTest { eq(publishConfig)); inOrder.verify(mockSessionCallback).onSessionConfigFailed(); - // (5) terminate + // (5) discovery session is no longer visible + sessionProxyCallback.getValue().onMatchExpired(peerHandle.peerId); + mMockLooper.dispatchAll(); + inOrder.verify(mockSessionCallback).onServiceLost(peerIdCaptor.capture()); + assertEquals(peerHandle.peerId, peerIdCaptor.getValue().peerId); + + // (6) terminate publishSession.getValue().close(); mMockLooper.dispatchAll(); inOrder.verify(mockAwareService).terminateSession(clientId, sessionId); - // (6) try an update (nothing) + // (7) try an update (nothing) publishSession.getValue().updatePublish(publishConfig); mMockLooper.dispatchAll(); @@ -502,12 +517,18 @@ public class WifiAwareManagerTest { eq(subscribeConfig)); inOrder.verify(mockSessionCallback).onSessionConfigFailed(); - // (5) terminate + // (5) discovery session is no longer visible + sessionProxyCallback.getValue().onMatchExpired(peerHandle.peerId); + mMockLooper.dispatchAll(); + inOrder.verify(mockSessionCallback).onServiceLost(peerIdCaptor.capture()); + assertEquals(peerHandle.peerId, peerIdCaptor.getValue().peerId); + + // (6) terminate subscribeSession.getValue().close(); mMockLooper.dispatchAll(); inOrder.verify(mockAwareService).terminateSession(clientId, sessionId); - // (6) try an update (nothing) + // (7) try an update (nothing) subscribeSession.getValue().updateSubscribe(subscribeConfig); mMockLooper.dispatchAll(); |